2026년 4월 28일 | 개인 프로젝트
structural variant의 평균 AUC 표를 몇 번 다시 보다가, 결국 숫자를 한 단계 더 아래로 내렸다. seed별 ranking까지는 이미 봤지만, 내가 정말 궁금했던 건 더 작은 단위였다. hardest seed 안에서 어떤 positive edge를 놓쳤고, 어떤 negative edge를 잘못 붙였는가. 이번 GNN 반복은 그 질문을 확인하려고 edge-level case table을 하나 추가한 작업이다.
앞선 글에서는 sample_collab_graph와 bipartite_bridge_graph를 같이 놓고, dataset별 hardest seed를 따로 골랐다. 그때는 reduced_plus_degree, reduced_plus_closed_triplets, propagation_only가 서로 다른 방식으로 버틴다는 정도까지 봤다. 그런데 AUC 하나만 보면 false positive와 false negative가 섞인다. 없는 edge를 너무 쉽게 붙이는 모델과, 있어야 할 edge를 계속 놓치는 모델은 둘 다 점수가 낮아질 수 있지만 고쳐야 할 방향은 다르다.
1. 이번에 추가한 것
코드는 크게 벌리지 않았다. 기존 GraphSAGE 학습 결과에 test edge별 probability와 logit을 남기고, multidataset_structural_variant_report에서 dataset별 hardest seed를 다시 읽어 같은 split 위에서 다섯 config를 재학습했다. 그런 다음 edge마다 config별 probability, predicted label, signed margin, structural snapshot을 저장했다.
- test_edge_scores: 각 test edge의 probability와 logit 저장
- edge-case JSON: dataset, hardest seed, edge label, config별 score를 한 파일에 정리
- CSV export: 나중에 spreadsheet나 notebook으로 다시 볼 수 있게 평평한 표로 저장
- 검증: edge-case table 생성 테스트를 추가했고 전체 테스트는 12개 전부 통과
이번에 마음에 들었던 지점은 새 모델을 붙이지 않았다는 점이다. 성능을 올리려는 반복이 아니라, 이미 나온 실패를 더 잘 쪼개는 반복이었다. 작은 프로젝트에서는 이 단계가 은근히 중요하다. 평균이 낮다는 말만 남기면 다음 행동이 너무 넓어지고, edge 단위로 보면 어느 쪽 오판부터 줄여야 하는지 조금 더 선명해진다.
2. 전체 edge 기준으로 본 실패 방향
두 데이터셋의 hardest seed에서 나온 test edge를 합쳐 config별 false positive와 false negative를 세어 봤다. 표본 수가 아직 작기 때문에 순위를 과하게 믿으면 안 된다. 그래도 방향성은 꽤 다르게 갈렸다.
| config | false positive | false negative | correct | mean margin | worst margin |
|---|---|---|---|---|---|
| reduced_plus_degree | 5 | 0 | 5 | -0.0006 | -0.0569 |
| propagation_only | 1 | 4 | 5 | -0.0027 | -0.0322 |
| reduced_plus_closed_triplets | 4 | 1 | 5 | -0.0052 | -0.4476 |
| hybrid_reduced | 2 | 3 | 5 | -0.0062 | -0.0835 |
| hybrid_full | 3 | 4 | 3 | -0.0062 | -0.1248 |
reduced_plus_degree는 false negative가 없었다. 대신 negative edge를 positive로 올리는 쪽으로만 틀렸다. 반대로 propagation_only는 false positive가 1개뿐이고 false negative가 4개다. 이 차이가 이번 표에서 제일 먼저 눈에 들어왔다. 둘 다 평균표에서는 비슷하게 애매해 보일 수 있지만, 한쪽은 너무 잘 붙이고 다른 한쪽은 너무 조심스럽다.
Figure 1. hardest seed의 edge-level false positive와 false negative 방향. 같은 AUC 하락이라도 틀리는 방향은 다르게 갈렸다.
Figure 1은 이 차이를 시각적으로 더 잘 보여 준다. reduced+degree는 빨간 막대만 있고, propagation-only는 파란 막대가 훨씬 길다. 나는 이런 표가 있어야 다음 실험이 덜 감정적으로 된다. 그냥 "이 설정이 낮다"가 아니라, threshold를 조정해야 하는지, positive recall을 올려야 하는지, structural feature를 빼야 하는지 방향이 달라지기 때문이다.
3. sample_collab에서 가장 크게 흔들린 edge
sample_collab_graph의 hardest seed는 5였다. 여기서는 negative edge 0-7과 5-8, positive edge 5-6과 7-8이 test edge로 잡혔다. 이 네 줄만 봐도 config별 성격이 꽤 달랐다.
| edge | label | 가장 잘 본 설정 | 가장 흔들린 설정 | 메모 |
|---|---|---|---|---|
| 0-7 | negative | hybrid_full | reduced_plus_closed_triplets | triads 쪽 probability가 0.9476까지 올라간 단일 최대 오판 |
| 5-8 | negative | reduced_plus_closed_triplets | reduced_plus_degree | 같은 negative라도 0-7과 반대로 triads가 제일 안정적으로 낮게 봄 |
| 5-6 | positive | reduced_plus_degree | reduced_plus_closed_triplets | positive recall에서는 degree add-back이 더 나은 쪽으로 작동 |
| 7-8 | positive | reduced_plus_closed_triplets | hybrid_full | full만 놓쳤고 나머지 설정은 모두 positive로 회수 |
특히 0-7이 재미있었다. structural snapshot을 보면 degree mean은 2.5, closed_triplets mean은 0, clustering mean도 0이었다. 그런데 reduced+closed_triplets는 이 negative edge를 거의 확신에 가깝게 positive로 봤다. 반면 같은 sample_collab 안의 negative edge 5-8에서는 triads가 probability 0.0037까지 낮게 봤다. 그러니까 closed_triplets를 넣었다고 항상 공격적이거나 항상 보수적인 게 아니다. edge context에 따라 방향이 뒤집힌다.
4. bipartite에서는 오판 방향이 더 깔끔하게 갈림
bipartite_bridge_graph의 hardest seed는 7이었다. 이쪽은 삼각형이 없는 그래프라 closed_triplets와 clustering이 대부분 죽는다. 그래서 sample_collab에서 붙인 역할 이름을 그대로 가져오면 바로 헷갈린다. edge table을 보니 오히려 오판 방향이 더 깔끔하게 갈렸다.
- reduced_plus_closed_triplets와 reduced_plus_degree는 positive edge 5-10, 5-11을 상대적으로 잘 회수했다.
- 대신 두 설정은 negative edge 0-11, 4-8에서 false positive로 기울었다.
- propagation_only와 hybrid_reduced는 반대로 negative edge를 비교적 잘 낮게 봤지만, positive edge를 자주 놓쳤다.
- hybrid_full은 positive와 negative 양쪽에서 모두 흔들려 전체 correct count가 가장 낮았다.
이 결과는 내가 기대했던 것보다 더 실용적이었다. reduced+degree와 propagation-only 중 무엇이 더 좋은가를 묻는 대신, 어떤 오류를 더 참을 수 있는가를 물어야 했다. 추천 시스템처럼 잘못 붙인 edge가 비용이 크면 propagation-only 쪽의 보수성이 나을 수 있고, 누락 비용이 더 크면 reduced+degree나 triads 쪽이 낫다. 물론 지금은 toy graph라 결론을 일반화할 수는 없지만, 평가 질문은 분명히 바뀌었다.
5. 다음 반복에서 볼 것
이번 반복을 하고 나니 다음 작업은 두 갈래로 보인다. 하나는 synthetic graph family를 더 늘려 edge-case table의 표본 수를 키우는 일이다. 지금은 dataset 2개와 hardest seed 2개라서 edge 수가 너무 작다. 다른 하나는 threshold calibration이다. probability 0.5 기준으로 자른 지금 표에서는 false positive와 false negative가 보이지만, 실제로는 config별로 적절한 cutline이 다를 수 있다.
나는 당장은 첫 번째가 더 맞다고 본다. calibration은 표본이 조금 더 있을 때 하는 편이 덜 위험하다. 지금 단계에서는 triangle-rich graph와 triangle-free graph를 하나씩 더 만들고, 같은 edge-case table을 다시 돌려 보는 게 낫다. 그래야 degree, closed_triplets, clustering 같은 structural feature가 정말 graph family에 따라 역할이 갈리는지 조금 더 자신 있게 말할 수 있다.
이번 작업은 성능을 올린 날이라기보다 실패를 더 잘 펼쳐 본 날에 가깝다. 그런데 이런 날이 있어야 다음 개선이 덜 막연해진다. 평균 AUC가 낮다는 한 줄보다, 없는 edge를 너무 붙이는지와 있는 edge를 너무 놓치는지가 갈라지는 순간 다음 실험의 모양도 달라진다.
'[AI 실험실] > [개인 프로젝트] GNN' 카테고리의 다른 글
| GNN | Validation threshold의 test 적용 리포트 (0) | 2026.05.04 |
|---|---|
| GNN | Threshold sweep로 본 FP/FN 균형 (0) | 2026.04.28 |
| GNN | Structural variant failure-case report (0) | 2026.04.27 |
| GNN | Structural variant의 bipartite 재검증 (0) | 2026.04.25 |
| GNN | Hybrid structural 축 ablation (0) | 2026.04.20 |