머신러닝을 위한 그래프 이론(Graph Theory for Machine Learning)

그래프(Graph)는 관계를 표현하는 자료구조(data structure)입니다. 데이터에 연결이 존재한다면 그래프 이론(graph theory)이 필요합니다.

유형: Build 언어: Python 선수 지식: Phase 1, Lesson 01-03(선형대수(linear algebra), 행렬(matrices)) 예상 시간: 약 90분

학습 목표

  • 인접 행렬(adjacency matrix)과 인접 리스트(adjacency list) 표현을 갖춘 그래프 클래스(graph class)를 만들고, 너비 우선 탐색(BFS)과 깊이 우선 탐색(DFS) 순회(traversal)를 구현합니다.
  • 그래프 라플라시안(graph Laplacian)을 계산하고, 그 고유값(eigenvalue)으로 연결 성분(connected component)을 찾아내고 노드(node)를 군집화(clustering)합니다.
  • 정규화된 인접 행렬(normalized adjacency matrix) 곱으로 GNN 방식 메시지 패싱(message passing) 한 단계(round)를 구현합니다.
  • 피들러 벡터(Fiedler vector)를 활용해 그래프를 분할하는 스펙트럼 클러스터링(spectral clustering)을 적용합니다.

문제

소셜 네트워크(social network), 분자(molecule), 지식 베이스(knowledge base), 인용 네트워크(citation network), 도로 지도(road map)는 모두 그래프(graph)입니다. 전통적인 머신러닝(traditional ML)은 데이터를 평평한 표(flat table)로 다룹니다. 각 행(row)은 독립적이고, 각 특성(feature)은 하나의 열(column)입니다. 그러나 연결 구조(connection structure)가 중요해지는 순간, 표 형식의 표현은 무너집니다.

소셜 네트워크를 떠올려 봅시다. 어떤 상품을 사용자가 살지 예측하고 싶다고 가정합니다. 사용자의 구매 이력(purchase history)도 중요하지만, 친구들의 구매 이력이 더 큰 단서가 되기도 합니다. 연결 그 자체가 신호(signal)를 담고 있기 때문입니다.

분자도 같은 이치입니다. 어떤 분자가 단백질(protein)에 결합(bind)하는지 예측하고 싶다고 합시다. 원자(atom) 자체도 중요하지만, 정말 결정적인 것은 원자들이 서로 어떤 방식으로 결합(bond)되어 있는가입니다. 구조가 곧 데이터입니다.

그래프 신경망(Graph Neural Network; GNN)은 딥러닝(deep learning) 분야에서 가장 빠르게 성장하는 영역입니다. 신약 발견(drug discovery), 소셜 추천(social recommendation), 사기 탐지(fraud detection), 지식 그래프 추론(knowledge graph reasoning) 등에서 활용됩니다. 모든 GNN은 같은 토대 위에 서 있는데, 바로 기본 그래프 이론입니다.

필요한 것은 다음 네 가지입니다.

  1. 그래프를 행렬로 표현하는 방법입니다. 그래야 곱셈 연산을 적용할 수 있습니다.
  2. 그래프 구조를 탐색하는 순회 알고리즘(traversal algorithm)입니다.
  3. 스펙트럼 그래프 이론(spectral graph theory)에서 가장 중요한 행렬인 라플라시안(Laplacian)입니다.
  4. GNN을 동작하게 만드는 핵심 연산인 메시지 패싱(message passing)입니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.인접 행렬(adjacency matrix)에서 `A[i][j] = 1`은 무엇을 의미하나요?

2.BFS는 어떤 자료구조(data structure)를 사용하고, 무엇을 찾나요?

0/2 답변 완료

개념

그래프(Graph): 노드(Node)와 엣지(Edge)

그래프 G = (V, E)는 꼭짓점(vertex), 즉 노드(node)의 집합 V와 엣지(edge)의 집합 E로 이루어집니다. 각 엣지는 두 노드를 연결합니다.

방향 그래프(directed graph)와 무방향 그래프(undirected graph). 무방향 그래프에서 엣지 (u, v)는 u가 v에 연결되어 있고 v도 u에 연결되어 있다는 뜻입니다. 방향 그래프, 곧 다이그래프(digraph)에서 엣지 (u, v)는 u가 v를 가리킨다는 의미이며, 그 반대 방향이 반드시 존재한다고 보장되지는 않습니다.

