Node2Vec 임베딩과 커뮤니티 감지로 그래프 구조 분석하기
Node2Vec 그래프 임베딩과 Louvain·Label Propagation 커뮤니티 감지의 작동 방식, 평가 지표, 확장 전략을 정리한다.
2026-08-14 · 최초 발행 2024-04-29
그래프의 관계를 벡터와 군집으로 해석하는 방법
그래프 데이터는 연결 자체에 의미가 있다. 노드의 속성만으로는 드러나지 않는 구조적 유사성, 연결 집단, 경계 밖의 이상 연결을 읽으려면 임베딩과 커뮤니티 감지를 함께 다룰 필요가 있다.
Node2Vec은 무작위 보행(Random Walk)으로 그래프를 샘플링하고 Skip-gram 학습을 적용하는 그래프 임베딩 기법이다. 되돌림을 조절하는 p와 탐험 성향을 조절하는 q를 통해 BFS/DFS 편향을 제어하며, 지역 구조와 전역 구조 학습 사이의 균형을 잡는다.
Louvain은 모듈러리티(Modularity)를 최대화하는 계층적 멀티레벨 군집화 알고리즘이다. 지역 단위 병합 뒤 슈퍼노드 압축을 반복하므로 빠르게 수렴하고 대규모 그래프 처리에 적합하다.
Label Propagation은 초기 라벨을 이웃 다수결로 반복 전파해 커뮤니티를 찾는다. 파라미터가 거의 없는 경량 방식이며 무감독·고속 특성을 갖지만, 랜덤 초기화에 따라 결과 일관성이 달라질 수 있다.
분석 전에 확정할 그래프의 형태
그래프를 만들 때 방향성과 가중치의 의미를 먼저 고정해야 한다. 방향 그래프를 양방향으로 변환할지, 가중치를 어떤 기준으로 정규화할지 결정하지 않으면 이후 임베딩과 커뮤니티 결과의 해석이 흔들린다.
노이즈나 허위 링크도 정리 대상이다. 최소 차수 또는 가중치 임계값을 적용하고, 연결요소를 분리해 처리할 필요가 있는지 검토한다. 대규모 그래프에서는 샘플링, 배치 학습, 병렬화로 메모리와 시간 복잡도를 관리한다.
Node2Vec의 입력은 그래프 G(V,E)와 {p, q, walk_length, num_walks, dimensions} 파라미터다. Alias Sampling 기반 랜덤 워크를 만든 뒤 Skip-gram을 학습해 노드 임베딩 Z를 생성한다. 결과 벡터 Z∈R^{|V|×d}는 유사도 계산, 링크 예측, 클러스터링에 사용할 수 있다.
Louvain과 Label Propagation의 선택 기준
Louvain은 모듈러리티를 기준으로 하며 resolution 파라미터로 커뮤니티 크기를 조절한다. 결과가 비교적 안정적이라는 장점이 있다. 반면 Label Propagation은 파라미터가 거의 없고 매우 빠르지만, 반복 실행 결과가 달라질 수 있어 평균화가 필요하다.
| 항목 | Node2Vec | Louvain | Label Propagation |
|---|---|---|---|
| 목적 | 임베딩 생성 | 커뮤니티 감지 | 커뮤니티 감지 |
| 성능 | 워크/학습 비용 큼, 병렬화로 가속 | 매우 빠름 | 초고속 |
| 확장성 | 수억 엣지까지 배치/분산 필요 | 수천만 엣지 실적 다수 | 수천만 엣지 용이 |
| 일관성 | 시드 고정 시 안정 | 비교적 안정 | 반복 실행 간 변동 가능 |
| 안정성 | 파라미터 민감 | 높은 편 | 노이즈에 민감 |
| 운영 편의 | 파라미터 다수 | 파라미터 적음 | 파라미터 거의 없음 |
재현성을 확보하려면 랜덤 시드를 고정하고, 실행 횟수와 평균 결과를 기록하며, 결과 버전을 관리해야 한다.
임베딩부터 운영 반영까지의 분석 흐름
관계 데이터가 쓰이는 분석 장면
추천과 링크 예측에서는 임베딩 기반 코사인 유사도로 사용자-아이템 또는 연구자-논문 연결을 생성하거나 확장할 수 있다. 신규 노드의 콜드스타트에는 이웃 기반 초기화나 콘텐츠와 그래프를 결합한 하이브리드 방식을 적용한다.
보안 분석에서는 네트워크 트래픽이나 계정 관계 그래프에서 커뮤니티 외부로 과도하게 연결된 outlier를 찾을 수 있다. 시간축 슬라이딩 윈도우로 커뮤니티 변동을 감시하고, 모듈러리티가 급격히 하락하면 경보 조건으로 활용한다.
시스템 서비스 호출 그래프에서는 커뮤니티를 배치와 스케일링 단위 최적화에 사용할 수 있다. 장애 전파 경로를 분석하고 커뮤니티 사이의 컷 엣지를 줄여 복원력을 높이는 방식이다.
임베딩과 커뮤니티 감지를 병행하면 기준 대비 정밀도/재현율 520%p 개선 가능 사례가 다수 있다. 라벨 전파를 선별 적용하면 대규모 그래프의 초기 세분화를 10배 이상 빠르게 수행할 수 있다. 커뮤니티 모니터링 기반 조기 경보는 평균복구시간(MTTR)을 1030% 단축할 수 있다.
튜닝과 확장 시 확인할 지점
Node2Vec에서는 p가 커질수록 되돌림이 강화되어 로컬 구조에, q가 커질수록 탐험이 강화되어 글로벌 구조에 치우친다. grid/random search를 병행해 목적에 맞는 균형을 찾는다. Louvain의 resolution을 높이면 작은 커뮤니티가 많아지므로, 업무 도메인에서 의미 있는 집단 크기와 맞는지 검증해야 한다. Label Propagation은 시드 고정과 다중 실행 평균화로 일관성 문제를 보완한다.
메모리가 부족하면 워크 수와 길이를 줄이고 Negative Sampling 배치나 샘플링 서브그래프를 활용한다. 분산 처리가 필요할 때는 Spark GraphFrames/GraphX, PyTorch-BigGraph, DGL/GraphBolt 등을 검토할 수 있다.
평가에는 모듈러리티, 커버리지, 콘덕턴스 같은 내부 지표를 사용하고, 정답 라벨이 있을 때는 NMI/ARI를 외부 지표로 둔다. 지표의 이동평균이나 권고 임계값 초과를 재학습 트리거로 삼아 드리프트를 감지한다.
실행 예제
전제조건
- Python 3.9+ 권장
- pip install networkx node2vec python-louvain scikit-learn
환경 예
- networkx>=2.8, node2vec>=0.4.6, python-louvain>=0.16
import numpy as np
import networkx as nx
from node2vec import Node2Vec
import community as community_louvain # package: python-louvain
from networkx.algorithms.community import label_propagation_communities
from networkx.algorithms.community.quality import modularity
from sklearn.metrics.pairwise import cosine_similarity
import warnings
# 1) 데이터 준비: Karate Club 예제 그래프
G = nx.karate_club_graph()
# 가중치 예시(없으면 1.0)
for u, v in G.edges():
G[u][v]["weight"] = 1.0
# 2) Node2Vec 임베딩
# 대규모 그래프는 workers 조정, walk_length/num_walks 축소 권장
n2v = Node2Vec(
G, dimensions=64, walk_length=80, num_walks=10,
p=1.0, q=1.0, workers=2, seed=42, weight_key="weight"
)
model = n2v.fit(window=10, min_count=1, batch_words=256, seed=42)
nodes = list(G.nodes())
def get_vec(n):
# 일부 구현은 str 키 사용
try:
return model.wv.get_vector(n)
except KeyError:
return model.wv.get_vector(str(n))
Z = np.vstack([get_vec(n) for n in nodes]) # |V| x d 임베딩
# 3) Louvain 커뮤니티 감지
partition = community_louvain.best_partition(
G, weight="weight", resolution=1.0, random_state=42
)
# dict -> list[set] 변환
comm_map = {}
for node, cid in partition.items():
comm_map.setdefault(cid, set()).add(node)
comms_louvain = list(comm_map.values())
# 4) Label Propagation 커뮤니티 감지
comms_lp = list(label_propagation_communities(G))
# 5) 품질 평가(모듈러리티)
mod_louvain = modularity(G, comms_louvain, weight="weight")
mod_lp = modularity(G, comms_lp, weight="weight")
print(f"Louvain communities: {len(comms_louvain)}, modularity={mod_louvain:.4f}")
print(f"Label Propagation communities: {len(comms_lp)}, modularity={mod_lp:.4f}")
# 6) 임베딩 활용 예: 임의 노드 유사 노드 Top-5 조회
idx = nodes.index(0)
sims = cosine_similarity(Z[idx:idx+1], Z).ravel()
top5 = [nodes[i] for i in sims.argsort()[::-1][1:6]]
print(f"Node 0 top-5 similar nodes: {top5}")
# 예외/품질 경고
if nx.number_connected_components(G) > 1:
warnings.warn("Disconnected graph detected: consider per-component processing.")
대규모 그래프에서는 walk_length(<=40), num_walks(<=5)로 시작하고 메모리 사용량을 점검한 뒤 늘린다. 모든 랜덤 소스(seed)와 패키지 버전(requirements.txt)을 고정하고, 결과 스냅샷을 저장한다.
Node2Vec으로 구조적 유사성을 벡터화하고 Louvain 또는 Label Propagation으로 커뮤니티를 식별하면, 탐색과 정교 분석을 분리해 운영할 수 있다. 초기 스캐닝은 Label Propagation으로 빠르게 수행하고, 이후 Louvain과 임베딩을 적용해 분석을 확장한다.