敦化網(wǎng)站建設最好的網(wǎng)站優(yōu)化公司
深度學習(36)—— 圖神經(jīng)網(wǎng)絡GNN(1)
這個系列的所有代碼我都會放在git上,歡迎造訪
文章目錄
- 深度學習(36)—— 圖神經(jīng)網(wǎng)絡GNN(1)
- 1. 基礎知識
- 2.使用場景
- 3. 圖卷積神經(jīng)網(wǎng)絡GCN
- (1)基本思想
- 4. GNN基本框架——pytorch_geometric
- (1)數(shù)據(jù)
- (2)可視化
- (3)網(wǎng)絡定義
- (4)訓練模型(semi-supervised)
1. 基礎知識
-
GNN考慮的事當前的點和周圍點之間的關系
-
鄰接矩陣是對稱的稀疏矩陣,表示圖中各個點之間的關系
-
圖神經(jīng)網(wǎng)絡的輸入是每個節(jié)點的特征和鄰接矩陣
-
文本數(shù)據(jù)可以用圖的形式表示嗎?
文本數(shù)據(jù)也可以表示圖的形式,鄰接矩陣表示連接關系 -
鄰接矩陣中并不是一個N* N的矩陣,而是一個source,target的2* N的矩陣
-
信息傳遞神經(jīng)網(wǎng)絡:
每個點的特征如何更新??
——考慮他們的鄰居,更新的方式可以自己設置:最大,最小,平均,求和等 -
GNN可以有多層,圖的結構不發(fā)生改變,即當前點所連接的點不發(fā)生改變(鄰接矩陣不發(fā)生變化)【卷積中存在感受野的概念,在GNN中同樣存在,GNN的感受野也隨著層數(shù)的增大變大】
-
GNN輸出的特征可以干什么?
- 各個節(jié)點的特征組合,對圖分類【graph級別任務】
- 對各個節(jié)點分類【node級別任務】
- 對邊分類【edge級別任務】
利用圖結構得到特征,最終做什么自定義!
2.使用場景
為什么CV和NLP中不用GNN?
因為圖像和文本的數(shù)據(jù)格式很固定,傳統(tǒng)神經(jīng)網(wǎng)絡格式是固定的,輸入的東西格式是固定的- 化學、醫(yī)療
- 分子、原子結構
- 藥物靶點
- 道路交通,動態(tài)流量預測
- 社交網(wǎng)絡——研究人
GNN輸入格式比較隨意,是不規(guī)則的數(shù)據(jù)結構, 主要用于輸入數(shù)據(jù)不規(guī)則的時候
3. 圖卷積神經(jīng)網(wǎng)絡GCN
圖卷積和卷積完全不同
- GCN不是單純的有監(jiān)督學習,多數(shù)是半監(jiān)督,有的點是沒有標簽的,在計算損失的時候只考慮有標簽的點。針對數(shù)據(jù)量少的情況也可以訓練
(1)基本思想
- 網(wǎng)絡層次:第一層對于每個點都要做更新,最后輸出每個點對應的特征向量【一般不會做特別深層的】
- 圖中的基本組成:G(原圖)A(鄰接)D(度)F(特征)
- 度矩陣的倒數(shù)* 鄰接矩陣 *度矩陣的倒數(shù)——>得到新的鄰接矩陣【左乘對行做歸一化,右乘對列做歸一化】
- 兩到三層即可,太多效果不佳
4. GNN基本框架——pytorch_geometric
它實現(xiàn)了各種GNN的方法
注意:安裝過程中不要pip install,會失敗!根據(jù)自己的device和python版本去下載scatter,pattern等四個依賴,先安裝他們?nèi)缓笤賞ip install torch_geometric==2.0
這里記得是2.0版本否則會出現(xiàn) TypeError: Expected ‘Iterator‘ as the return annotation for __iter__
of SMILESParser, but found ty
獻上github地址:這里
下面是一個demo
(1)數(shù)據(jù)
這里使用的是和這個package提供的數(shù)據(jù),具體參考:club
from torch_geometric.datasets import KarateClubdataset = KarateClub()
print(f'Dataset: {dataset}:')
print('======================')
print(f'Number of graphs: {len(dataset)}')
print(f'Number of features: {dataset.num_features}')
print(f'Number of classes: {dataset.num_classes}')data = dataset[0] # Get the first graph object.
在torch_geometric中圖用Data的格式,Data的對象:可以在文檔中詳細了解
其中的屬性
- edge_index:表示圖的連接關系(start,end兩個序列)
- node features:每個點的特征
- node labels:每個點的標簽
- train_mask:有的節(jié)點沒有標簽(用來表示哪些節(jié)點要計算損失)
(2)可視化
from torch_geometric.utils import to_networkxG = to_networkx(data, to_undirected=True)
visualize_graph(G, color=data.y)
(3)網(wǎng)絡定義
GCN layer的定義:
可以在官網(wǎng)的文檔做詳細了解
卷積層就有很多了:
import torch
from torch.nn import Linear
from torch_geometric.nn import GCNConvclass GCN(torch.nn.Module):def __init__(self):super().__init__()torch.manual_seed(1234)self.conv1 = GCNConv(dataset.num_features, 4) # 只需定義好輸入特征和輸出特征即可self.conv2 = GCNConv(4, 4)self.conv3 = GCNConv(4, 2)self.classifier = Linear(2, dataset.num_classes)def forward(self, x, edge_index):h = self.conv1(x, edge_index) # 輸入特征與鄰接矩陣(注意格式,上面那種)h = h.tanh()h = self.conv2(h, edge_index)h = h.tanh()h = self.conv3(h, edge_index)h = h.tanh() # 分類層out = self.classifier(h)return out, hmodel = GCN()
print(model)_, h = model(data.x, data.edge_index)
print(f'Embedding shape: {list(h.shape)}')# 輸出最后分類前的中間特征shapevisualize_embedding(h, color=data.y)
這時很分散
(4)訓練模型(semi-supervised)
import timemodel = GCN()
criterion = torch.nn.CrossEntropyLoss() # Define loss criterion.
optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # Define optimizer.def train(data):optimizer.zero_grad() out, h = model(data.x, data.edge_index) #h是兩維向量,主要是為了畫圖方便 loss = criterion(out[data.train_mask], data.y[data.train_mask]) # semi-supervisedloss.backward() optimizer.step() return loss, hfor epoch in range(401):loss, h = train(data)if epoch % 10 == 0:visualize_embedding(h, color=data.y, epoch=epoch, loss=loss)time.sleep(0.3)
然后就可以看到一系列圖,看點的變化情況了