가중 그래프(weighted graph)와 비가중 그래프(unweighted graph). 비가중 그래프에서는 엣지가 있거나 없거나 둘 중 하나입니다. 가중 그래프에서는 각 엣지에 수치 가중치(numerical weight)가 붙습니다. 거리, 비용, 결합 강도 같은 값이 가중치가 될 수 있습니다.

그래프 유형(Graph type)예시(Example)
무방향, 비가중(undirected, unweighted)페이스북 친구 관계 네트워크(Facebook friendship network)
방향, 비가중(directed, unweighted)트위터 팔로우 네트워크(Twitter follow network)
무방향, 가중(undirected, weighted)도로 지도(road map, 거리 기반)
방향, 가중(directed, weighted)웹 페이지 링크(web page links, PageRank 점수)

인접 행렬(Adjacency Matrix)

인접 행렬 A는 그래프의 핵심 표현입니다. 노드가 n개인 그래프에서 다음과 같이 정의합니다.

A[i][j] = 1    if there is an edge from node i to node j
A[i][j] = 0    otherwise

무방향 그래프에서는 A가 대칭(symmetric) 행렬입니다. 즉 A[i][j] = A[j][i]가 성립합니다. 가중 그래프에서는 A[i][j]가 엣지 (i, j)의 가중치 값이 됩니다.

예시: 삼각형(triangle).

Nodes: 0, 1, 2
Edges: (0,1), (1,2), (0,2)

A = [[0, 1, 1],
     [1, 0, 1],
     [1, 1, 0]]

인접 행렬은 모든 GNN의 입력(input)입니다. A에 가하는 행렬 연산은 그래프 위에서의 연산과 그대로 대응됩니다.

차수(Degree)

노드의 차수(degree)는 그 노드에 닿아 있는 엣지의 개수입니다. 방향 그래프에서는 들어오는 엣지 개수인 진입 차수(in-degree)와 나가는 엣지 개수인 진출 차수(out-degree)를 구분합니다.

차수 행렬(degree matrix) D는 대각 행렬(diagonal matrix)입니다.

D[i][i] = degree of node i
D[i][j] = 0    for i != j

앞의 삼각형 예시에서는 모든 노드가 다른 두 노드와 연결되어 있으므로 D = diag(2, 2, 2)가 됩니다.

차수는 노드의 중요도(importance)에 대한 정보를 줍니다. 차수가 큰 노드는 허브 노드(hub node)에 해당합니다. 네트워크의 차수 분포(degree distribution)는 그 구조를 드러냅니다. 소셜 네트워크는 거듭제곱 법칙(power law)을 따르는 경향이 있어, 허브는 적고 잎 노드(leaf node)는 많습니다. 무작위 그래프(random graph)는 푸아송 분포(Poisson-distributed) 차수를 갖습니다.

BFS와 DFS

그래프 순회(traversal)의 가장 기본이 되는 두 알고리즘입니다. 둘 다 익혀 두어야 합니다.

너비 우선 탐색(Breadth-First Search; BFS). 먼저 모든 이웃 노드(neighbor)를 살펴본 뒤, 그다음으로 이웃의 이웃을 살펴봅니다. 큐(queue, 선입선출/FIFO)를 사용합니다.

BFS from node 0:
  Visit 0
  Queue: [1, 2]        (neighbors of 0)
  Visit 1
  Queue: [2, 3]        (add neighbors of 1)
  Visit 2
  Queue: [3]           (neighbors of 2 already visited)
  Visit 3
  Queue: []            (done)

BFS는 비가중 그래프에서 최단 경로(shortest path)를 찾아 줍니다. 시작 노드(start)에서 임의의 노드까지의 거리는 그 노드가 처음 발견(discover)되는 BFS 레벨과 같습니다. 그래서 소셜 네트워크에서 홉 수(hop-count) 거리를 구할 때 BFS가 자주 쓰입니다.

깊이 우선 탐색(Depth-First Search; DFS). 가능하면 깊이 내려간 뒤에야 되돌아오는(backtracking) 방식입니다. 스택(stack, 후입선출/LIFO) 또는 재귀 호출(recursion)을 사용합니다.

