PyTorch Geometric でグラフ畳み込みニューラルネットワークを使う

概要

PyTorch GeometricPyG)を用いて,グラフ構造データに対する畳み込みニューラルネットワーク(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:インストーラーによるインストール

  1. Python公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンからWindows用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面の下部に表示される「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから python コマンドを実行できない。
  4. 「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 と入力 → 右クリック → 「管理者として実行」). 次のコマンドを実行し,PyTorchPyTorch GeometricPyG),および可視化用の 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 の値を変えて,精度や学習時間がどう変化するかを確かめるとよい.