AI 趨勢洞察

圖神經網路(Graph Neural Networks, GNNs)完整入門指南

Home » AI 趨勢洞察 » 圖神經網路(Graph Neural Networks, GNNs)完整入門指南

導言:網路無所不在

想像一下你在瀏覽社群媒體動態。你的朋友分享了昨晚聚餐的照片,你看到照片裡有幾位共同好友。同時,應用程式也建議了幾個「你可能認識的人」,其中有些人看起來的確眼熟。之後,你使用地圖應用程式尋找最快回家的路線,避開交通壅塞。晚上,你收到電影推薦,結果竟然非常符合你的喜好。

這些經驗之間的連結是什麼?是網路——由無形關係網構成的世界。這些網路在數學上表現為「圖」(graphs),也是人工智慧最令人振奮領域之一:圖神經網路(GNNs)的基礎。

什麼是圖?連結式數據的骨幹

在電腦科學中,「圖」並不是長條圖或折線圖,而是一種用來表示關係的數學結構。

想像夜空中的星座:星星是「節點」(或稱「頂點」),將它們連接起來的想像線則是「邊」。由節點與邊所構成的簡單結構,足以表示無數真實世界中的系統。

真實世界中的圖例:

社群網路、分子結構以及道路網路只是圖在我們生活中隨處可見的幾個例子:

社群網路:你的社交圈就是圖的一個完美範例。每個人都是一個節點,而彼此的友誼關係則是將節點連接起來的邊。當 Facebook 建議「你可能認識的人」時,系統即是在分析這個圖結構,找出與你有共同連結但尚未直接連接的節點(人)。

交通系統: 城市是節點,道路、航線或鐵路則是邊。這些邊通常具有一些屬性,例如道路的長度、車流密度或速限。當你的 GPS 計算最快路線時,它其實正在解決一個圖的問題。

生物網路: 在人體中,蛋白質會與其他蛋白質作用,形成複雜的生物途徑。科學家使用圖來呈現這些關係,以瞭解疾病與開發治療方式。每個蛋白質都是一個節點,彼此互動的關係則形成邊。

網際網路: 網站是節點,超連結是邊。Google 最初的 PageRank 演算法就是透過分析這個龐大圖結構來為網頁排名。

知識圖: 維基百科的文章是節點,而連結則形成了邊。這些知識圖能協助組織人類資訊,也為許多 AI 助手提供支援。

神經網路:學習的機器

在探討圖神經網路之前,讓我們先瞭解一般的神經網路。

想像你正在教一個孩子辨識水果。一開始,他們會分別觀察顏色、形狀與大小。隨著練習,他們逐漸學會哪些特徵的組合能區分蘋果與橘子,也就養成了一種不需明確規則的直覺理解。

神經網路的學習方式與此類似:

輸入層: 接收原始資料(例如影像的像素值)。

隱藏層: 以愈來愈抽象的方式轉化並組合資訊。

輸出層: 產生最後的預測或分類結果。

「學習」的過程在於調整神經元之間連結的強度。這些連結最初是隨機的,之後會透過大量範例逐漸改變,強化能導向正確答案的連結,並削弱那些導致錯誤的連結。

舉例來說,神經網路在學習辨識貓的過程中,可能會形成偵測貓鬍鬚、尖耳朵或毛皮花紋的神經元——並不是因為我們告訴它要找這些特徵,而是它在學習過程中發現這些特徵對於完成任務很有幫助。

圖之挑戰:傳統神經網路為何難以應對

傳統神經網路非常擅長處理結構良好的資料,如影像(像素網格)或文字(單詞序列)。然而,圖卻帶來了獨特的挑戰:

可變的大小與結構: 社群網路可能包含數百萬使用者,且擁有複雜的連結模式。一個分子可能只有幾個原子,也可能上千個;但傳統神經網路通常假設輸入的大小是固定的。

沒有自然順序:在影像中,像素可自左上到右下有固定的順序;文字有從頭到尾的排列。但圖中的節點並沒有內建的順序。

關係資訊: 在圖中,連結本身通常比各個節點更重要。你認識誰,往往比你個人的細節更能揭示你的資訊。

以推薦系統為例,重點不只是你看過哪些電影(節點屬性),更重要的是相似觀眾間的偏好模式(圖結構)。傳統神經網路難以有效利用這些關鍵的關係資訊。

圖神經網路登場:從關係中學習

