Lecture 6. Graph Neural Networks (1) GNN Model


이제 본격적으로 이번 강의의 메인 주제였던 딥러닝을 활용한 그래프 데이터 임베딩 방법에 대해 공부해 봅시다. 참고로 Deep Encoder은 그래프 뉴럴 네트워크(GNN)으로도 부르기 때문에 혼재해서 사용하더라도 헷갈리지 않으시길 바랍니다.

Setup

들어가기에 앞서 반복적으로 활용할 notation에 대해 간략히 설명하고 시작하겠습니다. 앞으로 아래 기호를 쭉 사용하여 설명을 할 예정이니 잘 알아두시기 바랍니다.

  • $V$: 노드 집합
  • $A$: 인접 행렬 (Adjacency matrix)
  • $X \in \mathbb{R}^{m\times |V|}$: 노드 features
  • $v$: 노드 집합에 포함된 한 노드, $N(v)$: $v$의 이웃 노드

그래프 구조는 엣지의 방향성 및 가중 여부에 따라 여러 종류로 분류할 수 있지만, 이해를 위해 여기서는 가장 간단한 undirected & unweighted 그래프로 설명하겠습니다. 따라서 인접 행렬은 0과 1로 이루어진, 대각 방향으로 symmetric한 행렬이라고 생각하실 수 있습니다.

또한, 이전의 Shallow Encoder과는 달리 이제 노드 feature도 함께 고려하여 노드 임베딩을 학습한다는 점에 유의하시기 바랍니다.

  • 사실 대부분의 그래프 데이터셋은 노드 feature을 포함하고 있지만, 만에 하나 없는 경우라면 다음과 같은 벡터/값을 노드 feature로 사용하기도 합니다.
    • 노드의 one-hot 인코딩 벡터
    • 상수 벡터 [1, 1, …, 1]
    • 노드 차수(degree)

Naive Approach

딥러닝 모델을 활용하여 그래프 및 노드를 임베딩 하기 위해 가장 쉽게 생각할 수 있는 방법은 단순하게 그래프의 구조적인 특성을 나타내는 인접 행렬과 노드 feature 행렬을 그냥 이어 붙여서 딥러닝 모델에 던져주는 것입니다.

Imgur

위와 같은 undirected 그래프의 각 노드가 2차원의 feature를 각각 가지고 있다면, 단순히 두 행렬을 이어 붙여서 만든 7차원의 벡터를 뉴럴 네트워크에 전달하면 각 노드를 간단히 임베딩 할 수 있을 것입니다. 하지만 이러한 방법에는 다음과 같은 문제가 존재합니다.

  • $O(|V|)$ 파라미터가 필요함
    노드 feature이 $d$차원이라고 가정하면, 각 노드가 뉴럴 네트워크에 입력되는 차원이 $|V|+d$ 이겠죠? 따라서 그래프의 노드 갯수에 비례하여 모델의 파라미터가 증가합니다.
  • 다른 사이즈의 그래프에는 적용할 수 없음
    위와 같은 그래프에 대해 뉴럴 네트워크를 기껏 학습시켜 놓았는데, 100개의 노드로 구성된 새로운 그래프가 인풋으로 들어온다면, 인풋 차원이 맞지 않아 학습시킨 임베딩 모델을 활용할 수 없을 것입니다.
  • 노드 순서가 바뀌면 동일 노드의 임베딩이 달라질 수 있음
    위 그래프에서 노드 순서를 A→B→C→D→E에서 B→E→A→C→D 등으로 바꾼다면, 이에 따라 인접 행렬도 바뀌게 됩니다. 이렇게 된다면 같은 A 노드를 임베딩 하기 위해 인풋으로 활용되는 7차원의 벡터가 달라지기 때문에 임베딩 결과 값도 달라질 것입니다.

From Images to Graphs

그렇다면 기존 CNN 모델에서 아이디어를 차용해보는 건 어떨까요?

Imgur

Imgur

이미지를 다루는 CNN은 위와 같이 고정된 사이즈의 convolution 필터를 사용하여 이미지를 주욱 훑습니다. 여기서의 convolution 필터는 붉은 원으로 표시된 타겟 픽셀의 주위 픽셀 정보를 축약하는 역할을 합니다. 사실 이미지가 특수한 형태의 그래프로 해석될 수 있음을 생각해보면, 그래프 데이터에서도 타겟 노드의 임베딩을 만들기 위해 주변 노드의 정보를 사용한다는 아이디어는 나쁘지 않아 보입니다.

