Home Pima Indian 데이터를 이용한 결정 트리 회귀
Post
Cancel

Pima Indian 데이터를 이용한 결정 트리 회귀

Pima Indians Diabetes Regression

sklearn 결정 트리를 이용한 회귀

데이터 셋 출처

Pima Indians Diabetes Database | Kaggle
sklearn

사용 라이브러리

1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import koreanize_matplotlib
from sklearn.model_selection import train_test_split
from sklearn.tree import plot_tree
from sklearn.metrics import accuracy_score

Data Load

1
2
df_pima = pd.read_csv("http://bit.ly/data-diabetes-csv")
df_pima.shape
1
(768, 9)

기본적인 학습

회귀에 대한 내용이므로, 결측치가 많았던 Insulin을 타겟으로 지정해 사용

1
_ = sns.kdeplot(data=df_pima, x="Insulin", hue="Outcome")

png

데이터 셋 나누기

1
label_name = "Insulin"
1
2
3
feature_names = df_pima.columns.tolist()
feature_names.remove(label_name)
feature_names
1
2
3
4
5
6
7
8
['Pregnancies',
 'Glucose',
 'BloodPressure',
 'SkinThickness',
 'BMI',
 'DiabetesPedigreeFunction',
 'Age',
 'Outcome']

Insulin을 예측하는 모델을 만들 예정이므로, Train 세트에는 Insulin의 값이 존재하는 데이터만 사용할 수 있음

1
2
3
train = df_pima[df_pima["Insulin"]>0]
test = df_pima[df_pima["Insulin"]==0]
print(f"train: {train.shape}\n test: {test.shape}")
1
2
train: (394, 9)
 test: (374, 9)
1
2
X_train, y_train, X_test, y_test = train[feature_names], train[label_name], test[feature_names], test[label_name]
print(f"X_train: {X_train.shape}\ny_train: {y_train.shape}\nX_test: {X_test.shape}\ny_test: {y_test.shape}")
1
2
3
4
X_train: (394, 8)
y_train: (394,)
X_test: (374, 8)
y_test: (374,)

회귀 알고리즘

결정 트리는 분류와 회귀에 모두 사용 가능한 CART 알고리즘이므로 결정 트리 기반의 회귀 모델을 사용함

1
2
3
4
from sklearn.tree import DecisionTreeRegressor

model = DecisionTreeRegressor(random_state=42)
model.fit(X_train, y_train)
1
DecisionTreeRegressor(random_state=42)

Cross validation (교차 검증)

모델 학습 시 데이터를 훈련용(train)과 검증용(valid)으로 선택하는 방법
모델 성능에 직접적인 영향은 없고, 평가의 정확도를 높이는 목적으로 사용
가장 많이 사용하는 방식은 K-Fold Cross Validation

교차 검증 종류

  1. Hold-out Cross-Validation: 특정 비율로 Train과 Test를 1회만 분할
  2. K-Fold Cross-Validation: 전체를 K개로 나누고, 1개를 Test로 나머지(K-1)개를 학습용으로 사용하는 과정을 K번 반복함
  3. LpOCV (Leave-p-Out Cross-Validatoin): 전체 데이터 중에서 p개의 샘플을 선택해 모델 검증에 활용
  4. LOOCV (Leave-One-Out CV): LpOCV에서 p=1인 경우
  • 장점
    • Overfitting 방지
    • 일반화된 모델 생성 가능
    • 적은 데이터에서 Underfitting 방지
  • 단점
    • 소요시간 증가
1
2
3
4
5
from sklearn.model_selection import cross_val_predict
# cv: k-fold의 k, 5 -> 4개로 학습하고 1개로 검증
# n_jobs: 사용할 코어의 개수
# verbose: 로그를 얼마나 출력할 것인지
y_valid_predict = cross_val_predict(model, X_train, y_train, cv=5, n_jobs=-1, verbose=0)
1
np.sum(y_train==y_valid_predict)
1
3
1
np.mean(y_train==y_valid_predict)
1
0.007614213197969543

정답을 3개 밖에 맞추지 못했습니다.. 정답률은 약 0.008%로 굉장히 낮습니다.

잔차(residual) 구하기

잔차를 시각화해봅니다

1
_ = sns.regplot(x=y_train, y=y_valid_predict)

png

