使用TF2與Keras實現經典GNN的開源庫——Spektral

機器之心發表於2020-05-10
Spektral 是一個基於 Keras API 和 TensorFlow 2,用於圖深度學習的開源 Python 庫。該專案的主要目的是提供一個簡單但又不失靈活性的圖神經網路(graph neural networks,GNNs) 框架。

我們可以使用 Spektral 來進行網路節點分類、預測分子特性、使用 GAN 生成新的拓撲圖、節點聚類、預測連結以及其他任意資料是使用拓撲圖來描述的任務。

使用TF2與Keras實現經典GNN的開源庫——Spektral


Spektral 中實現了多種目前經典的圖深度學習層:

  • Graph Convolutional Networks (GCN)

  • Chebyshev networks (ChebNets)

  • GraphSAGE

  • ARMA convolutions

  • Edge-Conditioned Convolutions (ECC)

  • Graph attention networks (GAT)

  • Approximated Personalized Propagation of Neural Predictions (APPNP)

  • Graph Isomorphism Networks (GIN)


也包含如下多種池化層:

  • DiffPool

  • MinCUT pooling

  • Top-K pooling

  • Self-Attention Graph (SAG) pooling

  • Global sum, average, and max pooling

  • Global gated attention pooling


專案地址:https://github.com/danielegrattarola/spektral/

效果展示

我們先來看一下這個專案的效果怎麼樣。以下是使用 Spektral 編寫的圖神經網路在 MNIST 資料集上的訓練結果:

使用TF2與Keras實現經典GNN的開源庫——Spektral


驗證結果如下:

使用TF2與Keras實現經典GNN的開源庫——Spektral


我們將網路權重視覺化後,可得到下面這樣的效果:

使用TF2與Keras實現經典GNN的開源庫——Spektral


下圖展示了兩個圖卷積層的視覺化效果。我們可以此來觀察圖神經網路是否能夠學習到,與傳統卷積神經網路類似的特徵。

使用TF2與Keras實現經典GNN的開源庫——Spektral


上手實測

Spektral 是依據 Keras API 的指導準則設計的,為的是對初學者友好的同時為專家及研究人員提供較好的靈活性。layers.convolutional 和 layers.pooling 是 Spektral 中最重要的兩個模組,裡面提供了多種用於構建 GNN 的經典網路層。由於 Spektral 是作為 Keras 的一個擴充套件被設計出的,這使得我們能夠將任意一個 Spektral 層加入現有的 Keras 模型中,而不用進行任何更改。

安裝方法

Spektral 支援 Python 3.5 及以上的版本,並在 Ubuntu 16.04+與 MacOS 上進行了測試,暫時不支援 Windows(抱歉了)。這裡我們以 Ubuntu 為例,安裝相關依賴項:
sudo apt install graphviz libgraphviz-dev libcgraph6

安裝 Spektral 最簡單的方式是透過 PyPi 來進行安裝:
pip install spektral

使用如下命令從源安裝 Spektral:
git clone https://github.com/danielegrattarola/spektral.gitcd spektralpython setup.py install # Or 'pip install .‘

機器之心友情提示:由於 TensorFlow API 的變化是個迷,推薦使用 TensorFlow 2.2 版本,並從源安裝 Spektral(不要問我是怎麼知道的)。

使用 GNN 處理 Cora 資料集中的分類問題

我們以 2017 年的那篇 ICLR 論文「SEMI-SUPERVISED CLASSIFICATION WITH GRAPH CONVOLUTIONAL NETWORKS」中所提出的圖卷積神經網路(Graph Convolutional Network,GCN) 為例,為大家介紹如何使用 Spektral 簡單、快速地搭建並訓練圖神經網路。

這裡對 GCN 的訓練問題屬於轉導推理(transductive learning),即在訓練時將所有節點與邊用作輸入,但其中僅有一部分輸入帶有標籤。訓練的目標是讓網路能夠預測那些沒有標籤的樣本。下圖表示 GCN 的示意圖。

使用TF2與Keras實現經典GNN的開源庫——Spektral

左圖為多層 GCN 示意圖。右圖為使用 t-SNE 對一個兩層 GCN 中隱含層啟用的視覺化結果。

