PyG 文檔(1)---Introduction by Example

一、舉例介紹

1踱启、圖數(shù)據(jù)的處理

PyG 中的單個圖由 torch_geometric.data.Data的實例描述,默認情況下它包含以下屬性:

  • data.x: 以 [num_nodes, num_node_features]形式描述的節(jié)點特征矩陣
  • data.edge_index: COO 格式的圖形連接,形狀為 [2, num_edges]请垛,類型為 torch.long搪搏。

COO 格式:PyTorch 實現(xiàn)了所謂的坐標(biāo)格式或 COO 格式狭握,作為實現(xiàn)稀疏張量的存儲格式之一,在 COO 格式中疯溺,指定的元素存儲為元素索引和相應(yīng)值的元組论颅“タ眩可以通過向函數(shù) torch.sparse_coo_tensor() 提供索引和值這兩個張量以及稀疏張量的大小(當(dāng)無法從索引和值張量推斷時)來構(gòu)造稀疏 COO 張量恃疯。假設(shè)我們要定義一個稀疏張量漏设,其中條目 3 位于位置 (0, 2),條目 4 位于位置 (1, 0)今妄,條目 5 位于位置 (1, 2)郑口。 未指定的元素被假定具有相同的值,填充值盾鳞,默認為零犬性。 然后我們會寫:

>>> i = [[0, 1, 1],
         [2, 0, 2]]
>>> v =  [3, 4, 5]
>>> s = torch.sparse_coo_tensor(i, v, (2, 3))
>>> s
tensor(indices=tensor([[0, 1, 1],
                       [2, 0, 2]]),
       values=tensor([3, 4, 5]),
       size=(2, 3), nnz=3, layout=torch.sparse_coo)
>>> s.to_dense()
tensor([[0, 0, 3],
        [4, 0, 5]])

torch.long是PyTorch中的一個數(shù)據(jù)類型,它表示64位整數(shù)類型腾仅。它在PyTorch中用于表示整數(shù)張量乒裆。

  • data.edge_attr: 形狀為[num_edges, num_edge_features] 的邊的特征矩陣
  • data.y: 訓(xùn)練目標(biāo)(可能具有任意形狀), e.g., node-level targets of shape [num_nodes, *] or graph-level targets of shape [1, *]
  • data.pos: 形狀為[num_nodes, num_dimensions] 的節(jié)點位置矩陣

注意:這些屬性都不是必需的,事實上推励,Data 對象甚至不限于這些屬性鹤耍。
以下展示了一個具有三個節(jié)點和四個邊的未加權(quán)無向圖的簡單示例,每個節(jié)點只包含一個特征:

