Repository: https://github.com/snap-stanford/GraphRNN Stars: 430 | Language: Python | License: MIT 論文: GraphRNN: Generating Realistic Graphs with Deep Auto-regressive Model(ICML 2018) 作者: Jiaxuan You*, Rex Ying*, Xiang Ren, William L. Hamilton, Jure Leskovec(Stanford SNAP Group)


1. 專案概覽 (Project Overview)

1.1 背景與研究團隊

GraphRNN 是 Stanford SNAP(Stanford Network Analysis Project;史丹佛網路分析專案)實驗室在 2018 年發表於 ICML(International Conference on Machine Learning; 國際機器學習大會)的圖生成 (graph generation; 圖形生成) 模型。作者群包含 Jiaxuan You 與 Rex Ying(共同一作),以及該實驗室的靈魂人物 Jure Leskovec 教授——SNAP 是後續 GraphSAGE、PinSAGE、OGB (Open Graph Benchmark)、DeepSNAP 等一系列圖神經網路 (graph neural network; GNN) 相關工具的發源地,GraphRNN 是這個生態系中「圖生成」方向的奠基性工作。

1.2 解決什麼問題

在 GraphRNN 之前,圖生成領域長期被兩類方法把持:

  1. 傳統統計模型:Erdős–Rényi (ER) 隨機圖、Barabási–Albert (BA) 無標度網路模型、Kronecker graph model(SNAP 團隊自己的前作)。這些模型都預先假設了圖的生成機制(例如「每條邊獨立同機率出現」),對真實世界圖(分子結構、社群網路、蛋白質交互作用網路)的複雜統計特性(degree distribution、clustering coefficient、community structure)擬合能力有限。
  2. 早期深度生成模型:直接把圖的鄰接矩陣 (adjacency matrix; 相鄰矩陣) 當成一張「圖片」丟進 VAE (Variational Autoencoder; 變分自編碼器) 或 GAN (Generative Adversarial Network; 生成對抗網路)。問題是鄰接矩陣是 $n \times n$($n$ 為節點數),生成 $n^2$ 個獨立元素的複雜度太高,且忽略了圖中「node ordering 不唯一」(node permutation invariance; 節點排列不變性) 的本質特性。

GraphRNN 的核心創新,是把「生成一張圖」重新表述成「生成一個序列 (sequence)」的問題:透過 BFS (Breadth-First Search; 廣度優先搜尋) 為圖的節點排序,再把圖拆解成「一個節點接一個節點加入、每個節點決定要跟哪些先前節點連邊」的自回歸 (auto-regressive) 過程。這讓模型可以用兩層 RNN (Recurrent Neural Network; 遞歸神經網路)——一層管節點層級的狀態、一層管每個節點的邊層級決策——來逐步生成整張圖。

1.3 為什麼重要

這個問題之所以重要,是因為「能生成逼真的圖」直接對應到許多實務場景:

  • 藥物設計:分子結構本質上是圖(原子=節點,化學鍵=邊),生成新分子等同生成新圖。
  • 網路科學研究:測試網路韌性、模擬社群演化、生成合成資料做壓力測試。
  • 異常偵測:先學會「正常圖長什麼樣子」,才能判斷什麼是「異常圖」。
  • 知識圖譜補全:理解圖的生成分佈,有助於推斷缺失的邊或節點。

GraphRNN 首次證明「深度自回歸序列模型」可以同時捕捉圖的局部結構(degree distribution)與全域結構(clustering、社群),並在多個 benchmark 資料集(grid、community、citation network 等)上大幅超越傳統統計模型與同時期的深度生成模型基準(B-A、E-R、Kronecker、MMSB、DeepGMG、GraphVAE)。

1.4 在 snap-stanford 生態系中的定位


graph TD
    A["SNAP 研究生態系"] --> B["圖分析基礎設施
SNAP C++ library"] A --> C["圖生成 (Graph Generation)"] A --> D["圖表徵學習 (Graph Representation Learning)"] A --> E["圖神經網路 Benchmark"] C --> C1["GraphRNN (2018)
本教學主角"] C --> C2["GraphVAE (baseline 對照)"] C --> C3["後續工作:GRAN, GraphAF 等"] D --> D1["node2vec"] D --> D2["GraphSAGE"] D --> D3["PinSAGE"] E --> E1["Open Graph Benchmark (OGB)"] E --> E2["DeepSNAP"] B --> B1["Kronecker graph model
(GraphRNN 的 baseline)"] style C1 fill:#4a90d9,color:#fff

GraphRNN 承接了 SNAP 早期 Kronecker graph model 的「圖生成」研究脈絡,並把它從「參數化統計模型」推進到「深度學習模型」;同時它也是 SNAP 後續一系列 GNN 工具(node2vec、GraphSAGE)在「生成式」而非「判別式/表徵式」方向上的重要分支。


2. 核心架構 (Core Architecture)

2.1 整體系統架構圖


flowchart TB
    subgraph sg1["資料準備層 (Data Preparation)"]
        D1["create_graphs.py
準備目標圖資料集"] --> D2["data.py
Graph_load / Graph_sequence_sampler_*"] D2 --> D3["BFS 節點排序 + 鄰接向量編碼
encode_adj"] end subgraph sg2["模型層 (Model)"] M1["model.py
GRU_plain / LSTM_plain
(graph-level RNN)"] --> M2["MLP_plain 或
output GRU/LSTM
(edge-level RNN)"] M2 --> M3["sample_sigmoid
(採樣下一條邊)"] end subgraph sg3["訓練/推論層 (Train & Generate)"] T1["main.py
參數載入 + 流程總控"] --> T2["args.py
Args 設定物件"] T1 --> T3["train.py
train_rnn / test_rnn_epoch"] end subgraph sg4["評估層 (Evaluation)"] E1["evaluate.py"] --> E2["eval/stats.py
MMD: degree/clustering"] E1 --> E3["eval/orca
orbit counts (motif 統計)"] end D3 --> M1 T3 --> M1 T3 --> M2 M3 --> E1 E1 --> R["figures/ · eval_results/
視覺化與量化報告"] style M1 fill:#4a90d9,color:#fff style M2 fill:#4a90d9,color:#fff

2.2 關鍵模組與資料流

檔案角色說明
main.py主執行入口讀取 args.py 設定,串起資料載入 → 建模 → 訓練 → 生成 → 存檔全流程
args.py超參數集中管理Args class:模型變體 (note)、資料集 (graph_type)、RNN 隱藏層維度、學習率排程等
data.py資料集載入與序列化載入 ENZYMES/DD/PROTEINS/citation network 等資料,將 networkx.Graph 轉為訓練用的序列 tensor
model.py模型定義LSTM_plain / GRU_plain(graph-level RNN)、MLP_plain(edge-level 輸出頭)、採樣函式 (sample_sigmoidgumbel_softmax 等)
train.py訓練與生成迴圈train_rnn_epoch(訓練一個 epoch)、test_rnn_epoch(自回歸生成新圖)
utils.py工具函式圖視覺化 (draw_graph_list)、圖存取 (save_graph_list/load_graph_list)、圖擾動 (perturb)
evaluate.py評估總控讀取生成圖與真實圖,呼叫 MMD 計算,輸出 eval_results/
eval/stats.py統計距離計算用 MMD (Maximum Mean Discrepancy; 最大平均差異) 比較 degree distribution、clustering coefficient distribution
eval/orca/Motif 統計C++ 實作的 ORCA 演算法,計算 graphlet/orbit counts,用於更細粒度的結構相似度評估
baselines/對照組模型baseline_simple.py(B-A、E-R)、mmsb.py(MMSB)、graphvae/(GraphVAE)
main_DeepGMG.py對照組模型DeepGMG baseline 的獨立實作

2.3 設計哲學與技術選擇分析

為什麼用兩層 RNN 而非一層? 這是 GraphRNN 最核心的設計決策。作者把「生成一張圖」分解成兩個巢狀的自回歸問題:

  • Graph-level RNNLSTM_plain/GRU_plainhas_output=False 版本):管理「目前生成到第幾個節點」的整體狀態,輸出一個 hidden vector 作為 edge-level RNN 的初始狀態。
  • Edge-level RNN 或 MLPGraphRNN_RNN 用第二層 RNN,GraphRNN_MLP 用 MLP 取代):在「加入第 $i$ 個節點」的當下,決定它要跟前面 $M$ 個節點(max_prev_node)中的哪些連邊,逐 bit 預測一個二元向量。

這個設計對應論文中「圖的分解定理」:任何圖都可以表示成節點依序加入、每次加入伴隨一個鄰接向量的序列。比起直接生成 $n \times n$ 矩陣,複雜度從 $O(n^2)$ 降到 $O(n \times M)$($M \ll n$,因為多數真實圖是稀疏的、BFS 排序後鄰接向量的有效長度很短)。

