[PYTHON] Pokemon x Data Science (3) - Réflexion sur la construction de partie du bouclier d'épée Pokemon à partir de l'analyse du réseau Où est le centre du réseau?

Bonjour, nous allons traiter de la théorie des graphes, une analyse de réseau dans l'article précédent](https://qiita.com/b_aka/items/9020e3237ff1a3e676e4) cette fois.

Dans l'article précédent, nous avons visualisé le réseau des parties de Pokemon Sword Shield Rank Battle. Cette fois, je vais réellement commencer l'analyse.

Le code et les données utilisés cette fois-ci se trouvent dans This Github Repository.

Le code complet est ici [https://github.com/moxak/pokemon-rankbattle-network-analysis/blob/master/002.ipynb)

Ce que je veux réaliser cette fois

Comme le titre l'indique, j'aimerais regrouper chaque nœud du Pokemon Swordsman Party Building Network. Nous souhaitons également capturer des nœuds importants en introduisant le concept de centralité avant le clustering.

Si vous pouvez faire quelque chose comme ça, vous avez atteint votre objectif.

community.gml.png

Centre dans le réseau

Il y a une centralité dans la théorie des réseaux (théorie des graphes).

La centralité est un indicateur permettant d'évaluer et de comparer l'importance de chaque sommet d'un réseau.

[Apprentissage de l'analyse de réseau 2e édition avec R Data Science](https://www.amazon.co.jp/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF % E3% 83% BC% E3% 82% AF% E5% 88% 86% E6% 9E% 90-% E7% AC% AC2% E7% 89% 88-R% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 83% BC% E3% 82% BF% E3% 82% B5% E3% 82% A4% E3% 82% A8% E3% 83% B3% E3% 82% B9-% E9% 88% B4% E6% 9C% A8-% E5% 8A% AA / dp / 4320113152 / ref = sr_1_4? __Mk_ja_JP =% E3% 82% AB% E3% 82% BF% E3 % 82% AB% E3% 83% 8A & dchild = 1 & keywords =% E3% 83% 8D% E3% 83% 83% E3% 83% 88% E3% 83% AF% E3% 83% BC% E3% 82% AF% À partir de E5% 88% 86% E6% 9E% 90 & sr = 8-4)

Il s'agit d'une tentative pour calculer mathématiquement à quel point chaque nœud est central = ** important ** dans le réseau.

Cette fois, j'aimerais utiliser cette théorie pour calculer l'importance de chaque nœud du réseau.

Cependant, il existe en fait de nombreux types de cette centralité.

1. Centralité des commandes

La première centralité est la centralité de l'ordre.

L'ordre est le nombre d'arêtes du nœud. Le nombre de commandes devient central tel quel.

Plus il y a de nœuds connectés, plus c'est important! Bien que ce soit une centralité de base basée sur l'idée, je pense que cela aboutit souvent à des choses qui ne sont pas intuitives.

2. Centralité de proximité, centralité d'excentricité

Viennent ensuite la centralité et l'excentricité de proximité, qui dérivent la centralité de la distance des autres nœuds.

Plus vous êtes proche du centre du réseau, plus c'est important! C'est l'idée.

La centralité de proximité prend l'inverse de la distance totale du propre nœud aux autres nœuds, et l'excentricité prend l'inverse de la distance maximale du propre nœud aux autres nœuds.

Puisque les résultats des deux utilisant la distance sont très similaires, j'aimerais utiliser la centralité de proximité cette fois.

3. Centralité de la médiation

Le plus couramment utilisé (je pense) est la centralité médiatisée.

En termes simples, l'idée est que plus elle est fréquemment localisée sur l'itinéraire le plus court, plus elle est importante (relais).

Un nœud avec un centre de médiation élevé dans un réseau communautaire signifie qu'il est dans une position où il n'est pas possible d'accéder à une autre communauté sans passer par ce nœud, ce qui semble intuitivement important. J'espère que vous pouvez comprendre cela.

4. Centralité vectorielle unique

La centralité des vecteurs propres est très différente des quatre centralités introduites jusqu'à présent, et c'est une centralité qui introduit l'idée de «à quel nœud est connecté».

En intégrant l'idée que «les nœuds connectés à des nœuds importants sont plus importants», le processus d'ajout des centralités des autres connectés à soi-même est répété, et la valeur convergée est définie comme centralité.

5. Classement de la page

Centralité conçue par les fondateurs de Google Larry Page et Sergei Brin.

L'idée de base est la même que celle de la centralité des vecteurs propres. Pour comprendre ce qui est différent, nous devons connaître le problème de la centralité des vecteurs propres.

Supposons que vous ayez un nœud dans votre réseau qui n'a pas d'arêtes d'autres nœuds. La centralité de ce nœud est bien entendu 0. C'est bien pour l'instant, mais le prochain est un peu délicat. Supposons que vous ayez un nœud i connecté uniquement à un tel nœud. Naturellement, la centralité de i ne change pas par rapport aux nœuds connectés, donc la centralité de i est également 0. Je pense que c'est contre-intuitif.

De plus, disons que vous avez un nœud i qui est connecté à un nœud j qui a une énorme quantité de centralité. Dans le concept de centralité des vecteurs propres, la centralité du nœud j passe au nœud i, mais le nœud i n'est qu'un des nombreux nœuds auxquels le nœud j attache une arête. Toute la centralité du nœud j doit-elle être transférée vers le nœud i?

Le classement de page est un indice de centralité qui résout ces problèmes dans une certaine mesure.

Il est devenu la base de l'algorithme de recherche de Google et est toujours utilisé pour calculer le facteur d'impact des papiers.

Dérivation de la centralité

Les données utilisées pour dériver la centralité sont les données de «classement Pokémon à adopter ensemble» et les données de classement d'adoption de la bataille de rang du bouclier d'épée Pokémon de la période précédente. Nous analyserons le réseau constitué des 100 meilleurs animaux du classement de recrutement.

df = pd.read_csv(FILEPATH_TEMOTI_POKEMON), encoding='utf-8')
df_rank = pd.read_csv(FILEPATH_ADO_RANK, encoding='utf-8')

df.columns = ['Season', 'Rule', 'Pokemon_From', 'Pokemon_To', 'Weight']
df['Weight'] = 10-df['Weight']

df_season11_double = df[(df['Season']==11)&(df['Rule']=='Double')]
df_season11_double = df_season11_double.drop(['Season', 'Rule'], axis=1)

#Limité aux 100 meilleurs taux de recrutement
df_season11_double = df_season11_double[df_season11_double['Pokemon_From'].isin(list(df_rank['Pokemon'])[:100])]
df_season11_double = df_season11_double[df_season11_double['Pokemon_To'].isin(list(df_rank['Pokemon'])[:100])]

df_season11_double.to_csv(OUTPUT_FILEPATH', index=False)
df_season11_double
index Pokemon_From Pokemon_To Weight
91394 Lézard Kyukon 9
91395 Lézard Tritodon 8
91396 Lézard Pippi 7
91397 Lézard Terrakion 6
91398 Lézard Yami Lami 5

504 rows × 3 columns

Créez un réseau à partir des données créées ci-dessus.

import networkx as nx
network_np = df_season11_double.values
G = nx.DiGraph()
G.add_weighted_edges_from(network_np)

default_network.png

1. Centralité des commandes

degree_centers = nx.degree_centrality(G)
df_dc = pd.DataFrame(sorted(degree_centers.items(), key=lambda x: x[1], reverse=True), columns=['Pokemon', 'Degree centrality'])
df_dc.head(10)
index Pokemon Degree centrality
0 Ulaos 0.500000
1 Flamme de Serre 0.490291
2 Achilleine 0.451456
3 Baril Moro 0.419903
4 Venteux 0.359223
5 Samayor 0.308252
6 Oronge 0.293689
7 Laplace 0.291262
8 Lézard 0.269417
9 Natley 0.237864

degree_centrality.png

2. Centralité de proximité

close_centers = nx.closeness_centrality(G)
df_cc = pd.DataFrame(sorted(close_centers.items(), key=lambda x: x[1], reverse=True), columns=['Pokemon', 'Closeness centrality'])
df_cc.head(10)
index Pokemon Closeness centrality
0 Ulaos 0.648440
1 Flamme de Serre 0.646345
2 Achilleine 0.628081
3 Baril Moro 0.612691
4 Venteux 0.594483
5 Samayor 0.572371
6 Laplace 0.562711
7 Oronge 0.551085
8 Pippi 0.545078
9 Natley 0.545078

closeness_centrality.png

3. Centralité de la médiation

between_centers = nx.betweenness_centrality(G)
df_bc = pd.DataFrame(sorted(between_centers.items(), key=lambda x: x[1], reverse=True), columns=['Pokemon', 'Betweenness centrality'])
df_bc.head(10)
index Pokemon Betweenness centrality
0 Kyukon 0.046012
1 persan 0.036945
2 Tritodon 0.028901
3 Lézard 0.025690
4 Terrakion 0.021207
5 Gracia 0.019807
6 Pain de sable 0.018529
7 Achilleine 0.013435
8 Nyai King 0.011381
9 Eleard 0.009867

betweenness_centrality.png

4. Centralité vectorielle unique

eigen_centers = nx.eigenvector_centrality_numpy(G)
df_ec = pd.DataFrame(sorted(eigen_centers.items(), key=lambda x: x[1], reverse=True), columns=['Pokemon', 'Eigen centrality'])
df_ec.head(10)
index Pokemon Eigen centrality
0 Ulaos 0.374252
1 Achilleine 0.362932
2 Flamme de Serre 0.341690
3 Baril Moro 0.332555
4 Samayor 0.297832
5 Venteux 0.292263
6 Patch Ragon 0.261000
7 Natley 0.259066
8 Pippi 0.237895
9 Laplace 0.218322

eigen_centrality.png

5. Classement de la page

pageranks = nx.pagerank(G)
df_pr = pd.DataFrame(sorted(pageranks.items(), key=operator.itemgetter(1),reverse = True), columns=['Pokemon', 'Page Rank'])
df_pr.head(10)

pagerank.png

J'ai essayé d'augmenter la police d'étiquette du nœud avec une grande centralité.

J'ai arrangé les classements publiés et chaque indice de centralité.

スクリーンショット2020-11-07224557.png

Dans le classement réduit aux 100 meilleurs animaux et aux 10 meilleurs animaux du classement combiné, on peut voir qu'Ulaos est plus élevé que le classement significativement publié dans n'importe quel indice. (Le sentiment d'être surfait)

À partir de maintenant, nous utiliserons le classement de page.

Regroupement de la structure du réseau

C'est enfin fini. Je voudrais entrer dans le clustering des structures de réseau, qui est le sujet de cette fois.

Il existe diverses méthodes de regroupement (extraction de communauté), telles que celles utilisant la centralité de médiation et la centralité des vecteurs propres dérivées plus tôt, la centralité de l'information, la méthode du verre de rotation et la marche aléatoire, qui ne sont pas introduites cette fois.

Cette fois, j'ai consacré une quantité considérable de texte à la dérivation de la centralité, je voudrais donc laisser l'exécution du clustering par chaque centralité et la comparaison des résultats à une autre opportunité.

Dépêchez-vous cette fois. Le clustering se fera en utilisant la méthode ici (Paper, Implementation Library).

Cette méthode est un indicateur de la densité du réseau ([Modularité](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%] A9% E3% 83% AA% E3% 83% 86% E3% 82% A3))) est une méthode de division au maximum, et elle diffère des k-moyennes en ce qu'il n'est pas nécessaire de spécifier le nombre de clusters à l'avance. il y a.

Les graphiques dirigés ne peuvent pas être utilisés dans cette implémentation, nous les convertirons donc en graphiques non orientés.

#Convertir un graphe orienté en graphe non orienté
G2 = nx.Graph(G)

import community
partition = community.best_partition(G2)
partition2 = {}
for i in partition.keys():
    sub_dict = {'community' : partition[i]}
    partition2[i] = sub_dict

labels = dict([(i, str(i)) for i in range(nx.number_of_nodes(G2))])
labels2 = {}
for i in range(len(labels)):
    sub_dict = {'labels' : labels[i]}
    labels2[list(partition.keys())[i]] = sub_dict

nx.set_node_attributes(G2, labels2)
nx.set_node_attributes(G2, partition2)
nx.write_gml(G2, ".//community.gml")

pd.DataFrame.from_dict(labels2).T.to_csv('.//community_labels.csv')

Interprétation des clusters

À la suite du regroupement, 6 clusters ont été extraits. Jetons un coup d'œil à chaque cluster.

df_pagerank = pd.DataFrame(sorted(pageranks.items(), key=operator.itemgetter(1),reverse = True), columns=['Pokemon', 'Page Rank'])
df_community = pd.concat([pd.DataFrame.from_dict(labels2).T, pd.DataFrame.from_dict(partition2).T], axis=1)
df_community = df_community.reset_index()
df_community.columns = ['Pokemon', 'label', 'community']

df_pagerank_community = pd.merge(left=df_pagerank, right=df_community, on = 'Pokemon')

Vérifiez la figure ci-dessous des Pokémon classés dans chaque cluster.

df_pagerank_community.groupby('community').count()['Pokemon'].plot.bar(rot=0, alpha=0.75)

plt.png

Vous pouvez voir que le cluster 3 représente près de 30% du total.

Jetons un coup d'œil au contenu de chaque cluster.

Cluster 0

df_pagerank_community[df_pagerank_community['community']==0].head(10)
index Pokemon Page Rank label community
13 Lézard 0.013742 0 0
18 Tritodon 0.007309 2 0
19 Sekitanzan 0.006604 32 0
20 Kyukon 0.006319 1 0
30 Yami Lami 0.002842 5 0
42 Manœuvre 0.001501 68 0
46 Nura 0.001235 55 0
53 Kovalon 0.001133 56 0
61 Leafia 0.000935 30 0
69 Village 0.000789 69 0

Est-ce une journée ensoleillée centrée sur Lizardon Kyukon? Lizardon est classé premier dans la centralité, et Tritodon, qui a une excellente compatibilité avec Lizardon, est classé à la deuxième place.

Groupe 1

df_pagerank_community[df_pagerank_community['community']==1].head(10)
index Pokemon Page Rank label community
8 Pippi 0.033903 3 1
16 Polygone Z 0.012646 27 1
17 Terrakion 0.009129 4 1
41 persan 0.001544 33 1
80 Rentler 0.000630 64 1
81 Ennute 0.000629 92 1

Ensuite, le groupe 1 était ces 6 animaux. Polygon Z, qui peut produire de la puissance super-thermique, a été classé par la pierre brillante Pippi, qui a des performances de support extrêmement élevées, et l'adaptabilité Dimax. L'impression est qu'il existe de nombreux Pokémon polyvalents qui peuvent être utilisés à n'importe quelle fête.

Groupe 2

df_pagerank_community[df_pagerank_community['community']==2].head(10)
index Pokemon Page Rank label community
7 Natley 0.038186 6 2
24 Nymphie 0.005511 20 2
28 Peripper 0.003061 57 2
29 Wonoragon 0.002859 46 2
32 Roi Dora 0.002468 49 2
33 Nyorotono 0.002321 47 2
35 Runpapa 0.002233 50 2
37 Gamageroge 0.001736 58 2
38 Chevalgo 0.001626 59 2
39 Matadogas 0.001572 44 2

Le cluster 2 est facile à comprendre, c'est un pa de pluie qui comprend peripper, kingdora, runpapa et ainsi de suite. La centralité du nutray, qui est excellente pour compléter la compatibilité avec le type d'eau, est élevée. De plus, le fait que Pokémon, comme Chevalgo, qui ne sont pas doués pour les types de flammes, soit composé de rain pas est conforme à mon intuition.

Groupe 3

df_pagerank_community[df_pagerank_community['community']==3].head(10)
index Pokemon Page Rank label community
0 Achilleine 0.107503 7 3
1 Flamme de Serre 0.093996 12 3
4 Venteux 0.056541 15 3
5 Patch Ragon 0.049160 16 3
14 Duraldon 0.013730 24 3
15 Oronge 0.013617 29 3
21 Amarjo 0.006167 17 3
26 Wogle 0.003980 23 3
27 Genger 0.003799 43 3
34 Lutin 0.002254 28 3

Le cluster 3 semble être concentré dans la méta supérieure de l'environnement. Si vous regardez les considérations de construction de groupe qui roulent sur le net, vous pouvez souvent voir la combinaison de Achilleine Firelow Patch Ragon comme une construction réussie, donc le Pokémon qui a eu une grande influence dans le double environnement de la saison 11 Je suppose qu'il y en a beaucoup.

Groupe 4

df_pagerank_community[df_pagerank_community['community']==4].head(10)
index Pokemon Page Rank label community
2 Baril Moro 0.083762 8 4
3 Samayor 0.061276 9 4
9 Bord sur 0.026956 25 4
11 Dosaidon 0.016228 21 4
12 Dadarin 0.014804 26 4
22 Lumière Chu 0.006124 13 4
25 Garula 0.005487 19 4
31 hochet 0.002758 39 4
40 Yadran 0.001563 40 4
45 Raidisseur 0.001322 82 4

Ce cluster est également très facile à comprendre. Samayor et Brimon, qui sont les déclencheurs du trille, Dosaidon, Dadarin et le hochet, qui sont les attaquants du trille, et Morobarrel, qui est le partisan, sont classés.

En regardant la centralité, nous pouvons voir que Morobarrel joue un rôle très important.

Groupe 5

df_pagerank_community[df_pagerank_community['community']==5].head(10)
index Pokemon Page Rank label community
6 Ulaos 0.045935 10 5
10 Laplace 0.024565 22 5
23 Kuwawa 0.005706 14 5
36 Numergon 0.002140 88 5
50 Onburn 0.001201 83 5
55 Kamex 0.001056 11 5
63 Mahip 0.000880 94 5
90 Togedemaru 0.000463 93 5

Le dernier groupe est ces 8 animaux. Quel genre de rassemblement sont ces Pokémon? C'était difficile à interpréter avec mes connaissances, j'attends donc les commentaires.

Visualisation

Enfin, visualisez le réseau avec Cytoscape, qui a été confirmé comment l'utiliser la dernière fois.

Chargez community.gml depuis ** Fichier> Importer> Réseau à partir d'un fichier ** et ** Importer une table à partir d'un fichier ** en haut (voir figure ci-dessous)

スクリーンショット2020-11-05021410.png

Depuis, chargez community_labels.csv et définissez la boîte de dialogue affichée comme suit.

Notez que la partie rouge doit être modifiée par rapport à la valeur par défaut.

スクリーンショット2020-11-07203853.png

Tout ce que vous avez à faire est de changer la forme et la couleur de chaque cluster en utilisant pleinement ** Mappage continu ** à partir de l'onglet ** Style **.

スクリーンショット2020-11-07204346.png

J'ai essayé de visualiser le réseau avec la couleur de police comme groupe et la taille de police comme rang de page.

community.gml.png

La prochaine fois, j'aimerais rechercher la méthode de clustering optimale pour ces données.

À la prochaine.

Source, etc.

© 2020 Pokémon © 1995-2020 Nintendo / Creatures Inc./GAME FREAK Inc. Pocket Monsters, Pokemon et Pokémon sont des marques déposées de Nintendo, Creatures et Game Freak.

Recommended Posts

Pokemon x Data Science (3) - Réflexion sur la construction de partie du bouclier d'épée Pokemon à partir de l'analyse du réseau Où est le centre du réseau?
Pokemon x Data Science (2) - Version d'essai de la réflexion sur la construction de groupe du bouclier d'épée Pokemon à partir de l'analyse de réseau
Visualisez le centre de l'environnement de combat de rang à partir de l'API Pokemon Home