25년 5월 3주차 그래프 오마카세

Graph Learning Will Lose Relevance Due To Poor Benchmarks

paper link : https://arxiv.org/pdf/2502.14546

  • ICLR 2025의 Position paper로 제출된 제목부터 상당히 흥미로운 주제를 다루는 논문을 이번주 오마카세로 소개해드리고자 합니다. 그래프 거장 선생님들께서 대다수 참여하신 프로젝트인 만큼, 독자 여러분들께서는 다음 논문을 꼭 정독해보시는 것을 추천드립니다.
  • 그래프 학습은 2022년 이전에 급부상하여 현재 머신 러닝의 다양한 도메인에서 긍정적으로 고려해볼 수 있는 툴로 많은 연구자들에게 영감을 주고 있습니다. 하지만 더욱 발전할 수 있는 그래프 학습 도메인에 있어서 그 발전을 저해하는 부실한 벤치마크가 문제의 원인이라는 것이 지속적으로 언급되어져 왔습니다.
  • 그로부터 수많은 그래프 벤치마크 데이터셋이 제안되었습니다. Large-scale graph benchmark, Long-range dependency benchmark, Temporal graph benchmark 등등이 존재합니다만 다음 Position paper에서는 여전히 부실한 벤치마크를 언급합니다.
  • 다음 논문에서는 크게 3가지 문제점을 제시합니다.
    • P1 : 혁신적인 실제 응용 프로그램의 부재 : LLM과 기하학적 생성 모델은 추론부터 단백질 접힘까지 다양한 도메인에 있어서 더더욱 강력해지고 복잡한 작업들을 해결할 수 있으나, Cora 또는 OGB 기반 GNN은 얼마나 혁신적일 수 있는가?
      • Cora, Citeseer 등의 일반적인 벤치마크로서는 현재의 새로운 트렌드를 커버할 수 있는 GNN의 성능을 제대로 평가할 수 없다는 사실을 (뒤에서도) 언급하며 트렌드에 맞는 적절한 벤치마크 및 도메인 적용 가능한 데이터셋의 필요성을 강조합니다.
    • P2 : 모든 데이터는 쉽게 그래프 형식으로 모델링할 수 있으나, 그렇지 않은 경우도 많이 존재한다. 엣지가 없는 일반적인 DeepSet 및 특정 노드 수에 고정된 에지를 갖는 Cayley 그래프를 기반으로 GNN을 분자 데이터셋에 적용해보는 간단한 실험에서도 상당히 경쟁력 있는 결과를 확인할 수 있었다.
    • P3 : (매우 심각한 문제) 엉망진창인 잘못된 벤치마킹 문화를 바로잡을 필요성이 크다. 데이터셋이 작고 (2025년부터는 Cora, MUTAG 같은 데이터셋을 사용하지 마라) 표준 분할이 없으며(No standard splits), 특히 생성형 모델을 평가할 때 이러한 문제는 더욱 심각해진다. 그리고 2020년 이후의 최신 그래프 모델들은 2016,17년도에 제안되었던 GCN 또는 GraphSAGE 모델보다 명백하게 형편이 없다..
      • 다음 문제를 해결하기 위해서는 포화되기 어려운 (harder to saturate) 더욱 전체적인 (holistic) 벤치마크가 필요함. 모든 머신러닝 분야에서 공통적인 문제점이지만, 표준 그래프 학습 벤치마크는 너무 오래되었고 2025년 현재 트렌드에서 집중하고 있는 해결 가능한 문제와의 규모와는 전혀 관련성이 없다.
  • 결과적으로 Graph Foundation Model을 구축하려고 하기엔 그 바탕이 너무 부족하다는 문제점을 언급합니다. 각 데이터셋에서 개별 모델을 학습하는 것 대신, "Encoder-Processor(GNN 또는 Graph Transformer)-Decoder" 청사진을 따라 대규모 학습을 거친 이후 그래프별 Enc/Dec만 파인튜닝하는 방법을 제안합니다.
    • 예를 들어, PCQM4M-v2(분자 벤치마크) / COCO-SP (슈퍼픽셀 이미지 벤치마크) 등의 다른 벤치마크에서 그래프 트랜스포머의 여러 모델들을 사전 학습하고 Peptides-struct / PascalVOC에서 파인 튜닝하였을때 사전 학습의 이점을 얻는다는 사실을 확인하였습니다.
  • 해당 프로젝트는 NIPS 2024를 전후하여, 그래프 거장이신 Christopher Morris께서 제안하신 그래프 학습의 문제점과 이 분야에서 영향력 있는 연구를 지속하는 방법에 대해 논의하기 위해 Michael Bronstein, Mikhail Garkin, Bryan Perozzi 등의 그래프 도메인에서 큰 발자취를 남기고 있는 훌륭하신 분들을 모아 시작되었다고 합니다.
  • 프로젝트 결과에 있어서는 개인적으로도 아주 유망할 것으로 예상하고 있기 때문에 2025년 이후로 그래프 학습을 새롭게 구상할 수 있는 판도가 열리지 않을까 조심스레 기대해보고 있습니다.