import torch
from torch_geometric.data import Data
edge_index = torch.tensor([[0, 1, 1, 2],
                           [1, 0, 2, 1]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)
data = Data(x=x, edge_index=edge_index)
>>> Data(edge_index=[2, 4], x=[3, 1])


注意:edge_index,定義所有邊的源節(jié)點和目標(biāo)節(jié)點的張量不是索引元組的列表验辞。如果您想以這種方式編寫索引稿黄,則應(yīng)該在將它們傳遞給數(shù)據(jù)構(gòu)造函數(shù)之前轉(zhuǎn)置并調(diào)用連續(xù)的索引。

import torch
from torch_geometric.data import Data
edge_index = torch.tensor([[0, 1],
                           [1, 0],
                           [1, 2],
                           [2, 1]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)
data = Data(x=x, edge_index=edge_index.t().contiguous())
>>> Data(edge_index=[2, 4], x=[3, 1])

注意: 為了最終的數(shù)據(jù)表示盡可能緊湊跌造,edge_index 中的元素必須僅保存 { 0, ..., num_nodes - 1} 范圍內(nèi)的索引杆怕。例如,我們希望分別通過 x[0] 和 x[1] 索引第一條邊 (0, 1) 的源節(jié)點特征和目標(biāo)節(jié)點特征壳贪,可以通過運行validate()檢查最終的 Data 對象是否滿足這些要求财著。
除了擁有許多節(jié)點級、邊級或圖級屬性之外撑碴,數(shù)據(jù)還提供了許多有用的實用函數(shù),例如:

data.num_nodes
>>> 3
data.num_edges
>>> 4
data.num_node_features
>>> 1
data.has_isolated_nodes()
>>> False
data.has_self_loops()
>>> False
data.is_directed()
>>> False
……
#You can find a complete list of all methods at [`torch_geometric.data.Data`]

2撑教、通用基準數(shù)據(jù)集

PyG包含大量常見的基準數(shù)據(jù)集,例如小行星數(shù)據(jù)集、圖形分類數(shù)據(jù)集等等醉拓。初始化數(shù)據(jù)集很簡單伟姐,數(shù)據(jù)集的初始化將自動下載其原始文件并將其處理為前面描述的數(shù)據(jù)格式,例如酶數(shù)據(jù)集亿卤, (由 6 個類中的 600 個圖表組成):

from torch_geometric.datasets import TUDataset
datasets = TUDataset(root='/tmp/ENZYMES', name='ENZYMES')
datasets.num_classes
#6
datasets.num_node_features
#3
data = datasets[0]
data
>>> Data(edge_index=[2, 168], x=[37, 3], y=[1])
# 包含37 個節(jié)點,每一個含有3個特征愤兵;
# 有 168/2 = 84 條無向邊,并且該圖恰好分配給一類排吴;
# 此外秆乳,數(shù)據(jù)對象恰好持有一個圖級目標(biāo)。

可以使用切片、長張量或布爾張量來分割數(shù)據(jù)集屹堰,例如肛冶,要創(chuàng)建 90/10 的訓(xùn)練/測試分割,輸入:

train_dataset = dataset[:540]
>>> ENZYMES(540)
test_dataset = dataset[540:]
>>> ENZYMES(60)
# 如果不確定數(shù)據(jù)集在分割之前是否已經(jīng)打亂,可以使用shuffle
dataset = dataset.shuffle()
#注意這一句代碼和以下代碼的得到的結(jié)果一致
perm = torch.randperm(len(dataset))
dataset = dataset[perm]

3扯键、Mini-batches

神經(jīng)網(wǎng)絡(luò)通常以批量方式進行訓(xùn)練睦袖。PyG 通過創(chuàng)建稀疏塊對角鄰接矩陣(由 edge_index 定義)并在節(jié)點維度中連接特征和目標(biāo)矩陣,實現(xiàn)小批量的并行化荣刑。這種組合允許在一批示例中使用不同數(shù)量的節(jié)點和邊馅笙,


PyG 包含自己的 torch_geometric.loader.DataLoader,它已經(jīng)處理了這個串聯(lián)過程厉亏,以下是一個例子:

from torch_geometric.datasets import TUDataset
from torch_geometric.loader import DataLoader
dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES', use_node_attr=True)
loader = DataLoader(dataset, batch_size=32, shuffle=True)
for batch in loader:
    batch
 >>> DataBatch(batch=[1082], edge_index=[2, 4066], x=[1082, 21], y=[32])
    batch.num_graphs
 >>> 32

torch_geometric.data.Batch繼承自torch_geometric.data.Data并包含一個名為batch的附加屬性,batch是一個是一個列向量董习,將每個節(jié)點映射到batch中各自的圖。

4爱只、數(shù)據(jù)Transform

Transform是 torchvision 中變換圖像和執(zhí)行增強的常用方法阱飘。PyG 帶有自己的Transform,它期望一個 Data 對象作為輸入并返回一個新的轉(zhuǎn)換后的 Data 對象虱颗。Transforms can be chained together using [torch_geometric.transforms.Compose] and are applied before saving a processed dataset on disk (pre_transform) or before accessing a graph in a dataset (transform).

5、圖的學(xué)習(xí)方法

將使用一個簡單的 GCN 層并在 Cora 引文數(shù)據(jù)集上復(fù)制實驗

#首先需要加載 Cora 數(shù)據(jù)集
from torch_geometric.datasets import Planetoid
dataset = Planetoid(root='/tmp/Cora', name='Cora')
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
#其中包含了2個GCNConv層(圖卷積層)和一個前向傳播方法蔗喂。
class GCN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        #它接收圖的節(jié)點特征數(shù)作為輸入維度
        self.conv1 = GCNConv(dataset.num_node_features, 16)
        #它的輸入維度為16(與第一層的輸出維度相匹配)忘渔,輸出維度為圖的類別數(shù)(即標(biāo)簽的數(shù)量)。
        self.conv2 = GCNConv(16,dataset.num_classes)
    #在前向傳播方法forward中缰儿,輸入數(shù)據(jù)data包含了節(jié)點特征x和邊的索引edge_index
    def forward(self,data):
        x,edge_index = data.x,data.edge_index
        #首先畦粮,將節(jié)點特征x和邊的索引edge_index作為輸入傳遞給第一個GCNConv層self.conv1進行圖卷積操作
        x= self.conv1(x,edge_index)
        #ReLU激活函數(shù)對輸出進行非線性變換
        x = F.relu(x)
        #應(yīng)用dropout操作以防止過擬合
        x= F.dropout(x,training=self.training)
        #將結(jié)果輸入到第二個GCNConv層self.conv2進行最終的圖卷積操作
        x = self.conv2(x,edge_index)
        #對輸出結(jié)果應(yīng)用log_softmax函數(shù),以便進行多類別分類問題的概率計算乖阵。最終宣赔,返回概率化的輸出結(jié)果。
        return F.log_softmax(x,dim=1)

###########################################################
 # 20次訓(xùn)練
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
#創(chuàng)建了一個GCN模型實例model瞪浸,并將其移動到之前確定的設(shè)備上                  
model  = GCN().to(device)
data = dataset[0].to(device)
#Data(x=[2708, 1433], edge_index=[2, 10556], y=[2708], train_mask=[2708], val_mask=[2708], test_mask=[2708])
#定義了一個Adam優(yōu)化器儒将,將模型的參數(shù)作為優(yōu)化器的參數(shù),并設(shè)置學(xué)習(xí)率和權(quán)重衰減
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
model.train()
for epoch in range(200):
    #首先將優(yōu)化器的梯度緩存清零
    optimizer.zero_grad()
    #模型前向傳播得到輸出結(jié)果out
    out = model(data)
    #計算損失函數(shù)对蒲,這里使用了負對數(shù)似然損失函數(shù)(negative log likelihood loss)
    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
    #根據(jù)損失函數(shù)的梯度進行反向傳播并更新模型的參數(shù)
    loss.backward()
    optimizer.step()  
############################################################
#最后钩蚊,我們可以在測試節(jié)點上評估我們的模型
#將模型設(shè)置為評估模式,確保在模型中的一些特定層(如dropout)在評估時不會進行隨機丟棄操作,以保持一致的輸出蹈矮。
model.eval()
#通過模型對數(shù)據(jù)進行前向傳播砰逻,得到預(yù)測結(jié)果pred。使用argmax(dim=1)將預(yù)測結(jié)果轉(zhuǎn)換為每個樣本的類別標(biāo)簽
pred = model(data).argmax(dim=1)
#計算在測試集上的預(yù)測準確率泛鸟。首先蝠咆,通過使用索引掩碼data.test_mask從預(yù)測結(jié)果pred和標(biāo)簽數(shù)據(jù)data.y中提取出測試集的部分。然后,將預(yù)測正確的樣本數(shù)進行求和計算刚操。
correct = (pred[data.test_mask] == data.y[data.test_mask]).sum()
#將預(yù)測正確的樣本數(shù)除以測試集樣本的總數(shù)
acc = int(correct) / int(data.test_mask.sum())
print(f'Accuracy: {acc:.4f}')
>>> Accuracy: 0.8150(可能會不同)

參考網(wǎng)址:https://pytorch-geometric.readthedocs.io/en/latest/index.html
備注:以上內(nèi)容如有錯誤,請聯(lián)系作者闸翅。著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市赡茸,隨后出現(xiàn)的幾起案子缎脾,更是在濱河造成了極大的恐慌,老刑警劉巖占卧,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遗菠,死亡現(xiàn)場離奇詭異,居然都是意外死亡华蜒,警方通過查閱死者的電腦和手機辙纬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叭喜,“玉大人贺拣,你說我怎么就攤上這事∥嬖蹋” “怎么了譬涡?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長啥辨。 經(jīng)常有香客問我涡匀,道長,這世上最難降的妖魔是什么溉知? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任陨瘩,我火速辦了婚禮,結(jié)果婚禮上级乍,老公的妹妹穿的比我還像新娘舌劳。我一直安慰自己,他們只是感情好玫荣,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布甚淡。 她就那樣靜靜地躺著,像睡著了一般捅厂。 火紅的嫁衣襯著肌膚如雪材诽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天恒傻,我揣著相機與錄音脸侥,去河邊找鬼。 笑死盈厘,一個胖子當(dāng)著我的面吹牛睁枕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼外遇,長吁一口氣:“原來是場噩夢啊……” “哼注簿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起跳仿,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤诡渴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后菲语,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妄辩,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年山上,在試婚紗的時候發(fā)現(xiàn)自己被綠了眼耀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡佩憾,死狀恐怖哮伟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妄帘,我是刑警寧澤楞黄,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站抡驼,受9級特大地震影響鬼廓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜婶恼,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柏副。 院中可真熱鬧勾邦,春花似錦、人聲如沸割择。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荔泳。三九已至蕉饼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間玛歌,已是汗流浹背昧港。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留支子,地道東北人创肥。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親叹侄。 傳聞我的和親對象是個殘疾皇子巩搏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容