2026년 7월 1일 | 개인 프로젝트 · GNN
Closed-triplet addback 리포트를 만들고 나니, 지난 회차에서 봤던 hard negative 하나가 조금 다르게 보였다. `sample_collab_graph`의 [0, 7] edge는 이미 baseline에서도 0.5를 살짝 넘고 있었지만, closed-triplet feature를 다시 얹는 순간 0.9476까지 튀었다. 이건 단순히 “threshold를 조금 넘었다”보다 모델이 이 negative edge를 너무 확신하게 됐다는 쪽에 가까웠다.
이번 질문은 오차가 아니라 확신도였다
지난 회차에서는 `hybrid_reduced` 대비 `reduced_plus_closed_triplets`의 probability delta가 +0.4185라는 점을 확인했다. 처음에는 이 숫자만 보고 “closed-triplet addback이 문제네” 정도로 넘길 수도 있었다. 그런데 막상 다시 보니, 이 edge는 baseline에서도 0.5291이었다. 0.5 threshold를 아래에서 위로 넘긴 사례가 아니라, 이미 positive 쪽으로 기울어 있던 edge를 high-confidence 영역까지 밀어 올린 사례였다.
그래서 이번에는 새 학습 루프를 돌리지 않고, 기존 ablation 산출물 위에 sensitivity 리포트를 한 겹 더 얹었다. 목표는 edge 하나를 세 가지 질문으로 나누는 것이었다. baseline은 threshold 주변인가, closed-triplet addback 뒤에 high-confidence 기준을 넘는가, 그리고 그 delta가 다음 probe로 보낼 만큼 큰가. 성능 표 전체를 다시 보는 것보다, 실패 edge 하나의 상태를 이렇게 분류하는 편이 다음 작업을 정하기 쉬웠다.
threshold-crossing과 confidence-amplification을 나눴다
새 리포트에서 가장 먼저 만든 라벨은 `threshold_crossed`와 `confidence_amplified`다. 전자는 baseline에서는 0.5 아래였는데 closed-triplet addback 뒤에 0.5를 넘는 경우다. 이런 케이스라면 threshold calibration이나 cost-sensitive policy 쪽으로 이어 붙일 수 있다. 반대로 후자는 baseline에서도 이미 0.5 이상이지만, addback 뒤에 0.8 high-confidence 기준을 넘는 경우다. 이쪽은 단순 threshold 조정보다 feature component 분석이 먼저다.
[0, 7]은 두 번째 라벨에 걸렸다. baseline margin은 +0.0291이라 결정 경계 바로 위에 있었고, closed-triplet addback 뒤 margin은 +0.4476까지 커졌다. score shift bucket도 `high_amplification`으로 들어갔다. 나는 이 구분이 꽤 중요하다고 느꼈다. 같은 false positive라도 0.51짜리 오차와 0.95짜리 오차는 모델을 고칠 때 보는 위치가 다르다.
구현은 기존 실패 사례 위에 작게 붙였다
코드 변경은 일부러 작게 잡았다. 입력은 전 회차에서 만든 `shared_neighbor_feature_ablation` 리포트 하나다. 그 안에서 `next_probe`가 `closed_triplet_addback_sensitivity`인 row만 골라 baseline probability, closed-triplet probability, delta, threshold margin을 다시 계산했다. 이후 JSON, CSV, PNG를 같은 runner에서 한 번에 남기도록 했다.
테스트도 두 개만 추가했다. builder 테스트에서는 [0, 7]이 `confidence_amplified`로 분류되는지 확인했고, runner 테스트에서는 JSON, CSV, PNG 산출물이 모두 만들어지는지 봤다. 전체 테스트는 40개가 통과했다. 큰 기능은 아니지만, 이전 회차에서 “다음에 봐야 할 것”으로 남겨 둔 probe를 실제 산출물로 닫았다는 점에서 만족스러웠다.
공통 이웃 하나가 만든 큰 점프
이 edge가 까다로운 이유는 train graph 안에서 node 1을 공통 이웃으로 공유하기 때문이다. common neighbor count는 1이고 Jaccard는 0.25라서 숫자만 보면 과하게 커 보이지 않는다. 그런데 closed-triplet 계열 feature를 다시 넣으면 score는 0.9476까지 올라간다. 작은 그래프에서는 공통 이웃 하나도 split과 heldout edge 주변 문맥에 따라 꽤 강한 신호가 된다.
여기서 바로 sampler를 바꾸거나 threshold를 올리면, 원인을 조금 뭉개게 된다. 이번 결과는 sampler 문제가 없다는 뜻이 아니라, 지금 관찰한 현상은 먼저 closed-triplet component 안에서 쪼개 보는 게 더 맞다는 뜻이다. 특히 `hybrid_full`은 오히려 0.4171로 낮았기 때문에, “structural feature 전체가 위험하다”보다 “특정 addback 조합이 국소적으로 확신도를 키웠다”는 해석이 더 자연스럽다.
다음 probe는 component breakdown
이번 리포트의 follow-up queue는 `closed_triplet_component_breakdown`으로 잡았다. 다음에는 closed-triplet addback을 하나의 덩어리로 보지 않고, 공통 이웃 수, Jaccard, Adamic-Adar, resource allocation 같은 similarity 성분과 실제 closed-triplet flag 성분을 더 잘게 나눠 볼 생각이다. score를 키운 게 단순한 공통 이웃 존재인지, 특정 similarity scaling인지, 아니면 다른 feature와의 조합인지 확인해야 한다.
작은 graph 실험은 가끔 너무 자잘해 보인다. 그래도 이런 식으로 실패 edge 하나를 계속 좁혀 가면, 나중에는 “모델이 틀렸다”가 아니라 “어떤 구조 신호가 어떤 상황에서 확신도를 키웠다”까지 말할 수 있다. 이번 회차의 결론은 그 정도다. [0, 7]은 threshold 주변 오차가 아니라 closed-triplet addback이 만든 high-confidence 증폭 사례였고, 다음 작업은 그 addback 내부를 분해하는 쪽으로 가야 한다.
'[AI 실험실] > [개인 프로젝트] GNN' 카테고리의 다른 글
| GNN | 13차원에서 비교한 Closed-triplet 마스킹 재학습 (1) | 2026.07.15 |
|---|---|
| GNN | Closed-triplet 단일 공통 이웃 분해 (1) | 2026.07.04 |
| GNN | Closed-triplet addback 점수 변화 (1) | 2026.06.27 |
| GNN | 공통 이웃 feature 압력 진단 (0) | 2026.06.24 |
| GNN | Negative target slice 분리 (0) | 2026.05.18 |