편향된 데이터를 랜덤 포리스트로 클래스 분류를 할 때는 class weight 를 설정하는 것이 좋다

개요



말하고 싶은 것은 제목에 쓰여진 거리입니다 (웃음)

실제 서비스의 데이터를 이용해 데이터 분석하거나 다양한 학습 모델을 작성하고 있다면 대개 데이터에 편향이 있는 경우가 대부분입니다.
예를 들어, 스팸 메일의 분류 등은 좋은 예입니다만, 대부분의 메일이 정상인 가운데 몇 안되는 스팸의 분류를 하면, 「전부 정상이라고 분류하는 편이 정답률이 올라 버려 표면상은 좋은 모델」 가 완성되어 버려, 실용에 견딜 수 없는 것이 되어 버립니다.

이번에는 그러한 편향된 데이터 세트(불균형 데이터라고 함)에 대해 클래스 분류 모델을 작성할 때의 포인트를 기술합니다.

분류를 수행하는 모델은 임의 포리스트를 지정합니다. 그러나, 다른 분류 모델에서도 응용할 수 있는 사고방식이므로, 이것을 눌러 두면 좋다고 생각합니다.

scikit-learn의 RandomForestClassifier 문서 에 의하면, class_weight 의 파라미터를 balanced (을)를 지정하면 클래스 마다의 샘플수의 가중치를 자동으로 붙여 준다고 하는 것. 편리하네요.
내용의 계산 방법은 n_samples / (n_classes * np.bincount(y)) 입니다.

실제로 데이터를 사용하여 확인



불균형 데이터에 대해 class_weight를 고려하지 않는 분류와 고려하는 분류에 어떤 차이가 있는지 살펴 보겠습니다.

이번에 사용한 파이썬 코드 ( jupyter notebook 형식 ) : htps : // 기주 b. 코 m / 카즈키 - 하야카와 / 랜드 m 푹신 st_ m m ぉ せ せ d / b ぉ b / 뭐 r / 랜드 m 푹신 st_ 의 테보오 k. 이 pyn b

스팸 분류와 같이 올바른 클래스를 정례, 오류 등에 사용되는 클래스를 부례라고 합니다. 이번에는 샘플 수가 적은 분을 부례라고 부릅니다.
이번에는 정례를 7000, 부례를 100이라는 불균형 데이터를 준비했습니다.

# 不均衡データセットの作成
import numpy as np 

np.random.seed(0)

X1 = np.random.rand(7000, 2)  
X2 = np.random.rand(100, 2) *0.2 + 0.9

y1 = np.array([1 for _ in range(7000)])
y2 = np.array([2 for _ in range(100)])

정례의 라벨을 1, 부례의 라벨을 2로 하고 있습니다.



계산을 위해 데이터를 7:3의 비율로 훈련 데이터와 테스트 데이터로 나눕니다.
from sklearn.cross_validation import train_test_split

X = np.concatenate([X1, X2])
y = np.concatenate([y1, y2])

# データを 7:3 で訓練用データとテストデータに分割する
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

불균형 데이터를 고려하지 않는 분류



그럼 우선은, 불균형 데이터를 고려하지 않고 보통으로 분류를 해 보겠습니다.
(샘플이므로 그리드 검색 등에 의한 하이퍼 파라미터의 조정은 실시하지 않습니다)
from sklearn.ensemble import RandomForestClassifier

# 不均衡データの考慮がない場合
clf = RandomForestClassifier()
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

결과는 다음과 같습니다.
(난수 생성이므로 사람에 따라서는 다른 결과가 나오는 경우가 있습니다만, 데모이므로 용서해 주세요)
正解率: 0.993896713615
負例の予測数: 21
実際の負例の数: 30
負例を正しく識別できている割合: 0.7

불균형 데이터를 고려한 분류



그런 다음 데이터 편향을 고려하여 class_weight를 명시 적으로 지정하여 분류합니다.
# 不均衡データの考慮をする場合
clf = RandomForestClassifier(class_weight='balanced')
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

결과는 다음과 같습니다.

正解率: 0.992018779343
負例の予測数: 25
実際の負例の数: 30
負例を正しく識別できている割合: 0.8333333333333334

요약



결과를 비교해 보면



불균형을 고려
불균형을 고려하지 않음


정답률
0.9920
0.9938

음수의 탐지율
0.833
0.700


이와 같이 불균형을 고려하지 않아도 나름의 정답률은 나오고 있습니다만, 이것은 「거의 1의 라벨이라면 전부 1이라고 생각해도 거의 정답해 버린다」현상이군요.
그러나 불균형을 고려하면 음의 검출률이 높아지고 있음을 알 수 있습니다.
이것은 스팸을 잘못 옳은 메일로 잘못 인식하지 않는다는 의미입니다.

실제의 서비스에 있어서는 부례의 검출력이 높은 모델이 요구되고 있는 경우가 있기 때문에, 모델의 용도나 데이터 세트에 따라서 이러한 궁리가 필요할까 생각됩니다.

참고로 한 사이트



Scikit-learn의 랜덤 포레스트
→ RandomForestClassifier 의 다른 파라미터의 의미가 쓰여져 공부가 되었습니다.

좋은 웹페이지 즐겨찾기