圖神經網路(GNNs)是一種專門針對圖結構資料設計的神經網路,它能將關係資訊納入學習過程

想像你參加一場雞尾酒派對,每個人一開始都擁有自己的一些資訊。在整個夜晚中,人們會與身邊的人交談,分享並收集資訊。到夜晚結束時,你所得到的認知已不只來自你直接對話的人,而是透過整個房間的訊息傳遞所累積的成果。

這基本上就是 GNNs 的運作方式。

訊息傳遞框架:GNNs 如何學習

大部分 GNNs 的核心機制稱為「訊息傳遞」,它包含以下幾個階段:

1. 節點初始化

每個節點都從一些初始特徵開始。這些特徵可能是:

  • 社群網路中個人的資料資訊
  • 分子中原子的化學性質
  • 路口的交通狀況
  • 推薦系統中使用者或產品的特徵

例如,在電影推薦的圖中,「使用者」節點可能包含人口統計資訊,而「電影」節點可能包含類型與上映年份等資訊。

2. 訊息建立與交換

節點會依據當前資訊建立「訊息」,並將它們傳送給相鄰節點。

想像一個犯罪調查板,上面有嫌疑人的照片,並用線連結代表彼此之間的關係。每位嫌疑人(節點)都有初始資訊(不在場證明、動機等)。在訊息傳遞過程中,嫌疑人會將自己的資訊「告訴」與其相連的嫌疑人,可能進而揭露「所有這些嫌疑人都曾在同一地點」的模式。

在交通網路中,一個路口可能將自身的壅塞程度「告訴」相鄰的路口,讓整體網路能逐漸掌握交通流動的模式。

3. 聚合

每個節點會收集來自相鄰節點的訊息並加以整合。由於圖節點並沒有固定的順序,因此這種聚合必須與順序無關,常見做法是透過加總、平均或取最大值等方式。

在派對的比喻中,這就像你在腦海中統整所有交談內容,擷取關鍵見解,而不是逐字記住所有對話。

在社群網路中,這可能是使用者節點從所有朋友節點收集資訊,進而理解這些朋友彼此之間的興趣或行為模式。

4. 更新

每個節點會依據當前狀態與聚合後的訊息來更新其表徵。

在派對的比喻中,這就好比你根據新得到的資訊來更新你對事物的理解。

在蛋白質交互作用網路中,一個蛋白質節點可能會更新它的表徵,不只顯示它本身的性質,也包含它與鄰近蛋白質的互動方式,進而揭示它在生物過程中的功能角色。

5. 重複

將步驟 2-4 重複多次,使資訊能在整個圖中傳遞。在每一輪結束後,節點就能獲取更廣範圍的鄰居資訊。

第一輪後,節點只能掌握直接相鄰的節點資訊;第二輪後,能掌握鄰居的鄰居;經過 K 輪後,理論上就能收到距離自己 K 步之內所有節點的資訊。

在科學論文的引文網路中,這讓一篇論文不僅能整合它直接引用的論文資訊,也能運用該領域更廣泛的研究基礎。

import torch
import torch.nn as nn
import torch.nn.functional as F
# Ensure you have torch_geometric installed: pip install torch_geometric
try:
    from torch_geometric.nn import GCNConv
    from torch_geometric.datasets import Planetoid
    from torch_geometric.transforms import NormalizeFeatures
except ImportError:
    print("PyTorch Geometric not found. Please install it: pip install torch_geometric")
    # You might also need to install dependencies based on your PyTorch+CUDA version
    # See: https://pytorch-geometric.readthedocs.io/en/latest/install/installation.html
    exit()

# --- 1. Load Dataset ---
try:
    # Load a standard citation network dataset (Cora)
    # NormalizeFeatures standardizes node features to have zero mean and unit variance
    dataset = Planetoid(root='./data/Cora', name='Cora', transform=NormalizeFeatures())
    data = dataset[0]  # Get the single graph object from the dataset
except Exception as e:
    print(f"Error loading dataset: {e}")
    print("Please ensure the dataset can be downloaded or accessed.")
    exit()

