PyTorch Geometric でグラフ畳み込みニューラルネットワークを使う
【概要】
PyTorch Geometric(PyG)を用いて,グラフ構造データに対する畳み込みニューラルネットワーク(Graph CNN)を,インストールから学習・評価まで図解で説明する.Python を使うのが前提である.ここで使う ChebConv 層は,Defferrard らの論文「Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering」https://arxiv.org/abs/1606.09375 で提案されたグラフ上のスペクトルフィルタ(Chebyshev 多項式による近似)を実装したものであり,PyTorch 環境でこの手法を利用する標準的な方法である.先人に感謝.
【目次】
【関連する外部ページ】
Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering https://arxiv.org/abs/1606.09375
PyTorch Geometric の公式ドキュメント(https://pytorch-geometric.readthedocs.io/)
【サイト内の関連情報】
CNN の他の利用例は,このサイトの「Convolutional Neural Networks の利用」のページ一覧を参照.
第1章 前準備
Python 3.12 のインストール
Pythonのインストールを行い、Pythonのプログラムを実行する環境を整える。扱う環境は、Windows搭載パソコンである。金子研究室では、Python 3.12.10を推奨する。
[Windows での Python 3.12 のインストール手順を見るには、ここをクリック]
Windows での Python 3.12 のインストール
以下のいずれかの方法でPython 3.12をインストールする。Pythonがインストール済みの場合、この手順は不要である。
方法 1:winget によるインストール
【インストールコマンドの実行方法】
管理者権限でコマンドプロンプトを起動する(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。
--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。
REM Python 3.12 をシステム領域にインストール
winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""
REM Python と Scripts を PATH 先頭に追加
powershell -NoProfile -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; $c=[Environment]::GetEnvironmentVariable('Path','Machine'); if((Test-Path $p) -and (';'+$c+';' -notlike \"*;$p;*\") -and (';'+$c+';' -notlike \"*;$s;*\")){[Environment]::SetEnvironmentVariable('Path',\"$p;$s;$c\",'Machine')}"
方法 2:インストーラーによるインストール
- Python公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンからWindows用インストーラーをダウンロードする。
- ダウンロードしたインストーラーを実行する。
- 初期画面の下部に表示される「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから
pythonコマンドを実行できない。 - 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。
インストールの確認
コマンドプロンプトで以下を実行する。
python --version
バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。
Git のインストール
Git の URL: https://git-scm.com/
PyTorch と PyTorch Geometric のインストール
管理者権限でコマンドプロンプトを起動する
(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」).
次のコマンドを実行し,PyTorch と PyTorch Geometric(PyG),および可視化用の matplotlib をインストールする.PyTorch Geometric は,バージョン 2.3 以降,PyTorch 本体だけで基本機能が動く(torch-scatter などの追加ライブラリは任意).
pip install -U --no-user torch torchvision torchaudio
pip install -U --no-user torch_geometric
pip install -U --no-user matplotlib
GPU(NVIDIA の CUDA)を使う場合は,PyTorch 公式サイト(https://pytorch.org/get-started/locally/)で,使用する CUDA のバージョンに応じたインストールコマンドを確認して実行する.
第2章 プログラムの作成
ここでは,MNIST の手書き数字画像を「スーパーピクセル」というグラフ構造に変換したデータセット MNISTSuperpixels(1画像あたり75個のノードからなるグラフ,10クラス分類)を用いて,ChebConv 層によるグラフ畳み込みニューラルネットワークを構築する.PyTorch Geometric が提供するデータセットクラスを使うため,データのダウンロードや前処理を自分で書く必要はない.
次のプログラムを train_chebnet.py という名前で保存する.このプログラムは単体で実行できる.
import torch
import torch.nn.functional as F
from torch_geometric.datasets import MNISTSuperpixels
from torch_geometric.loader import DataLoader
from torch_geometric.nn import ChebConv, global_mean_pool
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# データセットの取得(初回実行時に自動でダウンロードされる)
train_dataset = MNISTSuperpixels(root="data/MNISTSuperpixels", train=True)
test_dataset = MNISTSuperpixels(root="data/MNISTSuperpixels", train=False)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
class ChebNet(torch.nn.Module):
def __init__(self, num_features, num_classes, K=5):
super().__init__()
self.conv1 = ChebConv(num_features, 32, K=K)
self.conv2 = ChebConv(32, 64, K=K)
self.fc = torch.nn.Linear(64, num_classes)
def forward(self, x, edge_index, batch):
x = F.relu(self.conv1(x, edge_index))
x = F.relu(self.conv2(x, edge_index))
x = global_mean_pool(x, batch)
x = self.fc(x)
return x
model = ChebNet(train_dataset.num_features, train_dataset.num_classes).to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
def train_one_epoch():
model.train()
total_loss = 0.0
for data in train_loader:
data = data.to(device)
optimizer.zero_grad()
out = model(data.x, data.edge_index, data.batch)
loss = F.cross_entropy(out, data.y)
loss.backward()
optimizer.step()
total_loss += float(loss) * data.num_graphs
return total_loss / len(train_dataset)
@torch.no_grad()
def evaluate(loader, dataset):
model.eval()
correct = 0
for data in loader:
data = data.to(device)
out = model(data.x, data.edge_index, data.batch)
pred = out.argmax(dim=1)
correct += int((pred == data.y).sum())
return correct / len(dataset)
for epoch in range(1, 21):
loss = train_one_epoch()
train_acc = evaluate(train_loader, train_dataset)
test_acc = evaluate(test_loader, test_dataset)
print(f"epoch {epoch:2d}: loss={loss:.4f} train_acc={train_acc:.4f} test_acc={test_acc:.4f}")
ChebConv は,論文で提案された Chebyshev 多項式によるグラフ畳み込みをそのまま実装した層である.引数 K は多項式の次数(フィルタが参照するノードの近さの範囲)を表す.global_mean_pool は,1つのグラフに含まれる全ノードの特徴量を平均し,グラフ全体を1つのベクトルにまとめる処理であり,ノード単位の特徴からグラフ単位の分類へつなぐ役割を持つ.
第3章 学習と評価を実行してみる
第2章で保存した train_chebnet.py を実行する.
管理者権限でコマンドプロンプトを起動する
(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」).
cd c:\pytools
python train_chebnet.py
初回実行時は,MNISTSuperpixels データセット(約70,000個のグラフ)が自動的にダウンロードされるため,数分の時間がかかる.実行が進むと,エポックごとに学習損失(loss),訓練データでの正解率(train_acc),テストデータでの正解率(test_acc)が表示される.エポックを重ねるにつれて test_acc が上昇し,90%台後半に達することが確認できる.
このプログラムを土台に,ChebConv の層数やチャネル数,K の値を変えて,精度や学習時間がどう変化するかを確かめるとよい.