1
_ = sns.jointplot(x=y_train, y=y_valid_predict)

png

1
_ = sns.jointplot(x=y_train, y=y_valid_predict, kind="hex")

png

1
_ = sns.residplot(x=y_train, y=y_valid_predict)

png

residplot에서, 0은 추정치와 실제값의 차이가 없는 것을 의미하므로 0에 가까울수록 잘 예측한 값임

회귀를 측정하는 방식

R2_score

R2 score는 회귀 모델이 얼마나 설명력이 있느냐를 의미하며, 실제값의 분산 대비 예측값의 분산 비율이라고 이해 가능함
1에 가까울수록 좋은 성능을 가졌다고 해석할 수 있음

1
2
3
from sklearn.metrics import r2_score

r2_score(y_train, y_valid_predict)
1
-0.14429295602725567
1
2
df_y = pd.DataFrame({"y_train": y_train, "y_valid_predict": y_valid_predict})
df_y.head()
y_trainy_valid_predict
39425.0
4168480.0
68855.0
8543145.0
13846495.0
1
2
# 정답값과 예측값의 분포
_ = sns.displot(df_y, height=2, aspect=5, kde=True)

png

오차

1
2
3
# 오차에서 부호에 의미를 부여 가능하지만, 큰 의미가 없으므로 절대값을 사용
error = y_train - y_valid_predict
abs(error).describe()
1
2
3
4
5
6
7
8
9
count    394.000000
mean      86.571066
std       92.896321
min        0.000000
25%       22.250000
50%       55.000000
75%      115.000000
max      495.000000
Name: Insulin, dtype: float64
1
2
# 오차값의 분포
_ = sns.displot(abs(error), height=2, aspect=5)

png

MAE(Mean Absolut Error)

평균 절대 오차라고하며, 평균 절대 편차/차이와는 다른 개념임
$MAE = {\sum_{i=1}^n err_i \over n }$

1
abs(error).mean()
1
86.57106598984771

MAPE (Mean Absolute Percentage Error)

평균 절대비 오차라하며, 퍼센트 값을 가짐
0에 가까울수록 회귀 모형의 성능이 좋다고 해석 가능
평균 절대 백분율 편차 (MAPD)라고도 함
$MAPE = {100\% \over n} \sum_{i=1}^n |{y_i-\hat y_i \over y_i}|$

1
abs(error/y_train).mean()
1
0.687125648313691

MSE (Mean Squared Error)

평균 제곱 오차라하며, 제곱을 이용해 음수를 양수로 변환
$ MSE = {1 \over n} \sum_{i=1}^n (\hat y_i - y_i)^2 $

1
np.square(error).mean()
1
16102.373096446701

RMSE (Root Mean Squared Error)

평균 제곱근 편차라하며, 정밀도를 표현하는데 적합
$ RMSE = \sqrt{MSE} $

1
np.sqrt(np.square(error).mean())
1
126.89512636995443

트리 알고리즘 분석

1
model.feature_importances_
1
2
array([4.20201517e-02, 4.08219914e-01, 6.24932543e-02, 5.97519119e-02,
       1.10296456e-01, 1.63917473e-01, 1.52984660e-01, 3.16179009e-04])
1
_ = sns.barplot(x=model.feature_importances_, y=feature_names)

png

예측

회귀에서 사용한 cross-validation은 예측을 진행한것이 아니라, 모델 성능을 높이기 위해 진행한 과정임

1
y_predict = model.predict(X_test)
1
2
# 기존 Insulin 수치
train.groupby("Outcome")["Insulin"].describe()
countmeanstdmin25%50%75%max
Outcome
0264.0130.287879102.48223715.066.0102.5161.25744.0
1130.0206.846154132.69989814.0127.5169.5239.25846.0
1
2
3
# 예측한 값으로 Insulin 값을 채운 경우
test["Insulin"] = y_predict
test.groupby("Outcome")["Insulin"].describe()
countmeanstdmin25%50%75%max
Outcome
0236.0133.161017102.22403215.064.099.5158.25600.0
1138.0212.434783141.95223644.0115.0176.0267.00846.0

평균값만 봤을때는 큰차이가 없음

This post is licensed under CC BY 4.0 by the author.

Pima Indian 데이터를 이용한 결정 트리 분류

멋쟁이 사자처럼 AI Shcool 7주차

Comments powered by Disqus.