파이썬 분석 실무, 유저 Funnel 분석 - (4) 예측 모델을 통한 결측치 처리
31 Oct 2018 | python missing value prediction 머신러닝python 분석 실무, 유저 funnel 분석
결측값에 예측모형으로 예측치 넣기
결측치를 다루는 방법 중 적절성은 비교적 높으나 별도의 모형과 계산량이 필요하다.
1. 데이터 준비
sklearn
(사이킷런)을 이용함ind_cols
- 예측하고 싶은 값에 영향을 주는 요소 중 서로 독립적인 칼럼명만 넣어둔다.
- train, test, predict 데이터 x 값에 바로 넣기 편하다.
- DS school에서 배울 때에는 상관도를 이용하여 영향 없는 칼럼을 골랐었다.
# fill na using predictive model
# train without na
df_msl = df_ms.dropna()
# set independent cols <-- 서로 영향 없는 칼럼만 고르기
ind_cols = ['actiontype', 'ismydoc', 'ext', 'screen']
#split ind, tar --> 학습시키고 싶은 칼럼과 인풋 칼럼 나누기
x = df_msl[ind_cols]
y = df_msl[['documentposition']]
2. 항목값 전처리 - Label Encoder
Label Encoder는 독립 변수가 아닌 종속 변수(라벨)에 대해 사용한다. 문자열이나 정수로된 라벨 값을 0 ~ K−1 까지의 정수로 변환한다. 변환된 규칙은 classes_
속성에서 확인할 수 있다. 예측 결과에 적용할 수 있도록 역변환을 위한 inverse_transform
메서드도 지원한다. 출처
인코딩이란? 인코딩은 카테고리 값이나 텍스트 정보를 처리가 쉬운 정수로 변환하는 과정이다.
예전에 배웠을 때에는 ‘One-Hot-Encoder’를 사용했었음 One-Hot-Encoding은 항목형 데이터를 해당 항목 칼럼을 만들고 해당하는 값에만 정수 1을 넣어주는 방식이다. 참고
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
X = x.apply(lambda x: encoder.fit_transform(x))
y = y.apply(lambda y: encoder.fit_transform(y))
# .inverse_transform()를 이용해서 역방향도 가능하다.
3. 훈련데이터와 평가데이터 추출하기
train_test_split
는 데이터의 표본을 무작위로 추출해 훈련 데이터와 평가 데이터로 나눈다.
이때 random_state
속성값을 이용해서 적절히 섞은 곳에서 추출할 수 있다. (그냥 하는 경우 정렬되어 있거나 할 때 그 비율에 맞춰 추출될 가능성이 있는 것 같음 - 자세히 찾아봐라)
참고
from sklearn.model_selection import train_test_split
# X: df_ms_ind / y: df_ms_tar
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=10)
4. 학습모형 만들기 - KNN Algorithm
k-최근접 이웃 알고리즘(또는 줄여서 k-NN)은 분류나 회귀에 사용되는 비모수 방식이다. 특정한 공간내(X 값에 따라 결정) 내 k개의 가장 가까운 훈련 데이터를 가지고 해당 값을 예측하는 모델
- k-NN 분류에서 출력은 소속된 항목이다. 객체는 k개의 최근접 이웃 사이에서 가장 공통적인 항목에 할당되는 객체로 과반수 의결에 의해 분류된다(k는 양의 정수이며 통상적으로 작은 수). 만약 k = 1 이라면 객체는 단순히 하나의 최근접 이웃의 항목에 할당된다.
- k-NN 회귀에서 출력은 객체의 특성 값이다. 이 값은 k개의 최근접 이웃이 가진 값의 평균이다.
검증 표본(초록색 원)은 첫 번째 파랑 네모의 항목이나 빨강 삼각형의 두 번째 항목으로 분류되어야 한다. 만약 “k = 3” (실선으로 그려진 원)이면 두 번째 항목으로 할당되어야 한다. 왜냐하면 2개의 삼각형과 1개의 사각형만이 안쪽 원 안에 있기 때문이다. 만약 “k = 5” (점선으로 그려진 원)이면 첫 번째 항목으로 분류되어야 한다. (바깥쪽 원 안에 있는 3개의 사각형 vs. 2개의 삼각형)
참고 텐서플로우 knn
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5).fit(X_train, y_train)
5. 학습모형 평가하기 - Score
- 학습을 통해 만들어진 예측 모형에 평가 데이터를 넣어 실제값과 얼마나 유사하게 예측하는지 평가한다.
- 즉, X를 넣어 나온 predicted Y가 넣어준 Y와 맞는지 확인
- 즉, 스코어는 해당 모델의 예측 정확도를 확인할 수 있음
print(knn.score(X_test, y_test))
6. 학습모형 평가하기 - 분류 성능 평가(sklearn.metrics
)
분류 문제는 회귀 분석과 달리 다양한 성능 평가 기준이 필요하다.
- 분류 결과표
Confusion Matrix
- 분류 결과표는 타겟의 원래 클래스와 모형이 예측한 클래스가 일치하는지는 갯수로 센 결과이다.
- 원래 클래스는 행(row)으로 예측한 클래스는 열(column)로 나타낸다.
- 이진 분류 결과표
Binary Confusion Matrix
- 클래스가 0과 1 두 종류 밖에 없는 경우에는 일반적으로 클래스 이름을 “Positive”와 “Negative”로 표시한다.
- 또, 분류 모형의 예측 결과가 맞은 경우, 즉 Positive를 Positive라고 예측하거나 Negative를 Negative라고 예측한 경우에는 “True”라고 하고 예측 결과가 틀린 경우, 즉 Positive를 Negative라고 예측하거나 Negative를 Positive라고 예측한 경우에는 “False”라고 한다.
- 통계에서 1종 오류, 2종 오류 확인하는 것과 비슷하다
- 정보
- precision(정밀도) : 전체 중에 잘 맞게 들어간 비율
- recall(재현도) : 진짜 중에 진짜라고 분류된 것 비율
- Fall-Out (위양성율) : 가짜 중에 진짜라고 분류된 것 비율
- f1-score : precision(정밀도)와 recall(재현도)을 함께 고려한 값
- support : 그 값으로 예측된 항목 수
#행열에서 대각선 부분 외에는 잘 못 예측한것임
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, knn_pred))
# [[ 4733 0 0 0 3 0 0]
# [ 2 13895 0 0 0 0 0]
# [ 0 0 1920 0 3 0 0]
# [ 0 0 2 1085 0 0 0]
# [ 1 0 1 0 53383 0 0]
# [ 0 1 0 0 0 413 0]
# [ 0 3 0 0 0 0 19]]
from sklearn.metrics import classification_report
print(classification_report(y_test, knn_pred))
# precision recall f1-score support
#
# 0 1.00 1.00 1.00 4736
# 1 1.00 1.00 1.00 13897
# 2 1.00 1.00 1.00 1923
# 3 1.00 1.00 1.00 1087
# 4 1.00 1.00 1.00 53385
# 5 1.00 1.00 1.00 414
# 6 1.00 0.86 0.93 22
#
# avg / total 1.00 1.00 1.00 75464
7. 결측값에 예측치 채워 넣기
# 인코딩에서 숫자로 변환되었던 항목값
class_cd = pd.Series(encoder.classes_).to_dict()
# 결측치가 하나 이상 있는 Case만 선택
df_ms_only = df_ms[df_ms.isna().any(axis=1)]
# 결측치가 없는 Case만 선택
df_ms_dropna = df_ms.dropna()
# 평가에 필요한 칼럼만 뽑으면서, 동시에 인코딩 진행
df_ms_only[ind_cols].apply(lambda x: encoder.fit_transform(x))
# 학습모형에 집어 넣어 값 예측하기
knn.predict(df_ms_only[ind_cols].apply(lambda x: encoder.fit_transform(x)))
# 예측값 저장하기
fill_na_values = knn.predict(df_ms_only[ind_cols].apply(lambda x: encoder.fit_transform(x)))
# 결측치가 있는 곳에 예측값 집어 넣기
df_ms_only['documentposition'] = fill_na_values
# 인코딩된 칼럼값을 되돌리기
df_ms_only['documentposition'] = df_ms_only['documentposition'].replace(class_cd)
#원래 데이터에 합치기
df_ms_final = pd.concat([df_ms_dropna, df_ms_only], axis=0)