1. 모델 개발 단계에서 Concept Drift를 피하기 위해 고려해야하는 점
1) 학습과정에서 최대한 다양한 데이터를 사용한다.
2) Feature Engineering
3) 모델 선택
4) 정기적인 모델 업데이트 및 재학습
2. Drift Detection Algorithms
다음은 실시간 데이터 스트림에서 Drift를 감지하는 데 사용되는 알고리즘들이다.
이 알고리즘들은 데이터 스트림의 통계적 특성이 시간이 흐름에 따라 변화하는지 여부를 식별하는데 중점을 둔다.
1) ADWIN (Adaptive Windowing)
ADWIN은 데이터스트림에서 변화를 감지하기 위해 동적으로 조정되는 window의 크기를 기반으로,
두개의 연속적인 데이터 블록간의 평균값이 통계적으로 유의미하게 차이나는지 확인하고,
데이터 스트림 내 변화가 발생하는 시점을 감지하는 방법이다.
아래 예시를 보자.
먼저, 가장 처음에는 모든 데이터 포인트를 포함하는 하나의 window(전체 데이터스트림이라보면 됨)로 시작한다.
ex)
1) 주어진 데이터 스트림 : [1, 1, 1, 1, 1, 1, 0.8, 0.8, 0.6, 0.6, 0.4, 0.4, 0.2, 0.2, 0]
2) 초기 window : [1, 1, 1, 1, 1, 1, 0.8, 0.8, 0.6, 0.6, 0.4, 0.4, 0.2, 0.2, 0] -> 전체 스트림과 동일
3) [1...n] <- 쪼개어진 window간 평균값을 비교한다-> [n+1 ...m]
4) 평균값이 처음 설정한 임계치(drift를 탐지하기 위한 기준)를 초과할 경우,
해당 window 경계점의 포인터값이 drift로 의심할 만큼 차이가 커진것으로 간주하고 window의
크기를 조정한다.
from river import drift
adwin = drift.ADWIN()
data_stream = [0, 1, 0, 0, 1, 1, 0, 1, 1, 1] # 예시 데이터 스트림
for i, value in enumerate(data_stream):
adwin.update(value) # ADWIN에 데이터 포인트 업데이트
if adwin.change_detected:
print(f"Drift detected index {i}")
2. Page-Hinkley Test
Page-Hinkley Test는 데이터 스트림의 평균 변화를 모니터링하여 설정된 임계값을 초과하면
변화가 감지된것으로 판단하여 drift를 감지한다.
간단한 방법으로 예를들어, [0,0,0,1,1,1,0,0,0]과 같은 데이터스트림이 주어지고,
임계값을 0.5라고 가정했을때, 첫번째 데이터포인트부터 차례대로 누적평균을 구한다.
4번째 데이터포인트에서 1-0(이전 데이터포인트)=1이 되어 임계값을 초과하는 변화량을 감지하여
drift를 관측하는 방법이다.
from river import drift
ph = drift.PageHinkley()
data_stream = [0, 1, 0, 0, 1, 1, 0, 1, 1, 1] # 예시 데이터 스트림
for i, value in enumerate(data_stream):
ph.update(value) # Page-Hinkley에 데이터 포인트 업데이트
if ph.change_detected:
print(f"Drift detected index {i}")
3. CUSUM (Cumulative Sum Control Chart)
cusum은 데이터스트림에서 작은 변화를 감지하는데 사용되는데, 누적된 차이수가 특정 임계값을 초과할 경우
Drift가 감지된것으로 판단하는 방법이다.
예를들어, 주어진 데이터 스트림이 [1, 1, 2 ,2 ,2, 3, 3, 3, 3]이고 임계값이 2일때,
두번째에서 세번째 인덱스에서 차이가 '1' 관측되고(누적), 5번째에서 6번째로 넘어갈때 차이가 다시 '1'관측되어
누적 차이가 2가되어 임계값에 충족하게된다. 이때, 임계값 이상의 차이가 발생한 이후 시점의
3,3,3,3에 해당하는 부분에서 Drift가 발생한것으로 간주하는 방식이다.
import numpy as np
def cusum(data, threshold=5, drift=0):
S = 0
change_points = []
for i in range(1, len(data)):
S = max(0, S + data[i] - data[i-1] - drift)
if S > threshold:
change_points.append(i)
S = 0
return change_points
data_stream = np.random.normal(0, 1, 100) # 예시 데이터 스트림
change_points = cusum(data_stream)
print("Drift points:", change_points)
4. DDM (Drift Detection Method)
DDM은 분류모델에서 오류율의 변화를 감지하는 데 사용되며, 오류율이 특정 수준이상 증가하면 변화가
감지된것으로 판단하는 방법이다.
예를들어, classification task에서
'[정답, 정답, 오류, 정답, 오류, 오류, 정답, 정답, 오류, 오류]' 과 같이 측정되었다고 가정하자.
이를 DDM 알고리즘을 통해 오류율의 변화를 모니터링 하고, 임계값은 0.3으로 설정하고 진행해보자.
- 첫 번째 데이터 포인트 (정답): 오류율 = 0/1 = 0
- 두 번째 데이터 포인트 (정답): 오류율 = 0/2 = 0
- 세 번째 데이터 포인트 (오류): 오류율 = 1/3 ≈ 0.333
- 네 번째 데이터 포인트 (정답): 오류율 = 1/4 = 0.25
- 다섯 번째 데이터 포인트 (오류): 오류율 = 2/5 = 0.4
- 여섯 번째 데이터 포인트 (오류): 오류율 = 3/6 = 0.5
- 일곱 번째 데이터 포인트 (정답): 오류율 = 3/7 ≈ 0.429
- 여덟 번째 데이터 포인트 (정답): 오류율 = 3/8 = 0.375
- 아홉 번째 데이터 포인트 (오류): 오류율 = 4/9 ≈ 0.444
- 열 번째 데이터 포인트 (오류): 오류율 = 5/10 = 0.5
결국, 세번째 포인트부터 임계점인 0.3을 초과했지만, 다섯번째 이후부터 오류율이 지속적으로 크게 나타나는것을
볼 수 있다.
이렇게, 오류율이 지속적으로 임계점 이상을 초과할 경우 model에 drift가 발생한것으로 간주할 수 있다.
from river import drift
ddm = drift.DDM(min_num_instances=30, warning_zone=2, out_control_zone=3)
data_stream = [0, 1, 0, 0, 1, 1, 0, 1, 1, 1] # 예시 데이터 스트림의 결과
for i, value in enumerate(data_stream):
ddm.update(value) # DDM에 결과 업데이트
if ddm.change_detected:
print(f"Change detected index {i}")
elif ddm.warning_detected:
print(f"Drift warning index {i}")
마치며
오늘은 concept drift를 예방하고 탐지하기 위한 여러가지 방법론을 정리해보았다.
drift에 대응하기 위한, 생각보다 다양한 방법이 있다는것을 알게되었고,
실제 모델 구축 및 배포시 Drift로 인한 모델 성능저하를 빠르게 탐지하기 위해
적절한 모니터링 및 탐지 프로세스를 구축해야한다는 점을 이해하게 되었다.
다음에는 위 탐지 방법론들을 어떻게 프로세스로 녹여낼것인지에 대해 고민하고 정리해보도록 하자.
Reference
[1] Blog
https://calmmimiforest.tistory.com/120
https://danbi-ncsoft.github.io/works/2019/02/07/churn_prediction_in_practice-2.html
'DEVELOP_NOTE > MLOps' 카테고리의 다른 글
Drift를 감지하는 방법 (1) Data Drift Detection (0) | 2023.12.17 |
---|---|
Model Drift의 개념과 원인 (+ Data Drift, Label Drift, Concept Drift) (0) | 2023.12.16 |
MLOps란? (0) | 2023.12.14 |