
前言
在正文開始之前需要說明,這篇文章以比較簡單的視角去了解GCN,不做過多的理論分析,如果需要比較詳細的理論分析請連結到:
如何了解 Graph Convolutional Network(GCN)?www.zhihu.com
或者參考文章:
https://arxiv.org/abs/1905.10224arxiv.org
接下來的主要内容也是參照這篇文章而來的。
原理
首先需要明确的是我們為什麼需要GCN,原因很簡單,就是個體自身的特征已經無法完全代表個體的所有資訊,這有可能是在資料采集過程中丢失錯誤或者一些個體的僞裝,造成了一些特征的偏差。那麼我們就需要它鄰居節點的資訊作為目前節點的資訊補充。這樣我們就可以得到比單一個體特征,更完整的資訊。
那麼如何将鄰居的特征與目前節點的特征結合在一起,那當然是優秀的圖神經網絡。已經有足夠多的方法來做這個過程,這裡我們就選擇其中一種比較經典的方法來解釋。
這裡我們按照文章中給的式子進行解釋:
可以看到這是一個二層網絡,我們隻需要了解了第一層就很容易了解第二層了。也就是了解:
。激活函數我們先放在一邊,接下來就是三個矩陣相乘。我們以一個簡單的圖作為說明:
可見做為一個無向無權圖來說,它的鄰接矩陣
為:
,加上自己就得到
;為什麼要加上自己呢,因為自己的資訊肯定是需要被用上的(鄰居的資訊很重要,但是自己的資訊也是不能被遺忘的)。
接下來就是
,它表示的是每個節點的特征,也是就是帶的資訊。這裡假設它是一個二維的向量。
,這也是好了解的,每個節點都有自己的資訊。
最後就是
,它的作用是要是對特征進一步的抽象,因為每個特征之間是可能是有聯系的,通過這種全連的神經網絡可以很容易的将這些特征的聯系結合在一起。
我們來看矩陣乘法。首先是
,我們可以得到:
可見經過這個乘法之後,描述節點的特征由它自身的特征加上鄰居特征組成。例如:節點1,它的鄰居包括節點2,3,和4,那麼它的資訊就有1,2,3,4的所有資訊;再如節點4,因為它的鄰居隻有節點1,是以它的資訊隻有它自己加上節點1的資訊。
前面說過
是對特征的進一步抽象,這裡是屬于深度學習中最簡單的神經網絡就是一個全連層加上一個激活函數,我們就不展開了。我們來看經過一次如卷積的傳播,現在每個節點的情況:
還是上面的網絡,我們發現現在每個節點多有它鄰居的資訊,那麼如果我們再進行一次卷積會發生什麼情況呢,我們這個時候節點4的資訊就會傳播到節點2,3中,為什麼呢?因為第一次卷積節點4将它的資訊傳播給了節點1,接下來再進行一次卷積的話,節點1就會把它直到的節點4的資訊傳播給節點2和3。當然同樣的道理他也會将節點2,3的資訊傳播給4。這樣的話就可以得到下面的資訊圖
是以,我們可以直到每一次卷積都會多知道它高一階鄰居的資訊。
總結
優點:總的來說GCN形式簡單,也便于了解。
缺點:計算量比較大,對新加入的節點沒有很好的處理方法。
代碼分析
最後我們通過代碼來看模型:
class
這裡就是兩層的圖卷積網絡,我們來具體看一下GraphConvolution裡面的代碼:
class GraphConvolution(nn.Module):
def __init__(self, in_feature, out_feature, bias=True):
super(GraphConvolution, self).__init__()
self.in_features = in_feature
self.out_features = out_feature
self.weight = Parameter(torch.FloatTensor(in_feature, out_feature))
if bias:
self.bias = Parameter(torch.FloatTensor(out_feature))
else:
self.register_parameter('bias', None)
self.reset_parameters()
def reset_parameters(self):
stdv = 1. / math.sqrt(self.weight.size(1))
self.weight.data.uniform_(-stdv, stdv)
if self.bias is not None:
self.bias.data.uniform_(-stdv, stdv)
def forward(self, input, adj):
support = torch.mm(input, self.weight)
output = torch.spmm(adj, support)
if self.bias is not None:
return output + self.bias
else:
return output
我們可以看到這裡面的forward就是兩次的矩陣乘法。先解釋一下參數,input是輸入的特征大小為:
,adj當然就是鄰接矩陣,self.weight表示的是前面的W。具體的代碼可以參考: tkipf/pygcngithub.com
下面是我們整理的代碼,主要參考原作者的形式。
MrLeeeee/GCN-GAT-and-Graphsagegithub.com
GAT請參考這篇文章:
Mr-Lee:了解Graph Attention Networkszhuanlan.zhihu.com