GAT와 GraphSAGE: 그래프 신경망의 어텐션·귀납 학습 설계

GAT와 GraphSAGE의 메시지 패싱, 이웃 샘플링, 귀납 학습 구조를 비교하고 PyTorch Geometric 구현과 운영 설계를 정리한다.

2026-08-14 · 최초 발행 2024-04-29

이웃을 모두 같은 비중으로 볼 수 없는 그래프에서

그래프 신경망은 연결 관계를 따라 정보를 전달하지만, 모든 이웃이 예측에 똑같이 기여하는 것은 아니다. GAT(Graph Attention Networks)는 이웃마다 학습된 주의 계수 α_ij를 부여해 메시지를 가중합한다. 구조적 가중치를 학습하므로 이질적인 이웃의 영향력을 구분할 수 있다.

멀티헤드 어텐션은 표현력과 안정성을 높이는 데 쓰인다. 스파스 어텐션 마스크와 Dropout은 과적합이나 특정 이웃으로의 과도한 집중을 완화한다.

GraphSAGE는 다른 문제에서 강점을 보인다. k-홉 이웃을 샘플링한 뒤 미니배치에서 mean, LSTM, max-pool 같은 집계 함수를 적용한다. 학습된 집계 함수로 새 노드의 임베딩을 만들 수 있어 귀납 학습에 적합하다. 이웃 샘플링, 파라미터 공유, 지역적 연산을 기반으로 하므로 온라인·스트리밍 환경에도 맞는다.

전이 학습은 학습 시점에 관측한 전체 그래프 안에서 일반화하며, 미관측 노드 처리에는 제약이 있다. 반면 귀납 학습은 집계 함수를 학습하므로 미관측 노드나 부분 그래프에도 적용할 수 있다. 신규 사용자나 아이템을 실시간으로 반영해야 하는 경우 이 차이가 직접적인 선택 기준이 된다.

메시지 패싱 방식이 만드는 차이

GAT에서는 학습 가능한 e_ij = a(W h_i, W h_j)로 이웃 중요도를 계산하고, softmax 정규화 뒤 가중합을 수행한다. 노이즈 성격의 이웃을 억제하고 중요한 이웃을 부각할 수 있다. 멀티헤드를 병렬로 두면 표현력을 높이고 분산을 줄일 수 있으며, Residual·Dropout·LeakyReLU는 학습 안정화에 활용된다.

GraphSAGE는 계층마다 정해진 수의 이웃을 샘플링한다. k-hop과 fanout을 제한하므로 메모리 상한을 관리할 수 있고, 미니배치 병렬 처리도 쉬워진다. Mean, MaxPool, LSTM Aggregator 선택은 바이어스와 분산 사이의 절충과 연결된다. 깊은 모델에서는 Feature normalization과 Skip connections가 안정화 수단이 된다.

운영 환경에서는 샘플러와 연산 경로까지 모델 설계의 일부가 된다. NeighborLoader와 Sparse GPU 커널은 선형 확장성을 위한 기반이 되며, 고빈도 이웃 캐시와 피처 파이프라인 분리는 스루풋을 높인다. 링크 예측에서는 Negative sampling과 서브그래프 분산 학습을 조합할 수 있고, 최신성이 필요할 때는 온디맨드 임베딩 재계산 전략을 둔다.

어텐션이 한쪽으로 과도하게 집중되는 문제에는 Attention clipping과 α-temperature 조절을 사용할 수 있다. LayerNorm·BatchNorm은 분포를 안정화하고, Early stopping·LR warmup·Gradient clipping은 수렴을 다룬다. Seed 고정과 Deterministic ops는 재현성 확보에 필요하다.

학습부터 운영 대응까지의 흐름

입력: 그래프 G(V,E), 노드 특성X, 라벨 y샘플링: k-hop 이웃, fanoutper layer모델 레이어GAT: e_ij softmaxα_ij · 메시지 가중합GraphSAGE:Aggregator(mean/max/LSTM)은닉 임베딩 H^{(l+1)}손실 계산: CE/Ranking +규제(L2/Dropout)역전파·파라미터업데이트(Adam/AdamW)출력: 예측(logits)·노드/엣지임베딩모니터링OOM 시: fanout↓, batchsize↓, dtype FP16수렴 불안정: lr↓, clip_grad,norm/regularization

모델 선택에서 확인할 항목