# --- 2. Print Dataset Information ---
print(f'Dataset: {dataset}:')
print('===================')
print(f'Number of graphs: {len(dataset)}')
print(f'Number of nodes: {data.num_nodes}') # Use data.num_nodes
print(f'Number of node features: {dataset.num_node_features}') # Use dataset.num_node_features
print(f'Number of edge features: {dataset.num_edge_features}') # Use dataset.num_edge_features (usually 0 for Cora)
print(f'Number of classes: {dataset.num_classes}')
print(f'Number of edges: {data.num_edges}') # Use data.num_edges
print(f'Training nodes: {data.train_mask.sum().item()}') # Show count of training nodes
print(f'Validation nodes: {data.val_mask.sum().item()}')   # Show count of validation nodes
print(f'Test nodes: {data.test_mask.sum().item()}')     # Show count of test nodes
print(f'Graph has isolated nodes: {data.has_isolated_nodes()}')
print(f'Graph has self-loops: {data.has_self_loops()}')
print(f'Graph is undirected: {data.is_undirected()}')
print('=============================================================')

# --- 3. Define the GCN Model ---
class GCN(nn.Module):
    """
    A simple two-layer Graph Convolutional Network.
    """
    def __init__(self, in_channels, hidden_channels, out_channels):
        super(GCN, self).__init__()
        torch.manual_seed(12345) # for reproducibility
        # First Graph Convolutional layer: maps node features to hidden dimensions
        self.conv1 = GCNConv(in_channels, hidden_channels)
        # Second Graph Convolutional layer: maps hidden dimensions to output classes
        self.conv2 = GCNConv(hidden_channels, out_channels)

    def forward(self, x, edge_index):
        """
        Defines the forward pass of the GCN.
        Args:
            x (Tensor): Node feature matrix [num_nodes, in_channels]
            edge_index (LongTensor): Graph connectivity in COO format [2, num_edges]
        Returns:
            Tensor: Log-softmax probabilities for each node [num_nodes, out_channels]
        """
        # --- Layer 1 ---
        # Apply graph convolution
        x = self.conv1(x, edge_index)
        # Apply ReLU activation function
        x = F.relu(x)
        # Apply dropout for regularization (only during training)
        x = F.dropout(x, p=0.5, training=self.training)

        # --- Layer 2 ---
        # Apply second graph convolution
        x = self.conv2(x, edge_index)

        # --- Output ---
        # Apply log_softmax for classification (works well with NLLLoss)
        return F.log_softmax(x, dim=1)

# --- 4. Initialize Model and Optimizer ---
model = GCN(in_channels=dataset.num_node_features,
            hidden_channels=16, # A common choice for hidden layer size
            out_channels=dataset.num_classes)

print("nModel Architecture:")
print(model)
print('=============================================================')

# Optimizer: Adam is a popular choice
# weight_decay adds L2 regularization
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

# --- 5. Training Function ---
def train():
    """
    Performs a single training step.
    """
    model.train() # Set model to training mode (enables dropout)
    optimizer.zero_grad() # Clear gradients from previous iteration

    # Perform forward pass
    out = model(data.x, data.edge_index)

    # Calculate loss using Negative Log Likelihood Loss
    # Only calculate loss on the nodes in the training set (using train_mask)
    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])

    # Perform backward pass: compute gradients
    loss.backward()

    # Update model parameters
    optimizer.step()

    return loss.item() # Return the loss value for this step

# --- 6. Testing Function ---
def test(mask):
    """
    Evaluates the model on a given node mask (train, val, or test).
    Args:
        mask (BoolTensor): Mask indicating which nodes to evaluate.
    Returns:
        float: Accuracy on the specified node set.
    """
    model.eval() # Set model to evaluation mode (disables dropout)
    with torch.no_grad(): # Disable gradient calculation for efficiency
        out = model(data.x, data.edge_index)
        # Get predictions by finding the class with the highest log-probability
        pred = out.argmax(dim=1)
        # Compare predictions with true labels for the nodes in the mask
        correct = pred[mask] == data.y[mask]
        # Calculate accuracy
        acc = int(correct.sum()) / int(mask.sum())
    return acc

# --- 7. Training Loop ---
print("Starting training...")
for epoch in range(1, 201):
    loss = train()
    if epoch % 10 == 0:
        # Evaluate on training, validation, and test sets
        train_acc = test(data.train_mask)
        val_acc = test(data.val_mask) # Also test on validation set
        test_acc = test(data.test_mask)
        print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}, Train Acc: {train_acc:.4f}, Val Acc: {val_acc:.4f}, Test Acc: {test_acc:.4f}')
print("Training finished.")
print('=============================================================')

