기계 학습의 목적 변수를 정규 분포로

소개



단 3개월 정도 전에 기계 학습을 공부해 데이터 콤페에 참가하고 있었습니다. 잠시 기계 학습은 언급하지 않았지만 대학 학원 축제가 끝나고 서클 활동이 단락되었기 때문에 J리그 관객동원수 예측의 데이터 비교를 수정하고 더 나은 평가를 하려고 했습니다. (이전의 것은 여기 ) 기계 학습에 있어서 예측하려고 하고 있는 값이 정규 분포에 따르는 편이 정밀도가 좋아진다고 하는 것이 알려져 있으므로, 목적 변수를 정규화하는 것을 생각했습니다.

목적 변수 분포



우선, 본 기사를 쓰는데 이용한 데이터의 분포를 아래에 열거합니다.

분명히 정규 분포라고는 말하기 어렵네요. 이것을 정규 분포에 가깝게 가려고 생각합니다.

import 문



아래와 같습니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import pylab

로그 변환



목적변수의 분포가 선형회귀가 가정하고 있는 정규분포가 아니기 때문에, 목적변수를 대수변환하고, 정규분포와 같은 형태로 재형성하고, 선형회귀를 아래의 코드로 실시했습니다.
## yは目的変数
## trainデータはdf_trainにDataFrame型で格納
y = df_train['y'].values
df_train['logy'] = np.log(y)

그러면

RuntimeWarning: divide by zero encountered in log

라는 경고가 나왔습니다.
log의 계산을 할 수 없는 것으로 나오는 Warning이라고 하는 것으로 원 데이터를 확인해 보면, 1569번째의 데이터의 목적 변수에 0이 포함되어 있는 것을 알았습니다. 해당 데이터를 예외로 삭제하기로 결정했습니다.
0을 1회 대수 변환하면 -inf라고 하는 문자가 격납되고, 2회 log를 취하면 null가 격납되는 것을 알았으므로, 아래의 코드로 처리를 실시했습니다.
logy = df_train['logy'].values
df_train['loglogy'] = np.log(logy)
df_train=df_train.dropna(subset=['loglogy'])

결과적으로 아래 그림과 같이 되어 정규 분포에 접근할 수 있었다고 생각되지만 QQ 플롯과 샤피로윌크 검정을 사용하여 재확인하려고 했습니다.



QQ 플롯



QQ 플롯은, X축상에 관측한 누적 퍼센트, Y축상에 기대 누적 퍼센트를 가지는 그래프로, 일직선상에 되어 있으면 정규 분포가 되어 있는 것을 알 수 있는 것으로 알려져 있습니다. 코드는 아래와 같이 쓰면 됩니다.
stats.probplot(df_train['y'], dist="norm", plot=pylab)
plt.show()

결과적으로 정규화 전의 데이터는 아래 그림과 같습니다.


정규화 후의 데이터는 아래 그림과 같이 되었습니다. 정규 분포에 접근하는 것은 분명합니다.


샤필로 윌크 검정


b = stats.shapiro(df_train['y'])
print("対数変換前: ")
print(b)
print("")
a = stats.shapiro(df_train['logy'])
print("対数変換後: ")
print(a)

로그 변환 전 :
(0.8354302644729614, 6.124234808485181e-41)
로그 변환 후 :
(0.9928132891654968, 3.526571745737783e-08)
0.05 이하이기 때문에 정확한 정규 분포가 되지 않지만, 로그 변환에 의해 정규 분포에 접근하고 있는 것을 알 수 있습니다.

마지막으로



log로 한 후의 값을 교사 데이터로 하고 있으므로, 모델이 토출한 값에 대해서 exp를 실시할 필요가 있습니다. 반드시 잊지 않도록 합시다. 이 대수 변환을 실시한 결과, Score가 3,356.78983점→3,268.64733점이 되었습니다. 100점 가까이 줄어들 수 있었습니다. 현재 59위/580위입니다. 더 점수 늘려갈 수 있도록 노력하겠습니다.

좋은 웹페이지 즐겨찾기