파이썬 분석 실무, 유저 Funnel 분석 - (4) 예측 모델을 통한 결측치 처리

|

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)

실습 파일 확인하기