# --- 8. Final Evaluation ---
final_train_acc = test(data.train_mask)
final_val_acc = test(data.val_mask)
final_test_acc = test(data.test_mask)
print(f'Final Train Accuracy: {final_train_acc:.4f}')
print(f'Final Validation Accuracy: {final_val_acc:.4f}')
print(f'Final Test Accuracy: {final_test_acc:.4f}')
print('=============================================================')

# --- 9. Examine Node Embeddings (Optional) ---
print("nExamining node embeddings...")
model.eval() # Ensure model is in eval mode
with torch.no_grad():
    # --- Get embeddings after the first layer (before dropout and second layer) ---
    # Re-run the first part of the forward pass to get intermediate embeddings
    hidden_embeddings = model.conv1(data.x, data.edge_index)
    hidden_embeddings = F.relu(hidden_embeddings) # Apply activation

    print(f"nShape of hidden embeddings: {hidden_embeddings.shape}") # [num_nodes, hidden_channels]

    # Look at the embedding of the first few nodes
    print("nSample node embeddings after first GCN layer + ReLU:")
    print(hidden_embeddings[:3])

    # --- Analyze similarity between connected nodes ---
    if data.num_edges > 0:
        # Find a pair of connected nodes (using the first edge in the list)
        edge_index_sample = data.edge_index[:, 0]  # Take the first edge [source_node, target_node]
        node1_idx = edge_index_sample[0].item()
        node2_idx = edge_index_sample[1].item()

        print(f"nComparing embeddings for connected nodes {node1_idx} and {node2_idx}:")

        # Get their embeddings from the hidden layer
        emb1 = hidden_embeddings[node1_idx]
        emb2 = hidden_embeddings[node2_idx]

        # Calculate Cosine Similarity
        # unsqueeze(0) adds a batch dimension, required by cosine_similarity
        similarity = F.cosine_similarity(emb1.unsqueeze(0), emb2.unsqueeze(0))

        print(f"Embedding Node {node1_idx}: {emb1.numpy().round(2)}") # Print rounded numpy array
        print(f"Embedding Node {node2_idx}: {emb2.numpy().round(2)}")
        print(f"Cosine similarity: {similarity.item():.4f}")

        # --- Analyze similarity between potentially unconnected nodes (Optional) ---
        # Find two nodes that are likely not connected (e.g., node 0 and node 100)
        if data.num_nodes > 100:
             node3_idx = 0
             node4_idx = 100
             print(f"nComparing embeddings for potentially unconnected nodes {node3_idx} and {node4_idx}:")
             emb3 = hidden_embeddings[node3_idx]
             emb4 = hidden_embeddings[node4_idx]
             similarity_unconnected = F.cosine_similarity(emb3.unsqueeze(0), emb4.unsqueeze(0))
             print(f"Embedding Node {node3_idx}: {emb3.numpy().round(2)}")
             print(f"Embedding Node {node4_idx}: {emb4.numpy().round(2)}")
             print(f"Cosine similarity: {similarity_unconnected.item():.4f}")

    else:
        print("nGraph has no edges, cannot compare connected node embeddings.")

print("nAnalysis complete.")

GNN 架構:針對不同任務的各種形式

如同傳統神經網路有多種形式(例如影像的 CNNs、序列的 RNNs),GNN 也有不同的架構:

圖卷積網路(GCNs): 類似於用於影像的 CNNs,GCN 會對圖資料應用卷積運算,特別適用於節點分類任務,例如在引文網路中判斷一篇科學論文屬於哪一類別。

圖注意力網路(GATs): 讓節點能夠對其鄰居節點分配不同程度的「注意力」。在社群網路中,你可能比起一般認識的人,更在意親密朋友的狀況。GATs 則能自動學習這些注意力權重。

GraphSAGE: 這種架構會抽樣固定數量的鄰居,藉此在面對超大型圖時維持運算效率。就像你會集中注意力在最相關的聯絡人身上,而不是嘗試追蹤你認識的所有人一樣。

圖自編碼器(Graph Autoencoders): 透過學習壓縮式的圖表徵來應用於連結預測(例如判斷兩個使用者是否會成為朋友)或社群偵測等任務。

實際應用:GNNs 的現實運用

藥物研發

製藥產業在藥物研發上投資了鉅額資金,但大部分候選藥物在臨床試驗階段都會失敗。GNNs 正在革新這個過程:

