<!doctype html>
2026년 7월 5일 | 개발 공부
Macro F1은 클래스별 F1 score를 먼저 계산한 뒤, 각 클래스를 같은 비중으로 평균내는 지표다. F1 score는 precision과 recall의 조화평균이고, 양성이라고 꺼낸 후보의 품질과 실제 양성을 얼마나 건졌는지를 한 숫자로 묶는다. 여기까지는 익숙한데, 다중 클래스 문제로 넘어가면 “어떤 평균을 냈는가”가 생각보다 큰 차이를 만든다. 평균 방식 하나가 실패 해석의 방향을 바꾼다.
정확도만 보면 흐려지는 부분
불균형 분류에서 accuracy가 위험하다는 말은 이제 꽤 익숙하다. 다수 클래스가 90%인 데이터에서는 모델이 다수 클래스만 잘 맞혀도 전체 점수가 꽤 괜찮아 보인다. 그래서 Balanced Accuracy나 MCC 같은 지표를 옆에 둔다. Macro F1도 같은 계열의 경고등이다. 다만 질문이 조금 다르다. 각 클래스가 자기 몫의 precision과 recall을 어느 정도 지켰는가를 먼저 보고, 그다음 class 수만큼 나눠 평균을 낸다.
나는 리포트에서 “전체 F1 0.86” 같은 숫자를 보면 먼저 어떤 평균인지 확인한다. micro 평균이면 샘플 단위 결정이 많이 맞았다는 뜻에 가깝고, weighted 평균이면 support가 큰 클래스 성능이 숫자에 크게 반영된다. 둘 다 틀린 지표는 아니다. 다만 작은 클래스가 운영상 중요하다면, 그 숫자 하나로는 안심하기 어렵다.
Macro, micro, weighted를 나누는 감각
Macro F1은 클래스별 F1을 같은 무게로 평균낸다. 클래스 A가 900개이고 클래스 C가 20개여도 평균에서는 둘 다 한 표다. 반대로 weighted F1은 클래스 support를 가중치로 둔다. 데이터에 많이 등장한 클래스가 평균을 더 많이 움직인다. micro F1은 클래스별로 나누기보다 전체 TP, FP, FN을 합쳐 계산하므로, 다중 클래스 단일 라벨 문제에서는 전체 accuracy와 비슷하게 움직일 때가 많다.
그래서 세 값이 서로 가까우면 class별 성능이 비교적 고르게 나온 편이라고 볼 수 있다. 반대로 weighted F1은 높은데 Macro F1만 낮다면, 작은 클래스 중 하나가 무너졌을 가능성이 크다. 이때는 평균을 더 쪼개서 class별 precision, recall, F1과 support를 같이 봐야 한다.
헷갈리는 지점은 “큰 클래스가 중요하니 weighted만 보면 된다”와 “작은 클래스도 중요하니 macro만 보면 된다”가 둘 다 너무 빠른 결론이라는 점이다. 제품 로그 분류처럼 실제 트래픽 비율이 비용 구조와 거의 맞물리는 작업에서는 weighted 평균이 운영 체감과 더 가까울 수 있다. 반대로 안전 필터, 장애 탐지, 리뷰 라벨링처럼 드문 라벨 하나가 전체 의사결정을 바꾸는 작업에서는 macro 평균이 먼저 경고를 준다.
작은 예제로 보는 평균 착시
예를 들어 클래스 A의 F1이 0.92, B가 0.62, C가 0.15라고 하자. A는 샘플이 900개, B는 80개, C는 20개뿐이다. weighted 평균은 A의 0.92에 강하게 끌려 꽤 높게 나온다. 하지만 Macro F1은 세 클래스의 F1을 거의 그대로 평균내므로 C의 실패가 숫자 안에 남는다. 이 차이는 단순한 통계 취향이 아니라 운영 판단의 차이다. 같은 모델이라도 고객 문의 자동 분류에서는 C가 드문 오타 라벨일 수 있고, 의료 선별에서는 C가 반드시 잡아야 하는 위험 라벨일 수 있다. 지표 선택은 결국 어떤 실패를 먼저 볼 것인지의 선언에 가깝다.
내가 실제 모델 비교표를 만들 때 실수하기 쉬운 지점도 여기다. 작은 클래스가 “희귀하지만 중요하지 않은 잡음”이면 weighted 평균이 더 맞을 수 있다. 하지만 작은 클래스가 장애, 이상 거래, 위험 신호처럼 놓치면 비용이 큰 대상이면 Macro F1이 낮다는 사실을 먼저 받아들여야 한다. 평균을 예쁘게 만드는 대신, 모델이 못 보는 영역을 숨기지 않는 쪽이 더 안전하다.
Macro F1도 만능은 아니다
Macro F1은 작은 클래스를 살려 주지만, label noise가 심한 소수 클래스까지 같은 무게로 키운다는 단점도 있다. support가 5개뿐인 클래스의 F1이 우연히 크게 흔들리면 전체 Macro F1도 같이 흔들린다. 그래서 나는 Macro F1 옆에 class별 support와 confusion matrix를 꼭 붙인다. 가능하면 bootstrap confidence interval도 같이 본다. 소수 클래스에 같은 무게를 주는 것과, 소수 샘플의 우연한 흔들림까지 과하게 믿는 것은 다른 문제이기 때문이다.
또 하나는 threshold 문제다. binary one-vs-rest 식으로 score를 잘라 F1을 계산한다면 threshold를 어디에 두었는지가 중요하다. validation set에서 정한 threshold를 test에 고정했는지, test 결과를 보고 최고점을 고른 것인지가 섞이면 지표가 금방 낙관적으로 보인다. Macro F1은 class 균형을 보게 해 주지만, 평가 설계 자체를 대신해 주지는 않는다.
내가 표에 남기는 최소 항목
개발 중간 리포트라면 나는 보통 네 줄을 같이 남긴다. 첫째, 전체 accuracy나 micro F1. 둘째, weighted F1. 셋째, Macro F1. 넷째, class별 support와 class별 F1이다. 여기에 작은 클래스가 중요한 작업이면 class별 recall을 따로 강조한다. 이렇게 적어 두면 나중에 “모델 B가 평균은 조금 낮은데 왜 더 낫다고 봤지?” 같은 질문이 왔을 때, 당시의 판단 근거를 다시 찾기 쉽다.
특히 여러 모델을 한 표에 넣을 때는 최고값만 굵게 칠하지 않으려고 한다. Macro F1이 낮은 모델은 어느 클래스에서 깨졌는지 각주를 붙이고, weighted F1만 높은 모델은 support 분포를 같이 적는다. 이 작은 메모가 없으면 다음 실험에서 데이터 증강을 해야 하는지, threshold를 다시 잡아야 하는지, label 정의를 고쳐야 하는지 판단이 흐려진다.
Macro F1은 멋있는 새 지표라기보다 평균을 내기 전에 한 번 멈추게 만드는 장치에 가깝다. 숫자가 하나로 접히는 순간 어떤 클래스가 목소리를 잃는지 확인하는 일. 나는 이 지표를 볼 때마다 모델 성능표에서 평균보다 먼저 class별 행을 보는 버릇을 다시 떠올린다.
'[개발 공부]' 카테고리의 다른 글
| G-mean: 한쪽 Recall이 무너지면 함께 내려가는 분류 점수 (0) | 2026.07.10 |
|---|---|
| Micro F1와 Accuracy가 겹치는 지점 (0) | 2026.07.06 |
| Cohen's Kappa: 우연 일치가 만든 정확도 착시 (0) | 2026.07.03 |
| Balanced Accuracy: 다수 클래스 뒤의 실패율 (0) | 2026.07.03 |
| Matthews Correlation Coefficient: 불균형 분류의 네 칸 점수 (0) | 2026.07.02 |