1. wine 데이터를 활용하겠습니다.
import pandas as pd
red_url = 'https://raw.githubusercontent.com/PinkWink/forML_study_data/refs/heads/main/data/winequality-red.csv'
white_url = 'https://raw.githubusercontent.com/PinkWink/forML_study_data/refs/heads/main/data/winequality-white.csv'
red_wine = pd.read_csv(red_url, sep=';')
white_wine = pd.read_csv(white_url, sep=';')
red_wine['color'] = 1
white_wine['color'] = 0
wine = pd.concat([red_wine, white_wine])
wine['taste'] = [1. if grade > 5 else 0. for grade in wine['quality']]
X = wine.drop(['quality', 'taste'], axis = 1)
y = wine['taste']
color라는 새로운 컬럼을 만들어 주고 red와인 : 1 white와인 : 0으로 설정 해주고 두 개의 데이터를 concat으로 합쳐주었습니다.
taste라는 컬럼을 만들어 준 후 quality가 5보다 크면 1로 아니라면 0으로 설정해주었습니다.
2. 결정 나무 모델을 통해 학습시키겠습니다.
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
# 데이터 나누고 학습
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=13)
wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)
# 정확도 평가
y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)
accuracy_train = accuracy_score(y_train, y_pred_tr)
accuracy_test = accuracy_score(y_test, y_pred_test)
accuracy_train, accuracy_test
이제 데이터를 나눠주고 결정 나무 모델을 통해 학습 한 뒤 정확성 평가를 해보았습니다.
결과 : (0.7294593034442948, 0.7161538461538461) 두 개의 데이터 모두 72%의 정확도를 보여주는 것을 확인하였습니다.
3. 교차 검증을 위해 KFold를 통해 데이터를 5등분으로 나누어 주겠습니다.
from sklearn.model_selection import KFold
kfold = KFold(n_splits=5)
wine_tree_cv = DecisionTreeClassifier(max_depth=2, random_state=13)
len(X) # 원래 데이터는 6497개의 데이터가 있습니다.
# kfold로 5등분으로 나누어 몇개씩 있는지 확인해보겠습니다.
for train_index, test_index in kfold.split(X):
print(len(train_index), len(test_index))
train test
5197 1300
5197 1300
5198 1299
5198 1299
5198 1299
위의 값이 kfold를 통해 데이터를 5등분 나눈 것입니다. 이제 보시면 훈련세트와 테스트세트끼리의 숫자가 비슷합니다. 하지만 다들 5개 구간으로 나눠져있으며 모두 다른 훈련세트와 테스트 세트입니다.
그리고 train_index와 test_index는 해당 데이터들의 인덱스가 저장됩니다.
4. 이제 반복문을 통해 각각의 데이터를 훈련시킨 후 정확도 평가를 해보겠습니다.
import numpy as np
cv_accuracy = []
for train_idx, test_idx in kfold.split(X):
X_train, X_test = X.iloc[train_idx], X.iloc[test_idx] # 받은 인덱스들을 가지고 넣어준다.
y_train, y_test = y.iloc[train_idx], y.iloc[test_idx] # y 데이터 또한 넣어준다.
wine_tree_cv.fit(X_train, y_train) # 한 덩어리가 올 때만다 fit
pred = wine_tree_cv.predict(X_test) # 훈련이 끝난 값 예측
accuracy = accuracy_score(y_test, pred) # 그리고 y_test값과 예측값과의 정확도를 확인 해본다.
cv_accuracy.append(accuracy)
np.mean(cv_accuracy)
반복문을 통해 5번 동안 훈련 세트와 데이터 세트를 바꿔가며 훈련하고 예측값을 찾아낸 뒤 정확도를 평가하였습니다.
결과는 0번째 : 0.6007692307692307, 1번째 : 0.6884615384615385, 2번째 : 0.7090069284064665, 3번째 : 0.7628945342571208, 4번째 : 0.7867590454195535
확실히 훈련 세트 구간과 테스트 세트 구간을 바꾸면서 정확도를 평가해본 결과 0번째는 60% 점점 반복할 수록 70% 후반을 보여주는 모습입니다. 즉 모델이 점점 개선되는 것 같습니다.
마지막으로 평균을 계산 결과 정확도는 70%로 확인이 되었습니다.
5. 이번에는 특정 라벨이 많을 경우에 사용하는 StratifiedKFold() 보여드리겠습니다.
# StratifiedKFold : 특정 label의 데이터가 너무 많거나, 너무 적어 값의 분포가 한쪽으로 치우치는 경우 사용할 수 있다.
# (예를 들어 레드 와인 데이터가 5개 화이트 와인 데이터가 50개인 경우)
# 즉 , 비율을 맞춰 계산
from sklearn.model_selection import StratifiedKFold
skfold = StratifiedKFold(n_splits=5)
# shuffle=True, random_state=13
#shuffle => 데이터를 계속 섞는다 그러면 값이 바뀔수도 있을 수도 잇다.
wine_tree_cv = DecisionTreeClassifier(max_depth=2, random_state=13)
cv_accuracy = []
for train_idx, test_idx in skfold.split(X, y):
X_train, X_test = X.iloc[train_idx], X.iloc[test_idx] # 받은 인덱스들을 가지고 넣어준다.
y_train, y_test = y.iloc[train_idx], y.iloc[test_idx] # y 데이터 또한 넣어준다.
wine_tree_cv.fit(X_train, y_train) # 한 덩어리가 올 때만다 fit
pred = wine_tree_cv.predict(X_test) # 훈련이 끝난 값 예측
accuracy = accuracy_score(y_test, pred) # 그리고 y_test값과 예측값과의 정확도를 확인 해본다.
cv_accuracy.append(accuracy)
cv_accuracy
StratifiedKFold : 특정 label의 데이터가 너무 많거나, 너무 적어 값의 분포가 한쪽으로 치우치는 경우 사용할 수 있다.
(예를 들어 레드 와인 데이터가 5개 화이트 와인 데이터가 50개인 경우)
즉, 비율을 맞춰 계산하는 모델입니다.
비율을 맞춘 후 훈련시키고 정확도 평균을 구한 결과 68%로 확인되었습니다.
6. 반복문 사용하지 않고 cross_val_score를 통해 바로 정확도 구하기
from sklearn.model_selection import cross_val_score
skfold = StratifiedKFold(n_splits=5)
wine_tree_cv = DecisionTreeClassifier(max_depth=2, random_state=13)
cross_val_score(wine_tree_cv, X, y, cv=skfold)
# 바로 성능값이 나온다.
# 위에서 사용한 for문과 같은 기능이다.
위에서 처럼 반복문을 사용하지 않고 cross_val_score를 사용하면 바로 각각의 성능값이 확인됩니다.
7. cross_validate 방식으로도 출력할 수 있습니다.
from sklearn.model_selection import cross_validate
# train데이터에 대한 값 또한 출력하라
cross_validate(wine_tree_cv, X, y, cv=skfold, return_train_score=True)
이렇게 하면 test_score, train_score또한 볼 수 있습니다.
8. GridSearchCV를 사용해 다양한 하이퍼파라미터를 적용해보겠습니다.
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
# max_depth가 2,4,7,10일 경우의 값들을 적용하여 각각 학습한다.
params = {'max_depth':[2,4,7,10]}
wine_tree = DecisionTreeClassifier(random_state=13)
grid_search = GridSearchCV(wine_tree, param_grid=params, cv=5)
grid_search.fit(X_train, y_train)
grid_search.cv_results_
이렇게 사용해주시면 결정 트리에서 depth를 결정하는 하이퍼파라미터 max_depth를 여러 값을 넣어 테스트 해볼 수 있습니다.
그리고 다양하게 나온 score를 확인해보면 제일 좋은 하이퍼파라미터 값을 알아낼 수 있습니다.
cv_results_를 사용해주면 모든 값을 적용한 결과가 출력됩니다.
이런 식으로 모든 score값이 출력됩니다.
9. GridSearchCV에서 사용하는 다양한 함수
# 베스트 값으로 사용한 분류 모델을 출력해줍니다.
grid_search.best_estimator_
grid_search.best_params_
# 출력결과 : {'max_depth': 4}
grid_search.best_score_
# 출력 결과 : 0.6841165691863479
이것보다 많이 있으나 대표적인 3개입니다.
10. GridSearchCV의 함수와 모델을 모두 사용하고 Pipeline을 통해 묶어서 사용해보겠습니다.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier
# pipeline에 묶기 위한 작업
estimators = [('scaler', StandardScaler()), ('clf', DecisionTreeClassifier(random_state=13))]
pipe = Pipeline(estimators)
# gridsearchcv사용해서 훈련
param_grid = [{'clf__max_depth':[2,4,7,10]}]
grid_search = GridSearchCV(pipe, param_grid=param_grid, cv=5)
grid_search.fit(X_train, y_train)
# 제일 좋은 하이퍼파라미터를 사용한 모델의 트리구조 표현(max_depth=4)
import matplotlib.pyplot as plt
from sklearn import tree
fig = plt.figure(figsize=(10,8))
_ = tree.plot_tree(grid_search.best_estimator_['clf'], filled=True)
이렇게 pipeline을 통해 스케일링작업과 모델링 작업을 묶어 주고 GridSearchCV를 사용하여 제일 좋은 score가 나온 하이퍼파라미터 값을 찾아냅니다.
best_estimator_['clf']를 사용하여 제일 좋은 값을 넣은 모델의 트리 구조를 출력하였습니다.
이상으로 해당 글을 마치겠습니다.
이 글은 제로베이스 데이터 분석 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.
'Data Analyst > ML' 카테고리의 다른 글
[Zero-base] KNN(KNeighbors Classifier) - 1 (0) | 2024.10.07 |
---|---|
[Zero-base] Precision and Recall (0) | 2024.10.07 |
[Zero-base] Cross Validation(교차 검증) - 1 (0) | 2024.10.04 |
[Zero-base] Logistic Regression - 2 (0) | 2024.10.03 |
[Zero-base] Logistic Regression - 1 (1) | 2024.10.03 |