我們使用 Cora 資料集對 GCN 進行訓練,該資料集由 7 個類別的機器學習領域論文構成,分別是:

  • Case_Based

  • Genetic_Algorithms

  • Neural_Networks

  • Probabilistic_Methods

  • Reinforcement_Learning

  • Rule_Learning

  • Theory


Cora 資料集總共包含 2708 篇論文,其中每篇論文至少引用了該資料集中另外一篇論文,或者被其他論文所引用。在消除停詞以及除去文件頻率小於 10 的詞彙後,最終詞彙表中共有 1433 個詞彙。

使用 Spektral 中的 datasets.citation 模組,讓我們能夠方便地下載並讀取如:Cora、Citeseer 和 Pubmed 這類引文資料集。以下程式碼展示瞭如何讀取 Cora 資料集:
from spektral.datasets *import* citationA, X, y, train_mask, val_mask, test_mask = citation.load_data('cora')
N = A.shape[0]F = X.shape[-1]n_classes = y.shape[-1]

其中 A 為形狀為 (N, N) 的網路鄰接矩陣,X 為形狀為 (N, F) 的節點特徵,y 表示形狀為 (N, n_classes) 的標籤。

搭建 GNN

這裡我們使用 GraphConv 網路層以及其他一些 Keras 的 API 來搭建 GCN:
from spektral.layers import GraphConvfrom tensorflow.keras.models import Modelfrom tensorflow.keras.layers import Input, Dropout

搭建 GCN 的方式與搭建其他 Keras 模型沒有任何區別,只是需要注意 GraphConv 層的輸入為 X 與 A:
X_in = Input(shape=(F, ))A_in = Input((N, ), sparse=*True*)
X_1 = GraphConv(16, 'relu')([X_in, A_in])X_1 = Dropout(0.5)(X_1)X_2 = GraphConv(n_classes, 'softmax')([X_1, A_in])
model = Model(inputs=[X_in, A_in], outputs=X_2)

至此,我們已經完成了 GCN 的搭建,是不是非常簡單呢?

訓練 GNN 

在訓練 GCN 之前,我們首先需要對鄰接矩陣進行預處理,preprocess() 這一靜態類方法提供了每一層需要的預處理方法。在這一 GCN 的例子中,我們使用如下方法進行預處理:
A = GraphConv.preprocess(A).astype('f4')

至此全部準備工作就緒,使用如下程式碼對模型進行編譯:
model.compile(optimizer='adam',              loss='categorical_crossentropy',              weighted_metrics=['acc'])model.summary()

輸出如下:

使用TF2與Keras實現經典GNN的開源庫——Spektral


接下來我們就可以使用 Keras 中提供的 fit() 方法來訓練模型了:
# Prepare dataX = X.toarray()A = A.astype('f4')validation_data = ([X, A], y, val_mask)# Train modelmodel.fit([X, A], y,          epochs=200,          sample_weight=train_mask,          validation_data=validation_data,          batch_size=N,          shuffle=False)

以下為訓練過程的輸出:

使用TF2與Keras實現經典GNN的開源庫——Spektral


驗證模型

同樣地,我們可以便捷地使用 Keras 中提供的方法對模型進行驗證:
# Evaluate modeleval_results = model.evaluate([X, A],                              y,                              sample_weight=test_mask,                              batch_size=N)print('Done.\n''Test loss: {}\n''Test accuracy: {}'.format(eval_results))

結果如下:

使用TF2與Keras實現經典GNN的開源庫——Spektral

下圖為 GCN 論文中的分類結果:

使用TF2與Keras實現經典GNN的開源庫——Spektral


可以看到論文中 GCN 在 Cora 資料集中的分類準確率為 81.5%,而我們訓練的模型準確率為 74.9%。機器之心實測經過一些簡單的超引數調整(如增加 epoch),幾乎能達到與論文中一樣的準確率,感興趣的讀者可自行測試一番。

參考連線:
https://www.kaggle.com/kmader/mnist-graph-deep-learning
https://zhuanlan.zhihu.com/p/78452993

相關文章