항목 GAT GraphSAGE
성능(표현력) 이웃 중요도 학습으로 고표현력. 이질적 그래프에 강점 적절한 Aggregator·깊이로 강건한 성능. 구조 단순
확장성 전그래프/대심도 시 비용 증가. 미니배치 가능하나 α 계산 비용 존재 미니배치·샘플링 일관 설계. 대규모 그래프 선호
일관성(일반화) 전이 학습 강점, 귀납도 가능하나 피처 의존 귀납 일반화 본질. 신규 노드 처리 용이
안정성 어텐션 집중·노이즈 민감. 멀티헤드·정규화로 보완 샘플링 분산에 강건. Aggregator 선택으로 안정성 조율
운영 편의 파라미터·하이퍼 가중. 해석성(α 시각화) 장점 구현 단순·튜닝 용이. 추론 파이프라인 간결

대규모 그래프에서 신규 노드를 계속 받아들여야 한다면 GraphSAGE의 샘플링·집계 구조가 유리하다. 반대로 관계의 중요도가 균질하지 않고 복잡한 구조를 세밀하게 구분해야 한다면 GAT의 어텐션이 도움이 될 수 있다. GAT는 전그래프나 깊은 구조에서 비용이 커질 수 있고, α 계산 비용도 고려해야 한다.

추천·보안·지식 그래프에서의 적용

대규모 추천과 소셜 그래프에서는 GraphSAGE로 신규 사용자와 아이템 임베딩을 실시간 생성하고, 서빙 경로에 k-hop 피처 페치와 캐시를 결합할 수 있다. 이는 콜드스타트 완화와 CTR·정확도 개선에 연결된다.

보안과 이상 탐지에서는 GAT가 의심 계정 주변의 이웃 중요도를 가중해 공격 패턴의 국소 구조를 강조할 수 있다. 링크 예측을 결합하면 사기 탐지 점수 산출에도 활용할 수 있다.

엔터프라이즈 지식 그래프와 검색에서는 GraphSAGE로 엔티티 임베딩을 만들고 GAT로 관계 중요도를 학습하는 하이브리드 파이프라인을 구성할 수 있다. 질의 확장과 유사 엔티티 랭킹의 정밀도를 높이는 방향이다.

노드 분류와 링크 예측에서는 MLP 대비 820%p 정확도/AUROC 개선이 가능하며, 이는 데이터셋에 의존한다. 어텐션 기반 모델은 이질적 그래프에서 추가 이득이 관측되는 경향이 있다. Neighbor sampling 미니배치는 메모리 사용을 310배 줄이고 처리량을 2~5배 높일 수 있으며, 이는 배치·fanout·GPU 대수에 비례한다.

α 시각화는 근거를 제시하는 해석 가능성을 높인다. 새 노드의 온라인 반영은 제품 민첩성을 강화하고, 샘플링·집계·캐시를 표준화한 파이프라인은 운영 비용과 장애율 감소에 기여한다.

PyTorch Geometric으로 구현하는 GraphSAGE

전제조건은 Python 3.10, PyTorch ≥ 2.3, torch-geometric ≥ 2.5이며 CUDA는 선택 사항이다. 재현성을 위해 seed 고정과 deterministic 알고리즘 옵션을 검토한다.

설치 명령은 다음과 같다.

NeighborLoader로 귀납 학습 구성하기

# Python 3.10, torch 2.3, torch-geometric 2.5
import torch
from torch import nn
from torch_geometric.nn import SAGEConv
from torch_geometric.datasets import Planetoid
from torch_geometric.loader import NeighborLoader
import torch.nn.functional as F
import os, random

def set_seed(s=42):
    random.seed(s); torch.manual_seed(s); torch.cuda.manual_seed_all(s)

class SAGENet(nn.Module):
    def __init__(self, in_dim, hid, out_dim):
        super().__init__()
        self.conv1 = SAGEConv(in_dim, hid)
        self.conv2 = SAGEConv(hid, out_dim)
    def forward(self, x, edge_index):
        x = self.conv1(x, edge_index); x = F.relu(x); x = F.dropout(x, p=0.5, training=self.training)
        x = self.conv2(x, edge_index)
        return x

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
set_seed()

data = Planetoid(root='/tmp/cora', name='Cora')[0]  # 예시 데이터
train_loader = NeighborLoader(
    data, input_nodes=data.train_mask,
    num_neighbors=[15, 10], batch_size=1024, shuffle=True
)

model = SAGENet(data.num_features, 128, int(data.y.max())+1).to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

