주뇽's 저장소

GCN(Graph Convolution Network) 본문

GNN

GCN(Graph Convolution Network)

뎁쭌 2023. 8. 19. 13:02
728x90
반응형
1 2 3 4

H → 특징 행렬의 Coulmn을 통과

5 6
  • A = 인접 행렬
  • H = 특징 행렬
  • W = 가중치 행렬

HW (특징 행렬 X 가중치 행렬)

  • 현재 예제에서는 가중치 행렬의 필터 갯수를 6개로 했지만 보통 16인듯
7

AHW (인접행렬 X 특징 행렬 X 가중치 행렬)

8

READOUT - Permutation Invariance

  • 1번 그래프와 2번 그래프는 같은 그래프이지만 특징 행렬의 표현이 달라짐
  • 그래프는 순서의 상관없이 같은 값이 나와야 함
9

마지막 H(특징 행렬)에 MLP를 적용해서 벡터로 만들어서 활성화 함수를 통과

Overall

X → H(특징 행렬)

A → A(인접 행렬)

10 ### **Cora Dataset을 이용하여 GCN 논문 실습(Ensigner)**

https://www.youtube.com/watch?v=JfBMCFVEuoM

1. Graph Convolution Networks(GCN)

  • SEMI-SUPERVISED CLASSIFICATION WITH RAPH CONVOLUTIONAL NETWORKS

    1609.02907.pdf

ICLR 2017년에 나온 GCN에 대해 자세하게 다룬 첫 논문

2. Cora dataset

  • Nodes = publications(책, 또는 논문)
    • 2708개의 publications(책, 논문)들이 있으며 7개의 라벨링이 되어 있음
  • Edges = Citations(인용)
    • 각 논문당 인용에 대한 5429의 링크들이 존재
  • Node Features = Word vectors
    • 하나의 노드에는 1433사이즈의 유니크한 words가 있다.

구성

Cora dataset은 2개의 파일로 구성되어 있다.

  1. Cora.content
11
  • Paper id : 논문의 고유 ID(논문의 이름이 아님)
  • Word attributes : (특징 벡터) 각 논문의 특징을 나타내는 키워드 값을 벡터화
  • Class label : 각 논문이 어떤 주제인지 알 수 있음
  1. Cora.cites

    12
  • ID of cited paper : 인용된 논문

  • ID of citing paper : 인용하는 논문

    —# 오른쪽 논문이 왼쪽 논문을 인용 1033 논문이 35논문을 인용

3. 코드 실습

데이터 불러오기

  • 인접 행렬
    • sparse 행렬(서로서로 연결된 비율이 매우 낮음)
    • 약 13,264개가 Not nonzero, 행렬의 사이즈는 2,709 X 2,709이다.
    • 약 0.18퍼센트만이 데이터에 값이 있음
  • 특징 벡터
    • 각 노드에 해당하는 워드가 임베딩 되어 벡터 형태로 저장
  • 레이블
    • 7개의 레이블을 클래스 번호로 레이블링(카테고리화)
  • 학습 데이터
    • 0 ~ 139(140)개 데이터를 사용
  • 검증 데이터
    • 200 ~ 499(300)개 데이터를 사용
  • 테스트 데이터
    • 500 ~ 1400(1000)개를 사용

통상적으로 학습 : 7 검증 : 1 테스트 : 2 이지만 각자에 맞게 설정

Model(Pytorch)

  1. Model 정의
  • GraphConvolution
from torch import nn
from torch.nn.parameter import Parameter
import torch
import torch.nn.functional as F
import math

class GraphConvolution(nn.Module):
    def __init__(self, feature_numbers, out_numbers, bias=False) -> None:
        super().__init__()
        self.bias = bias
        self.w = Parameter(torch.FloatTensor(feature_numbers, out_numbers))
        if bias:
            self.b = Parameter(torch.FloatTensor(out_numbers))
        self.reset_parameters()

    def reset_parameters(self):
        stdv = 1. / math.sqrt(self.w.size(1))
        self.w.data.uniform_(-stdv, stdv)
        if self.bias is not False:
            self.b.data.uniform_(-stdv, stdv)

    def forward(self, x, adj):
        #-- input data 
        #-- X = 특징 행렬
        #-- adj = 인접 행렬(sparse matrix)
        support = torch.mm(x, self.w)
        out = torch.spmm(adj, support)
        #-- spmm(sparse mulple : sparse행렬 연산시 적은 메모리 사용 효율적으로 처리)
        if self.bias:
            out = out + self.b

        return out
  • NodeClassificationGCNN
class NodeClassificationGCNN(nn.Module):

    def __init__(self, feature_num, node_representation_dim, nclass, droupout=0.2, bias=False) -> None:
        super().__init__()
#-- 특징 행렬의 Column, Demention(CNN에서의 채널 수), output_dim
        self.gconv1 = GraphConvolution(feature_num, node_representation_dim, bias)
#-- 이전 레이어에서 나온 output, 최종 output class(7)
        self.gconv2 = GraphConvolution(node_representation_dim, nclass, bias)
        self.dropout = droupout

    def forward(self, x, adj):
        x = F.relu(self.gconv1(x, adj))
        x = F.dropout(x, self.dropout, self.training)
        x = F.relu(self.gconv2(x, adj))
        return F.log_softmax(x, dim=1)
#-- log를 이용하여 -무한대 값을 출력 가능
  1. Model 실행
from GCNN import NodeClassificationGCNN

#-- 특징벡터의 column개수, 256(CNN에서의 필터의 개수), 클래수 개수)
model = NodeClassificationGCNN(features.shape[1], 256, np.max(labels.detach().numpy())+1)
  • 학습
import torch.optim as optim
import torch.nn.functional as F

epochs=100
optimizer = optim.Adam(model.parameters(),lr=0.01)
train_losses=[]
val_losses=[]
train_accuracy=[]
val_accuracy=[]
for epoch in range(epochs):
    model.train()
    train_labels=labels[idx_train]
    val_labels=labels[idx_val]


    optimizer.zero_grad()
    output = model(features, adj)
    train_loss=F.nll_loss(output[idx_train],train_labels)
    train_losses.append(train_loss)
    t_a=accuracy(output[idx_train],train_labels)
    train_accuracy.append(t_a)
    print(f"Training epoch {epoch} ; accuracy: {accuracy(output[idx_train],train_labels)}; loss: {train_loss.item()}")
    train_loss.backward()
    optimizer.step()

    model.eval()
    output = model(features, adj)
    val_loss=F.nll_loss(output[idx_val],val_labels)
    val_losses.append(val_loss)
    v_a=accuracy(output[idx_val],val_labels)
    val_accuracy.append(v_a)
    print(f"Validation epoch {epoch} ; accuracy: {accuracy(output[idx_val],val_labels)}; loss: {val_loss.item()}")

'GNN' 카테고리의 다른 글

[Code] NGCF(Neural Graph Collaborative Filtering)  (0) 2023.08.19
LightGCN Preview  (0) 2023.08.19
GNN(Graph Neural Network)  (2) 2023.07.23