DFS from node 0:
  Visit 0
  Stack: [1, 2]        (neighbors of 0)
  Visit 2               (pop from stack)
  Stack: [1, 3]         (add neighbors of 2)
  Visit 3               (pop from stack)
  Stack: [1]
  Visit 1               (pop from stack)
  Stack: []             (done)

DFS는 다음 작업에 유용합니다.

  • 연결 성분(connected component) 찾기. 아직 방문하지 않은 노드에서 DFS를 새로 시작합니다.
  • 순환 탐지(cycle detection). DFS 트리의 후행 엣지(back edge)를 확인합니다.
  • 위상 정렬(topological sorting). DFS 종료 순서를 뒤집어서 얻습니다.
알고리즘(Algorithm)자료구조(Data structure)찾는 대상(Finds)활용 사례(Use case)
BFS큐(queue)최단 경로(shortest paths)소셜 네트워크 거리, 지식 그래프 순회
DFS스택(stack)연결 성분, 순환(components, cycles)연결성 판단, 위상 정렬

그래프 라플라시안(Graph Laplacian)

L = D - A로 정의됩니다. 스펙트럼 그래프 이론에서 가장 중요한 행렬입니다.

앞의 삼각형 예시에서는 다음과 같이 계산됩니다.

D = [[2, 0, 0],    A = [[0, 1, 1],    L = [[2, -1, -1],
     [0, 2, 0],         [1, 0, 1],         [-1, 2, -1],
     [0, 0, 2]]         [1, 1, 0]]         [-1, -1,  2]]

라플라시안은 다음과 같은 중요한 성질을 갖습니다.

  1. 양의 준정부호(positive semi-definite) 행렬입니다. 모든 고유값이 >= 0입니다.
  2. 영(zero) 고유값의 개수는 연결 성분의 개수와 같습니다. 연결된 그래프는 영 고유값을 정확히 하나 갖습니다. 서로 분리된 성분(disconnected component)이 3개라면 영 고유값도 3개입니다.
  3. 가장 작은 0이 아닌 고유값, 즉 피들러 값(Fiedler value)은 연결성(connectivity)을 측정합니다. 피들러 값이 크면 그래프가 단단하게 연결된 상태이고, 작으면 병목(bottleneck) 같은 약한 지점이 있다는 신호입니다.
  4. 피들러 값에 대응하는 고유벡터(Fiedler vector)는 좋은 분할(split)을 드러냅니다. 값이 양수인 노드를 한 그룹으로, 음수인 노드를 다른 그룹으로 묶으면 자연스러운 분할이 됩니다. 이것이 곧 스펙트럼 클러스터링입니다.
graph TD
    subgraph "Graph to Matrices"
        G["Graph G"] --> A["Adjacency Matrix A"]
        G --> D["Degree Matrix D"]
        A --> L["Laplacian L = D - A"]
        D --> L
    end
    subgraph "Spectral Analysis"
        L --> E["Eigenvalues of L"]
        L --> V["Eigenvectors of L"]
        E --> C["Connected components (zeros)"]
        E --> F["Connectivity (Fiedler value)"]
        V --> S["Spectral clustering"]
    end

스펙트럼 성질(Spectral Properties)

인접 행렬과 라플라시안의 고유값은 그래프를 직접 순회하지 않고도 구조적 성질(structural property)을 드러냅니다.

스펙트럼 클러스터링은 다음과 같이 동작합니다.

  1. 라플라시안 L을 계산합니다.
  2. L의 가장 작은 고유값에 대응하는 고유벡터 k개를 구합니다. 연결된 그래프에서는 첫 번째 모두-1 고유벡터(all-ones eigenvector)는 제외합니다.
  3. 이 고유벡터들을 각 노드의 새 좌표로 사용합니다.
  4. 그 좌표에 k-평균(k-means)을 적용합니다.

왜 잘 작동할까요? L의 고유벡터는 그래프 위에서 가장 "매끄러운"(smooth) 함수를 부호화(encode)합니다. 서로 잘 연결된 노드는 비슷한 고유벡터 값을, 병목으로 분리된 노드는 서로 다른 값을 갖게 됩니다. 결과적으로 고유벡터가 자연스럽게 군집(cluster)을 나누어 줍니다.