[Contact Info]

Gmail: jhbae1184@akane.waseda.jp

Twitter (X): @jhbae1184

LinkedIn


안녕하세요 정이태입니다. 어느덧 6주차 과정의 절반이 지난 4주차에 접어들었습니다. 지난주까지는 RAG, VectorRAG, GraphRAG의 기본 개념과 멘티분들이 활용할 게 서버 및 GDBMS & lightRAG engine 인프라 구축에 대해 리뷰하는 시간을 가졌다면, 이번 주에는 각 팀이 실제로 인프라를 사용하며 맞닥뜨린 문제와 그 해결 과정을 공유하는 시간을 가졌습니다. 추가로, 멘토링 끝난 뒤 실제 GraphRAG 구현시 발생할 문제 중 하나인 GDBMS 관리를 어떻게 전략적으로 접근하면 좋을지도 알아보는 시간을 가졌네요.

각 팀 discussion

Team 별 협업이 필요한 시기입니다. 때문에, 이번주차는 구현하며 필요한 협의점들을 정의하고 각 팀별로 어떤 협업을 해야할지 이야기하는 시간을 가졌습니다. 추가로, 오픈소스인 LightRAG를 사용하다보며 각 팀별로 보완이 필요한 부분이 하나둘씩 보이기 시작했는데요. 이 부분들을 github 이슈나 feature request 형태로 제안하며, 실질적으로 오픈소스 생태계에 무엇으로 기여하면 좋을지 고민도 해봤네요.각 팀 협업에 대한 구체적인 내용은 공개하기가 어려워서, 대략적인 협업 포인트들만 공유드려봅니다.

💡
[Team role]
Team1 -USTR 비정형 데이터(Document) 로부터 온톨로지 추출하기
Team2 -Graph DBMS(Backend) & LightRAG(RAG Engine) 관리하기
Team3 -GraphRAG을 활용할 페르소나(고객) 기획 및 Graph Evaluation dataset 만들기

Team 1 <-> Team 2
lightrag 의 source id (chunk,docu) 를 어떻게 선정할지.

Team 2 <-> Team 3
graph evaluation query 생성 후 어떻게 이를 정량화 평가할지.

Team 3 <-> Team 1
team3 에서 도메인 입력한 결과를 Team1 NER prompt 의 domain에 어떻게 입력할지

Insight

Team1 - prompting(main topic)

User prompt 뿐만아니라, System prompt 도 건드려보자.

  • system prompt leak github 를 공유하며, 기존 user prompt 에서 한 층 더 추상화 수준을 높인 고수준 계층에서 프롬프트를 입력하면 어떨까 라는 잠재적 개선 요소들을 이야기했어요.
  • 현재 진행하고 있는 prompt 는 system prompt 가 아닌, user prompt 로 작성해서 진행하고 있어서 추출한 ontology 의 품질이 만족스럽지 않을경우 개선 방향 중 하나이기 때문이에요. (userprompt,systemprompt 차이 조사해서 입력)
  • Team1 에서 prompts for graph generation 요소들 중 Goal & Real Data 를 핸들링하고 있다는 점을 recap 했어요.