하지만 그래프에서는 CNN에서와 같이 고정된 크기의 필터(?)를 사용할 수 없습니다. 어떤 노드는 한두개의 이웃 노드를 가지지만 또 어떤 노드는 수백수천개의 이웃 노드를 가질 수 있기 때문이죠.

Imgur

그렇다면 그래프를 임베딩 할 때 타겟 노드의 이웃 노드에서 정보를 전달받아 이를 활용하여 타겟 노드의 임베딩을 업데이트 하되, 타겟 노드마다 이웃 노드의 갯수가 다를 수 있는 점을 고려하여 각기 다른 computation graph를 갖도록 하는 것이 좋겠습니다!

다음과 같은 아이디어를 근간으로 Graph Convolutional Network가 등장하게 되었습니다. 남은 강의에서는 이 GCN을 디테일하게 설명하고 있습니다.

Idea: Aggregate Neighbors

주요 Idea: 이웃 노드 정보를 가지고 타겟 노드 임베딩을 생성하자!

Imgur

왼쪽과 같은 그래프에서 우리가 임베딩하고 싶은 타겟 노드가 노란색의 A 노드라고 생각해 봅시다. 그렇다면 A 노드의 이웃 노드, 그리고 그 이웃 노드들의 이웃 노드를 가지고 오른쪽과 같은 computation graph가 생깁니다.

타겟 노드 A는 직속 이웃인 노드 B, C, D로부터 메시지를 전달 받고, 모든 메시지를 합친 후 어떠한 변환을 거쳐 본인의 임베딩으로 활용합니다. 우측 그림에서 회색 박스로 표시된 뉴럴 네트워크가 바로 이러한 1) 메시지 변환, 2) 이웃 노드로부터 온 메시지를 통합하는 두 과정을 수행하게 됩니다. 이 뉴럴 네트워크 내의 모델 파라미터가 최종적인 우리의 학습 대상이 되는 것입니다.

여기서 또 눈여겨 보아야 할 점이 있습니다. 여지껏 우리는 노란색 A 노드를 타겟 노드로 한 computation graph만 보았는데, 그렇다면 B, C, D 등 다른 타겟 노드에 대해서도 동일한 computation graph를 가질까요?

Imgur

아닙니다. 노드마다 이웃 노드의 갯수와 종류가 다르기 때문에 당연히 노드마다 서로 다른 computation graph를 가지게 됩니다.

Deep Model: Many Layers

Imgur

Layer의 수

Deep Encoder은 여러 layer로 구성할 수 있는데, 한 layer이 직속 이웃 노드에 대한 정보를 aggregate하는 것이기 때문에 layer을 두 개 쌓는다면 직속 이웃 노드에 대한 이웃 노드, 즉 타겟 노드로부터 2-hop 떨어진 노드의 정보까지 활용하겠다는 의미로 해석할 수 있습니다. 위 그림에서도 잘 나타나 있는데, 2개의 layer로 구성된 모델을 사용하기 때문에 타겟 노드 A로부터 2-hop 떨어진 노드 E, F의 정보도 임베딩 생성에 활용되는 것을 볼 수 있습니다.

노드 임베딩 초기화

또한, 보통 Layer-0에서 최초 노드 임베딩으로 노드 feature을 사용합니다. 모든 노드 임베딩은 layer을 거칠수록 이웃 노드의 정보를 변환하고 합친 후 업데이트 됩니다. 결국 모든 layer을 거치고 나면 최종 노드 임베딩이 생성되어 우리가 downstream task를 위해 사용하게 되는 것이죠.

Aggregator 함수

여기서 타겟 노드 A가 이웃 노드 B, C, D의 메시지를 aggregation 할 때, 노드 B, C, D의 순서와 관계 없이 aggregate된 메시지는 동일해야 합니다. 즉, 메시지를 aggregate하는 함수는 permutation-invariant한 속성을 가져야 한다는 말입니다. 일반적인 GNN은 주로 합, 평균, 맥스 풀링등의 aggregator를 활용합니다.

The Math: Deep Encoder

Imgur

