Chapter 15. 실습

HA_·2024년 1월 6일

헷갈리는 개념

train_test_split()

: 머신러닝에서 train set과 test set으로 분할한다.

random_state
  • train_test_split()의 파라미터
  • 호출할 때 마다 동일한 학습 및 테스트용 데이터 세트를 생성하기 위해 주어지는 난수 값

출처: https://bigdaheta.tistory.com/54

  • sklearn.linear_model: 로지스틱 회귀 모델?
  • sklearn.metrics: 성능 평가(정확도 평가)를 위해 사용하는 모듈?
  • AUC 그래프는 직선에 가까울수록 머신러닝 성능이 떨어짐.

1. 직접 학습하기

1) 다시 와인데이터

import pandas as pd

wine_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/wine.csv'
wine = pd.read_csv(wine_url, index_col=0) # index_col=0 -> 인덱스 칼럼 지정
wine.head()

wine['taste'] = [1. if grade>5 else 0. for grade in wine['quality']]

X = wine.drop(['taste', 'quality'], axis=1)
y = wine['taste']

2) 데이터 분리

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=13)
  • train_test_split : 머신러닝에서 학습, 테스트를 위해 분할
  • random_state : 난수 값

3) 초 간단 로지스틱 회귀 테스트

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

lr = LogisticRegression(solver='liblinear', random_state=13)
lr.fit(X_train, y_train)
y_pred_tr = lr.predict(X_train)
y_pred_test = lr.predict(X_test)

print('Train Acc : ', accuracy_score(y_train, y_pred_tr))
print('Test Acc : ', accuracy_score(y_test, y_pred_test))

  • 'LogisticRegression'은 분류기 -> 분류기는 'classification' 문제 -> 'classification' 문제는 accuracy 등을 측정할 수 있음.
  • 그래서 성능 평가함.
  • solver -> 최적화 알고리즘을 뭘로 잡을건지
  • liblinear -> 보통 데이터 수가 작을 때 선택함.
  • y_pred_tr = lr.predict(X_train) => train 데이터에 대한 예측 결괏값은 학습을 완료한 LogisticRegression 분류기인 'lr'한테 predict 시키면 됨!!
    => train 데이터와 test 데이터의 accuracy의 큰 차이가 없음!

4) 스케일러까지 적용해서 파이프라인 구축(스탠다드 스케일러)

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

estimators = [
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(solver='liblinear', random_state=13))
]

pipe = Pipeline(estimators)

'scaler' -> 스케일러 단계
'clf' -> 분류기

5) fit (이제 훈련시킴)

pipe.fit(X_train, y_train)
  • 이 단계를 거치면 파이프라인을 구축했기 때문에
  • 내가 지정한 'StandardScaler'와 'LogisticRegression'을 한 번에 수행함!

6) 예측 성능 확인

y_pred_tr = pipe.predict(X_train)
y_pred_test = pipe.predict(X_test)

print('Train Acc : ', accuracy_score(y_train, y_pred_tr))
print('Test Acc : ', accuracy_score(y_test, y_pred_test))

  • 이전보다 조금 올라감.
  • 상승 효과가 있긴 함.

7) Decision Tree와 비교를 위한 작업

from sklearn.tree import DecisionTreeClassifier

wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)

models = {
    'logistic regression':pipe,
    'decision tree':wine_tree
}

8) AUC 그래프를 이용한 모델간 비교

from sklearn.metrics import roc_curve

plt.figure(figsize=(10, 8))
plt.plot([0, 1], [0, 1])
for model_name, model in models.items():
    pred = model.predict_proba(X_test)[:, 1]
    fpr, tpr, thresholds = roc_curve(y_test, pred)
    plt.plot(fpr, tpr, label=model_name)

plt.grid()
plt.legend()
plt.show()
  • for문에서 model_name은 'logistic regression', 'decision tree' (7번 코드에서 models 에서)
  • model은 'pipe', 'wine_tree' (7번 코드에서 models 에서)
  • [:, 1] -> 모든 행의 2번째 칼럼 (1번째 칼럼은 0일 확률, 2번째 칼럼은 1일 확률)
  • fpr -> 잘못 예측
  • tpr -> 잘 예측
  • 'logistic regression' 그래프가 성능이 'Decision tree'보다 더 좋음!
  • (ㄱ을 오른쪽으로 뒤집은 모양에 가까울수록 성능이 좋다.)

2. PIMA 인디언 당뇨병 예측

1) 데이터 읽기 및 확인

PIMA_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/diabetes.csv'
PIMA = pd.read_csv(PIMA_url)
PIMA.head()

PIMA.info()

2) float으로 데이터 변환

PIMA = PIMA.astype('float')
PIMA.info()

3) 일단 상관관계 확인

import seaborn as sns
import matplotlib.pyplot as plt

plt.figure(figsize=(12, 10))
sns.heatmap(PIMA.corr(), cmap="YlGnBu")
plt.show()

  • 'Outcome' 칼럼과 괜찮아 보이는 칼럼들 -> 'Pregnancies', 'Glucose', 'BMI', 'Age'

4) 상황상 0이 존재하면 이상하지만, 0이 있는 것 확인

(PIMA==0).astype(int).sum()


cf) EDA의 목적 => 이상한 걸 찾기 위함.

  • 결측치는 데이터에 따라 그 정의가 다르다.
  • 0은 NULL이 아니지만,
  • 0이라는 숫자가 혈압에 있다는 것은 상황상 이상하기 때문에 처리해야 함!

5) 0인 값 처리 - 일단 평균값으로 대체 (의학적 지식과 PIMA 인디언에 대한 정보가 없으므로)

zero_features = ['Glucose', 'BloodPressure', 'SkinThickness', 'BMI']
PIMA[zero_features] = PIMA[zero_features].replace(0, PIMA[zero_features].mean())
(PIMA==0).astype(int).sum()

6) 학습 시키기 위해 데이터 나누기

X = PIMA.drop(['Outcome'], axis=1)
y = PIMA['Outcome']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=13, stratify=y)

7) Pipeline을 만들고

estimators = [
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(solver='liblinear', random_state=13))
]

pipe_lr = Pipeline(estimators)
pipe_lr.fit(X_train, y_train)
pred = pipe_lr.predict(X_test)

8) 몇몇 수치를 확인

from sklearn.metrics import accuracy_score, recall_score, precision_score, roc_auc_score, f1_score
from sklearn.metrics import roc_auc_score, f1_score

print('Acciracy : ', accuracy_score(y_test, pred))
print('Recall : ', recall_score(y_test, pred))
print('Precision : ', precision_score(y_test, pred))
prin
t('AUC score : ', roc_auc_score(y_test, pred))
print('f1 score : ', f1_score(y_test, pred))

  • 그러나 상대적 의미를 가질 수 없어서 이 수치 자체를 평가할 수는 없다.

9) 다변수 방정식의 각 계수 값을 확인할 수 있다.

coeff = list(pipe_lr['clf'].coef_[0])
labels = list(X_train.columns)
coeff

  • pipeline 생성한 걸 사용함.
  • coef_[0] -> 2개의 리스트 중 하나만 선택

10) 중요한 feature에 대해 그려봄

feature = pd.DataFrame({'Feature': lables, 'importance': coeff})
feature

features.sort_values(by=['importance'], ascending=True, inplace=True)
features

features['positive'] = features['importance'] > 0
features

features.set_index('Features', inplace=True)
features

11) 해석

features['importance'].plot(kind='barh',
                           figsize=(11, 6),
                           color=features['positive'].map({True:'blue',
                                                          False:'red'}))
plt.xlabel('Importance')
plt.show()

0개의 댓글