[AI 실험실]/[개인 프로젝트] GNN / GNN | Negative edge score histogram 추가.md

GNN | Negative edge score histogram 추가

조회

시리즈: GNN 실험일지 #12

이전: 11편 | 목록 | 다음: 13편

2026년 5월 14일 | 개인 프로젝트


Negative edge score histogram을 붙여 보니, 직전 score bias probe에서 한 덩어리로 보였던 false positive 문제가 둘로 갈라졌다. 둘 다 negative_score_leak이라는 이름을 달고 있었지만, 실제 score bucket을 열어 보니 reduced_plus_degree는 모든 negative edge가 0.5 바로 위에 붙어 있었고, reduced_plus_closed_triplets는 하나의 edge가 유난히 크게 튀었다. 나는 이 차이가 꽤 중요하다고 봤다. 같은 FP-heavy라도 다음에 열어야 할 파일이 달라지기 때문이다.

이번 작업은 새 모델을 붙이는 일이 아니었다. 이미 만들어 둔 edge-case table과 score bias probe를 다시 읽어서, negative_score_histogram follow-up queue에 들어간 config만 따로 보는 얇은 리포트를 추가했다. 요즘 이 GNN 프로젝트는 계속 비슷한 방향으로 가고 있다. 평균 AUC를 한 번 더 올리기보다, 왜 어떤 split에서 없는 edge를 있다고 보는지 조금씩 아래로 내려가는 쪽이다. 처음에는 답답했는데, 막상 이렇게 실패 모양을 잘게 쪼개니 다음 실험이 더 덜 흔들린다.

왜 score 평균만으로는 부족했나

직전 probe에서는 positive edge 평균 score와 negative edge 평균 score를 나눠 봤다. 그 결과 reduced_plus_degree는 positive 평균이 0.5454, negative 평균이 0.5464였다. 거의 붙어 있다. reduced_plus_closed_triplets도 positive 평균 0.5050, negative 평균 0.5153이라 positive 쪽이 더 높지 않았다. 여기까지만 보면 둘 다 비슷한 실패처럼 보인다.

그런데 평균은 edge별 모양을 지워 버린다. negative edge가 전부 0.53 근처에 몰려 있는 것과, 네 개는 그럭저럭인데 하나가 0.95까지 튀는 것은 전혀 다른 문제다. 전자는 score surface 전체가 threshold 근처에서 살짝 밀린 쪽이고, 후자는 특정 edge context가 모델을 속였을 가능성이 더 크다. 그래서 이번에는 negative edge만 따로 뽑아서 bucket을 만들었다.

Negative edge score histogram
negative edge score를 hard leak, borderline leak, near-threshold safe, clear safe로 나눈 요약. degree variant는 넓은 borderline leak, closed-triplets variant는 hard outlier leak 성격이 더 강했다.

이번에 추가한 리포트

코드 쪽에서는 build_negative_score_histogram_report()와 runner를 추가했다. 입력은 기존 산출물 두 개다. 하나는 hardest seed 안의 edge별 probability를 담은 edge-case table이고, 다른 하나는 score bias probe 결과다. score bias probe의 follow-up queue에서 next_probenegative_score_histogram인 config만 골라서 분석한다.

bucket은 일부러 단순하게 뒀다. threshold 0.5를 기준으로 0.60 이상은 hard_leak, 0.50 이상 0.60 미만은 borderline_leak, 0.40 이상 0.50 미만은 near_threshold_safe, 그 아래는 clear_safe다. 처음부터 복잡한 histogram bin을 많이 만드는 것보다, 지금은 다음 행동을 고르는 데 필요한 정도로만 자르는 편이 낫다고 봤다.

그리고 각 bucket count만 남기지 않았다. leaked negative edge와 safe negative edge의 structural snapshot 평균도 같이 저장했다. 현재 snapshot에는 degree_mean, degree_gap, avg_neighbor_degree_mean, closed_triplets_mean, clustering_mean, two_hop_neighbors_mean이 들어간다. 나중에 degree gap이나 two-hop 구조가 false positive와 어떻게 엮이는지 바로 이어서 볼 수 있게 해 둔 셈이다.

결과: 두 종류의 leak

config leaked / negative leak rate hard leak borderline leak max negative score
reduced_plus_degree 5 / 5 100% 0 5 0.5569
reduced_plus_closed_triplets 4 / 5 80% 1 3 0.9476

reduced_plus_degree는 negative edge 5개가 전부 0.5 이상이었다. 그런데 max score는 0.5569다. 강하게 터진 edge가 있다기보다는 모든 negative edge가 애매하게 양성 쪽으로 넘어갔다. 이 경우에는 특정 outlier를 잡는 것보다, degree 관련 feature가 negative sampling 후보 전체에 어떤 bias를 주는지 봐야 한다.

reduced_plus_closed_triplets는 더 거칠다. negative edge 5개 중 4개가 leak이고, 그중 하나는 0.9476까지 올라갔다. 반대로 하나는 clear safe로 내려갔다. 이건 평균으로는 잘 안 보이는 모양이다. 나는 이 결과를 보고 closed-triplets variant를 바로 나쁘다고 결론내리기보다, hard leak edge를 먼저 case table로 열어야겠다고 생각했다.

structural snapshot에서 보인 단서

leaked negative edge의 structural snapshot도 조금 달랐다. reduced_plus_degree의 leaked edge 평균은 degree_mean=1.9, degree_gap=1.0, avg_neighbor_degree_mean=2.6833이었다. 아주 높은 degree edge가 한두 개 튄 모양은 아니다. 그래서 지금은 degree가 높은 edge만 문제라기보다, reduced core 위에 degree를 얹었을 때 borderline score가 전체적으로 올라가는 쪽을 의심하고 있다.

reduced_plus_closed_triplets의 hard leak top edge는 [0, 7]이었다. score가 0.9476이었고, snapshot은 degree_mean=2.5, degree_gap=1.0, two_hop_neighbors_mean=2.5, closed_triplets_mean=0.0, clustering_mean=0.0이었다. 재미있는 건 이름은 closed-triplets variant인데, 가장 크게 튄 edge 자체는 triangle signal이 살아 있는 edge가 아니었다는 점이다. 이건 좀 허무하면서도 유용했다. 내가 붙인 config 이름만 보고 원인을 단정하면 안 된다는 뜻이니까.

다음으로 볼 것

다음 반복은 negative edge context audit 쪽이 자연스럽다. 지금은 leaked negative edge가 몇 개인지와 score bucket만 봤다. 이제는 그 edge들을 degree gap, shared-neighbor, graph family로 다시 묶어야 한다. 특히 reduced_plus_degree는 borderline leak이 모든 negative edge에 퍼지는 이유를 봐야 하고, reduced_plus_closed_triplets는 hard outlier edge 하나를 자세히 열어야 한다.

이 프로젝트가 점점 느려지는 느낌도 있다. 모델을 하나 더 붙이면 글감은 빨리 나오는데, 지금은 작은 리포트를 계속 쌓고 있다. 그래도 링크 예측 쪽은 이런 작은 진단표가 없으면 평균 AUC에 쉽게 속는다. 없는 edge를 왜 있다고 보는지 설명하지 못하면, 다음 encoder를 올려도 같은 실수를 더 비싼 형태로 반복할 가능성이 크다. 그래서 당분간은 이 실패 장면을 조금 더 물고 늘어질 생각이다.

시리즈: GNN 실험일지 #12

이전: 11편 | 목록 | 다음: 13편

댓글

홈으로 돌아가기

검색 결과

"" 검색 결과입니다.