Entity extraction 결과가 만족스럽지 않을경우 chunk size를 늘려볼까?

  • LightRAG의 graph generation(ontology extraction) 하는 프롬프트를 다시 리뷰했어요. 구체적으로 어떤 관점으로 이를 개선하고 있는지 team1 뿐만아니라, team2,3 분들도 인지하는 것이 중요하다 생각했거든요. 추가로, 미팅 전에 이야기 나왔던 부분인 chunk size 에 따라 Entity 추출 갯수가 증가 감소 하는지 경향성과 이 경향성이 추출된 knowledge graph 품질과 무슨 연관성이 있을지를 고민해보는 시간을 가졌어요. 이 부분은 둘째시간에 이야기한 Neo4j 에서 Microsoft GraphRAG 구현 중 일부인 token count 와 chunk size 차트 이슈와 유사해요.
  • 산점도를 살펴보면 양의 경향이 있음을 빨간 선으로 보여주지만, 그 관계가 선형적이지 않고 점점 완만해지고 있음을 확인할 수 있는데요. 데이터 대부분은 토큰 수가 증가해도 비교적 적은 엔티티 수 구간에 몰려 있습니다.
  • 즉, 텍스트 청크 크기가 커질수록 추출되는 엔티티 수가 비례해서 늘어나지는 않습니다. 일부 이상치가 존재하더라도, 전반적인 패턴은 토큰 수가 많아진다고 해서 항상 더 많은 엔티티를 뽑아내는 것은 아님을 시사합니다.

다른 온톨로지는 어떨까?

  • schema.org 이외 IOF supply chain ontology 를 살펴보며 RDF 구체적으로 어떻게 구현되어 있는지 가볍게 살펴봤어요. 지금 적재되어있는 supply chain graph에 적용이 가능하지만, 기존 온톨로지도 충분하다고 생각하기에 심화 단계에서 적용해보면 좋을거란 이야기를 했어요.

Team2 - neo4j internal(main topic)

  • Querying algorithm.md 와 LightRAG 의 Case example of retrieval augmented generation Figure 3 를 대조하며 각각의 querying step이 RAG의 어느 step과 매칭되며 동작하는지 recap 하는 시간을 가졌어요.
  • 어떤 노드 Entity,엔티티간 관계와 description relationship,해당 서브그래프가 어디에서 가져왔는지 sourceid 3가지 요소들이 retrieval result 로 가져와요. 이를, augment 하고 generation 하는 포멧은 기존 graphRAG와 동일하지만 첫 단계에서 High-level / Low-level keyword extraction 을 기점으로 search 가 시작되어 Vector 그리고 Graph Search 까지 기존에 일반적으로 활용되는 search 기법들간 의존성이 생김을 다시 한 번 상기하는 시간을 가졌어요.
  • 이번 멘토링 기간 동안 LightRAG 오픈소스를 활용하는 방법뿐 아니라, GraphRAG를 현업에 도입할 때 마주칠 수 있는 문제와 해결 방안을 GDBMS 내부 트래버설 방식 및 스토리지 구조를 가볍게 살펴봤어요.

Neo4j 데이터 스토리지 구조 및 그래프 조회시 동작을 고려한 전략

  • Index-Free Adjacency 구조. Neo4j 에서 매우 강조하는 Index-free adjacency 에 대해 간단히 알아볼 필요가 있습니다. 우선 Neo4j는 노드(Node), 관계(Relationship), 속성(Property) 간에 서로 직접 연결된 포인터 필드를 사용해 “index-free adjacency”를 구현합니다. 이 구조 덕분에 인덱스 조회 없이도 포인터 체이싱만으로 이웃 요소를 빠르게 검색할 수 있습니다.
  • 구조에 대해 잠깐 알아보았으니, 이제 구조를 탐색하기 위해 실제 레코드가 어떻게 저장이 되는지를 알아야하는데요. 다음 그림과 같이 neo4j 는 node, relationship를 각각 관리합니다. 여기에선 node,relationship 만 이야기하지만, 이외에 property , label 도 따로 .db 로 저장이 됩니다.
  • 각 node, relationship마다 무슨 요소와 연결되어 있는지 특정 offset 마다 Point가 입력되어 있습니다. 이 point 들이 계속 연결되어 있는 형태로 노드,엣지가 구성되어 있는데요. 바로, Neo4j 에서 이야기하는 Linkedlist 가 이를 뜻합니다.
  • Neo4j의 레코드 저장 구조 및 포인터 체이싱
    Neo4j는 각 노드 레코드(NodeRecord, 약 15바이트)와 관계 레코드(RelationshipRecord, 약 34바이트)에 고정 크기의 포인터 필드를 두고 있어, 이 포인터를 따라가며(pointer-chasing) 그래프를 순회합니다. '고정 크기' 포인터 필드 덕분에, 특정 포인터 주소만 알면 메모리 연산 한 번으로 다음 레코드에 즉시 접근할 수 있는데요. 각 레코드들이 고정된 값들을 가지고 있기때문에, 포인터 주소값만 알고 있다면 레코드 byte 값 * 포인트 주소값 만 수행하면 바로 해당 Point 로 이동할 수 있기에 index-free 형태로 조회할 수 있습니다.