무작위 행보(random walk)와의 연결. 정규화 라플라시안(normalized Laplacian)은 그래프 위의 무작위 행보와 직접 관련됩니다. 무작위 행보의 정상 분포(stationary distribution)는 노드 차수에 비례합니다. 행보가 얼마나 빠르게 수렴(converge)하는지를 뜻하는 혼합 시간(mixing time)은 스펙트럼 간극(spectral gap)에 따라 결정됩니다.

메시지 패싱(Message Passing)

그래프 신경망(GNN)의 핵심 연산입니다. 각 노드는 이웃 노드로부터 메시지를 모으고, 집계(aggregate)한 뒤 자신의 상태(state)를 갱신(update)합니다.

h_v^(k+1) = UPDATE(h_v^(k), AGGREGATE({h_u^(k) : u in neighbors(v)}))

가장 단순한 형태에서는 AGGREGATE가 평균(mean), UPDATE가 선형 변환과 활성화 함수의 조합이 됩니다.

h_v^(k+1) = sigma(W * mean({h_u^(k) : u in neighbors(v)}))

사실 이 연산은 행렬 곱셈으로 다시 쓸 수 있습니다. 모든 노드 특성을 모아 놓은 행렬을 H, 인접 행렬을 A라 하면 다음과 같이 표현됩니다.

H^(k+1) = sigma(A_norm * H^(k) * W)

여기서 A_norm은 정규화된 인접 행렬로, 각 행(row)의 합이 1이 되도록 맞춘 것입니다.

메시지 패싱을 한 번 수행하면 각 노드는 바로 옆 이웃의 정보를 "보게" 됩니다. 두 번이면 이웃의 이웃까지, K번이면 K-홉(hop) 이웃 범위의 정보가 노드에 전달됩니다.

graph LR
    subgraph "Round 0"
        A0["Node A: [1,0]"]
        B0["Node B: [0,1]"]
        C0["Node C: [1,1]"]
    end
    subgraph "Round 1 (aggregate neighbors)"
        A1["Node A: avg(B,C) = [0.5, 1.0]"]
        B1["Node B: avg(A,C) = [1.0, 0.5]"]
        C1["Node C: avg(A,B) = [0.5, 0.5]"]
    end
    A0 --> A1
    B0 --> A1
    C0 --> A1
    A0 --> B1
    C0 --> B1
    A0 --> C1
    B0 --> C1

개념(Concept)과 머신러닝 적용(ML Application)

개념(Concept)머신러닝 적용(ML Application)
인접 행렬(adjacency matrix)GNN의 입력 표현
그래프 라플라시안(graph Laplacian)스펙트럼 클러스터링, 커뮤니티 탐지(community detection)
BFS/DFS지식 그래프 순회, 경로 탐색(path finding)
차수 분포(degree distribution)노드 중요도, 특성 공학(feature engineering)
메시지 패싱(message passing)GNN 계층(layer, 예: GCN, GAT, GraphSAGE)
라플라시안 L의 고유값커뮤니티 탐지, 그래프 분할(graph partitioning)
스펙트럼 클러스터링비지도 노드 그룹화(unsupervised node grouping)
페이지랭크(PageRank)노드 중요도 산정, 웹 검색

만들어 보기

1단계: 그래프 클래스(graph class) 직접 구현하기

class Graph:
    def __init__(self, n_nodes, directed=False):
        self.n = n_nodes
        self.directed = directed
        self.adj = {i: {} for i in range(n_nodes)}

    def add_edge(self, u, v, weight=1.0):
        self.adj[u][v] = weight
        if not self.directed:
            self.adj[v][u] = weight

    def neighbors(self, node):
        return list(self.adj[node].keys())

    def degree(self, node):
        return len(self.adj[node])

    def adjacency_matrix(self):
        import numpy as np
        A = np.zeros((self.n, self.n))
        for u in range(self.n):
            for v, w in self.adj[u].items():
                A[u][v] = w
        return A

    def degree_matrix(self):
        import numpy as np
        D = np.zeros((self.n, self.n))
        for i in range(self.n):
            D[i][i] = self.degree(i)
        return D

    def laplacian(self):
        return self.degree_matrix() - self.adjacency_matrix()