分子性質預測: 分子天生就能以圖形式表示(原子是節點、化學鍵是邊)。GNNs 可以用來預測溶解度或毒性等性質,而無需昂貴的實驗。Atomwise 與 DeepChem 等公司運用 GNNs 快速篩選數百萬潛在藥物化合物。

蛋白質結構預測: 理解蛋白質如何折疊能幫助科學家設計可與其作用的藥物。DeepMind 的 AlphaFold 2 雖不純粹是 GNN,但融入了基於圖的推理,在蛋白質結構預測上取得突破性成果。

以 COVID-19 的治療藥物開發為例,研究人員可以運用 GNNs 來找出可能與病毒關鍵蛋白質結合的分子,大幅縮小需要在實驗室中測試的候選名單。

社群網路分析

好友推薦: 當 LinkedIn 或 Facebook 建議你新增聯絡人時,常常使用的是基於圖的演算法。GNNs 能夠捕捉細微的模式——也許你更傾向與在特定規模公司工作的同行業人士建立連結。

假帳號偵測: 透過分析連結與互動模式,GNNs 能分辨可疑的帳號。一般使用者通常會隨時間有機成長地累積連結,但假帳號的連結模式常常非常特殊。

資訊擴散: 在公共衛生危機期間,瞭解資訊(與錯誤資訊)如何傳播至關重要。GNNs 能模擬這些擴散過程,協助平台識別並限制有害內容的傳播。

例如,在 COVID-19 大流行期間,GNNs 可以分析疫苗資訊在不同社群中的傳播方式,找出關鍵影響者與潛在的資訊落差。

交通預測與優化

交通預測: 洛杉磯、北京等城市使用基於 GNN 的系統來預測交通狀況。每個路段都被視為節點,具有當前車速、時間與天氣等特徵。GNN 能學習道路網路中不同區域之間的複雜依存關係。

共乘服務優化: Uber 與 Lyft 等公司使用基於圖的模型,以更有效率地為乘客與司機配對。GNNs 能協助預測整個城市的需求,並考量各種事件、天氣與歷史趨勢。

想像有一個系統能根據即時交通變化重新規劃配送車輛的路線,或依據預測的乘客流量來調整大眾運輸班次。

詐騙偵測

金融詐騙: 銀行利用 GNNs 來偵測可疑的交易模式。透過將使用者與交易表示為圖,許多不尋常的模式會變得更明顯,例如以循環方式轉帳的帳戶群組,或是異常集中的交易群。

保險詐騙: 保險理賠往往牽涉到個人、醫療機構與服務提供者之間的網路。GNNs 能偵測可疑的模式,例如經常申報不尋常醫療組合的機構,或有可疑關係的申請人群組。

舉例而言,GNN 可能會標示出一個可疑模式:數起車禍都涉及相同的一小群目擊者、駕駛以及維修廠——若只看單筆理賠申請,很可能會忽略這樣的詐騙集團。

推薦系統

電商推薦: Amazon 的「購買此商品的顧客也買了…」功能可以透過 GNNs 進一步強化,捕捉產品與消費者行為之間更複雜的關係。

內容推薦: Netflix 與 Spotify 等串流服務會構建豐富的圖結構,連結使用者、內容、藝術家、類型以及觀看/收聽記錄等。GNNs 能找出細微的偏好——或許你偏好科幻電影,但特別喜歡有強大女性角色且具哲學思維的作品。

跨領域推薦: GNNs 在整合不同種類項目的資訊方面表現優異。即使沒有使用者的跨領域反饋,系統也可能發現喜歡某些 podcast 的使用者也很可能喜歡特定書籍的關聯性。

想像一個串流平台發現你在週末傾向觀看科幻影集,而在平日晚間則喜歡看紀錄片,並依此調整推薦內容——不只知道你喜歡什麼,也知道你在什麼時候喜歡什麼。

最短路徑的突破:通用問題的解決方式

近期,AI 研究人員在神經網路領域取得重大進展,開發出能在各種不同規模的圖上解最短路徑問題的圖神經網路(GNNs)。這項突破對「演算法對齊」而言至關重要,展示了 AI 能學習以類似傳統演算法的方式進行系統化推理,而不僅只依賴模式辨識。

之所以令人驚豔,是因為:

傳統演算法 vs. 學習: 最短路徑問題早已有像 Dijkstra 或 Bellman-Ford 這樣的高效演算法。然而,研究人員證明 GNN 可以透過範例有效學習並實現 Bellman-Ford 演算法,而無需明確編程。