자, 이제 가장 기본적인 GNN 형태를 정의하고 이를 수식으로 나타내어 알고리즘의 원리를 자세히 들여다보는 시간을 갖겠습니다. 우리의 GNN은 타겟 노드의 이웃 노드 임베딩을 전달받아 이를 평균냄으로써 메시지를 aggregate 합니다. 그 후, 뉴럴 네트워크를 통해 어떠한 변환을 거치고 이를 활용하여 타겟 노드 임베딩을 업데이트 합니다. 이를 수식으로 나타내면 아래와 같습니다.

Imgur

식이 처음엔 되게 복잡해 보이지만, 하나씩 뜯어보면 사실 아주 간단합니다. 식 전반에 나타나는 $h_{v}^{(l)}$ 은 $l$번째 layer에서 노드 $v$의 임베딩을 나타낸다고 보시면 됩니다.

  1. 초록색 수식 블럭 : 첫 노드 임베딩을 노드 feature로 초기화합니다.
  2. 파란색 수식 블럭 : $l+1$번째 layer에서의 노드 임베딩을 만들기 위해, 먼저 타겟 노드 $v$의 이웃 노드에 대해 $l$ 번째 layer에서의 노드 임베딩 평균을 구합니다. 그 후, 이웃 노드의 평균 임베딩에 어떠한 transformation $W_{l}$ 을 가합니다.
  3. 빨간색 수식 블럭 : 타겟 노드의 임베딩을 업데이트할 때 이웃 노드 뿐 아니라, 이전 layer에서 갖고 있던 자기 자신의 임베딩도 활용합니다. 같은 방법으로 $h_{v}^{(l)}$에 어떠한 transformation $B_{l}$ 을 가합니다.
  4. 노란색 수식 블럭 : 최종적으로 비선형 함수를 적용해서 $l+1$번째 layer에서의 타겟 노드 임베딩을 구합니다.
  5. 보라색 수식 블럭 : 노드 임베딩 업데이트 과정을 $L$번 반복합니다. 이 때 최종적으로 형성된 노드 임베딩은 본인으로부터 L-hop 떨어진 노드의 정보까지 활용하여 만든 것입니다.

Matrix Formulation

이전에 Random Walk를 행렬 형태로 표현했듯이, 벡터식으로 다뤘던 GNN도 행렬식으로 다시 표현해보겠습니다.

모든 노드 임베딩 벡터를 한데 모아 노드 임베딩 행렬을 만든다면, 이는 아래와 같이 표현할 수 있습니다.

$H^{L} = {[h_{1}^{(l)} … h_{|V|}^{(l)}]}^T$

그렇다면 이웃 노드의 임베딩을 합산하는 과정은 그래프의 인접 행렬을 사용하여 아래와 같이 간단하게 나타낼 수 있습니다.

$\sum_{u\in N_{v}} h_{u}^{(l)} = A_{v:}H^{(l)}$

만약 대각 행렬을 이렇게 정의한다면, 이 대각 행렬의 역행렬은 다음과 같기 때문에,

$D_{v,v} = Deg(v) = |N(v)|$ , $D_{v,v}^{-1} = 1/|N(v)|$

이를 활용하면 이웃 노드의 임베딩을 평균내는 연산을 행렬식으로 간단하게 표현할 수 있습니다.

Imgur

따라서 최종적으로 노드 임베딩 업데이트 함수를 행렬식으로 나타내면 아래와 같습니다.

Imgur

벡터식으로 이해하기도 어려웠는데 왜 굳이 사서 행렬식으로 변환하냐고요? 사실 행렬식이 가지는 구현상의 이점이 있기 때문입니다. 행렬식을 사용한다면 각 노드에 대한 임베딩을 따로 따로 업데이트 하지 않고 하나의 행렬로써 한번에 업데이트 할 수 있으며, 이 과정에서 $\tilde{A}$가 희소 행렬이기 때문에 보다 더 효율적인 행렬 연산이 가능하기 때문에 구현할 때는 행렬식이 더 선호됩니다.

How to train a GNN

오늘 강의의 마지막 부분으로 이렇게 구성한 GNN을 어떻게 학습시켜야 하는지 알아보겠습니다. 시작하기에 앞서 학습의 대상이 되는 파라미터가 무엇인지 짚고 넘어가보죠.

Imgur

