隨著深度學習在歐幾里得空間的成功應用,例如CNN,RNN等極大的提高了圖像分類,序列預測等任務的效果,近期來圖神經網路也開始蓬勃發展。圖神經網絡分為譜域和空域兩大種類,譜域通過拉普拉斯算子對于圖進行類微分處理,而空域通過信息傳遞的方式更新節點的embedding,均可以大幅度提高節點預測,鏈接預測,不規則圖形分類等問題的效果。
在大規模圖數據上訓練圖神經網絡是一個大問題,計算代價過大,內存消耗過高均是制約圖神經網絡在大圖訓練的因素。而近期來,加速圖訓練、優化內存的論文不斷出現。以GraphSage,FastGCN,VR-GCN,GraphSaint,Cluster-GCN,L-GCN,L2-GCN等系列模型被提出,并且得到了令人矚目的結果。美中不足的是,他們仍然沒有做到億級別數據的訓練,最大的數據集不過是百萬節點,如果在億級別數據上進行訓練,時間和空間復雜度都會是一個極大的考驗。
SGC-Simplifying graph convolutional network 成為了最合適的替代品,在當今大圖計算仍然沒有一個最優且快的model的時候,在效果上退而求其次是不可避免的。SGC在訓練效果上和原始GCN持平,但是在速度上有這不可比擬的優勢,而且空間復雜度極小,具有在大圖上訓練的潛力。
本文使用了飛槳圖學習框架PGL,同時調用了多個Paddle API,包括全連接層和數據讀入以及優化函數。Paddle的優化函數具有出色的性能,加快了訓練速度,使得訓練效果有了良好的表現。首先非常推薦在AI Studio上面直接進行復現,AI Studio是一個很出色的平臺,同時對于優質作者有很強的算力支持,筆者是直接在AI Studio上面編輯復現的。當然,PGL也可以部署到本地,有意向在本地運行PGL的可以查詢PGL在github上的官網,從而實現本地部署。PGL的兩個特點在于高速性和模塊性,你可以很快的調動許多已有的module,而不需要底層實現,就可以完成一些論文的復現。
復現實現的難點往往在于特征的預處理,對于沒有預處理的特征,直接上模型可能效果非常的差,甚至不如多層感知機,但是在預處理之后,往往能夠達到論文的精確度和速度,筆者在復現的時候嘗試過直接把存入的data輸入至模型,但是效果非常差,大概只有50%左右的ACC,不如多層感知機。但是在經過一系列預處理后,可以直接復現論文水平。
本模型的特點在于模型簡單,速度快,但精確度只是略好于多層感知機,稍遜于其他模型。但是在工業應用上,已經擁有了極高的價值。這里我們其實并沒有調用PGL的庫函數,例如GCN等。因為我們的模型很簡單,并不需要調用已有模型,同時已有模型由于兼容性等原因會降低速度,所以我主要應用的是Paddle里面的nn.fc和decay_adam優化器,前者是全連接層,后者是有衰減值的adam優化器。筆者認為這兩個函數,尤其是后者大大加速了訓練。其次我們還使用了PGL的圖訓練框架來加速訓練,也達到了很好的效果。筆者認為,上面三個函數是PGL+Paddle模型遠遠快于Pytorch的原因。
論文模型理解
在原始GCN上被分為多步完成的圖卷積操作SGC通過一步就完成,同時得到了相同的效果,可以看出其優勢。
SGC最大的創新在于省去了激活函數,從而使得多個參數合成一個,減小了時間復雜度和空間復雜度。
論文模型復現過程
首先在AI Studio上安裝PGL庫函數和cython:
!pip install pgl
!pip install cython
這里對feature和adj矩陣都準備進行預處理,feature對行上進行歸一化處理,adj通過degree準備進行normalization:
import scipy.sparse as sp
degree=dataset.graph.indegree()
norm = np.zeros_like(degree, dtype=“float32”)
norm[degree 》 0] = np.power(degree[degree 》 0],-1.0)
dataset.graph.node_feat[“norm”] = np.expand_dims(norm, -1)
def row_normalize(mx):
“”“Row-normalize sparse matrix”“”
rowsum = np.array(mx.sum(1))
r_inv = np.power(rowsum, -1).flatten()
r_inv[np.isinf(r_inv)] = 0.
r_mat_inv = sp.diags(r_inv)
mx = r_mat_inv.dot(mx)
return mx
def aug_normalized_adjacency(adj):
adj = adj + sp.eye(adj.shape[0])
adj = sp.coo_matrix(adj)
row_sum = np.array(adj.sum(1))
d_inv_sqrt = np.power(row_sum, -0.5).flatten()
d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0.
d_mat_inv_sqrt = sp.diags(d_inv_sqrt)
return d_mat_inv_sqrt.dot(adj).dot(d_mat_inv_sqrt).tocoo()
通過之前的到的信息,對于feature和adj進行歸一化處理:
鄰接矩陣的歸一化方程:
def pre_sgc(dataset,feature,norm=None):
“”“
Implementation of Simplifying graph convolutional networks (SGC)
This is an implementation of the paper SEMI-SUPERVISED CLASSIFICATION
WITH Simplifying graph convolutional networks (https://arxiv.org/abs/1902.07153)。
Args:
gw: Graph wrapper object (:code:`StaticGraphWrapper` or :code:`GraphWrapper`)
feature: A tensor with shape (num_nodes, feature_size)。
output: The output size for sgc.
activation: The activation for the output
name: Gcn layer names.
norm: If :code:`norm` is not None, then the feature will be normalized. Norm must
be tensor with shape (num_nodes,) and dtype float32.
Return:
A tensor with shape (num_nodes, hidden_size)
”“”
num_nodes=np.shape(feature)[0]
adj=np.zeros((num_nodes,num_nodes))
#print(np.shape(dataset.graph.edges))
for u in range(len(dataset.graph.edges)):
adj[dataset.graph.edges[u][0],dataset.graph.edges[u][1]]=adj[dataset.graph.edges[u][1],dataset.graph.edges[u][0]]=1
feature=dataset.graph.node_feat[‘words’]
feature=row_normalize(feature)
if norm==True:
adj=aug_normalized_adjacency(adj)
for i in range(args.degree):
feature=adj.dot(feature)
return feature
得到預處理的圖算子:
這里的K我們在args中設置,degree為2。進行訓練并且得到結果,紅色是train而綠色是validation:
我們對比Pytorch的官方復現,要達到同樣的效果,Pytorch需要100-150輪訓練,我們利用PGL和Paddle可以在50輪甚至30輪達到收斂,速度極快!
正如之前開頭所說的那樣,我們需要的其實是工業應用圖神經網絡,而時間復雜度和空間復雜度往往是我們重點考慮的,Paddle在速度上的高效是其作為深度學習平臺的優點,同時他的接口也是簡單易懂,所以才可以迅速并簡單的復現一篇論文。
編輯:hfy
評論
查看更多