為什麼要 BFS 排序? 圖沒有「自然」的節點順序——同一張圖可以有 $n!$ 種節點編號方式。如果不排序,RNN 要學習的序列分佈會被這 $n!$ 種等價表示法稀釋,訓練訊號極度稀疏。BFS 排序後,鄰接矩陣呈現「帶狀」結構(band-limited),使得 max_prev_node 可以被大幅限制在一個較小範圍,大幅降低模型要建模的邊數。

MLP 版 vs RNN 版的取捨GraphRNN_MLP 假設同一節點的多條邊彼此獨立(給定 graph-level hidden state 之後);GraphRNN_RNN 用額外一層 RNN 顯式建模「邊與邊之間的相依性」(dependent Bernoulli sequence)。後者表達力更強但訓練成本更高——這是專案原始碼中 args.pyself.note 選項的取捨依據。


flowchart LR
    subgraph concept["自回歸圖生成的兩層分解"]
        direction TB
        N0["節點 0
初始狀態"] -->|hidden state| N1["節點 1
graph-RNN 更新"] N1 -->|hidden state| N2["節點 2
graph-RNN 更新"] N2 -->|hidden state| N3["節點 3 ...
graph-RNN 更新"] N1 -.->|生成鄰接向量| E1["edge-RNN/MLP:
是否連到節點 0?"] N2 -.->|生成鄰接向量| E2["edge-RNN/MLP:
是否連到節點 0,1?"] N3 -.->|生成鄰接向量| E3["edge-RNN/MLP:
是否連到節點 0,1,2?"] end

3. 安裝與設定 (Installation & Setup)

3.1 環境需求

⚠️ 重要提醒:這是一份 2018 年發表、對應 PyTorch 0.2.0~0.4.0 的舊版程式碼。原始碼中直接使用 Variable(PyTorch 0.4 後已併入 TensorVariable 是相容殼但已非慣用寫法)、nn.init.xavier_uniform(新版 API 已改名 xavier_uniform_)、F.sigmoid/F.softmax(新版建議用 torch.sigmoid/F.softmax(dim=...))等已棄用或已改名的 API。若要在現代環境(PyTorch 2.x)跑起來,必須做相容性修改,不能直接 pip install -r requirements.txt 後跑。

  • Python 3.6+(原始開發環境約為 Python 3.5/3.6)
  • PyTorch(原生測試 0.2.0/0.4.0;建議另建 legacy conda env 精確對齊,或自行修補 API)
  • CUDA GPU(程式碼內部大量硬編碼 .cuda() 呼叫,CPU-only 環境需要額外修改)
  • networkxnumpyscipymatplotlibtorchvision
  • C++ 編譯器(g++,用於編譯 eval/orca/orca.cpp,做 orbit-count 評估)

3.2 完整安裝步驟

 1# 1. Clone 專案
 2git clone https://github.com/snap-stanford/GraphRNN.git
 3cd GraphRNN
 4
 5# 2. 建議:用 conda 建立對齊舊版 PyTorch 的隔離環境(避免污染系統環境)
 6conda create -n graphrnn python=3.6 -y
 7conda activate graphrnn
 8
 9# 3. 安裝 PyTorch(官方頁面依 CUDA 版本挑選;舊版 GPU 環境常用 cuda90 對應舊 driver)
10conda install pytorch torchvision cuda90 -c pytorch
11
12# 4. 安裝其餘相依套件
13pip install -r requirements.txt
14
15# 5. 編譯 ORCA(用於 orbit-count 評估;repo 內已附 Ubuntu 預編譯二進位,
16#    非 Ubuntu 平台或版本不合需重新編譯)
17cd eval/orca
18g++ -O2 -std=c++11 -o orca orca.cpp
19cd ../..

3.3 資料集下載與準備

dataset/ 目錄下已隨 repo 附帶多個標準圖分類資料集的原始檔(.txt 格式的鄰接表 + 節點標籤 + 節點屬性),包含:

  • ENZYMESDDPROTEINS_full:生物資訊圖分類資料集(data.pyGraph_load_batch() 負責解析)
  • ind.cora.*ind.citeseer.*ind.pubmed.*:citation network 資料集(Planetoid 格式,Graph_load() 負責解析)

此外,create_graphs.py 也能現場合成多種經典圖拓樸做為訓練目標,不需下載外部資料:

1# 合成圖類型範例(於 args.py 的 graph_type 欄位設定):
2# 'grid'          — 規則格狀圖
3# 'caveman'       — Caveman graph(社群結構的經典模型)
4# 'community4'    — 4 個社群組成的複合圖
5# 'barabasi'      — Barabási–Albert 無標度網路
6# 'ladder_small'  — 梯狀圖

3.4 快速測試

1python main.py

main.py 會依 args.py 中預設的 self.graph_type = 'grid'self.note = 'GraphRNN_RNN' 設定,載入/合成 grid 資料集,訓練 GraphRNN_RNN 模型,並依 epochs_save(預設每 100 epoch)將產出寫入 graphs/model_save/figures/nll/ 等目錄(皆位於 args.dir_input,預設為 ./)。

3.5 常見問題排解

問題原因解法
AttributeError: module 'torch.nn.functional' has no attribute 'sigmoid'新版 PyTorch 移除頂層 F.sigmoid/F.softmax 別名全域替換為 torch.sigmoid(x) / F.softmax(x, dim=-1)
TypeError: xavier_uniform() missing... 或找不到函式新版 API 改名為 xavier_uniform_(in-place 版本)init.xavier_uniform 改為 init.xavier_uniform_
RuntimeError: CUDA error 或無 GPU 環境直接崩潰程式碼內大量硬編碼 .cuda()需要自行加入 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 並全面替換 .cuda() 呼叫
orca 執行檔無法執行 (Permission denied)預編譯二進位權限或平台不符chmod +x eval/orca/orca,或依 3.2 節重新編譯
訓練記憶體暴增max_prev_node 設為 None 時會自動依全資料集計算,遇到含高 degree 節點的圖集會使鄰接向量過長args.py 手動設定較保守的 max_prev_node 上限

4. 核心概念詳解 (Key Concepts)

4.1 把「圖」看成「序列」——核心類比

想像你在逐格畫一張社群關係圖:先畫第一個人(節點 0),畫第二個人時決定「他跟誌 0 認不認識」,畫第三個人時決定「他跟前兩人各自認不認識」……直到畫完所有人。這正是 GraphRNN 的核心類比——把畫圖這件事變成一格一格填空的過程,而不是一次把整張關係表 (鄰接矩陣) 畫出來。

用數學語言:給定一個節點排序 $\pi$,圖 $G$ 可以表示成一個序列

$$S^\pi = (S_1^\pi, S_2^\pi, \dots, S_n^\pi)$$

其中 $S_i^\pi \in {0,1}^{i-1}$ 是第 $i$ 個節點與前面所有節點的連邊向量。生成整張圖等價於生成這個序列,機率可以用鏈式法則 (chain rule) 分解:

$$p(S^\pi) = \prod_{i=1}^{n} p(S_i^\pi \mid S_1^\pi, \dots, S_{i-1}^\pi)$$

這正是 RNN 最擅長的建模型態——「給定過去,預測下一步」。

4.2 為什麼要 BFS 排序?——類比「整理書架」

如果隨便排列節點順序,鄰接向量 $S_i^\pi$ 的長度理論上要涵蓋前面所有 $i-1$ 個節點(因為任何一個都可能連邊),這讓模型要處理的向量長度隨節點數線性成長,且大量位置永遠是 0(稀疏、難學)。

BFS 排序就像整理書架時「按照類別/關聯性排列書本」——BFS 走訪保證:任兩個相鄰的節點在排序中的位置差距,不會超過該圖的「BFS 寬度」。這讓有效的 max_prev_node(模型只需回顧多少步之前的節點)大幅縮小,把稀疏、瑣碎的邊決策,壓縮成密集、有意義的局部決策視窗。


flowchart TD
    subgraph before["未排序:任意節點順序"]
        direction LR
        B1["節點順序混亂
鄰接向量長度 = i-1
(隨 i 線性成長)"] end subgraph after["BFS 排序後"] direction LR A1["鄰接向量長度
≈ max_prev_node
(遠小於 n,且固定上限)"] end before -->|"BFS 排序 (encode_adj)"| after style after fill:#4a90d9,color:#fff

4.3 兩層 RNN 的角色分工——類比「導演與演員」

可以把 graph-level RNN 想像成導演:他不直接決定每個演員的台詞,而是掌握整齣戲目前演到哪一幕、氛圍如何(對應 hidden state $h_i$)。edge-level RNN/MLP 則是演員:拿到導演給的「這一幕的氛圍指示」後,具體決定「這句台詞要不要講」(也就是「這條邊要不要連」)。

  • graph-level RNNmodel.pyLSTM_plain(has_output=False)):輸入是「上一個節點的鄰接向量」,輸出是更新後的 hidden state,傳給下一步。
  • edge-level 模組
    • GraphRNN_MLP 版本:直接用一個 MLP (MLP_plain) 把 hidden state 映射成整條鄰接向量的機率(假設向量內各 bit 條件獨立)。
    • GraphRNN_RNN 版本:用另一個 RNN 逐 bit 生成鄰接向量(bit 之間有序列相依性,即論文所稱 dependent Bernoulli sequence)。

4.4 訓練時的「監督式取樣」 vs 生成時的「自回歸取樣」

訓練階段用 teacher forcingtrain.py 中直接餵真實圖的鄰接向量做監督),模型看到的永遠是「正確答案」;生成階段則用 sample_sigmoidmodel.py)做自回歸取樣——模型自己上一步的輸出,會變成下一步的輸入。這是所有自回歸生成模型共通的「exposure bias」議題:訓練時看到的都是真實資料,測試/生成時卻要吃自己犯過的錯(累積誤差)。GraphRNN 用 sample_time 參數(一個時間步嘗試多次取樣,挑「至少產生一條邊」的結果)來緩解生成初期容易「整條全 0」的退化問題。