다음 식에서 학습되는 파라미터는 $W_{l}$와 $B_{l}$ 입니다. 딸린 subscript를 봐도 알 수 있듯이, 두 파라미터 행렬은 모두 layer마다 따로 존재하며, 한 layer 내에서는 공유됩니다. 이를 간단하게 그림으로 표현하면 아래와 같습니다.

Imgur

GNN을 학습하는 방법은 여느 딥러닝 학습과 마찬가지로 크게 지도 학습, 비지도 학습 세팅으로 나뉩니다. 이를 하나씩 살펴보도록 합시다.

  1. 지도 학습 세팅
    • 노드 label $y$가 존재하는 상황
    • 정답 노드 label $y$를 활용하여 $min_{\theta}\mathcal{L}(y,f(z_v))$를 풂, 이 때 task에 맞게 L2 loss 혹은 Cross entropy loss 등을 loss 함수를 사용함
    • 예시) 각 노드가 safe한지 혹은 toxic한지 분류하는 node classification → 분류 문제이므로 cross-entropy loss를 사용하고, 노드의 정답 클래스 label을 활용하여 직접 모델 학습 가능

      💡 아래 loss 식에서 $\sigma(z_v^T\theta)$는 학습된 노드 임베딩 $z_v^T$를 가지고 모델이 예측한 노드 $v$의 클래스 확률 을 나타냅니다.

    Imgur

    Imgur

  2. 비지도 학습 세팅
    • 노드 label이 존재하지 않는 상황
    • 3강에서 공부했던 그래프 상 노드 similarity를 supervision으로 활용

      Imgur

      임의의 supervision 시그널을 만들어 비지도 학습 세팅을 지도 학습 세팅으로 바꾸기 위해서 원본 그래프에서의 노드 similarity를 바탕으로 label을 지정해줍니다. 여기서 노드 similarity는 3강에서 다뤘던 Random Walk 등을 활용할 수 있습니다.

      간단하게 DeepWalk로 노드 similarity를 정의하는 경우를 생각해볼까요? 만약 두 노드 $u$와 $v$가 랜덤 워크 상에서 co-occur한다면 두 노드는 ‘similar’하다고 말할 수 있으며, $y_{u,v} = 1$로 임의의 label을 붙입니다. 또한 여기서 $DEC(z_u,z_v)$는 학습된 두 노드의 임베딩을 내적함으로써 임베딩 공간에서의 노드 similarity를 측정합니다. Loss 함수로 cross-entropy를 사용함으로써 그래프에서 노드 similarity를 최대한 잘 보존하도록 노드 임베딩을 학습할 수 있게 됩니다.

      💡 원본 그래프에서 similar한 노드는 → similar한 임베딩을 갖도록 합니다
      Imgur

Model Design: Overview

자 그럼, 오늘 배웠던 내용을 한번 쭉 훑어 정리하고 포스트를 마무리하도록 하겠습니다. 그래프를 위한 Deep Encoder, a.k.a. GNN 모델을 만들기 위해서 아래와 같은 단계를 따라가야 합니다.

  1. 이웃 노드 임베딩을 aggregate하는 함수를 정함
  2. Task의 특성에 맞추어 loss 함수를 정의함
  3. 여러 computation graph에 대해 GNN 모델을 학습시킴
  4. 학습된 모델을 갖고 노드에 대한 임베딩을 생성할 수 있음. 이 때, 모든 노드에 대해 뉴럴 네트워크의 파라미터가 공유되기 때문에 학습에 사용되지 않은 노드에 대해서도 임베딩을 생성할 수 있음 (Inductive Capability)

    Imgur Imgur Imgur

💡 Inductive Capability
1. 새로운 그래프 : 예를 들어 분자 그래프에서, 화합물 A에 대해 학습된 GNN 모델이 화합물 B 그래프에서 임베딩을 만드는데 활용될 수 있음
2. 새로운 노드 : 시간에 따라 evolving 하는 그래프에서 새로운 노드가 추가될 때마다 바로바로 임베딩을 생성할 수 있음

Summary

  • Deep Encoder (GNN)의 핵심 아이디어: 이웃 노드의 정보를 aggregate 함으로써 노드 임베딩을 생성하자!
  • 모델 내 Aggregator과 Transformation 함수를 각각 어떻게 정의하느냐에 따라 모델 구조가 달라질 수 있습니다.
  • 다음 강의에선 GNN variant의 하나인 GraphSAGE를 다룰 것입니다.