学習コースLearn
ネットワーク分析
人・モノ・要素の「つながり」をグラフとして表し、その構造や重要な要素を定量的に読み解く技術を、概要から理論、そして実際に動かせるコードまで、順を追って学ぶモジュールです。各ステップは「概要 → 仕組み(座学)→ コードで動かす」の3層で進みます。ページ内には手を動かせるデモを3つ用意しました。
この教材は日本語のみで提供していますThis learning material is available in Japanese only.
はじめにIntroduction
このモジュールの全体像
ネットワーク分析(network analysis)とは、要素どうしの「つながり」をグラフ(graph)として表し、その構造や、どの要素が重要かを定量的に読み解く技術です。友人関係のような社会ネットワーク、論文の引用、Web のリンク、ソフトウェアの依存関係、道路や鉄道の交通網まで、世の中の多くのものは「つながりの網」として捉えられます。
ネットワーク分析では、要素をノード(頂点)、つながりをエッジ(辺)として表します。この単純な枠組みに、次のような流れ(パイプライン)で数値的な道具を当てていきます。データからグラフを組み立て、指標を計算し、可視化して解釈します。
ネットワーク分析の基本パイプライン
ノードとエッジ
ネットワークはノード(頂点)と、それらをつなぐエッジ(辺)で表します。この「つながりの構造」そのものを数値で読み解くのがネットワーク分析です。
このモジュールは、上のパイプラインを左から順にたどります。各ステップは次の3層で構成します。
- 概要:その技術が何のためにあるのか、あらましをつかむ。
- 仕組み(座学):背後にある理論・定義・式を、ていねいに理解する。
- コードで動かす:Python の定番ライブラリ NetworkX や、ページ内デモで実際に動かして確かめる。
手を動かす題材には、実在の公開データセット(Zachary の空手クラブ、Les Misérables の共起ネットワークなど)や、ページ内の小さなサンプルグラフだけを使います。特別な環境がなくても、読みながら試せる構成です。
ネットワーク分析とは
What is network analysis概要Overview
ネットワーク分析は「関係」を主役に据える見方です。個々の要素の性質だけでなく、要素どうしがどうつながっているかに注目します。同じデータでも、表の1行ずつを別々に見るのと、行と行の関係を網として見るのとでは、見えてくるものが違います。ネットワークはあらゆる場所に現れます。
- 社会ネットワーク:人を点、友人関係やフォロー関係を線とする。
- 引用・参照:論文を点、引用を線とする。Web ページとリンクも同じ形。
- 依存関係:ソフトウェアのモジュールやパッケージを点、依存を線とする。
- 協働:開発者を点、同じファイルを一緒に触った関係を線とする。
- インフラ:駅や交差点を点、路線や道路を線とする。
仕組みHow it works
ノードとエッジという共通の言葉で表すと、分野が違っても同じ道具で分析できるのがネットワーク分析の強みです。このモジュールでは、次のような問いに答える道具を順に手に入れます。
- どのノードが重要か:つながりの多さや、橋渡しの役割を数値で測る(中心性)。
- まとまりはあるか:密につながった集団(コミュニティ)を見つける。
- どれくらい近いか:ノード間の最短経路や、ネットワーク全体の広がりを測る。
- 全体はどんな形か:スモールワールド性やスケールフリー性といった、大きな構造の特徴を捉える。
これらはすべて、グラフという同じ土台の上で計算できます。まずは、その土台となるグラフの基礎から始めましょう。
この Step のまとめ
ネットワーク分析は「関係」を主役にする見方。要素をノード、つながりをエッジとして表すと、社会・引用・依存・交通など分野をまたいで同じ道具が使えます。「重要なノード・まとまり・近さ・全体の形」を数値で読み解いていきます。
グラフの基礎
Graph basics概要Overview
グラフは、ノードの集合とエッジの集合の組です。とても単純ですが、表し方にいくつかの選択肢があり、そこから分析の第一歩となる基本的な指標が決まります。まずは用語と、もっとも基本的な量である「次数」をおさえます。
仕組みHow it works
有向グラフと無向グラフ
エッジに向きがないものを無向グラフと呼びます。友人関係のように「たがいに」つながる関係です。いっぽう、向きがあるものを有向グラフと呼びます。フォロー関係や引用のように「AからBへ」という一方向の関係です。エッジに数値(距離・重み・回数など)を付けたものは重み付きグラフです。
隣接行列と隣接リスト
グラフをコンピュータで表す代表的な方法が2つあります。隣接行列は、ノード数を n として n×n の表を作り、ノード i とノード j がつながっていれば 1(重み付きなら重み)を書きます。隣接リストは、各ノードについて「つながっている相手の一覧」を持ちます。エッジが少ない(疎な)グラフでは、隣接リストのほうが省メモリで効率的です。
次数(degree)
あるノードにつながっているエッジの本数を次数と呼びます。無向グラフでは単に本数ですが、有向グラフでは、入ってくるエッジの数を入次数(in-degree)、出ていくエッジの数を出次数(out-degree)と区別します。次数は「そのノードが何本の線を持つか」という、もっとも素朴な重要度の目安になります。
密度(density)
ネットワーク全体が「どれくらい密につながっているか」を表すのが密度です。実際にあるエッジ数を、あり得る最大のエッジ数で割った値で、0(線がまったくない)から 1(すべてのノードが互いにつながる完全グラフ)までの範囲を取ります。無向グラフでは次の式です。
あり得る最大エッジ数 n(n-1)/2 のうち、実際に何本あるかの割合です。
グラフと次数
プリセットのグラフを表示します。ノードをクリックすると、そのノードにつながるエッジ(次数)と隣接ノードを強調し、次数中心性を計算します。上のボタンでグラフを切り替えられます。もう一度クリックすると選択が解除されます。
コードで動かすRun the code
Python では NetworkX が定番です。ノードとエッジを足していくだけでグラフができ、次数や密度もすぐに取れます。デモと同じ7ノードのグラフ(A から G)を作ってみましょう。
import networkx as nx
G = nx.Graph()
for u, v in [("A", "B"), ("A", "C"), ("B", "C"), ("C", "D"),
("D", "E"), ("D", "F"), ("E", "F"), ("F", "G")]:
G.add_edge(u, v)
print(G.number_of_nodes(), G.number_of_edges())
print(dict(G.degree()))
print(round(nx.density(G), 3))
7 8
{'A': 2, 'B': 2, 'C': 3, 'D': 3, 'E': 2, 'F': 3, 'G': 1}
0.381有向グラフでは DiGraph を使い、入次数と出次数を区別できます。
# 有向グラフでは入次数と出次数を区別する
D = nx.DiGraph()
D.add_edges_from([("A", "B"), ("B", "C"), ("A", "C")])
print(dict(D.in_degree()))
print(dict(D.out_degree()))
{'A': 0, 'B': 1, 'C': 2}
{'A': 2, 'B': 1, 'C': 0}この Step のまとめ
グラフはノードとエッジの組。有向/無向・重みの有無で表し方が変わり、隣接行列や隣接リストで保持します。もっとも基本の量が次数で、そこから全体の密度もわかります。次はこの上で「どのノードが重要か」を測ります。
重要なノードを測る(中心性)
Centrality概要Overview
ネットワークで「どのノードが重要か」を数値化するのが中心性(centrality)です。ただし「重要」の意味は一通りではありません。つながりの多さが大事な場面もあれば、集団と集団の橋渡しをする役割が大事な場面もあります。目的に応じて指標を使い分けます。代表的な4つを見ていきましょう。
仕組みHow it works
次数中心性(degree centrality)
もっとも単純で、つながっている相手の多さをそのまま重要度とします。比較しやすいよう、次数を「あり得る最大の次数 n-1」で割って 0 から 1 に正規化します。SNS でフォロワーが多い人、といったイメージです。
媒介中心性(betweenness centrality)
ノードがどれだけ「橋渡し」をしているかを測ります。すべてのノード対の最短経路を考え、そのうち何割が自分を通るかを合計します。集団と集団をつなぐ位置にあるノードは、次数が少なくても媒介中心性が高くなります。情報や物の流れの「関所」にあたる重要な役割です。
近接中心性(closeness centrality)
あるノードから他のすべてのノードへ、どれだけ近いかを測ります。最短距離の合計が小さいほど、ネットワークの「中心」に近いと考えます。全体へ素早く到達できる位置にあるノードほど高くなります。
固有ベクトル中心性と PageRank
「重要なノードにつながっているノードは重要」という再帰的な考え方が固有ベクトル中心性です。つながりの数だけでなく、つながる相手の重要度まで考慮します。これを有向グラフ(Web のリンクなど)向けに改良し、実用的にしたのが PageRank です。Google の初期の検索順位づけで有名になりました。多くの重要なページからリンクされるページほど、高いスコアになります。
これらの指標は、同じグラフでも「誰が重要か」の答えが変わります。次のデモで、指標を切り替えながらその違いを体感してみましょう。
中心性ランキング
Step 2 と同じ交友グラフ(7ノード)に対して、指標を選ぶと各ノードの中心性スコアを計算し、高い順にランキングします。グラフ上のノードは、色が濃いほどスコアが高いことを表します。指標によって「重要なノード」が入れ替わることに注目してください。
コードで動かすRun the code
NetworkX には主要な中心性がひととおり用意されています。同じグラフに対して4つの指標を計算し、見やすいよう小数第3位で丸めて表示します。
import networkx as nx
G = nx.Graph()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D"),
("D", "E"), ("D", "F"), ("E", "F"), ("F", "G")])
def show(d):
return {k: round(v, 3) for k, v in d.items()}
print(show(nx.degree_centrality(G)))
print(show(nx.betweenness_centrality(G)))
print(show(nx.closeness_centrality(G)))
print(show(nx.pagerank(G)))
{'A': 0.333, 'B': 0.333, 'C': 0.5, 'D': 0.5, 'E': 0.333, 'F': 0.5, 'G': 0.167}
{'A': 0.0, 'B': 0.0, 'C': 0.533, 'D': 0.6, 'E': 0.0, 'F': 0.333, 'G': 0.0}
{'A': 0.429, 'B': 0.429, 'C': 0.6, 'D': 0.667, 'E': 0.5, 'F': 0.545, 'G': 0.375}
{'A': 0.125, 'B': 0.125, 'C': 0.179, 'D': 0.179, 'E': 0.126, 'F': 0.19, 'G': 0.075}※ NetworkX の betweenness_centrality は既定で正規化され、上の式の合計に 2/((n−1)(n−2)) を掛けた値を返します(n はノード数。この例では n=7 なので D の 9 本 × 2/30 = 0.6)。
結果を見比べると面白いことがわかります。次数では C・D・F が同点ですが、媒介中心性では D が最大(左右の集団をつなぐ橋渡し)、近接中心性でも D が最大(全体の中心)です。いっぽう PageRank では、末端の G から流れ込むぶんだけ F が少し高くなります。「重要さ」は測り方しだいなのです。
この Step のまとめ
中心性は「重要なノード」を数値化する道具。次数は多さ、媒介は橋渡し、近接は全体への近さ、PageRank は重要な相手からのつながりを重く見ます。目的に合った指標を選ぶことが肝心です。
まとまりを見つける(コミュニティ検出)
Community detection概要Overview
大きなネットワークには、内部が密につながった集団がしばしば潜んでいます。友人グループ、研究分野、機能ごとのモジュール群などです。こうしたまとまりを見つけ出すのがコミュニティ検出(community detection)です。全体をいくつかのグループに分け、構造を理解しやすくします。
仕組みHow it works
連結成分
もっとも素朴なまとまりが連結成分(connected component)です。エッジをたどって互いに行き来できるノードの集まりで、グラフが「いくつの島に分かれているか」を表します。まず全体がひとつながりかどうかを確かめるのが出発点です。
モジュラリティ
連結成分よりも細かく「密なまとまり」を見つけるには、分割の良さを測るものさしが要ります。定番がモジュラリティ(modularity)です。コミュニティの内部にエッジが多く、コミュニティ間のエッジが少ないほど値が大きくなります。よい分割ほどモジュラリティが高い、という考え方です。
実際の内部エッジが、ランダムな場合の期待値をどれだけ上回るかを足し合わせます。
コミュニティ検出の手法
モジュラリティを手がかりに分割を探す代表的な手法があります。ガーバン・ニューマン法は、橋渡しをするエッジ(媒介の高いエッジ)を少しずつ取り除いてコミュニティを浮かび上がらせます。Louvain 法は、モジュラリティが上がるようにノードをまとめていく高速な手法で、大規模なネットワークでもよく使われます。NetworkX の greedy_modularity_communities は、モジュラリティを貪欲に最大化する手法です。
クラスタリング係数
「友達の友達は友達か」という、まとまりやすさの局所的な指標がクラスタリング係数です。あるノードの隣どうしが、実際にどれだけ互いにつながっているかの割合で、社会ネットワークでは高くなりがちです。ネットワーク全体で平均したものを平均クラスタリング係数と呼びます。
コードで動かすRun the code
まず、島が2つに分かれた小さなグラフで連結成分を確かめます。
import networkx as nx
H = nx.Graph()
H.add_edges_from([("A", "B"), ("B", "C"), ("D", "E")])
print(nx.number_connected_components(H))
print([sorted(c) for c in nx.connected_components(H)])
2
[['A', 'B', 'C'], ['D', 'E']]次に、実在の公開データ Zachary の空手クラブ(34人の会員と、その交友関係からなる有名なネットワーク)で、コミュニティ検出とクラスタリング係数を試します。NetworkX に内蔵されているので、ダウンロード不要です。
G = nx.karate_club_graph() # 実在の空手クラブ・ネットワーク
print(nx.number_connected_components(G)) # 全体はひとつながり
comms = nx.community.greedy_modularity_communities(G)
print(len(comms)) # 見つかったコミュニティ数
print(round(nx.community.modularity(G, comms), 4))
print(round(nx.average_clustering(G), 4))
1
3
0.411
0.5706※ モジュラリティの値は NetworkX のバージョンによって変わります(上は NetworkX 3.6 で実行した結果。古い 2.x 系では約 0.38 になります)。
34人のネットワークが3つのコミュニティに分かれ、その分割のモジュラリティは約 0.41、平均クラスタリング係数は約 0.57 でした。空手クラブは実際に2つの派閥に分裂した歴史があり、こうした構造がデータからも読み取れます。
この Step のまとめ
コミュニティ検出は「密なまとまり」を見つける道具。連結成分でまず島の数を数え、モジュラリティを手がかりに Louvain 法などで細かく分割します。クラスタリング係数は「友達の友達は友達か」という局所的なまとまりやすさを表します。
経路と全体の構造
Paths & structure概要Overview
ネットワークの「近さ」や「広がり」は、ノードからノードへたどる経路で測ります。とくに大切なのが、あいだのエッジ数が最小の最短経路です。最短経路がわかると、ネットワーク全体がどれくらいコンパクトか、どんな大きな構造を持つかまで見えてきます。
仕組みHow it works
最短経路(BFS とダイクストラ)
重みのないグラフでは、幅優先探索(BFS: breadth-first search)で最短経路を求められます。始点から近い順に、波が広がるようにノードを訪れていくので、初めて終点に届いたときの経路が最短です。エッジに重み(距離など)があるグラフでは、ダイクストラ法を使います。次のデモは BFS で、始点から終点までの最短経路をたどります。
直径と平均経路長
すべてのノード対について最短距離を求めると、ネットワーク全体の広がりがわかります。最短距離の最大値を直径(diameter)、平均を平均経路長と呼びます。直径が小さいほど、ネットワークは「どこからどこへも近い」コンパクトな形です。
スモールワールドとスケールフリー
現実の多くのネットワークには、共通する2つの性質が見られます。ひとつはスモールワールド性で、巨大なネットワークでも、ごく少ないステップで任意の2ノードがつながります。「六次の隔たり」で知られる性質です。もうひとつはスケールフリー性で、次数の分布がべき則(power law)に従い、ごく一部の「ハブ」が飛び抜けて多くのつながりを持ちます。SNS や Web、引用ネットワークなどで観察されます。
最短経路(BFS)
Step 2 と同じ交友グラフで、始点と終点を選ぶと、BFS(幅優先探索)で最短経路を求め、グラフ上に太い線で示します。始点と終点は濃い緑、経路上のノードは薄い緑で表示します。経路の長さ(エッジの数)が最短距離です。
コードで動かすRun the code
NetworkX なら、最短経路も全体の構造も一行ずつで求まります。デモと同じグラフで確かめましょう。
import networkx as nx
G = nx.Graph()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D"),
("D", "E"), ("D", "F"), ("E", "F"), ("F", "G")])
print(nx.shortest_path(G, "A", "G"))
print(nx.shortest_path_length(G, "A", "G"))
print(nx.diameter(G))
print(round(nx.average_shortest_path_length(G), 3))
['A', 'C', 'D', 'F', 'G']
4
4
2.048A から G への最短経路は A → C → D → F → G の4ステップ、ネットワークの直径も4、平均経路長は約2.05でした。橋渡しの役割を担う C と D を必ず通っていることに注目してください。Step 3 で C と D の媒介中心性が高かったのは、まさにこのためです。
この Step のまとめ
ネットワークの「近さ」は最短経路で測り、重みがなければ BFS で求まります。全体の広がりは直径や平均経路長で表します。現実のネットワークには、少ないステップでつながるスモールワールド性と、一部のハブが偏って多くつながるスケールフリー性がよく見られます。
可視化とこれから
Visualization & what is next概要Overview
数値だけでなく、ネットワークは絵にすると理解が一気に進みます。ただし、ノードをどこに置くかで見え方が大きく変わります。よい配置(レイアウト)と、大規模なネットワークをどう扱うかが、可視化の鍵になります。
仕組みHow it works
レイアウト
グラフ描画で広く使われるのが力学モデル(force-directed layout)です。エッジをばね、ノードどうしを反発する電荷に見立て、力がつり合う位置へノードを配置します。密につながったノードは近くに、そうでないノードは遠くに集まるので、コミュニティ構造が自然と見えてきます。
大規模ネットワークと動的ネットワーク
ノードが数万・数百万になると、すべてを描くと「毛玉」のようになり、かえって読み取れません。重要な部分だけを抜き出す、集約する、対話的に拡大縮小するといった工夫が要ります。専用ツールの Gephi や、Python の igraph・graph-tool は大きなグラフに向いています。また、つながりが時間とともに変わる動的ネットワークを扱う研究も進んでいます。
描画のコード
小さなグラフなら、NetworkX と matplotlib で手軽に描けます。レイアウトを計算し、ノード・エッジ・ラベルを重ねて描画します。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.karate_club_graph()
pos = nx.spring_layout(G, seed=42) # 力学モデル(force-directed)で配置
nx.draw_networkx_nodes(G, pos, node_size=300)
nx.draw_networkx_edges(G, pos, alpha=0.4)
nx.draw_networkx_labels(G, pos, font_size=8)
plt.axis("off")
plt.savefig("karate.png", dpi=150)
この Step のまとめ
可視化はレイアウトしだいで見え方が変わり、力学モデルはコミュニティ構造を自然に浮かび上がらせます。大規模・動的なネットワークには専用の道具と工夫が必要です。ここまでの「グラフ構築 → 指標 → まとまり → 経路 → 可視化」が、ネットワーク分析の基本の一巡です。
まとめWrap-up
学びの振り返りと、さらに学ぶために
このモジュールでは、つながりを読み解く基本の道具を、パイプラインに沿って順に手に入れました。
- グラフの基礎:ノードとエッジ、有向/無向・重み、次数と密度。
- 中心性:次数・媒介・近接・PageRank で「重要なノード」を測る。
- コミュニティ検出:連結成分とモジュラリティで「密なまとまり」を見つける。
- 経路と構造:BFS で最短経路を求め、直径や平均経路長で全体の広がりを測る。
- 可視化:力学モデルで構造を絵にし、大規模・動的なネットワークへ広げる。
次に進むなら、下の道具と資料が役に立ちます。
公開データセット
- Zachary の空手クラブ:34人の交友ネットワーク。
nx.karate_club_graph()で内蔵。 - Les Misérables 共起ネットワーク:小説の登場人物の共起関係。ネットワーク可視化の定番。
- SNAP:スタンフォード大学が公開する大規模グラフ集(SNS・道路・引用など)。
ライブラリ
- NetworkX:Python の定番。学習・中小規模に最適。
- igraph:C 実装で高速、Python から使える。
- graph-tool:大規模グラフ向けの高速ライブラリ。
- Gephi:対話的なネットワーク可視化ツール。
参考書
- Mark Newman『Networks』(Oxford University Press)
- Albert-László Barabási『Network Science』(邦訳『ネットワーク科学』)
- Easley, Kleinberg『Networks, Crowds, and Markets』
次のモジュールへ
- 機械学習(分類・回帰・評価)
- 深層学習(ニューラルネットの基礎)
- リポジトリマイニング入門(開発者ネットワークの元データ)
おつかれさまでした
ここで学んだ「グラフにする → 指標で測る → まとまりや経路を読む」という流れは、関係を持つあらゆるデータに共通する考え方です。3つのデモのノードやグラフを切り替えたり、始点・終点を変えたりして、値がどう変わるかを確かめてみてください。指標ごとに「重要なノード」が入れ替わる感覚がつかめると、理解がぐっと深まります。
発展トピックBeyond this module
このコースでは扱わない、関係する発展トピック
このモジュールでは、グラフを組み立て、指標で測り、構造を読み解く「基礎の流れ」を扱いました。いっぽうで近年のネットワーク分析は、機械学習や深層学習と結びつき、急速に広がっています。ここでは、このコースでは踏み込まないものの、知っておくと視野が広がる発展的なトピックを、特に近年の主流を中心に紹介します。深掘りは各自の興味に合わせてどうぞ。グラフニューラルネットワーク(GNN)はこのコースの範囲外の発展トピックで、深層学習のモジュールでも名前を挙げるにとどめています。
グラフの表現学習
- グラフ埋め込み:ノードを密なベクトルに変換し、機械学習に使えるようにする手法(node2vec・DeepWalk)。ランダムウォークと word2vec の考え方を組み合わせます。
- スペクトラルクラスタリング:グラフのラプラシアン行列の固有ベクトルを使って分割する、数理的なコミュニティ検出。
グラフニューラルネットワーク
- GNN:隣接ノードの情報を集約しながら学習する深層モデル(GCN・GraphSAGE・GAT)。ノード分類やグラフ分類に強力。このコースの範囲外(発展トピック)。
- メッセージパッシング:GNN に共通する、近傍から情報を伝え合う枠組み。
予測と動的ネットワーク
- リンク予測:まだ存在しないつながりを予測する(友人推薦・共著予測など)。
- 動的・時系列ネットワーク:時間とともに変化するつながりをモデル化し、成長や消滅を捉える。
大規模グラフと拡散
- 大規模グラフ処理:数億ノード規模を扱う分散処理や近似アルゴリズム(graph-tool・分散グラフ基盤)。
- 拡散・伝播:情報や感染がネットワーク上をどう広がるかのモデル(感染症モデル・影響最大化)。