4.5 評估:如何量化「這張生成的圖有多真實」?

單一張圖沒有辦法直接比較「相似度」,因為節點數、拓樸都不同。GraphRNN 採用 MMD (Maximum Mean Discrepancy; 最大平均差異) 比較一組真實圖一組生成圖在某個統計量(degree distribution、clustering coefficient distribution、orbit/motif counts)上的分佈差異,而非逐點比較。可以類比成:不比較「兩個人的身高完全一樣嗎」,而是比較「兩個班級的身高分佈曲線像不像」。


flowchart LR
    RG["真實圖集合
(Test set)"] --> RD["計算統計量分佈
degree / clustering / orbit"] GG["生成圖集合
(GraphRNN 輸出)"] --> GD["計算統計量分佈"] RD --> MMD["MMD 距離計算
eval/stats.py"] GD --> MMD MMD --> Score["MMD 分數
越小 = 越逼真"]

5. 使用方式與程式碼範例 (Usage & Code Examples)

5.1 基礎用法:直接跑訓練

最基本的用法就是修改 args.py 中的設定物件,再執行 main.py

 1# args.py(節錄修改示範)— 設定模型變體、資料集與訓練規模
 2class Args():
 3    def __init__(self):
 4        self.cuda = 0                       # 使用第 0 號 GPU
 5        self.note = 'GraphRNN_RNN'          # 使用兩層 RNN 版本(相較 GraphRNN_MLP 表達力更強)
 6        self.graph_type = 'community4'      # 用內建合成的 4-社群圖做訓練
 7        self.max_num_node = None            # 自動計算資料集內最大節點數
 8        self.max_prev_node = None           # 自動計算 BFS 排序後的最大回顧範圍
 9
10        self.hidden_size_rnn = 128
11        self.hidden_size_rnn_output = 16
12        self.embedding_size_rnn = 64
13        self.embedding_size_rnn_output = 8
14
15        self.batch_size = 32
16        self.epochs = 3000                  # 3000 epoch,每 epoch = batch_ratio(32) 個 batch
17        self.lr = 0.003
18        self.milestones = [400, 1000]       # 學習率在第 400、1000 epoch 時衰減
19        self.lr_rate = 0.3
20
21        self.epochs_save = 100              # 每 100 epoch 存一次 checkpoint + 生成樣本
1# 執行訓練(會自動依上面設定跑完整流程:載入/合成資料 → 訓練 → 定期生成 → 存檔)
2python main.py

5.2 進階用法:讀取已訓練模型並生成新圖、視覺化

 1# 示範腳本:載入已存的圖清單並視覺化(依 utils.py 提供的工具函式)
 2import pickle as pkl
 3from utils import load_graph_list, draw_graph_list
 4
 5# graphs/ 目錄下的檔名格式一般為
 6# {note}_{graph_type}_{...超參數...}_pred_{epoch}_1.dat
 7generated_graphs = load_graph_list(
 8    'graphs/GraphRNN_RNN_community4_4_128_pred_3000_1.dat',
 9    is_real=False
10)
11
12print(f'共生成 {len(generated_graphs)} 張圖')
13print(f'第一張圖節點數: {generated_graphs[0].number_of_nodes()}')
14print(f'第一張圖邊數:   {generated_graphs[0].number_of_edges()}')
15
16# 視覺化前 16 張生成圖,存成 4x4 grid 圖檔
17draw_graph_list(
18    generated_graphs[:16],
19    row=4, col=4,
20    fname='figures/my_generated_samples'
21)

5.3 進階用法:自訂 MMD 評估流程

 1# evaluate.py 的核心邏輯示範:計算 degree distribution 的 MMD
 2from eval.stats import degree_stats, clustering_stats
 3from utils import load_graph_list
 4
 5real_graphs = load_graph_list('graphs/GraphRNN_RNN_community4_4_128_test_0.dat', is_real=True)
 6pred_graphs = load_graph_list('graphs/GraphRNN_RNN_community4_4_128_pred_3000_1.dat', is_real=False)
 7
 8# degree distribution 的 MMD(值越低代表生成圖的度分佈越接近真實圖)
 9mmd_degree = degree_stats(real_graphs, pred_graphs)
10print(f'Degree distribution MMD: {mmd_degree:.4f}')
11
12# clustering coefficient distribution 的 MMD
13mmd_clustering = clustering_stats(real_graphs, pred_graphs)
14print(f'Clustering coefficient MMD: {mmd_clustering:.4f}')

執行完整評估流程(含 orbit counts):

1python evaluate.py

5.4 實際應用場景展示:自訂資料集訓練

若要用自己的資料(例如公司內部的社群互動圖、分子資料集),核心步驟是把資料轉成 networkx.Graph 物件的清單,接到 create_graphs.py 的資料載入介面:

 1# 自訂資料集接入範例
 2import networkx as nx
 3import pickle as pkl
 4
 5def load_my_custom_graphs(edge_list_dir):
 6    """
 7    將自己的邊清單檔案(每行 'node_a,node_b')轉為 networkx.Graph 清單
 8    """
 9    graphs = []
10    for fname in edge_list_dir_files(edge_list_dir):  # 假設的檔案枚舉函式
11        G = nx.Graph()
12        with open(fname) as f:
13            for line in f:
14                a, b = line.strip().split(',')
15                G.add_edge(a, b)
16        # 過濾太小的圖(GraphRNN 對節點數過少的圖訓練訊號不足)
17        if G.number_of_nodes() >= 10:
18            graphs.append(G)
19    return graphs
20
21# 後續接到 create_graphs.py 中新增一個 elif 分支,
22# 對應到 args.py 的 self.graph_type = 'my_custom_dataset'

6. 進階應用場景 (Advanced Use Cases)

6.1 真實世界的應用案例

  • 分子生成 (Molecule Generation):把原子當節點、化學鍵當邊,GraphRNN 系的自回歸序列生成思路直接啟發了後續分子生成模型(如 GraphAF、MoFlow),差異在於加入化學鍵類型 (bond type) 與原子價 (valence) 的約束。
  • 社群網路合成資料生成:在資料隱私法規(如 GDPR)限制下,用生成模型產生「統計上相似但非真實使用者」的社群圖,供演算法測試或壓力測試使用。
  • 網路韌性模擬:生成大量結構相似但個體不同的圖,測試某種防禦/攻擊策略在「一類圖」而非「單一圖」上的穩健性。
  • 教學與 benchmark 基準:作為圖生成領域公認的基準模型,後續論文(GraphAF、GRAN、GraphGen)幾乎都會引用 GraphRNN 的 MMD 評估協議做比較。

6.2 與其他 snap-stanford 工具的整合


flowchart LR
    GR["GraphRNN
生成合成圖"] --> N2V["node2vec
對生成圖做節點嵌入"] GR --> GS["GraphSAGE
用生成圖做資料增強
(data augmentation)"] GR --> OGB["OGB benchmark
可作為圖生成任務的
對照基準模型"] SNAP["SNAP C++ library"] -->|"Kronecker graph
作為 baseline"| GR
  • 與 node2vec / GraphSAGE 整合:GraphRNN 生成的合成圖可以作為下游 GNN 模型的訓練資料擴增來源,尤其在真實圖資料稀缺(如罕見疾病的蛋白質交互作用網路)時,先用 GraphRNN 學會「這類圖的統計特性」,再生成更多樣本供 GraphSAGE 類模型訓練,緩解小樣本問題。
  • 與 SNAP C++ library 整合baselines/baseline_simple.py 直接沿用 SNAP 的 Kronecker graph 實作做為對照基準,說明 GraphRNN 從一開始就設計成「可與既有 SNAP 工具鏈並存比較」。

6.3 效能調校與最佳實踐

  • max_prev_node 是效能的關鍵旋鈕:這個值決定了 edge-level 模組每步要處理的向量長度,設太大會讓訓練變慢且梯度稀疏(大部分位置仍是 0),設太小會漏掉遠距連邊。建議先讓 args.py 自動計算一次,再依實際訓練 loss 曲線微調。
  • batch_ratioepochs 的關係:程式碼把「一個 epoch」定義為 batch_ratio 個 batch(非傳統定義的「跑過一次全資料集」),調整訓練規模時要注意這個非標準用法,避免誤解訓練進度。
  • sample_time 影響生成品質與速度的權衡:生成階段每步嘗試多次取樣以避免退化解,sample_time 越大生成品質越穩定但速度越慢,建議先用預設值 2 驗證,再視生成圖是否常見「全空/退化圖」問題調整。
  • 學習率排程 (milestones + lr_rate):預設在第 400、1000 epoch 做 0.3 倍衰減,屬於典型的階梯式衰減 (step decay);遷移到新資料集時建議先監控 loss 曲線再決定是否需要調整 milestone 位置。

7. 與 AIKT 的關聯分析 (AIKT Integration Analysis)

7.1 GraphRNN 可作為 AIKT 的資料來源或分析工具嗎?

可以,且有兩個明確角色

  1. 作為 L2(ai-gh-save)的知識擷取對象:GraphRNN 本身就是一個典型的「值得收錄」的 GitHub repo——有論文、有明確方法論、有 430 stars 的社群驗證。本篇教學正是透過 gh-tutorial-qd(L12)流程產出的範例。
  2. 作為 L4(graphify)知識圖譜的「圖生成」節點類比參照:graphify 本身建構的是「AIKT 系統內部的知識圖譜」(repo 之間、概念之間的關聯),而 GraphRNN 是「學習如何生成逼真圖」的模型。兩者的關聯不是直接呼叫關係,而是方法論類比:如果 AIKT 未來需要「生成合成的知識圖譜」(例如測試 graphify 在大規模圖上的效能、或產生匿名化但統計相似的知識圖供分享),GraphRNN 的自回歸圖生成思路就是可直接借鏡的技術路徑。

7.2 AIKT 的哪些 Layer 可以包裝或編排此專案?


flowchart TB
    subgraph L1_3["L1-3 知識擷取"]
        GH["L2 ai-gh-save
已完成:收錄 GraphRNN repo"] end subgraph L12_15["L12-15 教學與智財"] TQ["L12 gh-tutorial-qd
本教學文件的產出流程"] end subgraph L4_6["L4-6 知識索引"] GF["L4 graphify
將本教學納入知識圖譜節點"] GN["L6 gitnexus
若需深度分析 GraphRNN 原始碼
符號圖/呼叫關係"] end subgraph L18_19["L18-19 研究與藥物"] RP["L18 research-pipeline-v2
若研究主題涉及分子生成
可將 GraphRNN 列為方法論參考"] TU["L19 tu-plan-generator
藥物開發計畫中若涉及
de novo 分子設計,GraphRNN 系
模型是背景技術參照"] end subgraph L9_11["L9-11 研究工具"] PS["L9 paper-search
搜尋 GraphRNN 後續引用文獻
(GraphAF/GRAN/MoFlow 等)"] end GH --> TQ --> GF GH --> GN PS -.->|"若需深入方法論比較"| RP RP -.->|"分子生成場景"| TU style TQ fill:#4a90d9,color:#fff

具體場景說明:

  • L9 paper-search:若後續研究需要追蹤 GraphRNN 之後的圖生成技術演進(GraphAF、GRAN、MoFlow、GraphGen 等),可用 paper: GraphRNN citations 或類似查詢,透過跨資料庫學術搜尋找到引用鏈。
  • L6 gitnexus:若需要對 GraphRNN 原始碼做更深入的符號級分析(例如追蹤 sample_sigmoidtrain.pymodel.py 之間的呼叫關係),可用 gitnexus: 前綴建立程式碼符號圖,輔助理解或做 code review。

7.3 潛在整合場景與價值

  1. 教學資產沉澱:本篇教學本身即是 L12 → L4 的閉環範例——gh-tutorial-qd 產出教學文件後,透過 graphify update . 讓 GraphRNN 這個節點的方法論摘要(BFS 序列化、雙層 RNN、MMD 評估)成為 AIKT 知識圖譜中可被檢索、可被關聯到其他圖生成/分子生成主題的節點。
  2. 方法論比較基準:未來若有其他圖生成類 repo 被收錄(GraphVAE、GraphAF、GRAN 等),graphify 的知識圖譜可以把它們與 GraphRNN 關聯起來,形成一條「圖生成技術演進時間線」,供研究時快速定位技術脈絡而非逐篇重讀論文。
  3. 價值與限制:GraphRNN 本身不是可以直接被 AIKT 各 Layer 呼叫的 API 或服務——它是一個需要 GPU、需要訓練資料、需要相容性修補的研究型程式碼庫。因此它在 AIKT 中的角色定位主要是知識資產與方法論參照,而非可編排執行的工具鏈節點(不同於 docling、quarkdown 這類「可直接被腳本呼叫」的 Layer)。

8. 優缺點與生態系定位 (Strengths, Limitations & Ecosystem Position)

8.1 核心優勢與創新點

  • 理論貢獻扎實:把圖生成問題嚴謹地表述成「透過 BFS 排序後的序列生成」,並給出機率分解的數學依據(chain rule),不是憑經驗拼湊的架構。
  • 兩層 RNN 分解優雅:graph-level / edge-level 的分工清楚對應「節點加入順序」與「邊的相依性」兩個不同粒度的建模需求,是後續多篇圖生成論文沿用的設計範式。
  • 評估協議成為業界標準:MMD-based 的 degree/clustering/orbit 三項統計量比較,至今仍是圖生成論文(包含非 RNN 系的 GraphAF、GRAN 等)的標準評估方式,這比模型本身的影響力更為長遠。
  • 開源完整度高:附帶多組 baseline(B-A、E-R、Kronecker、MMSB、DeepGMG、GraphVAE)的可執行實作,方便直接復現論文的比較實驗,而非只放核心模型。

8.2 目前限制與改進空間

  • 程式碼時效性差:對應 PyTorch 0.2.0/0.4.0 的舊版 API(VariableF.sigmoidxavier_uniform 無底線版),直接在現代環境執行會報錯,需要相容性修補(見第 3.5 節)。
  • 強耦合 CUDA:程式碼內大量硬編碼 .cuda(),沒有 GPU 就無法直接執行,缺乏 CPU fallback 的彈性設計。
  • 可擴展性受限於序列長度:BFS 排序雖然降低了 max_prev_node,但對節點數極大(數萬以上)的圖,自回歸生成仍然是逐步驟的序列計算,生成速度慢於後續一次性 (one-shot) 生成的方法(如部分基於 GAN 或 Diffusion 的圖生成模型)。
  • 缺乏化學/領域約束:作為通用圖生成模型,沒有內建分子價數、環狀結構合法性等領域知識,若直接套用到分子生成需額外加約束層(這也是後續 GraphAF/MoFlow 等工作補強的方向)。

8.3 與同領域工具的比較

模型生成方式相依性建模主要優勢主要限制
GraphRNN(本專案)自回歸序列(BFS 排序)雙層 RNN 顯式建模理論扎實、評估協議業界標準序列生成速度慢、程式碼老舊
Kronecker graph model遞迴矩陣運算參數化統計假設計算快、理論簡潔表達力有限,難擬合複雜真實圖
GraphVAE一次性生成鄰接矩陣VAE 隱空間生成速度快(非序列)$O(n^2)$ 複雜度,難擴展到大圖
DeepGMG逐步生成(節點+邊決策)訊息傳遞 (message passing)可建模更豐富的節點/邊屬性訓練與生成成本高
GraphAF(後續工作)Normalizing Flow + 自回歸Flow-based 精確似然精確似然估計、適合分子生成架構複雜度更高

8.4 適用場景建議

  • 適合:學術研究中需要生成式圖模型作為 baseline 比較對象、需要理解「序列化圖生成」方法論、教學用途展示 RNN 如何應用在非序列型資料(圖)上。
  • 不建議直接生產環境使用:若需要工業級部署(如即時分子生成服務),建議直接採用後續更成熟、對 API 相容性維護更好的框架(如支援 PyTorch Geometric 生態的現代圖生成模型),GraphRNN 更適合作為理解基礎方法論復現經典評估協議的教學/研究工具,而非直接落地的生產系統。

參考資料

  • 論文:You, J., Ying, R., Ren, X., Hamilton, W. L., & Leskovec, J. (2018). GraphRNN: Generating Realistic Graphs with Deep Auto-regressive Model. ICML 2018. https://arxiv.org/abs/1802.08773
  • 程式碼:https://github.com/snap-stanford/GraphRNN
  • 補充教材:Jesse Bettencourt & Harris Chan 在 David Duvenaud 教授研討課的介紹投影片:https://duvenaud.github.io/learn-discrete/slides/graphrnn.pdf