[AI 실험실]/[개인 프로젝트] GNN / GNN | Closed-triplet addback 점수 변화.md

GNN | Closed-triplet addback 점수 변화

조회

시리즈: GNN 실험일지 #17

이전: 16편 | 목록 | 다음: 18편

2026년 6월 27일 | 개인 프로젝트 · GNN


GNN 링크 예측 실험에서 hard negative 하나가 계속 신경 쓰였다. `sample_collab_graph`의 [0, 7] edge는 실제로는 negative인데, 몇몇 structural variant에서는 positive처럼 높은 점수를 받았다. 전 회차에서는 이 edge가 train graph 안에서 node 1을 공통 이웃으로 공유한다는 것까지 확인했다. 그래서 이번에는 질문을 조금 더 좁혔다. “공통 이웃이 있다”는 사실이 실제 score에서는 어떤 feature 조합을 통해 커지는가.

Shared-neighbor feature ablation에서 closed-triplet addback, degree addback, full feature 조합의 probability delta를 비교한 그래프
Figure 1. hybrid_reduced를 기준으로 feature addback별 hard negative score 변화를 비교했다.

이번에는 threshold가 아니라 feature addback을 먼저 봤다

처음에는 threshold를 다시 조정해야 하나 싶었다. negative edge가 0.5 근처를 넘나들면, test threshold를 조금 올리는 방식으로 false positive를 줄일 수도 있기 때문이다. 그런데 이 edge는 그런 식으로 바로 넘기기에는 모양이 애매했다. 어떤 설정에서는 0.50 근처에 있고, 어떤 설정에서는 0.94까지 올라갔다. threshold 문제가 아니라 특정 feature 조합이 edge 하나를 강하게 밀어 올리는지를 먼저 봐야 했다.

이번에 추가한 리포트는 그래서 단순하다. 전 회차의 common-neighbor audit에서 `shared_neighbor_feature_ablation`으로 넘겨 둔 target edge만 가져온다. 그다음 기존 edge-case table에 들어 있던 config별 probability를 다시 붙인다. baseline은 `hybrid_reduced`로 잡았다. 여기서 structural core만 남긴 상태를 기준으로 두고, closed-triplet addback, degree addback, full feature 조합이 각각 score를 얼마나 움직이는지 계산했다.

이 방식이 마음에 드는 이유는, 모델을 새로 크게 돌리지 않고도 이미 저장한 실패 사례를 더 작게 해부할 수 있기 때문이다. 나는 실험 로그를 오래 쌓다 보면 “성능이 올랐다”, “false positive가 늘었다” 같은 큰 문장만 남기기 쉬운데, 실제로 다음 액션을 정하려면 edge 하나의 score가 어느 설정에서 튀었는지를 더 좁게 봐야 한다.

닫힌 삼각형 addback이 혼자 크게 움직였다

결과는 꽤 분명했다. `hybrid_reduced`에서 [0, 7]의 probability는 0.5291이었다. propagation-only의 0.5021과 비교하면 약간 올라간 정도다. degree를 다시 더한 `reduced_plus_degree`도 0.5404라서 baseline 대비 delta가 +0.0113에 그쳤다. 이 정도면 degree addback이 이 hard negative를 주범처럼 끌어올렸다고 말하기는 어렵다.

반면 `reduced_plus_closed_triplets`는 probability가 0.9476까지 올라갔다. baseline 대비 delta가 +0.4185다. 같은 edge, 같은 seed, 같은 문제인데 closed-triplet addback을 넣는 순간 score가 거의 positive 확신에 가까워졌다. 이건 threshold를 몇 칸 옮겨서 해결할 종류의 신호가 아니다. feature 쪽에서 “이 edge를 positive처럼 보는 이유”가 강하게 들어왔다고 보는 편이 맞다.

재미있는 건 full feature 조합인 `hybrid_full`은 오히려 0.4171로 낮게 나왔다는 점이다. 모든 structural feature를 넣으면 항상 더 위험해지는 게 아니었다. 이 결과만 보면, 전체 feature set이 문제라기보다 reduced core 위에 closed-triplet 계열을 얹었을 때 생기는 국소적인 상승을 따로 봐야 한다. 이런 패턴은 성능 표 하나만 봐서는 잘 안 보인다.

공통 이웃 하나가 만드는 착시

