Tutorial PyTorch Geometric: Graph Neural Network dengan PyTorch

# Memulai dengan PyTorch Geometric: Graph Neural Network di PyTorch Sebagian besar machine learning bekerja pada grid (gambar) atau urutan (teks), tetapi banyak data dunia nyata secara alami berbentu...

By Ruby Abdullah · · tutorial
PyTorch GeometricGraph Neural NetworksGNNDeep LearningPyTorchPython

Memulai dengan PyTorch Geometric: Graph Neural Network di PyTorch

Sebagian besar machine learning bekerja pada grid (gambar) atau urutan (teks), tetapi banyak data dunia nyata secara alami berbentuk graf: orang terhubung dengan teman, atom terikat menjadi molekul, transaksi menghubungkan akun. PyTorch Geometric (PyG) adalah pustaka di atas PyTorch yang membuat pelatihan neural network langsung pada data terhubung semacam ini menjadi praktis. Tutorial ini mengasumsikan Anda sudah nyaman dengan PyTorch dasar (tensor, nn.Module, training loop) tetapi belum pernah bekerja dengan graph neural network.

Apa Itu Graph Machine Learning?

Sebuah graf adalah kumpulan node (disebut juga simpul) yang dihubungkan oleh edge (sisi). Baik node maupun edge dapat membawa fitur. Struktur graf itu sendiri — siapa terhubung dengan siapa — membawa informasi yang akan diabaikan oleh jaringan feed-forward biasa jika semuanya diratakan menjadi sebuah tabel.

Graph machine learning muncul di banyak skenario produksi:

  • Graf sosial dan rekomendasi. Pengguna, item, dan interaksinya membentuk graf. Memprediksi item yang akan diklik pengguna adalah masalah link prediction; mengklasifikasikan pengguna sebagai bot adalah node classification.
  • Molekul dan material. Atom adalah node, ikatan kimia adalah edge. Memprediksi kelarutan atau toksisitas molekul adalah tugas regresi atau klasifikasi pada level graf.
  • Fraud dan risiko. Akun, perangkat, dan transaksi membentuk graf. Komplotan fraud (fraud ring) adalah subgraf padat yang hampir tidak terlihat jika setiap transaksi dinilai secara terpisah.
  • Knowledge graph. Entitas dan relasi bertipe (misalnya "Jakarta — ibukotadari — Indonesia") mendukung penalaran dan pencarian. Ini biasanya berupa graf heterogen dengan banyak tipe node dan edge.

Benang merahnya adalah prediksi tentang satu elemen bergantung pada tetangganya, bukan hanya fiturnya sendiri.

Intuisi: Message Passing