인접 리스트(self.adj)는 이웃 노드를 효율적으로 저장합니다. 스펙트럼 연산에는 행렬 형태가 필요하므로, 인접 행렬로의 변환 단계에서 numpy를 사용합니다.

2단계: BFS와 DFS

from collections import deque

def bfs(graph, start):
    visited = set()
    order = []
    distances = {}
    queue = deque([(start, 0)])
    visited.add(start)
    while queue:
        node, dist = queue.popleft()
        order.append(node)
        distances[node] = dist
        for neighbor in graph.neighbors(node):
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, dist + 1))
    return order, distances


def dfs(graph, start):
    visited = set()
    order = []
    stack = [start]
    while stack:
        node = stack.pop()
        if node in visited:
            continue
        visited.add(node)
        order.append(node)
        for neighbor in reversed(graph.neighbors(node)):
            if neighbor not in visited:
                stack.append(neighbor)
    return order

BFS는 양방향 큐(double-ended queue)인 deque를 사용해 O(1) 시간에 popleft를 수행합니다. DFS는 리스트(list)를 스택처럼 활용합니다. 두 알고리즘 모두 모든 노드를 정확히 한 번씩 방문하므로 전체 시간 복잡도는 O(V + E)입니다.

3단계: 연결 성분(connected component)과 라플라시안 고유값

def connected_components(graph):
    visited = set()
    components = []
    for node in range(graph.n):
        if node not in visited:
            order, _ = bfs(graph, node)
            visited.update(order)
            components.append(order)
    return components


def laplacian_eigenvalues(graph):
    import numpy as np
    L = graph.laplacian()
    eigenvalues = np.linalg.eigvalsh(L)
    return eigenvalues

eigvalsh는 대칭 행렬용 함수입니다. 무방향 그래프의 라플라시안은 항상 대칭이므로 그대로 사용할 수 있습니다. 이 함수는 고유값을 오름차순(ascending order)으로 반환하므로, 0의 개수를 세면 연결 성분의 개수를 바로 알 수 있습니다.

4단계: 스펙트럼 클러스터링(spectral clustering)

def spectral_clustering(graph, k=2):
    import numpy as np
    L = graph.laplacian()
    eigenvalues, eigenvectors = np.linalg.eigh(L)
    features = eigenvectors[:, 1:k+1]

    labels = np.zeros(graph.n, dtype=int)
    for i in range(graph.n):
        if features[i, 0] >= 0:
            labels[i] = 0
        else:
            labels[i] = 1
    return labels

k=2인 경우에는 피들러 벡터의 부호(sign)만으로 그래프를 두 군집으로 나눌 수 있습니다. k > 2인 경우에는 자명한 모두-1 고유벡터를 제외한 앞쪽 k개의 고유벡터에 k-평균을 적용합니다.

5단계: 메시지 패싱(message passing)

def message_passing(graph, features, weight_matrix):
    import numpy as np
    A = graph.adjacency_matrix()
    row_sums = A.sum(axis=1, keepdims=True)
    row_sums[row_sums == 0] = 1
    A_norm = A / row_sums
    aggregated = A_norm @ features
    output = aggregated @ weight_matrix
    return output

이 함수는 GNN 메시지 패싱을 한 번 수행한 것입니다. 각 노드의 새 특성은 이웃 노드 특성의 가중 평균(weighted average)에 가중치 행렬(weight matrix)을 곱해 변환한 결과입니다. 여러 단계를 쌓으면 정보가 더 멀리 전파(propagate)됩니다.

사용하기

NetworkX와 numpy를 사용하면 위와 같은 연산을 한 줄로 처리할 수 있습니다.

import networkx as nx
import numpy as np

G = nx.karate_club_graph()

A = nx.adjacency_matrix(G).toarray()
L = nx.laplacian_matrix(G).toarray()

eigenvalues = np.linalg.eigvalsh(L.astype(float))
print(f"가장 작은 고유값: {eigenvalues[:5]}")
print(f"연결 성분 수: {nx.number_connected_components(G)}")

