學習有關圖神經網絡的所有知識,包括 GNN 是什么,不同類型的圖神經網絡,以及它們的用途。此外,了解如何使用 PyTorch 構建圖神經網絡。
為適合中文閱讀習慣,閱讀更有代入感,原文翻譯后有刪改。轉載請注明原文出處,并說明由我得學城翻譯整理。
? ? ? ? Abid Ali Awan| 作者?
1. 什么是圖?
圖是一種包含節點和邊的數據結構。一個節點可以是一個人、地方或物體,邊定義了節點之間的關系。邊可以是有向的,也可以是無向的,基于方向性依賴關系。
在下面的示例中,藍色圓圈是節點,箭頭是邊。邊的方向定義了兩個節點之間的依賴關系。
讓我們了解一下復雜的圖數據集:爵士音樂家網絡。它包含198個節點和2742條邊。
爵士音樂家網絡https://datarepository.wolframcloud.com/resources/Jazz-Musicians-Network
在下面的社區圖中,不同顏色的節點代表爵士音樂家的各種社區,邊連接著它們。存在一種協作網絡,其中單個音樂家在社區內外都有關系。
爵士音樂家網絡的社區圖
圖在處理具有關系和相互作用的復雜問題方面非常出色。它們在模式識別、社交網絡分析、推薦系統和語義分析中得到應用。創建基于圖的解決方案是一個全新的領域,為復雜且相互關聯的數據集提供了豐富的見解。
2. 使用 NetworkX 創建圖
在本節中,我們將學習使用NetworkX創建圖。
下面的代碼受到 Daniel Holmberg 在 Python 中的圖神經網絡博客的影響。
創建 networkx 的DiGraph對象“H”
添加包含不同標簽、顏色和大小的節點
添加邊以創建兩個節點之間的關系。例如,“(0,1)”表示 0 對 1 有方向性依賴。我們將通過添加“(1,0)”來創建雙向關系
以列表形式提取顏色和大小
使用 networkx 的draw函數繪制圖
import?networkx?as?nx H?=?nx.DiGraph() #adding?nodes H.add_nodes_from([ ??(0,?{"color":?"blue",?"size":?250}), ??(1,?{"color":?"yellow",?"size":?400}), ??(2,?{"color":?"orange",?"size":?150}), ??(3,?{"color":?"red",?"size":?600}) ]) #adding?edges H.add_edges_from([ ??(0,?1), ??(1,?2), ??(1,?0), ??(1,?3), ??(2,?3), ??(3,0) ]) node_colors?=?nx.get_node_attributes(H,?"color").values() colors?=?list(node_colors) node_sizes?=?nx.get_node_attributes(H,?"size").values() sizes?=?list(node_sizes) #?Plotting?Graph nx.draw(H,?with_labels=True,?node_color=colors,?node_size=sizes)
?
?
在下一步中,我們將使用to_undirected()函數將數據結構從有向圖轉換為無向圖。
#?轉換為無向圖 G?=?H.to_undirected() nx.draw(G,?with_labels=True,?node_color=colors,?node_size=sizes)
3. 為什么分析圖很難?
基于圖的數據結構存在一些缺點,數據科學家在開發基于圖的解決方案之前必須了解這些缺點。
圖存在于非歐幾里得空間中。它不在 2D 或 3D 空間中存在,這使得解釋數據變得更加困難。為了在 2D 空間中可視化結構,您必須使用各種降維工具。
圖是動態的;它們沒有固定的形式。可以存在兩個在視覺上不同的圖,但它們可能具有相似的鄰接矩陣表示。這使得使用傳統的統計工具來分析數據變得困難。
對于人類解讀來說,圖的規模和維度會增加圖的復雜性。具有多個節點和數千條邊的密集結構更難理解和提取洞察。
4. 什么是圖神經網絡(GNN)?
圖神經網絡是一種特殊類型的神經網絡,能夠處理圖數據結構。它們受到卷積神經網絡(CNNs)和圖嵌入的很大影響。GNNs 用于預測節點、邊和基于圖的任務。
CNNs 用于圖像分類。類似地,GNNs 應用于圖結構(像素網格)以預測一個類。
循環神經網絡用于文本分類。類似地,GNNs 應用于圖結構,其中每個單詞是句子中的一個節點。
GNNs 是在卷積神經網絡由于圖的任意大小和復雜結構而無法取得最佳結果時引入的。
圖像由 Purvanshi Mehta 提供
輸入圖經過一系列神經網絡。輸入圖結構被轉換成圖嵌入,允許我們保留關于節點、邊和全局上下文的信息。
然后,節點 A 和 C 的特征向量通過神經網絡層。它聚合這些特征并將它們傳遞到下一層。
4.1 圖神經網絡的類型
有幾種類型的神經網絡,它們大多數都有一些卷積神經網絡的變體。在本節中,我們將學習最流行的 GNNs。
圖卷積網絡(GCNs, Graph Convolutional Networks)類似于傳統的 CNNs。它通過檢查相鄰節點來學習特征。GNNs 聚合節點向量,將結果傳遞給稠密層,并使用激活函數應用非線性。簡而言之,它包括圖卷積、線性層和非學習激活函數。有兩種主要類型的 GCNs:空間卷積網絡和頻譜卷積網絡。
圖自編碼器網絡(Graph Auto-Encoder Networks)使用編碼器學習圖表示,并嘗試使用解碼器重建輸入圖。編碼器和解碼器通過瓶頸層連接。它們通常用于鏈路預測,因為自編碼器擅長處理類平衡問題。
循環圖神經網絡(RGNNs, Recurrent Graph Neural Networks)學習最佳擴散模式,它們可以處理單個節點具有多個關系的多關系圖。這種類型的圖神經網絡使用正則化器來增強平滑性并消除過度參數化。RGNNs 使用更少的計算能力產生更好的結果。它們用于生成文本、機器翻譯、語音識別、生成圖像描述、視頻標記和文本摘要。
門控圖神經網絡(GGNNs, Gated Graph Neural Networks)在執行具有長期依賴性的任務方面優于 RGNNs。門控圖神經網絡通過在長期依賴性上添加節點、邊和時間門來改進循環圖神經網絡。類似于門控循環單元(GRUs),門用于在不同狀態下記住和忘記信息。
4.2 圖神經網絡任務類型
下面,我們列舉了一些圖神經網絡任務類型,并提供了示例:
圖分類(Graph Classification:):用于將圖分類為不同的類別。其應用包括社交網絡分析和文本分類。
節點分類(Node Classification:):這個任務使用相鄰節點的標簽來預測圖中缺失的節點標簽。
鏈路預測(Link Prediction):預測圖中具有不完整鄰接矩陣的一對節點之間的鏈接。這通常用于社交網絡。
社區檢測(Community Detection):基于邊的結構將節點劃分為不同的群集。它類似地從邊的權重、距離和圖對象中學習。
圖嵌入(Graph Embedding):將圖映射到向量,保留有關節點、邊和結構的相關信息。
圖生成(Graph Generation:):從樣本圖分布中學習,以生成一個新的但相似的圖結構。
圖神經網絡類型
4.3 圖神經網絡的缺點
使用 GNNs 存在一些缺點。了解這些缺點將幫助我們確定何時使用 GNN 以及如何優化我們的機器學習模型的性能。
大多數神經網絡可以深度學習以獲得更好的性能,而 GNNs 大多是淺層網絡,主要有三層。這限制了我們在大型數據集上獲得最先進性能的能力。
圖結構不斷變化,這使得在其上訓練模型變得更加困難。
將模型部署到生產環境面臨可擴展性問題,因為這些網絡在計算上很昂貴。如果您有一個龐大且復雜的圖結構,將難以在生產環境中擴展 GNNs。
5. 什么是圖卷積網絡(GCN)?
大多數 GNNs 都是圖卷積網絡,了解它們在進入節點分類教程之前很重要。
GCN 中的卷積與卷積神經網絡中的卷積相同。它將神經元與權重(濾波器)相乘,以從數據特征中學習。
它在整個圖像上充當滑動窗口,以從相鄰單元中學習特征。該濾波器使用權重共享在圖像識別系統中學習各種面部特征。
現在將相同的功能轉移到圖卷積網絡中,其中模型從相鄰節點中學習特征。GCN 和 CNN 之間的主要區別在于,GCN 被設計為在非歐幾里得數據結構上工作,其中節點和邊的順序可能變化。
CNN vs GCN
有兩種類型的 GCNs:
空間圖卷積網絡(Spatial Graph Convolutional Networks)使用空間特征從位于空間空間的圖中學習。
頻譜圖卷積網絡(Spectral Graph Convolutional Networks)使用圖拉普拉斯矩陣的特征值分解進行節點間的信息傳播。這些網絡靈感來自信號與系統中的波動傳播。
6. 圖神經網絡如何工作?使用 PyTorch 構建圖神經網絡
我們將構建和訓練用于節點分類模型的譜圖卷積。代碼源可在文末獲取,讓您體驗并運行您的第一個基于圖的機器學習模型。
6.1 準備
我們將安裝 Pytorch 軟件包,因為 pytorch_geometric 是在其基礎上構建的。
?
?
!pip?install?-q?torch
?
?
然后,我們將使用 torch 版本安裝 torch-scatter 和 torch-sparse。之后,我們將從 GitHub 安裝 pytorch_geometric 的最新版本。
?
?
%%capture import?os import?torch os.environ['TORCH']?=?torch.__version__ os.environ['PYTHONWARNINGS']?=?"ignore" !pip?install?torch-scatter?-f?https://data.pyg.org/whl/torch-${TORCH}.html !pip?install?torch-sparse?-f?https://data.pyg.org/whl/torch-${TORCH}.html !pip?install?git+https://github.com/pyg-team/pytorch_geometric.git
?
?
6.2 Planetoid Cora 數據集
Planetoid 是來自 Cora、CiteSeer 和 PubMed 的引文網絡數據集。節點是具有 1433 維詞袋特征向量的文檔,邊是研究論文之間的引文鏈接。有 7 個類別,我們將訓練模型以預測缺失的標簽。
我們將導入 Planetoid Cora 數據集,并對詞袋輸入特征進行行標準化。之后,我們將分析數據集和第一個圖對象。
?
?
from?torch_geometric.datasets?import?Planetoid from?torch_geometric.transforms?import?NormalizeFeatures dataset?=?Planetoid(root='data/Planetoid',?name='Cora',?transform=NormalizeFeatures()) 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. print(data)
?
?
Cora 數據集有 2708 個節點、10,556 條邊、1433 個特征和 7 個類別。第一個對象有 2708 個訓練、驗證和測試掩碼。我們將使用這些掩碼來訓練和評估模型。
?
?
Dataset:?Cora(): ====================== Number?of?graphs:?1 Number?of?features:?1433 Number?of?classes:?7 Data(x=[2708,?1433],?edge_index=[2,?10556],?y=[2708],?train_mask=[2708],?val_mask=[2708],?test_mask=[2708])
?
?
6.3 使用 GNN 進行節點分類
我們將創建一個包含兩個 GCNConv 層、relu 激活和 0.5 的丟棄率的 GCN 模型結構。該模型包含 16 個隱藏通道。
GCN 層:
上述方程中的 W(?+1) 是一個可訓練的權重矩陣,Cw,v 表示每個邊的固定標準化系數。
?
?
from?torch_geometric.nn?import?GCNConv import?torch.nn.functional?as?F class?GCN(torch.nn.Module): ????def?__init__(self,?hidden_channels): ????????super().__init__() ????????torch.manual_seed(1234567) ????????self.conv1?=?GCNConv(dataset.num_features,?hidden_channels) ????????self.conv2?=?GCNConv(hidden_channels,?dataset.num_classes) ????def?forward(self,?x,?edge_index): ????????x?=?self.conv1(x,?edge_index) ????????x?=?x.relu() ????????x?=?F.dropout(x,?p=0.5,?training=self.training) ????????x?=?self.conv2(x,?edge_index) ????????return?x model?=?GCN(hidden_channels=16) print(model) >>>?GCN( ????(conv1):?GCNConv(1433,?16) ????(conv2):?GCNConv(16,?7) ??)
?
?
6.4 可視化未經訓練的 GCN 網絡
讓我們使用 sklearn.manifold.TSNE 和 matplotlib.pyplot 來可視化未經訓練的 GCN 網絡的節點嵌入。它將繪制一個包含 7 個維度節點嵌入的 2D 散點圖。
?
?
%matplotlib?inline import?matplotlib.pyplot?as?plt from?sklearn.manifold?import?TSNE def?visualize(h,?color): ????z?=?TSNE(n_components=2).fit_transform(h.detach().cpu().numpy()) ????plt.figure(figsize=(10,10)) ????plt.xticks([]) ????plt.yticks([]) ????plt.scatter(z[:,?0],?z[:,?1],?s=70,?c=color,?cmap="Set2") ????plt.show()
?
?
然后我們將評估模型,然后將訓練數據添加到未經訓練的模型中以可視化各種節點和類別。
?
?
model.eval() out?=?model(data.x,?data.edge_index) visualize(out,?color=data.y)
?
?
6.5 訓練 GNN
我們將使用 Adam 優化器和交叉熵損失函數(Cross-Entropy Loss)對模型進行 100 輪訓練。
在訓練函數中,我們有:
清除梯度
執行一次前向傳播
使用訓練節點計算損失
計算梯度,并更新參數
在測試函數中,我們有:
預測節點類別
提取具有最高概率的類別標簽
檢查有多少個值被正確預測
創建準確率比,使用正確預測的總和除以節點的總數。
?
?
model?=?GCN(hidden_channels=16) optimizer?=?torch.optim.Adam(model.parameters(),?lr=0.01,?weight_decay=5e-4) criterion?=?torch.nn.CrossEntropyLoss() def?train(): ??????model.train() ??????optimizer.zero_grad() ??????out?=?model(data.x,?data.edge_index) ??????loss?=?criterion(out[data.train_mask],?data.y[data.train_mask]) ??????loss.backward() ??????optimizer.step() ??????return?loss def?test(): ??????model.eval() ??????out?=?model(data.x,?data.edge_index) ??????pred?=?out.argmax(dim=1) ??????test_correct?=?pred[data.test_mask]?==?data.y[data.test_mask] ??????test_acc?=?int(test_correct.sum())?/?int(data.test_mask.sum()) ??????return?test_acc for?epoch?in?range(1,?101): ????loss?=?train() ????print(f'Epoch:?{epoch:03d},?Loss:?{loss:.4f}') GAT( ??(conv1):?GATConv(1433,?8,?heads=8) ??(conv2):?GATConv(64,?7,?heads=8) ) ..?..?..?.. ..?..?..?.. Epoch:?098,?Loss:?0.5989 Epoch:?099,?Loss:?0.6021 Epoch:?100,?Loss:?0.5799
?
?
6.6 模型評估
我們將使用測試函數在未見過的數據集上評估模型,如您所見,我們在準確率上取得了相當不錯的結果,為 81.5%。
?
?
test_acc?=?test() print(f'Test?Accuracy:?{test_acc:.4f}')
?
?
輸出:
?
?
>>>?測試準確率:0.8150
?
?
現在,我們將可視化經過訓練的模型的輸出嵌入以驗證結果。
?
?
model.eval() out?=?model(data.x,?data.edge_index) visualize(out,?color=data.y)
?
?
正如我們所看到的,經過訓練的模型為相同類別的節點產生了更好的聚類。
6.7 訓練 GATConv 模型
在第二個例子中,我們將使用 GATConv 層替換 GCNConv。圖注意力網絡使用掩碼的自注意力層來解決 GCNConv 的缺點并取得最先進的結果。
您還可以嘗試其他 GNN 層,并嘗試不同的優化、丟失率和隱藏通道數量,以獲得更好的性能。
在下面的代碼中,我們只是用具有 8 個注意力頭的 GATConv 替換了 GCNConv,其中第一層有 8 個頭,第二層有 1 個頭。
我們還將設置:
dropout為 0.6
隱藏通道為 8
學習率為 0.005
我們修改了測試函數以找到特定掩碼(驗證、測試)的準確率。這將幫助我們在模型訓練期間打印出驗證和測試分數。我們還將驗證和測試結果存儲到后面的繪圖線圖中。
?
?
from?torch_geometric.nn?import?GATConv class?GAT(torch.nn.Module): ????def?__init__(self,?hidden_channels,?heads): ????????super().__init__() ????????torch.manual_seed(1234567) ????????self.conv1?=?GATConv(dataset.num_features,?hidden_channels,heads) ????????self.conv2?=?GATConv(heads*hidden_channels,?dataset.num_classes,heads) ????def?forward(self,?x,?edge_index): ????????x?=?F.dropout(x,?p=0.6,?training=self.training) ????????x?=?self.conv1(x,?edge_index) ????????x?=?F.elu(x) ????????x?=?F.dropout(x,?p=0.6,?training=self.training) ????????x?=?self.conv2(x,?edge_index) ????????return?x model?=?GAT(hidden_channels=8,?heads=8) print(model) optimizer?=?torch.optim.Adam(model.parameters(),?lr=0.005,?weight_decay=5e-4) criterion?=?torch.nn.CrossEntropyLoss() def?train(): ??????model.train() ??????optimizer.zero_grad() ??????out?=?model(data.x,?data.edge_index) ??????loss?=?criterion(out[data.train_mask],?data.y[data.train_mask]) ??????loss.backward() ??????optimizer.step() ??????return?loss def?test(mask): ??????model.eval() ??????out?=?model(data.x,?data.edge_index) ??????pred?=?out.argmax(dim=1) ??????correct?=?pred[mask]?==?data.y[mask] ??????acc?=?int(correct.sum())?/?int(mask.sum()) ??????return?acc val_acc_all?=?[] test_acc_all?=?[] for?epoch?in?range(1,?101): ????loss?=?train() ????val_acc?=?test(data.val_mask) ????test_acc?=?test(data.test_mask) ????val_acc_all.append(val_acc) ????test_acc_all.append(test_acc) ????print(f'Epoch:?{epoch:03d},?Loss:?{loss:.4f},?Val:?{val_acc:.4f},?Test:?{test_acc:.4f}') ..?..?..?.. ..?..?..?.. Epoch:?098,?Loss:?1.1283,?Val:?0.7960,?Test:?0.8030 Epoch:?099,?Loss:?1.1352,?Val:?0.7940,?Test:?0.8050 Epoch:?100,?Loss:?1.1053,?Val:?0.7960,?Test:?0.8040
?
?
正如我們所觀察到的,我們的模型并沒有比 GCNConv 表現得更好。它需要進行超參數優化或更多輪次的訓練才能取得最先進的結果。
6.8 模型評估
在評估部分,我們使用 matplotlib.pyplot 的折線圖可視化驗證和測試分數。
?
?
import?numpy?as?np plt.figure(figsize=(12,8)) plt.plot(np.arange(1,?len(val_acc_all)?+?1),?val_acc_all,?label='Validation?accuracy',?c='blue') plt.plot(np.arange(1,?len(test_acc_all)?+?1),?test_acc_all,?label='Testing?accuracy',?c='red') plt.xlabel('Epochs') plt.ylabel('Accurarcy') plt.title('GATConv') plt.legend(loc='lower?right',?fontsize='x-large') plt.savefig('gat_loss.png') plt.show()
?
?
經過 60 輪次,驗證和測試準確率達到了穩定的值,約為 0.8+/-0.02。
再次,讓我們可視化 GATConv 模型的節點聚類。
?
?
model.eval() out?=?model(data.x,?data.edge_index) visualize(out,?color=data.y)
?
?
正如我們所見,GATConv 層在相同類別的節點上產生了相同的聚類結果。
我們可以通過添加第二個驗證數據集來減少過擬合,并通過嘗試來自 pytoch_geometric 的各種 GCN 層來提高模型性能。
GNN 常見問題
圖神經網絡(GNN)用于什么?
圖神經網絡直接應用于圖數據集,您可以訓練它們以預測節點、邊緣和與圖相關的任務。它用于圖和節點分類、鏈路預測、圖聚類和生成,以及圖像和文本分類。
在圖神經網絡中,什么是圖?
在圖神經網絡中,圖是一種包含節點和節點之間連接(稱為邊)的數據結構。邊可以是有向的或無向的。它具有動態形狀和多維結構。例如,在社交媒體中,節點可以是您朋友群中的人,而邊則是您與每個人之間的關系。
圖神經網絡有多強大?
在圖像和節點分類方面,圖神經網絡優于典型的卷積神經網絡(CNN)。許多圖神經網絡的變體在節點和圖分類任務中取得了最先進的結果 - openreview.net。
神經網絡是否使用圖論?
是的,神經網絡與設計用于處理非歐幾里得數據的圖論密切相關。其中一些神經網絡本身就是圖,或者輸出圖。
什么是圖卷積網絡?
圖卷積網絡類似于用于圖數據集的卷積神經網絡。它包括圖卷積、線性層和非線性激活。GNN 通過圖上的濾波器,檢查可用于對數據中的節點進行分類的節點和邊。
在深度學習中,什么是圖?
圖深度學習也被稱為幾何深度學習。它使用多個神經網絡層以實現更好的性能。這是一個活躍的研究領域,科學家們正試圖在不影響性能的情況下增加層數。
審核編輯:黃飛
評論
查看更多