[0, 7]은 train graph 안에서 node 1을 공통 이웃으로 공유한다. 사람 눈으로 보면 “둘이 한 다리 건너 연결돼 있으니 edge가 생길 수도 있겠네”라고 볼 수 있다. 링크 예측 모델 입장에서도 비슷한 압력이 생긴다. 문제는 test negative 안에는 이런 모양의 edge도 들어 있고, heldout positive 주변 정보까지 겹치면 score가 쉽게 부풀 수 있다는 점이다.

전 회차에서 이 edge의 common neighbor count는 1, Jaccard는 0.25, Adamic-Adar는 1.4427로 나왔다. 숫자만 놓고 보면 아주 큰 값은 아니다. 그런데 이번 score delta를 붙여 보니, 작은 공통 이웃 신호라도 특정 addback 조합에서는 꽤 큰 확신으로 증폭될 수 있었다. 나는 여기서 “feature가 많으면 좋다”보다 “어떤 feature가 어떤 split에서 착시를 만드는가”를 따로 기록해야 한다는 쪽으로 생각이 바뀌었다.

특히 toy graph나 작은 benchmark에서는 이런 문제가 더 잘 드러난다. edge 수가 적으면 공통 이웃 하나의 의미가 상대적으로 커지고, train/test split에 따라 heldout positive 주변의 문맥도 쉽게 흔들린다. 그래서 이번 리포트는 큰 모델 개선이라기보다, 작은 graph에서 structural feature를 다룰 때 어디를 먼저 의심해야 하는지 알려 주는 진단 도구에 가깝다.

구현은 실패 사례 테이블에 한 겹 더 얹었다

코드 쪽에서는 새 학습 루프를 만들지 않았다. 이미 저장해 둔 `common_neighbor_feature_audit`와 `edge_cases` 산출물을 join하는 방식으로 처리했다. target edge의 dataset, hardest seed, edge tuple을 key로 맞춘 뒤 config별 probability를 한 row에 모았다. 그다음 `hybrid_reduced`를 기준으로 네 가지 delta를 계산했다.

이번에 남긴 핵심 비교는 네 개다. closed-triplet addback delta, degree addback delta, full-vs-reduced delta, reduced-vs-propagation delta. 그리고 가장 큰 양의 delta가 일정 기준을 넘으면 다음 probe를 자동으로 라우팅한다. 이번 edge는 `closed_triplet_addback_sensitivity`로 넘어갔다. 이름은 길지만, 다음에 해야 할 일은 단순하다. closed-triplet 계열을 더 잘게 켜고 끄면서 이 상승이 어디서 생기는지 확인하면 된다.

테스트도 그 방향에 맞췄다. builder가 [0, 7]의 closed-triplet addback delta를 +0.4185로 계산하는지 확인했고, runner가 JSON, CSV, PNG 산출물을 모두 쓰는지도 확인했다. 전체 테스트는 38개가 통과했다. 작은 기능이지만, 이전 회차에서 “다음에 봐야 할 것”으로 남긴 항목을 실제 리포트로 닫았다는 점에서 진행감이 있었다.

다음 액션은 sampler보다 sensitivity check

이번 결과를 보고 바로 negative sampler를 바꾸지는 않기로 했다. sampler도 결국 봐야 할 수 있지만, 지금은 closed-triplet addback 하나가 너무 크게 튀었다. 먼저 이 feature가 특정 edge에서만 과하게 반응하는지, 아니면 같은 유형의 shared-neighbor negative들에서도 반복되는지를 봐야 한다.

다음 반복에서는 `closed_triplet_addback_sensitivity` 리포트를 만들 생각이다. 후보는 두 가지다. 하나는 closed-triplet addback을 유지하되, shared-neighbor negative를 더 넓게 모아 edge별 delta 분포를 보는 방식이다. 다른 하나는 closed-triplet과 Jaccard/Adamic-Adar 같은 similarity 계열을 분리해서 “닫힌 삼각형 자체”와 “공통 이웃 유사도” 중 무엇이 더 score를 밀어 올리는지 보는 방식이다.

이번 회차에서 얻은 결론은 짧다. [0, 7] hard negative는 degree addback 문제가 아니었다. propagation-only에서 reduced core로 넘어가는 변화도 작았다. score를 크게 흔든 건 closed-triplet addback이었다. 그래서 다음 실험은 threshold 조정보다 feature sensitivity 쪽으로 가는 게 맞다. 이 정도로 방향이 좁혀지면, 작은 graph 실험도 그냥 로그가 아니라 다음 결정을 만드는 재료가 된다.

시리즈: GNN 실험일지 #17

이전: 16편 | 목록 | 다음: 18편

댓글

홈으로 돌아가기

검색 결과

"" 검색 결과입니다.