communities = nx.community.greedy_modularity_communities(G)
print(f"찾은 커뮤니티 수: {len(communities)}")

pr = nx.pagerank(G)
top_nodes = sorted(pr.items(), key=lambda x: x[1], reverse=True)[:5]
print(f"상위 5개 PageRank 노드: {top_nodes}")

NetworkX는 최적화된 C 백엔드(backend)를 활용해 다양한 규모의 그래프를 처리합니다. 실서비스(production)에서는 NetworkX를 활용하고, 처음부터 직접 구현한 코드는 내부에서 무슨 일이 일어나는지를 이해하는 학습용으로 쓰면 됩니다.

numpy를 활용한 스펙트럼 분석(spectral analysis)

import numpy as np

A = np.array([
    [0, 1, 1, 0, 0],
    [1, 0, 1, 0, 0],
    [1, 1, 0, 1, 0],
    [0, 0, 1, 0, 1],
    [0, 0, 0, 1, 0]
])

D = np.diag(A.sum(axis=1))
L = D - A

eigenvalues, eigenvectors = np.linalg.eigh(L)
print(f"고유값: {np.round(eigenvalues, 4)}")
print(f"피들러 값(Fiedler value): {eigenvalues[1]:.4f}")
print(f"피들러 벡터(Fiedler vector): {np.round(eigenvectors[:, 1], 4)}")

fiedler = eigenvectors[:, 1]
group_a = np.where(fiedler >= 0)[0]
group_b = np.where(fiedler < 0)[0]
print(f"군집 A: {group_a}")
print(f"군집 B: {group_b}")

핵심 역할은 피들러 벡터가 맡습니다. 양수 항(positive entry)은 한 군집, 음수 항(negative entry)은 다른 군집으로 갈립니다. 반복적인 최적화(iterative optimization)는 필요 없고, 고유값 분해(eigendecomposition)를 한 번만 수행하면 됩니다.

산출물 만들기

이 강의의 최종 산출물은 outputs/skill-graph-analysis.md입니다. 그래프 형태의 데이터(graph-structured data)를 분석할 때, 어떤 표현을 쓰고 어떤 알고리즘을 적용할지, GNN을 도입할지 판단하는 참조 자료(reference)로 사용합니다.

연결

개념(Concept)등장하는 곳(Where it shows up)
인접 행렬(adjacency matrix)GCN, GAT, GraphSAGE의 입력
라플라시안(Laplacian)스펙트럼 클러스터링, ChebNet 필터
BFS지식 그래프 순회, 최단 경로 질의(shortest path query)
메시지 패싱(message passing)모든 GNN 계층, 신경 메시지 패싱(neural message passing)
스펙트럼 간극(spectral gap)그래프 연결성, 무작위 행보의 혼합 시간(mixing time)
차수 분포(degree distribution)거듭제곱 법칙 네트워크(power-law network), 노드 특성 공학
연결 성분(connected component)전처리(preprocessing), 분리된 그래프 처리
페이지랭크(PageRank)노드 중요도 순위, 어텐션(attention) 초기값

GNN은 별도로 짚어 둘 만합니다. GCN(Kipf & Welling, 2017)의 그래프 합성곱(graph convolution) 연산은 자기 루프(self-loop)를 더한 인접 행렬 A_hat = A + I를 사용합니다.

H^(l+1) = sigma(D_hat^(-1/2) * A_hat * D_hat^(-1/2) * H^(l) * W^(l))

여기서 A_hat = A + I이고, D_hatA_hat의 차수 행렬입니다. 자기 루프 덕분에 집계 단계에서 각 노드가 자기 자신의 특성도 포함하게 됩니다. 이 식은 대칭 정규화(symmetric normalization)를 적용한 메시지 패싱과 같으며, D_hat^(-1/2) * A_hat * D_hat^(-1/2)가 정규화된 인접 행렬에 해당합니다. 라플라시안이 등장하는 이유는 이 정규화가 L_sym = I - D^(-1/2) * A * D^(-1/2)와 직접 연결되기 때문입니다. 라플라시안을 이해하면 GCN이 왜 잘 작동하는지를 함께 이해할 수 있습니다.