(Person:Bob)-[:LIKES]->(Person:Alice) 라는 쿼리가 입력되었다고 할때 작동 순서입니다.

  1. NodeRecord (Bob, id=1)firstRel 포인터 = 100번(RelationshipRecord#100)의 파일 오프셋다른 필드: property 포인터, label 포인터 등
  2. RelationshipRecord#100 (LIKES, id=100)startNode 포인터 = 1 (Bob의 레코드 ID)endNode 포인터 = 2 (Alice의 레코드 ID)prevRelForStart = 0 (Bob 쪽 이전 관계가 없으므로 null)nextRelForStart = 0 (다음 관계도 없음)prevRelForEnd = 0 (Alice 쪽 이전 관계 없음)nextRelForEnd = 0 (다음 관계도 없음)
  3. NodeRecord (Alice, id=2)firstRel 포인터 = 100번(RelationshipRecord#100)

메모리 관리 전략

  • Neo4j는 Java로 구현되어 있으며, JVM 힙 크기가 약 32 GB를 초과하면 compressed ordinary object pointers(COOMPs)가 비활성화됩니다. 따라서 대용량 메모리를 효율적으로 사용하려면 그래프 핵심 구조를 오프-힙(off-heap)에 저장하도록 설계해야 합니다. 때문에, neo4j 공식 문서 에 "neo4j-admin server memory-recommendation" 를 입력해서 나온 결과물대로 적용하곤합니다.
  • Compressed Ordinary Object Pointers는 64비트 JVM에서 객체 참조 크기를 줄이는 방식입니다. 기본적으로 객체 참조는 8바이트가 필요하지만, 대부분의 Java 애플리케이션은 4GB 이하의 힙만 사용하므로 32비트 오프셋만으로도 충분합니다. JVM은 힙 주소를 8바이트 단위로 정렬하고, 하위 3비트를 버린 뒤 실행 시점에 베이스 주소를 더해 전체 64비트 주소를 복원합니다.
  • 이를 통해 포인터 저장 공간을 절반으로 줄이고 캐시 효율을 높일 수 있습니다. 힙 크기가 약 32GB를 초과하면 32비트 오프셋으로 전체 힙을 표현할 수 없게 되어 JVM이 자동으로 압축 포인터 기능을 해제하고, 다시 8바이트 포인터를 사용하게 됩니다.
  • Neo4j는 대규모 그래프 데이터를 처리하기 위해 여러 오프-힙 전략을 사용합니다. 먼저 운영체제의 메모리 매핑 I/O(mmap)를 활용하는 페이지 캐시로 노드·관계·속성·인덱스 등 스토어 파일을 자바 힙이 아닌 네이티브 메모리에 올립니다. 예를 들어 neo4j.conf에서 dbms.memory.pagecache.size=60G로 설정해 페이지 캐시 크기를 지정할 수 있습니다.
  • 둘째, java.nio API의 DirectByteBuffer를 이용해 네이티브 메모리 영역에 버퍼를 생성해 GC 부담 없이 대용량 데이터를 처리합니다. 셋째, Neo4j 내부 네이티브 라이브러리에서 임시 구조체(레코드 페이지, 트랜잭션 로그 버퍼 등)를 저장할 커스텀 메모리 풀을 오프-힙에 구성하여 GC 지연을 최소화합니다. 마지막으로 자바 힙과 오프-힙 메모리 사용량을 모두 고려해 운영체제에서 스와핑이 발생하지 않도록 튜닝해야 합니다.
  • 여기에서 모든 퍼포먼스 튜닝 전략을 알아보기엔, 내용이 너무 많으니 추가적인 내용들은 여기 neo4j performance 를 참고하시는걸 추천드려요. 이 부분도 멘토링 이후에 한 번 다뤄보도록 하겠습니다.

데이터 모델링과 데이터 인스턴스 확장(sharding) 을 활용한 최적화 전략

LightRAG backend 가 dozerdb이다보니, 당연하게도 Enterprise feature들을 모두 활용할 수 있을줄 알았습니다. dbms.components 를 찍으면 당연하게도 enterprise가 띠용 하고 나오니깐요. 당연하게도 :use db 로 instance 를 오고가며 활용할 수 있고, create db 또한 자유롭게 작동하며 가장 중요한 create composite database db 명령어가 문제없이 작동했거든요.

하지만 ₩Query across federation and shards, Query across multiple shards₩ 같은 쿼리들은 작동치 않더군요. 의아해서 다시 show database 를 살펴보니, 그 이유를 알게 되었습니다. 아래 그림의 빨간 박스에 있는 standard 가 composite 여야 하는데, 그렇지 않았던거죠. 즉, database type 까지는 지원하지 않았던 겁니다.

아마, 이를 사용하려면 application (python) 딴에서 여러개 db에 쿼리를 날려서 병합하는 수밖에 없는거 같더라구요. 이 부분은 아쉽지만 흥미롭기도해서 멘토링 끝나고 한 번 graphrag 와 조합해서 어떤 이점이 있을지 게시물로 작성해서 공유드려보도록 하겠습니다. 그때까지 혹시나 sharding 에 대해 궁금하실 분들을 위해 아래 첨부링크를 남기고갑니다.

Team3 - persona & task

  • LightRAG 에서 baseline 들을 recap했고, 각 baseline 들을 왜 그렇게 지정했는지 의도를 고민해보는 시간을 가졌어요.
  • prompts for query generation 과 prompts for evaluation 을 살펴보며, 기존 LightRAG에서 지정한 Evaluation 프레임에서 무엇을 변형해야 우리의 목적에 맞는 Evaluation 을 할 수 있을지 알아봤어요.
  • 서로 다른 그래프(Domain & Lexical) graph들을 LightRAG에 적용해서 valuation 을 하려다보니, Task를 어떻게 지정하면 좋을지 고민이 많았었요. 이를 Task1,2,3 로 나누어 가장 심플한 task1(document graph -> chunk에서 multi-hop)으로 시작하는게 어떨지 고민해보기로 했어요.

Team3 의 내용은 보완이 좀 더 필요할 거 같아서, 차주에 다뤄보도록 하겠습니다.


이번 4주차에도 다양한 이야기와 인사이트가 오갔습니다. 매주 내용을 정리하면서 얻는 통찰이 참 많습니다. 매주차마다 진행한 내용을 리뷰하며 가장 크게 느낀 점은 논문 속 이상적인 애플리케이션을 여러 사람들이 직접 사용해보며 겪는 시행착오 그리고 공유하며 얻게되는 인사이트들이 정말 값지다 라는 겁니다.

멘토링 하며, 지식을 '나눈다' 라고만 생각했는데, 되려 나누는 과정에서 더 많은 배움을 얻는 신기한 경험을 하고 있습니다. 저 역시 멘토로서 멘티분들의 토론에서 얻는 인사이트를 바탕으로 ‘편리하게 활용할 수 있는 GraphRAG’를 고민하다 보니, 그 과정 자체가 제게도 큰 성장의 자양분이 되고 있구요.

기회가 되신다면 여러분도 멘토링에 참여해 보시는건 어떠실까요. 새로운 관점을 얻고, 보다 넓은 시야로 사용자를 고민하며 한층 다른 성장을 경험하실 수 있을 거라 생각되어 강력히 추천드립니다!!!

Subscribe for daily recipes. No spam, just food.