深度學(xué)習(xí)(36)—— 圖神經(jīng)網(wǎng)絡(luò)GNN(1)
這個系列的所有代碼我都會放在git上,歡迎造訪
1. 基礎(chǔ)知識
-
GNN考慮的事當(dāng)前的點和周圍點之間的關(guān)系
-
鄰接矩陣是對稱的稀疏矩陣,表示圖中各個點之間的關(guān)系
-
圖神經(jīng)網(wǎng)絡(luò)的輸入是每個節(jié)點的特征和鄰接矩陣
-
文本數(shù)據(jù)可以用圖的形式表示嗎?
文本數(shù)據(jù)也可以表示圖的形式,鄰接矩陣表示連接關(guān)系 -
鄰接矩陣中并不是一個N* N的矩陣,而是一個source,target的2* N的矩陣
-
信息傳遞神經(jīng)網(wǎng)絡(luò):
每個點的特征如何更新??
——考慮他們的鄰居,更新的方式可以自己設(shè)置:最大,最小,平均,求和等 -
GNN可以有多層,圖的結(jié)構(gòu)不發(fā)生改變,即當(dāng)前點所連接的點不發(fā)生改變(鄰接矩陣不發(fā)生變化)【卷積中存在感受野的概念,在GNN中同樣存在,GNN的感受野也隨著層數(shù)的增大變大】
-
GNN輸出的特征可以干什么?
- 各個節(jié)點的特征組合,對圖分類【graph級別任務(wù)】
- 對各個節(jié)點分類【node級別任務(wù)】
- 對邊分類【edge級別任務(wù)】
利用圖結(jié)構(gòu)得到特征,最終做什么自定義!
2.使用場景
-
為什么CV和NLP中不用GNN?
因為圖像和文本的數(shù)據(jù)格式很固定,傳統(tǒng)神經(jīng)網(wǎng)絡(luò)格式是固定的,輸入的東西格式是固定的 - 化學(xué)、醫(yī)療
- 分子、原子結(jié)構(gòu)
- 藥物靶點
- 道路交通,動態(tài)流量預(yù)測
- 社交網(wǎng)絡(luò)——研究人
GNN輸入格式比較隨意,是不規(guī)則的數(shù)據(jù)結(jié)構(gòu), 主要用于輸入數(shù)據(jù)不規(guī)則的時候
3. 圖卷積神經(jīng)網(wǎng)絡(luò)GCN
圖卷積和卷積完全不同
- GCN不是單純的有監(jiān)督學(xué)習(xí),多數(shù)是半監(jiān)督,有的點是沒有標(biāo)簽的,在計算損失的時候只考慮有標(biāo)簽的點。針對數(shù)據(jù)量少的情況也可以訓(xùn)練
(1)基本思想
- 網(wǎng)絡(luò)層次:第一層對于每個點都要做更新,最后輸出每個點對應(yī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
獻(xiàn)上github地址:這里
下面是一個demo
(1)數(shù)據(jù)
這里使用的是和這個package提供的數(shù)據(jù),具體參考:club
from torch_geometric.datasets import KarateClub
dataset = 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的對象:可以在文檔中詳細(xì)了解
其中的屬性
- edge_index:表示圖的連接關(guān)系(start,end兩個序列)
- node features:每個點的特征
- node labels:每個點的標(biāo)簽
- train_mask:有的節(jié)點沒有標(biāo)簽(用來表示哪些節(jié)點要計算損失)
(2)可視化
from torch_geometric.utils import to_networkx
G = to_networkx(data, to_undirected=True)
visualize_graph(G, color=data.y)
(3)網(wǎng)絡(luò)定義
GCN layer的定義:
可以在官網(wǎng)的文檔做詳細(xì)了解
卷積層就有很多了:
import torch
from torch.nn import Linear
from torch_geometric.nn import GCNConv
class 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, h
model = GCN()
print(model)
_, h = model(data.x, data.edge_index)
print(f'Embedding shape: {list(h.shape)}')# 輸出最后分類前的中間特征shape
visualize_embedding(h, color=data.y)
這時很分散文章來源:http://www.zghlxwxcb.cn/news/detail-643032.html
(4)訓(xùn)練模型(semi-supervised)
import time
model = 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-supervised
loss.backward()
optimizer.step()
return loss, h
for 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)
然后就可以看到一系列圖,看點的變化情況了文章來源地址http://www.zghlxwxcb.cn/news/detail-643032.html
到了這里,關(guān)于深度學(xué)習(xí)(36)—— 圖神經(jīng)網(wǎng)絡(luò)GNN(1)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!