for epoch in range(1, 51):
    model.train(); total_loss = 0.0
    for batch in train_loader:
        batch = batch.to(device)
        optimizer.zero_grad(set_to_none=True)
        out = model(batch.x, batch.edge_index)
        loss = F.cross_entropy(out[batch.input_id], batch.y[batch.input_id])
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
        optimizer.step()
        total_loss += float(loss)
    print(f'Epoch {epoch:02d} | loss {total_loss/len(train_loader):.4f}')

num_neighbors=[15,10]은 2계층 fanout 설정이다. 메모리가 부족하면 fanout과 batch size를 줄인다. 미니배치 학습에서는 batch.input_id를 이용해 입력 노드의 로짓에만 손실을 계산한다.

GAT의 주의 기반 학습 구성

다음 예시는 full-batch에서 시작해 중형 그래프까지 적용하는 GAT 구성이다.

import torch
from torch import nn
from torch_geometric.nn import GATConv
from torch_geometric.datasets import Planetoid
import torch.nn.functional as F

class GATNet(nn.Module):
    def __init__(self, in_dim, hid, out_dim, heads=8):
        super().__init__()
        self.conv1 = GATConv(in_dim, hid, heads=heads, dropout=0.6)
        self.conv2 = GATConv(hid*heads, out_dim, heads=1, concat=False, dropout=0.6)
    def forward(self, x, edge_index):
        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

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
data = Planetoid(root='/tmp/cora', name='Cora')[0].to(device)
model = GATNet(data.num_features, 8, int(data.y.max())+1).to(device)
opt = torch.optim.Adam(model.parameters(), lr=0.005, weight_decay=5e-4)

for epoch in range(1, 201):
    model.train(); opt.zero_grad(set_to_none=True)
    out = model(data.x, data.edge_index)
    loss = F.cross_entropy(out[data.train_mask], data.y[data.train_mask])
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
    opt.step()
    if epoch % 20 == 0:
        model.eval()
        pred = out.argmax(dim=-1)
        acc = (pred[data.val_mask] == data.y[data.val_mask]).float().mean().item()
        print(f'Epoch {epoch:03d} | val acc {acc:.4f}')

대규모 그래프에서는 GAT도 NeighborLoader 기반 미니배치로 전환하는 편이 낫다. heads와 hidden 크기를 줄여 α 계산 비용을 제어할 수 있다. Half-precision(FP16)과 GradScaler는 메모리·속도 최적화에 활용하며, 과집중이 나타나면 attention dropout을 높이거나 temperature를 조절한다.

샘플링과 서빙에서 생기는 절충점

균일 샘플링은 단순하고 빠르지만 구조 편향이 생길 수 있다. 중요도 또는 레이블 의존 샘플링은 정확도 측면의 이점이 있을 수 있는 대신 구현 복잡도와 편향 위험이 따른다. fanout은 레이어별로 감쇠시키는 방식, 예를 들어 [25,10,5]처럼 설계해 품질과 비용을 조절한다.

깊이가 늘어나면 오버스무딩이 발생할 수 있으므로 Skip, Jumping Knowledge, Norm을 고려한다. GAT에서 α가 폭주하면 clipping과 entropy regularization을 적용한다.

피처 경로는 Offline ETL과 Online KV/Feature Store로 분리할 수 있다. 서빙 단계에서는 k-hop 피처 프리페치와 TTL 캐시를 두고, 임베딩 재계산 주기와 온라인 Aggregation 사이의 비용·신선도 절충을 관리한다.

평가에서는 시간 분할 검증(temporal split)으로 누설을 막고, 링크 예측은 negative sampling의 일관성을 유지한다. 추론 지연(latency), 메모리 피크, batch 실패율, 샘플러 큐 대기시간은 운영 지표로 지속적으로 확인한다.

GraphSAGE는 샘플링·집계 기반 귀납 학습으로 대규모·온라인 환경에 맞으며, Aggregator와 fanout 튜닝이 핵심이다. GAT는 이웃 중요도 학습으로 표현력을 높여 이질적이고 복잡한 구조에 유리하지만 비용과 안정성 관리가 필요하다. 초기에는 GraphSAGE로 확장성을 확보하고, 성능 병목 구간에서 GAT 또는 초기 SAGE와 상위 계층 GAT를 결합한 하이브리드를 적용할 수 있다.

그래프 신경망GATGraphSAGE귀납 학습PyTorch Geometric