Hampir semua GNN modern adalah bentuk dari message passing (kadang disebut neighborhood aggregation atau graph convolution). Idenya sederhana dan diulang melalui beberapa layer:

  • Setiap node melihat tetangga-tetangganya.
  • Node mengumpulkan ("agregasi") vektor fitur tetangga — misalnya dengan menjumlahkan atau merata-ratakannya.
  • Node menggabungkan pesan teragregasi dengan fiturnya sendiri saat ini untuk menghasilkan representasi yang diperbarui.
  • Setelah satu layer, representasi setiap node mencerminkan tetangga langsungnya. Setelah dua layer, representasinya mencerminkan tetangga-dari-tetangga, dan seterusnya. Menumpuk k layer membuat informasi mengalir melintasi tetangga sejauh k-hop.

    Secara formal, sebuah layer message passing generik memperbarui node i sebagai:

    hi' = UPDATE( hi , AGGREGATE( { MESSAGE(hi, hj, eij) : j in N(i) } ) )
    

    di mana N(i) adalah tetangga dari i, dan MESSAGE, AGGREGATE, serta UPDATE adalah bagian yang didefinisikan berbeda oleh setiap varian GNN. Graph Convolutional Network (GCN) memakai penjumlahan ternormalisasi, GraphSAGE melakukan sampling dan konkatenasi, dan Graph Attention Network (GAT) mempelajari bobot untuk setiap tetangga. Kita akan segera melihatnya.

    Instalasi

    PyG berjalan di atas PyTorch, jadi pasang dulu build PyTorch yang sesuai. Untuk pengaturan CPU saja, dasarnya adalah:

    pip install torch
    

    pip install torchgeometric

    Untuk sebagian besar tutorial level node dan graf, ini sudah cukup — versi PyG terbaru mengimplementasikan operasi inti dalam PyTorch murni.

    PyG juga menyediakan wheel ekstensi terkompilasi opsional (pyglib, torchscatter, torchsparse, torchcluster, torchsplineconv). Wheel ini mempercepat operasi scatter/gather dan sparse, serta diperlukan untuk beberapa fitur lanjutan (sampler dan rutin cluster tertentu). Wheel tersebut harus cocok dengan versi PyTorch sekaligus build CUDA Anda, jadi pasang dari indeks wheel PyG, bukan dari PyPI:

    # Ganti 2.4.0 dan cu121 dengan versi torch dan tag CUDA Anda sendiri.
    

    Gunakan cpu sebagai pengganti cu121 untuk mesin CPU saja.

    pip install pyglib torchscatter torchsparse torchcluster torchsplineconv \

    -f https://data.pyg.org/whl/torch-2.4.0+cu121.html

    Untuk menemukan tag yang tepat, periksa versi yang terpasang:

    import torch
    

    print(torch.version) # mis. 2.4.0

    print(torch.version.cuda) # mis. 12.1, atau None untuk CPU

    Ketidakcocokan versi antara wheel ini dan build PyTorch Anda adalah masalah instalasi yang paling sering terjadi, jadi pastikan tag-nya benar sebelum memasang.

    Objek Data: Satu Graf di Memori

    Satu graf di PyG adalah objek torchgeometric.data.Data. Atribut terpentingnya adalah:

    • x: matriks fitur node berbentuk [numnodes, numnodefeatures].
    • edgeindex: konektivitas dalam format COO, berbentuk [2, numedges]. Kolom k berarti "ada edge dari edgeindex[0, k] ke edgeindex[1, k]."
    • edgeattr: matriks fitur edge opsional, berbentuk [numedges, numedgefeatures].
    • y: target — satu label per node, atau satu label untuk seluruh graf.
    • mask (trainmask, valmask, testmask): vektor boolean yang menandai node mana yang termasuk ke setiap split.

    Mari kita bangun graf kecil tak berarah dengan tiga node secara manual. Karena PyG memperlakukan edge sebagai berarah, sebuah edge tak berarah antara 0 dan 1 disimpan sebagai dua kolom: 0->1 dan 1->0.

    import torch
    

    from torchgeometric.data import Data

    Tiga node, masing-masing dengan vektor fitur berdimensi 2.

    x = torch.tensor([[1.0, 0.0],

    [0.0, 1.0],

    [1.0, 1.0]], dtype=torch.float)

    Edge tak berarah 0-1 dan 1-2, masing-masing dicantumkan dua arah.

    edgeindex = torch.tensor([[0, 1, 1, 2],

    [1, 0, 2, 1]], dtype=torch.long)

    Satu label kelas per node.

    y = torch.tensor([0, 1, 0], dtype=torch.long)

    data = Data(x=x, edgeindex=edgeindex, y=y)

    print(data)

    print("Node:", data.numnodes, "Edge:", data.numedges)

    print("Ada node terisolasi:", data.hasisolatednodes())

    Tensor edgeindex harus menggunakan torch.long, dan indeksnya harus berupa id node yang valid. PyG menyediakan data.validate() untuk menangkap kesalahan umum lebih awal.

    Dataset Bawaan

    PyG menyertakan banyak dataset benchmark standar sehingga Anda dapat fokus pada pemodelan, bukan pengolahan data.

    Cora (melalui Planetoid) adalah jaringan sitasi: node adalah paper, edge adalah sitasi, dan tugasnya adalah mengklasifikasikan topik setiap paper. Ini adalah benchmark kanonis untuk node classification.
    from torchgeometric.datasets import Planetoid
    
    

    dataset = Planetoid(root="data/Cora", name="Cora")

    data = dataset[0] # satu graf besar tunggal

    print("Jumlah graf:", len(dataset))

    print("Fitur per node:", dataset.numnodefeatures)

    print("Jumlah kelas:", dataset.numclasses)

    print("Node train/val/test:",

    int(data.trainmask.sum()),

    int(data.valmask.sum()),

    int(data.testmask.sum()))

    TUDataset adalah kumpulan dataset graph-classification. Di sini setiap item adalah graf kecil terpisah (misalnya sebuah molekul) dengan satu label.
    from torchgeometric.datasets import TUDataset
    
    

    dataset = TUDataset(root="data/MUTAG", name="MUTAG")

    print("Jumlah graf:", len(dataset))

    print("Jumlah kelas:", dataset.numclasses)

    print("Graf pertama:", dataset[0])

    Mini-Batching Graf

    Untuk node classification pada Cora, seluruh graf muat di memori, jadi batching tidak diperlukan. Untuk graph classification Anda memiliki banyak graf kecil, dan Anda mem-batch-nya dengan DataLoader. PyG mem-batch dengan memperlakukan gabungan terpisah (disjoint union) beberapa graf sebagai satu graf besar; sebuah vektor batch mencatat dari graf asal mana setiap node berasal.

    from torchgeometric.loader import DataLoader
    
    

    loader = DataLoader(dataset, batchsize=32, shuffle=True)

    for batch in loader:

    print(batch) # sebuah objek Batch

    print("Graf dalam batch:", batch.numgraphs)

    print("Bentuk vektor batch:", batch.batch.shape) # [totalnodedalambatch]

    break

    Vektor batch.batch inilah yang memungkinkan pooling pada level graf: ia memberi tahu operator pooling node mana yang harus diagregasi bersama.

    Membangun GNN dengan GCNConv

    PyG menyediakan layer konvolusi sebagai nn.Module yang siap pakai. Yang paling umum:

    • GCNConv — Graph Convolutional Network; penjumlahan tetangga ternormalisasi simetris.
    • SAGEConv — GraphSAGE; mengagregasi tetangga (yang mungkin di-sampling) dan mengonkatenasinya dengan fitur node itu sendiri, sehingga skalanya baik.
    • GATConv — Graph Attention Network; mempelajari bobot attention per tetangga.
    • GINConv — Graph Isomorphism Network; secara teori sangat ekspresif, populer untuk tugas level graf.

    Sebuah GCN dua layer terlihat hampir seperti MLP biasa, kecuali setiap layer linear diganti dengan graph convolution yang juga menerima edgeindex.

    import torch.nn.functional as F
    

    from torch import nn

    from torchgeometric.nn import GCNConv

    class GCN(nn.Module):

    def init(self, inchannels, hiddenchannels, numclasses):

    super().init()

    self.conv1 = GCNConv(inchannels, hiddenchannels)

    self.conv2 = GCNConv(hiddenchannels, numclasses)

    def forward(self, x, edgeindex):

    x = self.conv1(x, edgeindex)

    x = F.relu(x)

    x = F.dropout(x, p=0.5, training=self.training)

    x = self.conv2(x, edgeindex)

    return x # logit mentah

    Tugas 1: Node Classification pada Cora

    Kita melatih GCN untuk memprediksi topik setiap paper, menghitung loss hanya pada node training dan melaporkan akurasi pada setiap split.

    import torch
    

    from torchgeometric.datasets import Planetoid

    device = torch.device("cuda" if torch.cuda.isavailable() else "cpu")

    dataset = Planetoid(root="data/Cora", name="Cora")

    data = dataset[0].to(device)

    model = GCN(dataset.numnodefeatures, 16, dataset.numclasses).to(device)

    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weightdecay=5e-4)

    def train():

    model.train()

    optimizer.zerograd()

    out = model(data.x, data.edgeindex)

    loss = F.crossentropy(out[data.trainmask], data.y[data.trainmask])

    loss.backward()

    optimizer.step()

    return float(loss)

    @torch.nograd()

    def evaluate():

    model.eval()

    logits = model(data.x, data.edgeindex)

    pred = logits.argmax(dim=1)

    accs = {}

    for name, mask in [("train", data.trainmask),

    ("val", data.valmask),

    ("test", data.testmask)]:

    correct = (pred[mask] == data.y[mask]).sum()

    accs[name] = float(correct) / int(mask.sum())

    return accs

    bestval = 0.0

    for epoch in range(1, 201):

    loss = train()

    accs = evaluate()

    if accs["val"] > bestval:

    bestval = accs["val"]

    if epoch % 20 == 0:

    print(f"Epoch {epoch:3d} | loss {loss:.4f} | "

    f"train {accs['train']:.3f} val {accs['val']:.3f} test {accs['test']:.3f}")

    GCN dua layer biasanya mencapai akurasi tes sekitar 80% pada Cora. Perhatikan weightdecay pada optimizer — graf sitasi kecil cepat overfit, jadi regularisasi penting.

    Tugas 2: Graph Classification pada TUDataset

    Di sini setiap graf memiliki satu label. Setelah message passing menghasilkan embedding node, kita meringkasnya menjadi satu embedding graf dengan global pooling, lalu menerapkan classifier. globalmeanpool menggunakan vektor batch untuk merata-ratakan embedding node dalam setiap graf.

    import torch
    

    from torch import nn

    import torch.nn.functional as F

    from torchgeometric.datasets import TUDataset

    from torchgeometric.loader import DataLoader

    from torchgeometric.nn import GCNConv, globalmeanpool

    dataset = TUDataset(root="data/MUTAG", name="MUTAG").shuffle()

    traindataset = dataset[:150]

    testdataset = dataset[150:]

    trainloader = DataLoader(traindataset, batchsize=32, shuffle=True)

    testloader = DataLoader(testdataset, batchsize=32)

    class GraphGCN(nn.Module):

    def init(self, inchannels, hidden, numclasses):

    super().init()

    self.conv1 = GCNConv(inchannels, hidden)

    self.conv2 = GCNConv(hidden, hidden)

    self.lin = nn.Linear(hidden, numclasses)

    def forward(self, x, edgeindex, batch):

    x = F.relu(self.conv1(x, edgeindex))

    x = F.relu(self.conv2(x, edgeindex))

    x = globalmeanpool(x, batch) # [numgraphs, hidden]

    x = F.dropout(x, p=0.5, training=self.training)

    return self.lin(x)

    device = torch.device("cuda" if torch.cuda.isavailable() else "cpu")

    model = GraphGCN(dataset.numnodefeatures, 64, dataset.numclasses).to(device)

    optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

    def trainepoch():

    model.train()

    total = 0.0

    for batch in trainloader:

    batch = batch.to(device)

    optimizer.zerograd()

    out = model(batch.x, batch.edgeindex, batch.batch)

    loss = F.crossentropy(out, batch.y)

    loss.backward()

    optimizer.step()

    total += float(loss) batch.numgraphs

    return total / len(trainloader.dataset)

    @torch.nograd()

    def test(loader):

    model.eval()

    correct = 0

    for batch in loader:

    batch = batch.to(device)

    pred = model(batch.x, batch.edgeindex, batch.batch).argmax(dim=1)

    correct += int((pred == batch.y).sum())

    return correct / len(loader.dataset)

    for epoch in range(1, 101):

    loss = trainepoch()

    if epoch % 10 == 0:

    print(f"Epoch {epoch:3d} | loss {loss:.4f} | "

    f"train {test(trainloader):.3f} | test {test(testloader):.3f}")

    MUTAG berukuran kecil, jadi hasilnya bervariasi antar-run; merata-ratakan beberapa split acak memberi estimasi yang lebih jujur.

    Link prediction bertanya: dengan edge yang ada, edge hilang mana yang kemungkinan nyata? Resep standarnya adalah encode lalu decode. Sebuah encoder GNN mengubah node menjadi embedding; decoder menilai kandidat edge (i, j) melalui dot product dari embedding keduanya. Karena sebagian besar pasangan node bukan edge, kita melatih dengan negative sampling — memasangkan setiap edge nyata dengan non-edge yang diambil secara acak.

    import torch
    

    import torch.nn.functional as F

    from torchgeometric.datasets import Planetoid

    from torchgeometric.nn import GCNConv

    from torchgeometric.utils import negativesampling

    from torchgeometric.transforms import RandomLinkSplit

    device = torch.device("cuda" if torch.cuda.isavailable() else "cpu")

    dataset = Planetoid(root="data/Cora", name="Cora")

    Bagi edge menjadi set message-passing, supervisi, dan evaluasi.

    transform = RandomLinkSplit(numval=0.05, numtest=0.1,

    isundirected=True, addnegativetrainsamples=False)

    traindata, valdata, testdata = transform(dataset[0])

    traindata = traindata.to(device)

    class Encoder(torch.nn.Module):

    def init(self, inchannels, hidden, outchannels):

    super().init()

    self.conv1 = GCNConv(inchannels, hidden)

    self.conv2 = GCNConv(hidden, outchannels)

    def forward(self, x, edgeindex):

    x = F.relu(self.conv1(x, edgeindex))

    return self.conv2(x, edgeindex)

    def decode(z, edgelabelindex):

    src, dst = edgelabelindex

    return (z[src] z[dst]).sum(dim=-1) # skor dot-product (logit)

    model = Encoder(dataset.numnodefeatures, 128, 64).to(device)

    optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

    def train():

    model.train()

    optimizer.zerograd()

    z = model(traindata.x, traindata.edgeindex)

    # Negative sample baru di setiap epoch.

    negedgeindex = negativesampling(

    edgeindex=traindata.edgeindex,

    numnodes=traindata.numnodes,

    numnegsamples=traindata.edgelabelindex.size(1))

    edgelabelindex = torch.cat(

    [traindata.edgelabelindex, negedgeindex], dim=1)

    edgelabel = torch.cat([

    traindata.edgelabel,

    traindata.edgelabel.newzeros(negedgeindex.size(1))], dim=0)

    out = decode(z, edgelabelindex)

    loss = F.binarycrossentropywithlogits(out, edgelabel)

    loss.backward()

    optimizer.step()

    return float(loss)

    @torch.nograd()

    def test(data):

    model.eval()

    z = model(traindata.x, traindata.edgeindex)

    out = decode(z, data.edgelabelindex).sigmoid()

    pred = (out > 0.5).float()

    return float((pred == data.edgelabel).float().mean())

    for epoch in range(1, 101):

    loss = train()

    if epoch % 20 == 0:

    print(f"Epoch {epoch:3d} | loss {loss:.4f} | "

    f"val acc {test(valdata.to(device)):.3f}")

    Untuk link prediction, akurasi adalah metrik yang lemah karena ketidakseimbangan kelas; AUC atau average precision (dari torchmetrics atau sklearn) adalah pilihan yang umum di praktik.

    Message Passing Kustom

    Ketika layer bawaan tidak sesuai kebutuhan Anda, turunkan (subclass) MessagePassing. Anda mengimplementasikan message (cara membangun pesan dari node sumber ke node target) dan opsional update, lalu memanggil self.propagate(...) yang menangani gather, agregasi terpilih, dan scatter kembali ke node target. Contoh di bawah mengimplementasikan ulang layer agregasi rata-rata sederhana.

    import torch
    

    from torch import nn

    from torchgeometric.nn import MessagePassing

    from torchgeometric.utils import addselfloops

    class MeanConv(MessagePassing):

    def init(self, inchannels, outchannels):

    super().init(aggr="mean") # agregasi mean bawaan

    self.lin = nn.Linear(inchannels, outchannels)

    def forward(self, x, edgeindex):

    edgeindex, = addselfloops(edgeindex, numnodes=x.size(0))

    x = self.lin(x)

    return self.propagate(edgeindex, x=x) # memicu message + aggregate

    def message(self, xj):

    # xj memuat fitur node sumber (tetangga) untuk setiap edge.

    return xj

    Akhiran j berarti "node sumber dari edge"; i berarti node target. aggr dapat berupa "mean", "sum", "max", atau modul Aggregation kustom. Pola ini mencakup sebagian besar varian GNN yang mungkin ingin Anda ciptakan.

    Graf Heterogen

    Banyak graf nyata memiliki beberapa tipe node dan edge — misalnya pengguna dan item yang dihubungkan oleh edge "membeli" dan "melihat". PyG memodelkan ini dengan HeteroData, yang menyimpan x terpisah per tipe node dan edgeindex terpisah per triple relasi (tipesumber, relasi, tipetarget).

    from torchgeometric.data import HeteroData
    
    

    data = HeteroData()

    data["user"].x = torch.randn(100, 16)

    data["item"].x = torch.randn(50, 32)

    data["user", "buys", "item"].edgeindex = torch.randint(0, 50, (2, 200))

    Alih-alih menulis layer spesifik tipe secara manual, Anda dapat membangun GNN homogen biasa dan mengonversinya otomatis dengan tohetero, yang mereplikasi message passing per relasi dan menjumlahkan antar-relasi ke setiap tipe node target.

    from torchgeometric.nn import SAGEConv, tohetero
    
    

    class HGNN(torch.nn.Module):

    def init(self, hidden, out):

    super().init()

    self.conv1 = SAGEConv((-1, -1), hidden) # -1 = inferensi dimensi input

    self.conv2 = SAGEConv((-1, -1), out)

    def forward(self, x, edgeindex):

    x = self.conv1(x, edgeindex).relu()

    return self.conv2(x, edgeindex)

    model = HGNN(hidden=64, out=8)

    model = tohetero(model, data.metadata(), aggr="sum")

    out = model(data.xdict, data.edgeindexdict)

    Menggunakan (-1, -1) dan inisialisasi malas (lazy) membuat model menginferensi dimensi input per tipe pada forward pass pertama.

    Menskalakan ke Graf Besar dengan Neighbor Sampling

    Pelatihan full-batch (contoh Cora) memuat seluruh graf di setiap langkah. Cara itu gagal pada graf dengan jutaan node. Sebagai gantinya, NeighborLoader melakukan sampling sejumlah tetangga tetap per hop di sekitar sekumpulan node target, menghasilkan subgraf yang cukup kecil untuk muat di memori GPU. Ini adalah strategi pelatihan GraphSAGE.

    from torchgeometric.loader import NeighborLoader
    
    

    loader = NeighborLoader(

    data,

    numneighbors=[15, 10], # 15 tetangga di hop 1, 10 di hop 2

    batchsize=128,

    inputnodes=data.trainmask,

    shuffle=True,

    )

    for subgraph in loader:

    # batchsize node pertama adalah node benih (target).

    print(subgraph)

    break

    Anda kemudian melatih pada setiap subgraf hasil sampling seolah-olah ia graf kecil yang utuh, menghitung loss hanya pada node benih. Memadukan NeighborLoader dengan SAGEConv adalah kombinasi yang telah teruji untuk node classification skala besar.

    Tips Praktis

    Over-smoothing. Menumpuk terlalu banyak layer message-passing membuat embedding setiap node konvergen ke nilai yang sama, sehingga akurasi turun. Sebagian besar graf bekerja paling baik dengan dua hingga empat layer. Jika butuh kedalaman, gunakan koneksi residual, konkatenasi jumping-knowledge, atau GCNConv dengan add
    selfloops. Normalisasi. Tambahkan BatchNorm atau LayerNorm di antara layer (torchgeometric.nn.BatchNorm sadar-graf). Ini menstabilkan pelatihan dan memungkinkan Anda sedikit lebih dalam. Self-loop dan arah. GCNConv menambahkan self-loop secara default agar node mempertahankan informasinya sendiri; periksa apakah layer lain melakukannya. Untuk graf berarah, putuskan secara sengaja apakah akan menambahkan edge balik — banyak tugas memperlakukan graf sebagai tak berarah. Evaluasi. Gunakan split resmi dataset bila tersedia. Untuk link prediction dan tugas node yang tidak seimbang, laporkan AUC atau average precision alih-alih akurasi. Rata-ratakan beberapa seed, karena graf kecil memiliki varians tinggi. Reproduksibilitas. Atur seed dengan torchgeometric.seedeverything(seed) dan ingat bahwa loader berbasis sampling memunculkan keacakan antar-run. Pemeriksaan kewajaran. Panggil data.validate(), pastikan edgeindex bertipe long dan dalam batas, serta periksa node terisolasi sebelum menyalahkan model atas hasil yang buruk.

    Kesimpulan dan Poin Penting

    • Graph machine learning berlaku ketika hubungan antar-titik data itu penting — jejaring sosial, molekul, komplotan fraud, knowledge graph.
    • Hampir setiap GNN adalah message passing: mengagregasi fitur tetangga, menggabungkannya dengan fitur node itu sendiri, dan mengulanginya antar-layer sehingga informasi mengalir melintasi tetangga multi-hop.
    • Objek Data menampung satu graf (x, edgeindex dalam COO, edgeattr, y, mask). HeteroData memperluasnya ke beberapa tipe node dan edge.
    • Dataset bawaan PyG (Planetoid, TUDataset) dan mini-batching DataLoader (vektor batch) memungkinkan Anda langsung memodelkan.
    • Tiga tugas inti — node classification, graph classification (dengan globalmean_pool), dan link prediction (encode/decode dengan negative sampling) — berbagi layer konvolusi yang sama seperti GCNConv, SAGEConv, GATConv, dan GINConv.
    • Untuk apa pun yang kustom, turunkan MessagePassing; untuk skala, gunakan NeighborLoader; dan waspadai over-smoothing dengan menjaga jaringan tetap dangkal dan menambahkan normalisasi.

    Dengan blok bangunan ini, Anda dapat beralih dari contoh mainan Cora ke graf produksi sambil menggunakan kembali pola yang sama.

    Artikel Terkait

    Tutorial Ray Train & Ray Tune: Training Terdistribusi dan Tuning Hyperparameter

    Ray Train & Ray Tune: Pelatihan Terdistribusi dan Penyetelan Hiperparameter Sebagian besar proyek machine learning dimul...

    Tutorial OpenCV + Deep Learning: Image Processing Modern dengan Python

    OpenCV + Deep Learning: Tutorial Komprehensif Daftar Isi Pendahuluan Prasyarat Dasar-Dasar Preprocessing Gambar [T...

    Tutorial Lengkap Hugging Face Transformers: NLP Modern dengan Python

    Tutorial Lengkap Hugging Face Transformers: Pretrained Models untuk NLP dan Vision Hugging Face Transformers adalah libr...

    Tutorial Lengkap Ultralytics: Object Detection dengan YOLO

    Tutorial Lengkap Ultralytics: Object Detection dengan YOLO Ultralytics adalah framework Python yang menyediakan implemen...