ソーシャルネットワーク、分子構造、交通網、推薦システム — 現実世界の多くのデータはグラフ構造を持っています。グラフ上の各ノードを分類したり、グラフ全体の性質を予測したりするようなタスクでは、グラフの構造情報を活用した表現学習が不可欠です。
Twitterのフォロー関係を例に考えてみましょう。各ユーザー(ノード)はプロフィール情報(特徴ベクトル)を持ち、フォロー関係(エッジ)でつながっています。あるユーザーが「ボットか人間か」を判定したいとき、そのユーザーの特徴だけでなく、フォロワーやフォロー先の特徴も重要な手がかりになります。ボットアカウントは互いにフォローし合う傾向があるため、近傍の構造パターンを調べることで検出精度が大幅に向上します。
Graph Convolutional Network (GCN)はグラフ上で畳み込みを実現する画期的な手法でしたが、グラフ全体のラプラシアン行列を必要とするため、新しいノードが追加されたときに全体を再計算する必要がありました。SNSで新しいユーザーが登録されるたびに、全ユーザーの表現を再計算するのは現実的ではありません。1日に数万人から数十万人の新規ユーザーが登録される大規模プラットフォームでは、このような再計算は計算コストの観点から完全に不可能です。
GraphSAGE(Hamilton et al., 2017)は、この問題を近傍サンプリングと集約というシンプルなアイデアで解決しました。各ノードの表現を、その近傍ノードの情報を集約(SAGe: SAmple and aggrEgate)して生成するため、未知のノードにも対応できる帰納的(inductive)な学習が可能になりました。
日常的な例えを使うと、GCNは「全校生徒の人間関係図を一度に作って、そこから各生徒の特徴を読み取る」方法です。転校生が来たら図を全部書き直す必要があります。GraphSAGEは「各生徒の友達5人に話を聞いて、その情報を元にその生徒の特徴をまとめる」方法です。転校生が来ても、その子の周りの友達に話を聞くだけで済みます。
GraphSAGEを理解すると、以下のことが可能になります。
- 動的グラフへの対応: 新しいノードやエッジが追加されても即座に推論可能
- 大規模グラフの学習: ミニバッチ学習による効率的な大規模グラフ処理
- 多様なタスクへの応用: ノード分類、リンク予測、グラフ分類
- GNNの発展理解: GIN, GAT等の発展手法の基盤
実際にPinterest(画像共有SNS)では、GraphSAGEをベースにしたPinSageというシステムが30億以上のノードを持つ巨大グラフ上で推薦システムを動かしており、産業応用としても非常に大きな成功を収めています。
本記事の内容
- GCNの限界と帰納学習の必要性
- GraphSAGEのアルゴリズム
- 3つの集約関数(Mean, LSTM, Pool)
- 近傍サンプリングの役割
- Pythonでのスクラッチ実装
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
- ニューラルネットワークの基礎 — MLPの構造
- CNNの基礎 — 畳み込みの概念
グラフニューラルネットワークの基本
グラフの定義
グラフ $G = (V, E)$ は、ノード集合 $V$ とエッジ集合 $E \subseteq V \times V$ で定義されます。各ノード $v$ は特徴ベクトル $\bm{x}_v \in \mathbb{R}^d$ を持つとします。ノード $v$ の近傍を $\mathcal{N}(v) = \{u : (v, u) \in E\}$ と表します。
たとえばSNSであれば、ノードは各ユーザー、エッジはフォロー関係、特徴ベクトルはプロフィール情報(年齢、投稿数、アクティブ時間帯など)を数値化したものに相当します。グラフはこのように「もの」と「もの同士の関係」を同時に表現できるデータ構造であり、テーブルデータや画像データでは失われてしまう関係性の情報を保持できるのが最大の強みです。画像は格子状のグラフ、文は直線状のグラフと捉えることもでき、グラフは非常に一般的なデータ構造だと言えます。
メッセージパッシングの枠組み
多くのGNNはメッセージパッシング(message passing)の枠組みで理解できます。各ノードが近傍ノードから「メッセージ」を受け取り、自身の表現を更新します。イメージとしては、学校の教室で「隣の席の人から情報を集めて、自分の考えを更新する」プロセスを何回か繰り返すようなものです。
数式で書くと、各層 $l$ での更新は次の2ステップです。
$$ \begin{align} \bm{m}_v^{(l)} &= \text{AGGREGATE}^{(l)}\left(\{\bm{h}_u^{(l-1)} : u \in \mathcal{N}(v)\}\right) \\ \bm{h}_v^{(l)} &= \text{UPDATE}^{(l)}\left(\bm{h}_v^{(l-1)}, \bm{m}_v^{(l)}\right) \end{align} $$
$\bm{h}_v^{(0)} = \bm{x}_v$(初期特徴)、$l$ は層のインデックスです。1行目のAGGREGATEが近傍から情報を集める操作、2行目のUPDATEが集めた情報を使って自分の表現を更新する操作です。
$K$ 層のメッセージパッシング後、各ノードは $K$ ホップ以内の近傍の情報を集約した表現を持ちます。たとえば2層のGNNでは、あるノードは「友達の友達」まで情報が届きます。層数を増やすほど広い範囲の情報を集められますが、あまり深くすると「全ノードの情報が混ざって区別がつかなくなる」問題(over-smoothing)が発生するため、通常は2〜3層が使われます。
GCNとの違い
GCN(Kipf and Welling, 2017)では、集約関数が次のように定義されます。
$$ \bm{H}^{(l)} = \sigma\left(\tilde{\bm{D}}^{-1/2}\tilde{\bm{A}}\tilde{\bm{D}}^{-1/2}\bm{H}^{(l-1)}\bm{W}^{(l)}\right) $$
$\tilde{\bm{A}} = \bm{A} + \bm{I}$ は自己ループ付き隣接行列、$\tilde{\bm{D}}$ は次数行列です。
この式を分解して理解しましょう。$\tilde{\bm{D}}^{-1/2}\tilde{\bm{A}}\tilde{\bm{D}}^{-1/2}$ は正規化された隣接行列で、各ノードの次数(接続数)の違いを補正する役割を果たします。これに特徴行列 $\bm{H}^{(l-1)}$ を掛けることで、近傍の特徴の加重平均が計算されます。最後に重み行列 $\bm{W}^{(l)}$ で線形変換し、活性化関数 $\sigma$ を適用します。
重要なのは、この計算がグラフ全体の隣接行列 $\bm{A}$ を一度に使う行列演算であるという点です。これはトランスダクティブ(transductive)な学習であり、学習時にグラフに存在しなかったノードには適用できません。新しいノードを追加するには、隣接行列を再構築し、すべてのノードの表現を再計算する必要があります。
GraphSAGEはこの制限を克服し、近傍の集約操作のみでノード表現を生成するため、未知のノードにも帰納的に適用可能です。では、GraphSAGEが具体的にどのようなアルゴリズムでこれを実現しているのかを見ていきましょう。
GraphSAGEのアルゴリズム
基本構造
GraphSAGEの各層は以下の2ステップで構成されます。
ステップ1: 近傍の集約(AGGREGATE)
まず、ノード $v$ の近傍ノードの表現を集約して1つのベクトルにまとめます。
$$ \bm{h}_{\mathcal{N}(v)}^{(l)} = \text{AGGREGATE}^{(l)}\left(\{\bm{h}_u^{(l-1)} : u \in \mathcal{N}(v)\}\right) $$
この集約関数には、入力の順序を入れ替えても結果が変わらない順序不変性(permutation invariance)が要求されます。グラフのノードには自然な順序がないため、近傍ノードをどの順番で処理しても同じ結果を返す必要があるのです。
ステップ2: 自身の表現と結合(CONCAT + TRANSFORM)
次に、ステップ1で得た近傍の集約結果と、ノード $v$ 自身の前層の表現を連結(concatenation)し、重み行列で変換します。
$$ \begin{equation} \bm{h}_v^{(l)} = \sigma\left(\bm{W}^{(l)} \cdot \text{CONCAT}\left(\bm{h}_v^{(l-1)}, \bm{h}_{\mathcal{N}(v)}^{(l)}\right)\right) \end{equation} $$
ここで $\bm{W}^{(l)} \in \mathbb{R}^{d_l \times 2d_{l-1}}$ は学習可能な重み行列、$\sigma$ は活性化関数(ReLUなど)です。入力次元が $2d_{l-1}$ になっているのは、自身の表現($d_{l-1}$ 次元)と近傍の集約結果($d_{l-1}$ 次元)を連結しているためです。
GCNが近傍の平均を取って自身と混ぜるのに対し、GraphSAGEは自身の表現と近傍の集約結果を明示的に連結して変換します。この連結操作により、「自分自身の情報」と「近傍から得た情報」を明確に区別して保持できるのがGraphSAGEの重要な設計上の工夫です。
さらに、各層の出力は $\ell_2$ 正規化されることもあります。
$$ \bm{h}_v^{(l)} \leftarrow \frac{\bm{h}_v^{(l)}}{\|\bm{h}_v^{(l)}\|_2} $$
この正規化により、異なるノード間の表現のスケールが統一され、学習が安定します。
3つの集約関数
GraphSAGEの論文では3つの集約関数が提案されています。それぞれ異なる特性を持ち、タスクに応じて使い分けることができます。
Mean Aggregator:
$$ \bm{h}_{\mathcal{N}(v)}^{(l)} = \frac{1}{|\mathcal{N}(v)|}\sum_{u \in \mathcal{N}(v)} \bm{h}_u^{(l-1)} $$
最もシンプルで計算効率が高い集約関数です。近傍ノードの表現の平均を取るだけなので、実装も直感的です。GCNの集約とほぼ同じ操作ですが、GraphSAGEでは集約結果を自身の表現と連結する点が異なります。Mean Aggregatorは近傍の「平均的な特徴」を捉えますが、「最も特徴的な近傍の情報」は平均化によって薄まってしまう可能性があります。
LSTM Aggregator:
近傍ノードの特徴をランダムな順序に並べ、LSTMで処理します。LSTMは本来、系列データを処理するための構造であり、入力の順序に敏感です。しかし、グラフのノードには自然な順序がないため、ランダムな順列を使うことで順序不変性を近似します。LSTMは平均やmaxでは捉えられない、近傍の特徴間の複雑な相互作用を学習できる可能性がありますが、計算コストが高く、順序不変性が厳密には保証されないという欠点があります。
Pool Aggregator:
$$ \bm{h}_{\mathcal{N}(v)}^{(l)} = \max_{u \in \mathcal{N}(v)}\left(\sigma(\bm{W}_\text{pool}\bm{h}_u^{(l-1)} + \bm{b}_\text{pool})\right) $$
各近傍ノードの特徴をまず全結合層(MLP)で変換し、$\sigma$(ReLUなど)を適用した後、要素ごとのmax poolingで集約します。$\bm{W}_\text{pool}$ は学習可能な変換行列です。maxを取ることで、各次元について最も顕著な特徴を持つ近傍の情報が選択されます。Mean Aggregatorが「全員の平均的な意見」を集めるのに対し、Pool Aggregatorは「各トピックについて最も強い意見」を集めるイメージです。
論文の実験では、3つの集約関数の性能はタスクによって異なりましたが、Mean AggregatorとPool Aggregatorが多くのタスクで良好な結果を示しました。実務ではMean Aggregatorが最もよく使われます。
近傍サンプリング
大規模グラフでは、各ノードの近傍全体を集約すると計算量が指数的に増加します。$K$ 層のGNNでは、各ノードが平均次数 $d$ の近傍を持つとすると、1つのノードの計算に最大 $d^K$ ノードの情報が必要になります。たとえば平均次数100のグラフで3層のGNNを使うと、1ノードの計算に100万ノードの情報が必要になり、これは明らかに実用的ではありません。
GraphSAGEは各ステップで固定数 $S$ 個の近傍をランダムにサンプリングすることでこの問題を解決します。
典型的には $S_1 = 25$(1層目)、$S_2 = 10$(2層目)が使われ、各ノードの計算量は $S_1 \times S_2 = 250$ に制限されます。サンプリングされなかった近傍の情報は失われますが、確率的な近似として実用上十分な精度が得られることが複数の実験で示されています。
サンプリングにはいくつかの戦略があります。最もシンプルなのは一様ランダムサンプリングですが、ノードの重要度に応じた重み付きサンプリングを行うことで精度を向上させることもできます(PinSageで採用された手法)。
近傍サンプリングのもう1つの重要な利点は、ミニバッチ学習が可能になることです。GCNではグラフ全体を一度に処理する必要がありましたが、GraphSAGEでは対象ノードとそのサンプリングされた近傍だけを処理すればよいため、通常のニューラルネットワークと同じようにミニバッチ学習ができます。これにより、GPUメモリに載りきらないような巨大グラフでも学習が可能になります。
それでは、ここまでの理論をPythonコードで実装して、GraphSAGEの動作を確認してみましょう。
帰納学習 vs トランスダクティブ学習
GraphSAGEの最大の強みである帰納学習(inductive learning)について、もう少し掘り下げて考えてみましょう。
トランスダクティブ学習(GCNなど)では、学習時に全ノードの情報が必要です。テストノードもグラフ内に存在し、ただしラベルが隠されている状態で学習が進みます。つまり、テストノードの特徴やエッジ情報は学習中に利用されています。新しいノードを追加するには、グラフ全体を再構築してモデルを再学習する必要があります。
帰納学習(GraphSAGEなど)では、学習時に存在しなかったノードに対しても推論が可能です。GraphSAGEが学習するのは「近傍をどのように集約するか」という関数(重み行列 $\bm{W}^{(l)}$)であり、特定のグラフに依存しません。新しいノードが追加されたら、そのノードの近傍を見つけてサンプリングし、学習済みの集約関数を適用するだけで、即座に表現を生成できます。
この違いは実用上極めて重要です。たとえば以下のような場面で帰納学習が威力を発揮します。
- ECサイトの商品推薦: 毎日新しい商品が追加される動的な環境で、即座に推薦対象にできる
- 不正アカウント検出: 新しく作成されたアカウントがボットかどうかをリアルタイムに判定できる
- 分子設計: 学習時に存在しなかった新しい分子構造の物理化学的性質を予測できる
Pythonでの実装
以下のコードでは、GraphSAGEのMean Aggregatorをスクラッチで実装し、Zachary’s Karate Club風の2コミュニティグラフで動作を確認します。ランダムに初期化されたモデルの出力を可視化することで、近傍集約が構造情報をどのように反映するかを観察します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
def sigmoid(z):
return 1 / (1 + np.exp(-np.clip(z, -10, 10)))
class GraphSAGE:
"""GraphSAGE (Mean Aggregator)"""
def __init__(self, input_dim, hidden_dim, output_dim, n_samples=5):
self.n_samples = n_samples
# 層1
self.W1 = np.random.randn(hidden_dim, input_dim * 2) * np.sqrt(2.0 / (input_dim * 2))
self.b1 = np.zeros(hidden_dim)
# 層2
self.W2 = np.random.randn(output_dim, hidden_dim * 2) * np.sqrt(2.0 / (hidden_dim * 2))
self.b2 = np.zeros(output_dim)
def sample_neighbors(self, adj, node):
"""近傍をサンプリング"""
neighbors = np.where(adj[node] > 0)[0]
if len(neighbors) == 0:
return [node]
if len(neighbors) <= self.n_samples:
return neighbors.tolist()
return np.random.choice(neighbors, self.n_samples, replace=False).tolist()
def mean_aggregate(self, features, neighbors):
"""Mean集約"""
if len(neighbors) == 0:
return np.zeros(features.shape[1])
return np.mean(features[neighbors], axis=0)
def forward(self, features, adj, nodes=None):
"""順伝播"""
if nodes is None:
nodes = range(features.shape[0])
n = len(nodes)
# 層1: 近傍の集約 + 自身との連結
h1 = np.zeros((n, self.W1.shape[0]))
for i, v in enumerate(nodes):
neighbors = self.sample_neighbors(adj, v)
agg = self.mean_aggregate(features, neighbors)
concat = np.concatenate([features[v], agg])
h1[i] = np.maximum(0, self.W1 @ concat + self.b1)
# 層2
h2 = np.zeros((n, self.W2.shape[0]))
for i, v in enumerate(nodes):
neighbors = self.sample_neighbors(adj, v)
# 近傍のh1を集約(近傍もnodesに含まれている前提を簡略化)
neigh_h1 = []
for u in neighbors:
if u in nodes:
idx = list(nodes).index(u)
neigh_h1.append(h1[idx])
else:
# 簡易的に元の特徴から計算
ns = self.sample_neighbors(adj, u)
agg = self.mean_aggregate(features, ns)
concat = np.concatenate([features[u], agg])
neigh_h1.append(np.maximum(0, self.W1 @ concat + self.b1))
if neigh_h1:
agg2 = np.mean(neigh_h1, axis=0)
else:
agg2 = np.zeros(h1.shape[1])
concat2 = np.concatenate([h1[i], agg2])
h2[i] = self.W2 @ concat2 + self.b2
return h2
# --- グラフの生成(Zachary's Karate Club風) ---
n_nodes = 34
adj = np.zeros((n_nodes, n_nodes))
# コミュニティ1: ノード0-16
for i in range(17):
for j in range(i+1, 17):
if np.random.rand() < 0.3:
adj[i, j] = adj[j, i] = 1
# コミュニティ2: ノード17-33
for i in range(17, 34):
for j in range(i+1, 34):
if np.random.rand() < 0.3:
adj[i, j] = adj[j, i] = 1
# コミュニティ間の接続(少数)
for _ in range(5):
i = np.random.randint(0, 17)
j = np.random.randint(17, 34)
adj[i, j] = adj[j, i] = 1
# ノード特徴(ランダム)
features = np.random.randn(n_nodes, 8)
# ラベル(コミュニティ)
labels = np.array([0]*17 + [1]*17)
# --- GraphSAGEの出力を可視化 ---
model = GraphSAGE(input_dim=8, hidden_dim=16, output_dim=2, n_samples=5)
embeddings = model.forward(features, adj, nodes=list(range(n_nodes)))
# PCA for visualization
mean = embeddings.mean(axis=0)
centered = embeddings - mean
U, S, Vt = np.linalg.svd(centered, full_matrices=False)
projected = centered @ Vt[:2].T
fig, axes = plt.subplots(1, 2, figsize=(14, 5.5))
# (a) グラフ構造の可視化
ax = axes[0]
pos = np.random.randn(n_nodes, 2)
# 簡易レイアウト(コミュニティごとに配置)
pos[:17, 0] -= 1
pos[17:, 0] += 1
for i in range(n_nodes):
for j in range(i+1, n_nodes):
if adj[i, j] > 0:
ax.plot([pos[i,0], pos[j,0]], [pos[i,1], pos[j,1]],
"gray", alpha=0.2, linewidth=0.5)
colors = ["tab:blue" if l == 0 else "tab:orange" for l in labels]
ax.scatter(pos[:, 0], pos[:, 1], c=colors, s=80, edgecolors="black",
linewidth=0.5, zorder=5)
ax.set_title("Graph Structure (2 communities)", fontsize=13)
ax.set_xlabel("x", fontsize=11)
ax.set_ylabel("y", fontsize=11)
ax.grid(True, alpha=0.2)
# (b) GraphSAGE埋め込みの可視化
ax = axes[1]
ax.scatter(projected[:17, 0], projected[:17, 1], c="tab:blue", s=80,
edgecolors="black", linewidth=0.5, label="Community 1", zorder=5)
ax.scatter(projected[17:, 0], projected[17:, 1], c="tab:orange", s=80,
edgecolors="black", linewidth=0.5, label="Community 2", zorder=5)
ax.set_title("GraphSAGE Embeddings (PCA)", fontsize=13)
ax.set_xlabel("PC1", fontsize=11)
ax.set_ylabel("PC2", fontsize=11)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("graphsage.png", dpi=150, bbox_inches="tight")
plt.show()
この可視化から、GraphSAGEの動作が確認できます。
-
左図(グラフ構造): 2つのコミュニティ(青と橙)がグラフとして表現されています。コミュニティ内のエッジが密で、コミュニティ間のエッジが疎であることが確認できます。これはソーシャルネットワークでよく見られるパターンであり、GraphSAGEのようなGNNが得意とするデータ構造です
-
右図(GraphSAGE埋め込み): ランダム初期化の段階でも、GraphSAGEの埋め込みは近傍の集約により構造的な情報を反映しています。同じコミュニティに属するノードは近傍構造が類似しているため、集約後の表現も似たものになります。学習後には、損失関数の勾配によって重み行列が最適化され、2つのコミュニティがさらに明確に分離されることが期待されます。実際のノード分類タスクでは、このPCA上の分離がそのまま分類境界に対応することになります
GraphSAGEの損失関数と学習
GraphSAGEの学習は、タスクに応じて異なる損失関数を使います。
教師あり学習
ノード分類タスクでは、最終層の出力 $\bm{h}_v^{(K)}$ にSoftmaxを適用し、交差エントロピー損失で学習します。これは通常のニューラルネットワークの分類と同じ枠組みであり、勾配はミニバッチ内のノードについて逆伝播されます。
$$ \mathcal{L}_{\text{sup}} = -\sum_{v \in V_{\text{train}}} \sum_{c=1}^{C} y_{v,c} \log \hat{y}_{v,c} $$
ここで $y_{v,c}$ はノード $v$ のクラス $c$ の正解ラベル(one-hot)、$\hat{y}_{v,c}$ はモデルの予測確率、$V_{\text{train}}$ は訓練ノード集合です。
教師なし学習
ラベルがない場合でも、グラフの構造情報だけで有用な表現を学習できます。GraphSAGEの教師なし損失は、「近傍にあるノードの表現は似ていて、遠いノードの表現は異なる」ように学習するものです。
$$ \mathcal{L}_{\text{unsup}} = -\log\sigma(\bm{h}_v^\top \bm{h}_u) – Q \cdot E_{v_n \sim P_n(v)}[\log\sigma(-\bm{h}_v^\top \bm{h}_{v_n})] $$
ここで $u$ はノード $v$ の近傍ノード(正例)、$v_n$ はランダムにサンプルされたノード(負例)、$Q$ は負例のサンプル数です。この構造はWord2VecのNegative Samplingと同じ発想であり、グラフ上の「近さ」を埋め込み空間の「近さ」に変換します。
教師なし学習で得られた埋め込みは、下流タスク(ノード分類、リンク予測、クラスタリングなど)の入力特徴として汎用的に使えるため、ラベルが少ない実世界の問題で特に有用です。
GraphSAGEと他のGNNの比較
GraphSAGEの登場以降、多くのGNNの発展手法が提案されています。主な手法との関係を整理しましょう。
| 手法 | 集約方式 | 学習方式 | 特徴 |
|---|---|---|---|
| GCN | 正規化平均 | トランスダクティブ | グラフ畳み込みの基本形 |
| GraphSAGE | Mean/LSTM/Pool | 帰納的 | 近傍サンプリング |
| GAT | Attention重み付き平均 | 帰納的 | 近傍の重要度を学習 |
| GIN | 和 + MLP | 帰納的 | GNNの理論的上限に達する |
GAT(Graph Attention Network, Velickovic et al., 2018)はGraphSAGEのMean集約を拡張し、各近傍ノードに学習可能なAttention重みを付与します。つまり、全ての近傍を均等に扱うのではなく、「より重要な近傍の情報」を強く反映できます。Transformerにおけるself-attentionと同様の考え方がグラフに適用されたものです。
GIN(Graph Isomorphism Network, Xu et al., 2019)は、GNNの表現力の理論的上限を分析し、単射的な集約関数(sum + MLP)を使うことで最大の識別能力を達成することを示しました。GraphSAGEのMean集約やGCNの正規化平均は情報を失う可能性がありますが、GINの和集約は理論的に情報を失いません。
これらの手法は全てGraphSAGEと同じメッセージパッシングの枠組みに基づいており、集約関数の設計が異なるだけです。GraphSAGEのアーキテクチャを理解していれば、これらの発展手法も「集約関数を何に置き換えたか」という観点で統一的に把握できます。
まとめ
本記事では、GraphSAGEの理論を近傍サンプリングと集約関数の観点から解説しました。
- GraphSAGEは近傍ノードの情報を集約して表現を生成する帰納的なGNN
- 3つの集約関数: Mean(平均)、LSTM(系列処理)、Pool(max pooling)。Meanが最もシンプルで実用的
- 近傍サンプリングにより計算量を制御し、大規模グラフにスケール可能
- GCN(トランスダクティブ)と異なり、未知のノードにも推論可能(帰納的)
- 教師あり・教師なしの両方の学習に対応し、柔軟な表現学習が可能
GraphSAGEは「サンプリングして集約する」というシンプルかつ強力な原理に基づいており、GNN分野の発展を大きく牽引しました。この原理を理解しておくことで、GAT、GIN、PinSageなどの後続手法も「集約関数をどう改良したか」という統一的な視点で理解できるようになります。
次のステップとして、以下の記事も参考にしてください。
- GIN(Graph Isomorphism Network)の理論 — GNNの表現力の限界と最適な集約
- グラフプーリングの理論 — グラフレベルの表現学習