지난주 모델이 더 좋았는데 아무도 못 찾는다 · 모델은 그대로인데 세상이 바뀌었다 · 이론
범위 안에서 움직이는 분포
한 줄 요약
드리프트는 계약 위반이 아니다 — 값이 전부 허용 범위 안에 있어도 분포가 옮겨
갈 수 있고, 그것을 잡으려면 범위 검사가 아니라 분포를 비교하는 지표가 필요하다.
왜 이게 필요했나
앞 모듈에서 만든 데이터 계약은 강력하지만 한 가지를 못 잡는다. 사용 시간의 평균이
38 시간에서 55 시간으로 옮겨 가도, 그 값들은 여전히 "0~400" 이라는 범위 안에 있다.
계약은 통과하고 학습도 정상이고 경보도 없다. 그런데 모델이 배운 관계는 옛날 분포
위에서 세운 것이라, 예측은 조금씩 빗나가기 시작한다.
레이블이 바로 오지 않는 문제가 여기에 겹친다. 해지 예측이라면 그 고객이 정말
해지했는지는 한 달 뒤에야 안다. 정확도로 이상을 알아채려면 한 달을 기다려야 하는데,
입력 분포는 지금 당장 잴 수 있다. 그래서 드리프트 감시는 레이블을 기다리는 동안
쓰는 조기 신호다.
어떻게 동작하나
TFX 문서는 데이터 검증을 세 가지로 나눠 설명한다. 스키마 기반 검증, 학습-서빙
왜곡(training-serving skew) 탐지, 그리고 일련의 데이터를 이어 보며 드리프트를
찾는 것이다([TensorFlow Data Validation](https://www.tensorflow.org/tfx/guide/tfdv)).
세 번째가 이 모듈의 주제이고, 앞의 두 가지와 별개의 검사라는 점이 요점이다.
가장 단순한 형태는 기준 데이터의 평균과 표준편차를 기억해 두고 새 데이터의 평균이
몇 시그마나 옮겨 갔는지를 보는 것이다. 모집단 표준편차는 표준 라이브러리로 바로
계산된다([statistics](https://docs.python.org/3/library/statistics.html)).
shift_sigma = (새 데이터의 평균 − 기준의 평균) ÷ 기준의 모집단 표준편차|shift_sigma| 0.1 정도 잡음 범위|shift_sigma| 1.0 이상 기준 분포에서 확실히 벗어남 → 경보시그마 하나로 모든 것을 잴 수 있는 것은 아니다. 범주형 특징에는 평균이 없고,
분포가 한쪽으로 크게 치우친 값에서는 평균 이동이 실제 변화보다 작게 보인다.
그래서 실무에서는 구간을 나눠 비율의 차이를 재는 방식이나 분위값 비교를 함께
쓴다. 어느 방식이든 공통점은 같다 — 기준 분포를 어딘가에 저장해 두어야 하고,
그 저장물도 모델처럼 버전이 있어야 한다는 것이다.
기준을 무엇으로 삼을지가 다음 결정이다. 학습에 쓴 데이터로 고정하면 "모델이 배운
세상" 과의 거리를 재는 것이고, 지난주 운영 데이터로 삼으면 "갑자기 바뀌었는가" 를
재는 것이다. 둘은 다른 질문이라 대개 함께 둔다.
지표로 만들고 나면 그다음은 감시 시스템의 일이다. 특징마다 하나씩 값을 내보내고
임계값을 넘을 때 경보를 건다. 지표 이름은 단위를 접미사로 붙이고 기본 단위를 쓰는
관례를 따르는 편이 나중에 읽기 쉽다([Metric and label naming](https://prometheus.io/docs/practices/naming/)).
경보를 재학습 트리거에 그대로 연결할 수도 있지만, 그 앞에 승격 관문이 있어야 한다 —
분포가 바뀌었다는 이유로 다시 학습한 모델이 더 나을 것이라는 보장은 없기 때문이다.
드리프트를 잰다고 해서 모델을 바로 바꿀 필요는 없다. 감시의 첫 목적은 **놀라지
않는 것**이다. 분포가 움직이고 있다는 사실을 알고 있으면, 한 달 뒤 정확도가
떨어졌을 때 원인을 처음부터 찾지 않아도 된다. 반대로 아무것도 재고 있지 않으면
그 한 달은 통째로 추측이 된다.
현장에서 만나는 모습
가장 흔한 실패는 경보가 너무 많은 것이다. 특징이 200개인 모델에서 각각에 임계값을
걸면 매일 몇 개는 넘는다. 며칠 지나면 아무도 안 본다. 그래서 실제로는 모델이 크게
의존하는 상위 몇 개 특징만 감시하거나, 특징별 값을 하나의 요약값으로 접어 경보를 건다.
두 번째는 드리프트를 곧장 사고로 읽는 것이다. 요금제를 개편하면 사용 시간 분포는
당연히 바뀐다. 그건 데이터가 망가진 것이 아니라 세상이 바뀐 것이고, 필요한 대응은
롤백이 아니라 재학습이다. 반대로 상류 파이프라인이 단위를 분에서 시간으로 바꿔
버린 경우라면 재학습이 아니라 수정이 필요하다. 지표는 둘을 구분해 주지 않으므로
경보에는 언제나 "무엇을 확인하라" 가 붙어 있어야 한다.
세 번째는 경보를 자동 재학습에 곧장 연결해 두는 것이다. 분포가 움직였다는 이유로
다시 학습한 모델이 더 나을 것이라는 보장은 어디에도 없고, 오히려 망가진 데이터를
그대로 학습해 버릴 수도 있다. 그래서 경보와 재학습 사이에는 데이터 계약 검증이,
재학습과 배포 사이에는 승격 관문이 각각 놓여 있어야 한다.
네 번째는 기준을 갱신하지 않는 것이다. 재학습으로 챔피언을 바꿨으면 드리프트의
기준도 새 학습 데이터로 옮겨야 하는데, 이걸 빠뜨리면 경보가 영원히 켜져 있다.
네 번째는 특징 하나만 보고 원인을 단정하는 것이다. 사용 시간이 올라간 것이 정말
사용자 행동의 변화인지, 수집 방식이 바뀐 것인지, 아니면 특정 고객군이 대량으로
유입된 것인지는 그 한 숫자만으로 갈라지지 않는다. 그래서 경보 옆에는 언제나 같은
기간의 표본 수와 상위 분위값이 함께 있어야 한다. 평균만 보면 표본이 열 배로
늘어난 것과 값이 옮겨 간 것을 구분할 수 없다.
다음 퀴즈에서 확인할 것
계약 검증과 드리프트 탐지가 각각 무엇을 잡는지, 레이블이 늦게 오는 상황에서 입력
분포를 재는 이유가 무엇인지, 드리프트 경보를 재학습에 바로 연결할 때 무엇이
더 필요한지를 확인한다.