トランスフォーマーによるグラフ分類
Graph classification with Transformers.
前回のブログでは、グラフ上での機械学習の理論的な側面について調査しました。このブログでは、Transformersライブラリを使用してグラフ分類を行う方法について調査します(デモノートブックをここからダウンロードして一緒に進めることもできます!)
現時点では、Transformersで利用できる唯一のグラフトランスフォーマーモデルはMicrosoftのGraphormerですので、こちらを使用します。他のモデルも使用して統合する人々がどのような結果を出すか楽しみにしています 🤗
必要条件
このチュートリアルに従うためには、datasets
とtransformers
(バージョン>= 4.27.2)がインストールされている必要があります。これはpip install -U datasets transformers
で行うことができます。
データ
グラフデータを使用するためには、独自のデータセットから始めるか、Hubで利用可能なデータセットを使用することができます。既に利用可能なデータセットを使用することに焦点を当てますが、自分のデータセットを追加することも自由です!
- AWS Inferentia2を使用してHugging Face Transformersを高速化する
- 中国語話者向けのHuggingFaceブログをご紹介します:中国のAIコミュニティとの協力の促進
- Hugging Face Unity APIのインストールと使用方法
読み込み
Hubからのグラフデータセットの読み込みは非常に簡単です。まず、ogbg-mohiv
データセット(StanfordのOpen Graph Benchmarkのベースライン)をロードしましょう。これはOGB
リポジトリに保存されています:
from datasets import load_dataset
# Hubには1つのスプリットしかありません
dataset = load_dataset("OGB/ogbg-molhiv")
dataset = dataset.shuffle(seed=0)
このデータセットにはすでにtrain
、validation
、test
の3つのスプリットがあり、これらのスプリットはすべて興味のある5つの列(edge_index
、edge_attr
、y
、num_nodes
、node_feat
)を含んでいます。これはprint(dataset)
を実行することで確認できます。
他のグラフライブラリがある場合は、それらを使用してグラフをプロットし、データセットをさらに検査することができます。例えば、PyGeometricとmatplotlibを使用する場合:
import networkx as nx
import matplotlib.pyplot as plt
# 最初のトレイングラフをプロットしたい
graph = dataset["train"][0]
edges = graph["edge_index"]
num_edges = len(edges[0])
num_nodes = graph["num_nodes"]
# networkx形式に変換
G = nx.Graph()
G.add_nodes_from(range(num_nodes))
G.add_edges_from([(edges[0][i], edges[1][i]) for i in range(num_edges)])
# プロット
nx.draw(G)
形式
Hubでは、グラフデータセットは主にグラフのリストとして格納されます(jsonl
形式を使用)。
単一のグラフは辞書であり、以下はグラフ分類データセットの期待される形式です:
edge_index
はエッジ内のノードのインデックスを含み、エッジインデックスの2つのパラレルリストを含むリストとして格納されます。- タイプ:整数の2つのリストのリスト
- 例:ノードが0、1、2、3の4つであり、接続が1→2、1→3、3→1の場合、
edge_index = [[1, 1, 3], [2, 3, 1]]
となります。ここでノード0が存在しないことに注意してください。次の属性が重要な理由です。
num_nodes
はグラフ内の利用可能なノードの総数を示します(デフォルトでは、ノードは連続的に番号が付けられていると想定されています)。- タイプ:整数
- 例:上記の例では、
num_nodes = 4
です。
y
はグラフを予測するためのマッピングです(クラス、プロパティ値、または複数のタスク用のバイナリラベルなど)。- タイプ:整数のリスト(マルチクラス分類の場合)、浮動小数点数(回帰の場合)、または1と0のリスト(バイナリマルチタスク分類の場合)
- 例:グラフのサイズ(小=0、VoAGI=1、大=2)を予測することができます。ここでは
y = [0]
です。
node_feat
は、グラフの各ノードの利用可能な特徴(存在する場合)をノードインデックスの順に含みます。- タイプ:整数のリストのリスト(オプション)
- 例:上記のノードは、例えば分子中の異なる原子のようなタイプを持つかもしれません。これは
node_feat = [[1], [0], [1], [1]]
となります。
edge_attr
は、エッジインデックスの順に、各エッジの利用可能な属性(存在する場合)を含みます。- タイプ:整数のリストのリスト(オプション)
- 例:上記のエッジは、例えば分子内の化学結合のようなタイプを持つかもしれません。これは
edge_attr = [[0], [1], [1]]
となります。
前処理
グラフ変換フレームワークでは、通常、データセットに特定の前処理を適用して、学習タスク(この場合は分類)を支援するための追加の特徴とプロパティを生成します。ここでは、Graphormerのデフォルトの前処理を使用しています。これにより、ノード間の入出力度情報、最短経路行列など、モデルにとって興味のあるその他のプロパティが生成されます。
from transformers.models.graphormer.collating_graphormer import preprocess_item, GraphormerDataCollator
dataset_processed = dataset.map(preprocess_item, batched=False)
また、この前処理をオンザフライ(データコレータのパラメータでon_the_fly_processing
をTrueに設定することで)適用することも可能です。すべてのデータセットがogbg-molhiv
ほど小さくないため、大規模なグラフの場合、事前にすべての前処理済みデータを保存することは非常にコストがかかるかもしれません。
モデル
読み込み
ここでは、既存の事前学習済みモデル/チェックポイントを読み込み、下流タスクで微調整します。この下流タスクはバイナリ分類タスクです(したがってnum_classes = 2
です)。また、回帰タスク(num_classes = 1
)やマルチタスク分類タスクでもモデルを微調整することができます。
from transformers import GraphormerForGraphClassification
model = GraphormerForGraphClassification.from_pretrained(
"clefourrier/pcqm4mv2_graphormer_base",
num_classes=2, # 下流タスクのクラス数
ignore_mismatched_sizes=True,
)
これを詳しく見てみましょう。
モデル上のfrom_pretrained
メソッドを呼び出すと、重みがダウンロードされ、キャッシュされます。予測のためのクラス数はデータセットに依存するため、新しいnum_classes
をモデルのチェックポイントとともに渡します。これにより、タスクに特化したカスタム分類ヘッドが作成され、元のデコーダヘッドとは異なる可能性があることが保証されます。
また、既知のチェックポイントのパラメータを使用して、新しくランダムに初期化されたモデルを作成することも可能です。
トレーニングまたは微調整
モデルをシンプルにトレーニングするために、Trainer
を使用します。インスタンス化するには、トレーニングの設定と評価メトリックを定義する必要があります。最も重要なのはTrainingArguments
で、トレーニングをカスタマイズするためのすべての属性を含むクラスです。モデルのチェックポイントを保存するために使用されるフォルダ名を指定する必要があります。
from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
"graph-classification",
logging_dir="graph-classification",
per_device_train_batch_size=64,
per_device_eval_batch_size=64,
auto_find_batch_size=True, # バッチサイズはOOMを防ぐために自動的に変更される可能性があります
gradient_accumulation_steps=10,
dataloader_num_workers=4, #1,
num_train_epochs=20,
evaluation_strategy="epoch",
logging_strategy="epoch",
push_to_hub=False,
)
グラフデータセットの場合、十分なサンプルでトレーニングする一方で、メモリ不足のエラーを回避するために、バッチサイズと勾配蓄積ステップを調整することが特に重要です。
最後の引数push_to_hub
は、Trainerがモデルをトレーニング中に定期的にHubにプッシュすることを可能にします。
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset_processed["train"],
eval_dataset=dataset_processed["validation"],
data_collator=GraphormerDataCollator(),
)
グラフ分類のためのTrainer
では、特定のグラフデータセット用のデータコレータを渡すことが重要です。これにより、個々のグラフがバッチに変換され、トレーニングに使用されます。
train_results = trainer.train()
trainer.push_to_hub()
モデルがトレーニングされたら、push_to_hub
を使用して関連するトレーニングアーティファクトとともにモデルをハブに保存することができます。
このモデルは非常に大きいため、CPU(IntelCore i7)で20エポックのトレーニング/微調整に約1日かかります。より高速にするには、パワフルなGPUと並列化を使用し、Colabノートブックまたは選択したクラスターでコードを直接実行することができます。
エンディングノート
今、あなたはtransformers
を使用してグラフ分類モデルをトレーニングする方法を知っているので、コミュニティの他のメンバーが使用できるように、お気に入りのグラフトランスフォーマーチェックポイント、モデル、データセットをHubで共有してみてください!
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles