콘텐츠로 이동

이상 탐지 (Anomaly Detection)

난이도: 중급
선수 지식: 불균형 데이터, 군집화
관련 문서: 정밀도-재현율 트레이드오프 | 생성 모델 | MLOps 기초

핵심 요약: 이상 탐지는 “정상이 무엇인지 배운 뒤, 거기서 벗어난 것을 찾는” 문제다. 일반 분류와 결정적으로 다른 점은 ① 이상 사례가 극소수(0.1~1%)이고 ② 라벨이 거의 없으며이상의 종류를 미리 알 수 없다는 것이다. 그래서 대개 비지도로 접근하며, 가장 어려운 부분은 알고리즘이 아니라 어디서 자를지(임계값) 정하는 일이다.

  • 이상치(Anomaly / Outlier): 대다수와 확연히 다른 관측. 오류일 수도, 진짜 신호일 수도 있다.
  • 정상 모델링: 이상의 종류를 모두 알 수 없으므로, 정상이 어떻게 생겼는지만 학습하고 벗어남을 재는 접근.
  • contamination: 데이터에 이상이 몇 % 섞여 있는지에 대한 사전 추정치. 대부분의 알고리즘이 이 값을 요구한다.
  • 이상 점수(Anomaly Score): 각 샘플이 얼마나 이상한지의 연속값. 여기에 임계값을 걸어 이상/정상을 가른다.
  • 신규성 탐지(Novelty Detection): 학습 데이터가 전부 정상일 때, 새 데이터가 정상인지 판정하는 것.

이상 탐지는 겉보기에 이진 분류처럼 보이지만, 실제로는 매우 다른 문제다.

일반 분류이상 탐지
클래스 비율대체로 균형99.9% vs 0.1%
라벨양쪽 다 있음거의 없음
이상의 종류미리 정의됨알 수 없음 (새로운 유형이 계속 나옴)
학습 방식두 클래스를 구분정상만 학습하고 벗어남을 측정

이 차이 때문에 “사기 거래를 분류하는 모델”을 만들려다 실패하는 일이 흔하다. 사기 수법은 계속 진화하므로, 과거 사기 사례를 학습한 분류기는 새로운 수법을 놓친다. 반면 이상 탐지는 “정상이 아님”만 보므로 처음 보는 수법도 잡을 수 있다.

비유: 은행 창구 직원의 감각이다. 직원은 “사기꾼의 얼굴 목록”을 외우지 않는다. 대신 평범한 거래가 어떤 모습인지를 수천 번 보며 익히고, 뭔가 평소와 다르면 촉이 온다. 새벽 3시, 해외 IP, 평소의 40배 금액 — 각각은 가능하지만 함께 나타나면 이상하다. 이상 탐지 알고리즘이 하는 일이 정확히 이것이다.


이상 탐지의 뿌리는 통계학의 이상치 검출이다. 19세기부터 천문 관측에서 “이 측정값은 버려야 하는가”를 판단하는 방법이 논의되었다.

그러나 현대적 의미의 이상 탐지가 중요해진 것은 세 가지 산업적 필요 때문이었다.

  • 금융 사기 탐지: 신용카드가 보급되며 실시간으로 이상 거래를 잡아야 했다
  • 네트워크 침입 탐지: 알려진 공격 패턴만 막아서는 새로운 공격을 놓쳤다
  • 제조 설비 예지보전: 고장 데이터가 거의 없어 지도 학습이 불가능했다

세 분야의 공통점이 이상 탐지의 정체성을 만들었다 — “찾으려는 것의 사례가 거의 없고, 그 형태도 계속 변한다.”

알고리즘 측면의 전환점은 Liu et al.(2008)의 Isolation Forest였다. 그전까지는 “정상의 밀도를 모델링하고 밀도가 낮은 곳을 찾는” 접근이 주류였는데, Isolation Forest는 발상을 뒤집었다 — 이상치는 무작위로 잘라내면 빨리 고립된다. 밀도를 추정할 필요가 없어 고차원에서도 빠르게 작동했다.


유형설명예시
점 이상개별 값이 튄다평소 5만원 결제인데 500만원
맥락 이상값 자체는 정상인데 맥락상 이상새벽 3시의 대량 주문
집단 이상개별은 정상인데 패턴이 이상소액 결제가 1분에 100건

맥락 이상과 집단 이상은 점 이상보다 훨씬 어렵다. 시간·순서·그룹 정보를 특성으로 만들어야 잡을 수 있으며, 이것이 이상 탐지에서 특성 공학이 중요한 이유다.

알고리즘원리강점약점
통계적(z-score, IQR)평균·분위수에서 벗어남단순, 설명 쉬움단변량, 정규성 가정
Isolation Forest무작위 분할로 빨리 고립되는빠름, 고차원 OK맥락 이상에 약함
LOF이웃 대비 국소 밀도가 낮음밀도가 불균일해도 OK느림, 파라미터 민감
One-Class SVM정상을 감싸는 경계 학습이론적 근거느림, 스케일링 필수
오토인코더정상을 복원하도록 학습, 복원 오차로 판정복잡한 패턴, 이미지·시계열데이터·연산 많이 필요

Isolation Forest가 실무 기본값인 경우가 많다. 빠르고, 파라미터가 적고, 고차원에서도 무난하기 때문이다.

알고리즘은 이상 점수라는 연속값을 준다. 어디서 자를지는 알고리즘이 정해주지 않는다.

라벨이 없으면 임계값을 데이터로 고를 수 없다. 그래서 실무에서는 다음 중 하나를 쓴다.

방법설명
운영 용량 기준”조사팀이 하루 50건 처리 가능” → 상위 50건
도메인 지식”경험상 사기는 0.2% 수준” → contamination=0.002
비용 기반놓침 비용 vs 오탐 비용을 비교해 최적점
소량 라벨 확보100건이라도 라벨링해 정밀도-재현율 곡선을 그림

마지막 방법이 가장 좋다. 완전 비지도로 시작하더라도, 탐지 결과를 사람이 검토해 라벨을 쌓으면 이후 판단이 훨씬 정확해진다.

거래 1,000건 중 이상이 30건(3%)인 데이터에 Isolation Forest를 적용했다. contamination(예상 이상 비율)만 바꿔가며 결과를 보자.

contamination탐지 수정밀도재현율
0.01101.0000.333
0.03300.8000.800
0.05500.5000.833
0.101000.2600.867

읽는 법:

  • 0.01: 10건만 지목했고 전부 진짜 이상(정밀도 1.0). 하지만 30건 중 10건만 잡아 20건을 놓쳤다.
  • 0.10: 100건을 지목해 26건을 잡았지만(재현율 0.867), 74건이 오탐이다. 조사팀이 100건을 뒤져 26건을 찾는 셈이다.
  • 0.03: 실제 비율과 일치시켰을 때 정밀도·재현율이 0.8로 균형을 이룬다.

핵심은 이것이다 — 0.03이 최선인 것을 정답 라벨이 있었기 때문에 알 수 있었다. 실무에서 라벨이 없다면 이 표를 그릴 수 없고, 도메인 지식으로 3%라는 값을 짐작하는 수밖에 없다.

그래서 이상 탐지에서 진짜 병목은 알고리즘이 아니라 “이상이 몇 %인지 아는 것”이다.


라벨이 얼마나 있는가로 갈린다.

라벨 상황접근
이상 라벨이 전혀 없다비지도 이상 탐지
정상 라벨만 있다신규성 탐지(One-Class)
이상 라벨이 소수라도 있다불균형 분류가 대체로 더 정확
이상 라벨이 충분하다일반 분류

라벨이 있다면 지도 학습이 거의 항상 낫다. 이상 탐지는 라벨이 없을 때의 차선책이다. 다만 새로운 유형의 이상을 잡아야 한다면, 라벨이 있어도 이상 탐지를 병행하는 것이 안전하다.

이상 탐지 시스템은 배포 후 정상의 정의가 변한다는 문제를 겪는다.

  • 사용자 행동이 바뀌면 과거의 정상이 지금은 이상으로 잡힌다(오탐 폭증)
  • 반대로 이상이 서서히 정상에 섞이면 모델이 그것을 정상으로 학습한다

그래서 드리프트 모니터링과 주기적 재학습이 다른 어떤 문제보다 중요하다.


상황적합도
사기·침입 탐지, 라벨 거의 없음매우 적합
설비 예지보전(고장 사례 희소)매우 적합
데이터 품질 검사(입력 오류 탐지)적합
이상 라벨이 수천 건 있음불균형 분류가 나음
이상의 정의가 명확하고 고정적규칙 기반이 나음

오탐 때문에 시스템이 꺼진 사례

섹션 제목: “오탐 때문에 시스템이 꺼진 사례”

한 제조사가 설비 센서 데이터에 이상 탐지를 도입했다. 목표는 고장 예방이었고, 재현율을 최대한 높이는 방향으로 임계값을 설정했다.

첫 주 결과는 알림 1,847건이었다. 정비팀은 하루 20건 정도를 처리할 수 있었다.

2주째, 정비팀은 알림 대부분을 무시하기 시작했다. 3주째에는 알림 시스템 자체를 껐다. 그리고 5주째에 실제 고장이 발생했다 — 시스템은 그것을 정확히 탐지했지만, 아무도 보지 않았다.

원인은 임계값 설정 철학이었다. 팀은 “놓치는 것보다 오탐이 낫다”고 판단했는데, 사람이 처리할 수 있는 양을 계산에 넣지 않았다.

재설계 후에는 임계값을 “하루 15건”이라는 운영 용량에서 역산해 정했다. 재현율은 떨어졌지만 정비팀이 실제로 모든 알림을 확인했고, 이후 3건의 고장을 사전에 막았다.

교훈: 이상 탐지의 임계값은 통계가 아니라 운영 용량에서 나와야 하는 경우가 많다. 아무도 보지 않는 알림의 재현율은 0이다.


import numpy as np
from sklearn.ensemble import IsolationForest
from sklearn.metrics import precision_score, recall_score
rng = np.random.default_rng(0)
normal = rng.normal(0, 1, (970, 2)) # 정상: 원점 주변에 밀집
anomaly = rng.uniform(-6, 6, (30, 2)) # 이상: 넓게 흩어짐
X = np.r_[normal, anomaly]
y = np.r_[np.zeros(970), np.ones(30)] # 1 = 이상
print(f"이상 비율 {y.mean():.1%} (30/1000)\n")
print(f"{'contamination':>14} {'탐지 수':>8} {'정밀도':>8} {'재현율':>8}")
for c in (0.01, 0.03, 0.05, 0.10):
m = IsolationForest(contamination=c, random_state=0).fit(X)
p = (m.predict(X) == -1).astype(int) # -1 = 이상으로 판정
print(f"{c:>14.2f} {p.sum():>8} {precision_score(y,p,zero_division=0):>8.3f} {recall_score(y,p):>8.3f}")
# 실행 결과:
# 이상 비율 3.0% (30/1000)
#
# contamination 탐지 수 정밀도 재현율
# 0.01 10 1.000 0.333 <- 확실한 것만, 20건 놓침
# 0.03 30 0.800 0.800 <- 실제 비율과 일치
# 0.05 50 0.500 0.833
# 0.10 100 0.260 0.867 <- 74건이 오탐

contamination을 올릴수록 재현율은 오르고 정밀도는 떨어진다정밀도-재현율 트레이드오프가 그대로 나타난다.

가장 중요한 점은 0.03이 최선이라는 것을 정답 라벨(y) 덕분에 알 수 있었다는 것이다. 실무에서 이상 탐지를 쓰는 상황은 대개 바로 그 y가 없는 상황이다. 그러면 이 표를 그릴 수 없고, contamination을 도메인 지식으로 짐작해야 한다.

그래서 실무에서는 임계값을 통계가 아니라 “조사팀이 하루 몇 건을 처리할 수 있는가”에서 역산하는 경우가 많다.


  1. “이상치는 제거해야 할 오류다” — 이상치가 바로 찾으려는 대상인 경우가 많다(사기, 고장). 데이터 정제와 이상 탐지를 혼동하면 안 된다.

  2. “재현율을 최대한 높이는 것이 안전하다” — 오탐이 사람이 처리할 수 있는 양을 넘으면 알림 전체가 무시된다. 아무도 보지 않는 알림의 재현율은 0이다.

  3. “라벨이 없으니 이상 탐지를 쓴다” — 라벨이 조금이라도 있으면 불균형 분류가 대체로 더 정확하다. 이상 탐지는 차선책이다.

  4. “정확도로 평가한다” — 이상이 1%면 “전부 정상”이라고 해도 정확도 99%다. 정밀도·재현율·PR-AUC를 봐야 한다.

  5. “한 번 만들면 계속 쓸 수 있다”정상의 정의가 변한다. 사용자 행동이 바뀌면 오탐이 폭증하고, 이상이 서서히 섞이면 모델이 그것을 정상으로 학습한다. 모니터링과 재학습이 필수다.


1. 이상 탐지가 일반 분류와 다른 점 세 가지는?

정답 보기

① 이상 사례가 극소수(0.1~1%), ② 라벨이 거의 없다, ③ 이상의 종류를 미리 알 수 없다(새로운 유형이 계속 나온다). 특히 ③ 때문에 과거 사례를 학습한 분류기는 새로운 수법을 놓치는 반면, 이상 탐지는 “정상이 아님”만 보므로 처음 보는 유형도 잡을 수 있다.

2. 라벨이 전혀 없을 때 contamination 값을 어떻게 정하는가?

정답 보기

데이터로는 고를 수 없다. 실무에서는 ① 운영 용량(“조사팀이 하루 50건 처리 가능” → 상위 50건), ② 도메인 지식(“경험상 사기는 0.2%”), ③ 비용 비교(놓침 비용 vs 오탐 비용) 중 하나를 쓴다. 가장 좋은 것은 소량이라도 라벨을 확보해 PR 곡선을 그리는 것이다.

3. 재현율을 최대로 올린 이상 탐지 시스템이 실패할 수 있는 이유는?

정답 보기

오탐이 처리 용량을 넘어서면 사람이 알림 전체를 무시하게 된다. 하루 1,847건의 알림을 20건 처리 가능한 팀에 주면 시스템은 곧 꺼진다. 그 시점부터 실질 재현율은 0이다. 임계값은 통계가 아니라 운영 용량에서 역산해야 하는 경우가 많다.