規模泛化: 大多數神經網路在面對比其訓練範例大很多的輸入時都會失效,這就像一個學生只能做兩位數乘法,卻無法處理五位數乘法。然而,研究人員的 GNN 能從小型圖學習,然後在任意大型的圖上解最短路徑問題。

演算法對齊: 其中的關鍵概念是「演算法對齊」——透過對 GNN 的結構進行設計,使其能自然地表達 Bellman-Ford 演算法的運作原理,再結合稀疏化正則化(鼓勵大部分權重為零),就能迫使網路「發現」這個真正的演算法。

這就好比你只用幾條街的小鎮教某人導航原理,卻發現他能完美掌握世界上任何一座城市的路線——即使是從未見過的超大型都市。這正是研究人員所取得的成果。

實務考量:使用 GNNs

如果你考慮在專案中使用 GNNs,以下是一些實務上的考量:

資料表示方式: 你會如何將問題表示為圖?節點、邊,以及它們的特徵是什麼?這些基本決策會影響之後的一切。

運算資源: 在大型圖上使用 GNNs 可能需要大量運算資源。鄰居抽樣或以叢集為基礎的方法能協助降低這方面的負擔。

特徵工程: 儘管 GNNs 會從圖結構中學習,提供更具資訊性的節點與邊特徵,仍能大幅提升效能。

評估方式: 你會如何衡量成效?使用節點分類的準確率、連結預測的效能,或是整個圖層級的分類?選擇的評估指標應該與你的問題目標一致。

可解釋性: 你能理解 GNN 為何做出特定預測嗎?對醫療或金融等關鍵應用而言,可解釋性可能相當重要。

挑戰與未來方向

儘管 GNNs 強大,仍面臨下列挑戰:

表達力的限制: 部分 GNNs 難以區分特定的圖結構。研究人員正在開發更具表達力的架構來克服這個問題。

動態圖: 許多真實世界的圖會隨著時間變化——好友關係可能新增或刪除,道路狀況也會改變。如何讓 GNNs 適應動態環境仍是活躍的研究領域。

可擴充性: 具有數百萬或數十億節點的超大圖在運算上構成嚴峻挑戰。工業應用通常需要專門的實作。

異質圖: 真實世界的圖通常包含不同類型的節點與邊。例如,一個知識圖可能包含人物、地點、事件和概念等多種類型節點,並透過不同關係類型連結。如何有效處理這種異質性仍是持續發展的研究領域。

未來的可能方向包含:

自我監督式學習: 不依賴標記資料便能學習有用的圖表徵,將能大幅拓展 GNN 的應用範圍。

圖生成: 建構符合特定需求且有效的全新圖,在藥物開發、材料科學以及合成資料產生等領域都有應用前景。

與其他方法結合: 將 GNNs 與強化學習或 transformer 等技術整合能帶來全新的可能性。

開始探索 GNNs

如果你對 GNNs 感興趣並想進一步探索:

打好基礎: 在研究 GNNs 之前,先確保自己對一般神經網路有紮實的理解。

由淺入深: 先從基礎的圖問題和小型資料集開始,再逐漸擴大規模。

使用現有函式庫: PyTorch Geometric、Deep Graph Library (DGL) 以及 Spektral 等框架都提供了常見 GNN 架構的實作。

加入社群: 這個領域正在快速發展。多關注研究論文,加入線上社群,或參加類似 Kaggle 等平台上的競賽。

總結:迎向更緊密連結的未來

圖神經網路代表了機器學習的一次根本轉變——從分析單獨的實體,到在脈絡中理解這些實體。它們體認到,在這個互聯的世界裡,關係往往比單一屬性更重要。

隨著世界越來越互聯化——從全球供應鏈到數位社群網路再到物聯網——GNNs 為理解並優化這些複雜系統提供了強而有力的方法。

在學習演算法(例如最短路徑查找)方面的突破,暗示著更大的發展潛力:神經網路能學習一般性的演算法原則,而不僅只是統計模式。這或許能讓 AI 結合神經網路的適應力與演算法的可靠性與泛化能力。

無論你是推動前沿研究的科學家、構建應用的開發者,還是對 AI 演進充滿好奇的一般人,圖神經網路都能提供一個令人著迷的視角——機器如何透過一次一次的連結,學習並航行在這個充滿網路關係的世界中。

✦延伸閱讀:AI Agent 是什麼?與 AI 助理、Chatbot 差異比較和應用場景解析