Kipf和Welling最近發表的一篇論文提出,使用譜傳播規則(spectral propagation)快速近似spectral Graph Convolution。
和之前討論的求和規則和平均規則相比,譜傳播規則的不同之處在於聚合函式。它使用提升到負冪的度矩陣D對聚合進行歸一化這一點與平均規則類似,但是它的歸一化是不對稱的。讓我們一起來看看。
Aggregation as a weighted sum
我們可以理解,前面提到的聚合函式是加權和,其中每個聚合規則選擇不同的權重。在講解spectral rule之前,先看看平均規則的過程。
The Sum Rule
使用求和規則計算第i個節點的聚合特徵,計算過程如下:
如方程式1a所示,第i個節點的聚合特徵表示為向量矩陣乘積,我們可以將這個矩陣乘積表示為一個簡單的加權和,如方程1b所示,對X中的每一行求和。
1b中,第j個節點在聚合中的權重由A的第i行、第j列的值確定。由於A是鄰接矩陣,當節點j與節點i為鄰居時,該值為1,否則為0。因此,1b簡化為對第i個節點的鄰居節點的特徵表示求和。
總的來說,每個鄰居的貢獻取決於鄰接矩陣定義的鄰域。
The Mean Rule
要了解平均規則如何聚合節點表示,我們還是看如何計算第i行,現在使用平均規則。為了簡單起見,我們只考慮“原始”鄰接矩陣上的平均規則,而不考慮A和矩陣I之間的加法,這僅僅對應於向圖中新增自迴圈。
看上面的公式,求導過程明顯更長了。在方程2a中,我們首先轉換鄰接矩陣A,把它乘上D(度矩陣)的逆矩陣。在2b中有更加明確的計算。D-1是一個對角矩陣,沿對角線的值是節點的反度(inverse degree),也就是說位置(i,i)的值是節點i的反度(inverse degree)。因此,我們可以移除其中一個求和符號,得到方程2c。2c可以進一步變形得到2d和2e。
如方程2e所示,我們再次鄰接矩陣中的每一行求和。在求和過程中提到的,這相當於對每個節點的鄰居求和。不同的是,我們要保證2e中的加權和的權重於第i個節點的度相加等於1。因此,2e對應第i個節點的鄰居特徵表示的平均值。
The Spectral Rule
那麼現在我們來看看Spectral 規則。
平均規則中,我們使用度矩陣D轉換鄰接矩陣A。上圖中的3a所示,我們將D的冪提高到-0.5,然後乘上矩陣A的每一邊。該操作如3b所示,D是對角矩陣,因此我們可以進一步簡化方程3b,得到3d。
方程3e很有趣,當我們計算第i個節點的聚合特徵表示時,我們不僅要考慮節點i的度,還要考慮節點j的度。
類似平均規則,Spectral 規則對聚合結果進行歸一化,使得聚合特徵表示與輸入特徵大致保持相同的比例。不同的是,如果鄰居的度低,則加權和中的權重高,如果鄰居的度高,則加權和中的權重低。當低度鄰居提供比高度鄰居更有用的資訊時,這種處理便起作用了。
用GCN進行半監督分類
除了Spectral 規則,Kipf和Welling還演示了GCNs用來進行半監督分類。在半監督學習中,我們希望既有標記樣本,也有未標記樣本。也就是說,我們知道所有的節點,但是不知道所有節點的標籤。
在上述的規則中,我們聚合節點鄰域,因此共享鄰居的節點往往具有相似的特徵表示。如果圖具有同質性,這屬性將很有用,即有連線的節點往往相似(即有相同的標籤)。同質性在很多真實的網路中都存在,特別是社交網路。
即使是隨機初始化的GCN,僅僅通過使用圖結構,也可以很好地分離同質圖中節點的特徵表示。我們可以在標記節點上訓練GCN,通過更新所有節點共享的權重矩陣,有效的將節點標籤資訊傳播給為標記的節點,從而進一步推進上述步驟。具體如下:
1、通過GCN執行前向傳播;
2、在GCN最後一層逐行應用sigmoid函式;
3、計算已知節點標籤上的交叉熵損失;
4、反向傳播損失並更新每層中的權重矩陣W。
空手道俱樂部的社交網路預測
空手道俱樂部
Zachary空手道俱樂部是一個小型的社交網路,在這裡,俱樂部管理員和教練之間會發生衝突。任務是預測,當衝突發生時,俱樂部成員會站在哪一邊。俱樂部社交網路圖表示如下:
每個節點表示俱樂部的每個成員,成員之間的連線表示他們在俱樂部外進行的互動。管理員用是節點A,教練是節點I。
Spectral Graph Convolutions in MXNet
我使用MXNet實現Spectral 規則,MXNet是一個容易實現的高效的深度學習框架,具體如下:
class SpectralRule(HybridBlock):
def __init__(self,
A, in_units, out_units,
activation, **kwargs):
super().__init__(**kwargs)
I = nd.eye(*A.shape)
A_hat = A.copy() + I
D = nd.sum(A_hat, axis=0)
D_inv = D**-0.5
D_inv = nd.diag(D_inv)
A_hat = D_inv * A_hat * D_inv
self.in_units, self.out_units = in_units, out_units
with self.name_scope():
self.A_hat = self.params.get_constant('A_hat', A_hat)
self.W = self.params.get(
'W', shape=(self.in_units, self.out_units)
)
if activation == 'ident':
self.activation = lambda X: X
else:
self.activation = Activation(activation)
def hybrid_forward(self, F, X, A_hat, W):
aggregate = F.dot(A_hat, X)
propagate = self.activation(
F.dot(aggregate, W))
return propagate
建立GCN
根據上面的程式碼,可以實現Spectral 規則,我們將這些層疊在一起。使用一個兩層架構,其中第一個隱藏層有4個單元,第二個隱藏層有兩個單元。這種架構可以輕鬆地顯示最終的二維嵌入。有三個值得注意的地方:
1、我們使用的是Spectral 規則;
2、啟用函式:第一層使用tanh 啟用函式,不然的話,死亡神經元的概率很高;第二層使用identity 啟用函式,因為最後一層我們要分類節點。
最後,我們在GCN頂部加上邏輯迴歸層進行節點分類。上述體系結構的python實現如下:
def build_model(A, X):
model = HybridSequential()
with model.name_scope():
features = build_features(A, X)
model.add(features)
classifier = LogisticRegressor()
model.add(classifier)
model.initialize(Uniform(1))
return model, features
訓練GCN
程式碼如下:
def train(model, features, X, X_train, y_train, epochs):
cross_entropy = SigmoidBinaryCrossEntropyLoss(from_sigmoid=True)
trainer = Trainer(
model.collect_params(), 'sgd',
{'learning_rate': 0.001, 'momentum': 1})
feature_representations = [features(X).asnumpy()]
for e in range(1, epochs + 1):
for i, x in enumerate(X_train):
y = array(y_train)[i]
with autograd.record():
pred = model(X)[x] # Get prediction for sample x
loss = cross_entropy(pred, y)
loss.backward()
trainer.step(1)
feature_representations.append(features(X).asnumpy())
return feature_representations
值得注意的是,圖中節點只有管理員和教練才打了標籤,其餘的節點沒有。GCN可以找到標記的節點和沒有標記的節點表示,並在訓練中利用這兩種資訊來進行半監督學習。具體地,在半監督學習中,GCN通過聚合節點的標籤和節點未標記的鄰居來產生節點的特徵表示。訓練過程中,我們反向傳播二進位制交叉熵損失,以更新所有節點之間的共享權重。而這種損失取決於標記節點的特徵表示,而該特徵表示又取決於有標籤的節點和未標記的節點。
視覺化特徵
正如上面所說,每個時間的特徵表示被儲存,我們可以看到特徵表示在訓練期間如何變化。我考慮了兩種輸入特徵表示。
表示一
在第一種表示中,我們簡單地使用稀疏34 x 34單位矩陣I,作為特徵矩陣X,即one-hot encoding圖中的每個節點。這樣表示的好處是,可以適用於任何圖,但網路中的每個節點都需要輸入引數,這需要大量記憶體和計算能力來訓練,並且可能過擬合。幸好空手道俱樂部的網路很小。
表示1中出現的分類錯誤
通過對網路中的所有節點進行集體分類,我們得到了網路中錯誤的分佈情況,如上所示。這裡,黑色表示錯誤分類。儘管將近一半( 41 % )的節點被錯誤分類,但與管理員或教練(但不是兩者)密切相關的節點傾向於正確分類。
使用表示1,訓練過程中特徵表示的變化
上面我已經說明訓練過程中特徵表示是如何變化的。最初,節點是密集的聚集在一起,隨著訓練,教練和管理員被拉開,同時它們拖動一些節點。
雖然教練和管理員的表示不同,但是它們拖動的節點並不一定完全屬於它們的社群。
這是因為圖卷積嵌入了在特徵空間中共享鄰居的節點,但是共享鄰居的兩個節點可能並不等同的連線到管理員和教練。特別是,使用對角矩陣作為特徵矩陣導致每個節點高度區域性的表示,也就是說在圖中相同區域的節點可能緊密嵌入在一起。這使得網路很難以歸納的方式在全域性上共享知識。
表示二
我們將改進表示1,改進的方法是增加兩個特徵,這兩個特徵不具體到任何一個節點或者網路中的區域,是衡量教練和管理員的連通性。為此,我們計算了網路中每個節點到管理員和教練的最短路徑,並將這兩個特徵連線到前面的表示中。
表示2中出現的分類錯誤
如前面所述,我們對網路中的所有節點進行了總體分類,並繪製了上圖。表示2只有4個節點被錯誤分類,與表示1相比有了很大的提高。仔細檢查特徵矩陣後,原因可能是因為這些節點在最短路徑上的距離更靠近教練,但它實際上屬於管理員社群。
表示2訓練過程中特徵表示的變化
如上所示,節點最初是緊密的聚集在一起,但是在訓練開始之前,它在某種程度上已經分成了兩個社群,隨著訓練過程,社群之間的距離增大。
參考連結
原文連結:
https://towardsdatascience.com/how-to-do-deep-learning-on-graphs-with-graph-convolutional-networks-62acf5b143d0
資料連結:
https://github.com/TobiasSkovgaardJepsen/posts/tree/master/HowToDoDeepLearningOnGraphsWithGraphConvolutionalNetworks/Part2_SemiSupervisedLearningWithSpectralGraphConvolutions