연습문제

  1. (쉬움) PageRank를 처음부터 구현하기. 모든 노드를 균일한 점수에서 시작합니다. 각 단계마다 score(v) = (1-d)/n + d * sum(score(u)/out_degree(u))를 계산합니다. 여기서 uv를 가리키는 모든 노드입니다. d=0.85를 사용하고, 점수 변화량이 1e-6보다 작아질 때까지 반복하여 작은 웹 그래프(web graph)에서 검증합니다.

  2. (중간) 스펙트럼 클러스터링으로 커뮤니티 찾기. 두 개의 완전 부분 그래프(clique)가 단 하나의 엣지로 이어진 그래프처럼, 두 군집이 뚜렷이 갈리는 그래프를 만듭니다. 스펙트럼 클러스터링을 실행해 올바른 분할을 찾는지 확인합니다. 군집 간(cross-cluster) 엣지를 점점 더 추가하면 결과가 어떻게 변하나요?

  3. (중간) 가중 그래프의 최단 경로를 위한 다익스트라 알고리즘(Dijkstra's algorithm) 구현. 모든 엣지의 가중치가 같은 그래프에서 BFS 결과와 비교합니다.

  4. (어려움) 2계층 메시지 패싱 신경망 만들기. 서로 다른 가중치 행렬을 두 번 적용해 메시지 패싱을 두 단계 수행합니다. 두 단계 후에는 각 노드가 2-홉 이웃의 정보를 가지게 됨을 확인합니다.

  5. (어려움) 실제 그래프 분석. 가라테 클럽 그래프(Karate Club graph; 34 노드, 78 엣지)를 사용합니다. 차수 분포, 라플라시안 고유값, 스펙트럼 클러스터링을 계산하고, 스펙트럼 클러스터링 결과를 알려진 정답 분할(ground truth split)과 비교합니다.

핵심 용어

용어흔한 설명실제 의미
그래프(graph)"노드와 엣지"쌍별 관계(pairwise relationship)를 부호화한 수학적 구조 G=(V,E)이다.
인접 행렬(adjacency matrix)"연결 관계 표"노드 ij가 연결되어 있으면 A[i][j] = 1이 되는 n x n 행렬이다.
차수(degree)"노드가 얼마나 많이 연결되었는가"해당 노드에 닿아 있는 엣지의 개수이다.
라플라시안(Laplacian)"D 빼기 A"L = D - A로 정의되며, 고유값이 그래프 구조를 드러내는 행렬이다.
피들러 값(Fiedler value)"대수적 연결도(algebraic connectivity)"L의 가장 작은 0이 아닌 고유값으로, 그래프가 얼마나 잘 연결되어 있는지를 측정한다.
너비 우선 탐색(BFS)"한 단계씩 넓혀 가는 탐색"더 깊이 들어가기 전에 모든 이웃을 먼저 방문하며 최단 경로를 찾는 순회이다.
깊이 우선 탐색(DFS)"일단 깊이부터"되돌아오기 전에 한 경로를 끝까지 따라가는 순회이다.
메시지 패싱(message passing)"노드끼리 이웃과 대화한다"각 노드가 이웃의 정보를 집계하는 과정으로, GNN의 핵심이다.
스펙트럼 클러스터링(spectral clustering)"고유벡터로 군집화한다"라플라시안의 고유벡터를 사용해 그래프를 분할한다.
연결 성분(connected component)"따로 떨어진 덩어리"모든 노드가 서로 도달 가능한 최대 부분 그래프(maximal subgraph)이다.

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

graph theory
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

skill-graph-analysis

Analyze graph-structured data and choose the right graph algorithm for ML tasks

Skill

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.연결 그래프(connected graph)의 그래프 라플라시안(graph Laplacian) `L = D - A`는 0인 고유값(zero eigenvalue)을 몇 개 가지나요?

2.GNN 메시지 패싱(message passing)에서 `h_v^(k+1) = sigma(W * mean({h_u^(k) : u in neighbors(v)}))`는 무엇을 계산하나요?

3.스펙트럼 클러스터링(spectral clustering)은 `L`의 두 번째로 작은 고유값에 대응하는 고유벡터인 피들러 벡터(Fiedler vector)를 어떻게 사용하나요?

0/3 답변 완료