1. 사이킷런?
파이썬 머신러닝 라이브러리 중 가장 많이 사용되는 라이브러리
-> 기본적으로 아나콘다에 사이킷런은 설치되어 있음
#install
conda install scikit-learn
#import
import sklearn
#version 확인
import sklearn
print(sklearn.__version__)
2. 붓꽃 품종 예측하기
- 머신러닝 만들기 전 기초 준비
# 붓꽃 데이터 로드
from sklearn.datasets import load_iris
# 의사결정 트리를 사용
from sklearn.tree import DecisionTreeClassifier
#학습데이터와 테스트 데이터 분류
from sklearn.model_selection import train_test_split
1) load 함수를 이용해 DataFrame 변환
import pandas as pd
iris=load_iris()
#Iris의 피쳐 값들로만 구성된 numpy
iris_data=iris.data
#Iris의 레이블(label)들로만 구성된 numpy
iris_label=iris.target
print("iris target 명: ", iris.target_names)
# 시각적으로 편리하게 보기 위해 DataFrame으로 변환
iris_df=pd.DataFrame(data=iris_data, columns=iris.feature_names)
iris_df["label"]=iris.target
iris_df.head(3)
2) 데이터 세트 분리
데이터를 학습하기 위해서는 먼저 학습용 데이터와 테스트 데이터를 분리해야 한다.
- 학습데이터: 모델을 학습하는 데이터
- 테스트데이터: 모델이 제대로 데이터를 학습하였는지 평가하는 데 사용하는 데이터
-> 데이터 분류는 train_test_split()를 통해서 쉽게 가능함.
# 학습데이터와 테스트 데이터 분류
X_train, X_test, y_train, y_test=train_test_split(iris_data, iris_label, test_size=0.2, random_state=11)
3) 학습 개체 생성 및 학습
학습을 진행해보면, 학습 모델은 의사결정 트리로 이용
의사결정트리 객체 생성은 DecisionTreeClassifer()라는 API를 통해 쉽게 구현 가능
객체 생성 후, DecisionTreeClassifer 의 fit() 메소드를 통해 학습시키면 됨.
# 의사결정트리 객체 생성 및 학습
dt_clf=DecisionTreeClassifier(random_state=11)
dt_clf.fit(X_train,y_train)
- fit 메소드 : 지도학습-모델을 학습 시키는 역할,
비지도 학습-입력 데이터의 형태에 맞춰 데이터를 변환하는 역할
4) 예측 수행 및 평가
#예측 수행
pred =dt_clf.predict(X_test)
#정확도(예측값과 정답 비교)
from sklearn.metrics import accuracy_score
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))
-> 모든 머신러닝 문제는 데이터처리, ML 알고리즘 학습/예측 수행, 모델 평가로 이뤄진다.
3. 교차검증
교차검증: 학습데이터를 학습데이터 세트와 검증데이터 세트로 분리하여 다양한 학습과 평가를 반복적으로 실시하는것.
ex) 기말고사 전에 여러번의 쪽지시험을 보는 형태
Q. 교차검증을 사용하는 이유는?
A: 과적합 때문
Q:과적합이란?
A: 모델이 학습데이터에만 과도하게 학습되어 실제 다른 데이터를 예측할때 성능이 과도하게 떨어지는 것을 말함.
Q.학습 데이터만 반복적으로 바꿔주면 안되나? 왜 검증데이터가 필요할까?
A: 학습데이터와 테스트 데이터를 평가하면, 테스트 데이터만 최적의 성능을 발휘하는 문제가 발생됨.
이를 해결하기 위해 여러번의 테스트를 지속적으로 수행하는 검증데이터 필요
4. K 폴드 교차 검증
가장 보편적인 교차검증 방법
K 폴드 교차 검정: K개의 데이터 폴드 세트를 만들어 k번만큼 각 폴트 세트에 학습과 검증 평가를 반복적으로 수행 방법
1) 실습
필요한 부분 import
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
import numpy as np
kFold() 메소드 사용해 데이터를 5개의 데이터 세트로 분류로 선언
#데이터 생성 및 모델 정의
iris=load_iris()
features=iris.data
label=iris.target
dt_clf=DecisionTreeClassifier(random_state=156)
# 5개의 KFold 객체 생성
kfold = KFold(n_splits=5)
cv_accuracy=[]
print('붓꽃 데이터 세트 크기:', features.shape[0])
kfold.split()를 통해 train 데이터와 검증데이터 분류
kfold.split()는 train data와 test data의 인덱스를 array형태로 반환합니다.
n_iter =0
# KFold 교차검증을 통한 학습 진행
for train_index, test_index in kfold.split(features):
# kfold.split()으로 반환된 인덱스를 이용하여 학습용, 검증용 테스트 데이터 추출
X_train, X_test = features[train_index],features[test_index]
y_train, y_test = label[train_index],label[test_index]
#학습 및 예측
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
n_iter += 1
# 매 반복에서 정확도 측정
accuracy = np.round(accuracy_score(y_test,pred), 4)
train_size=X_train.shape[0]
test_size=X_test.shape[0]
print('\n#{0} 교차 검증 정확도: {1}, 학습 데이터 크기:{2}, 검증 데이터크기: {3}'.format(n_iter,accuracy,train_size,test_size))
print('#{0} 검증 세트 인덱스:{1}'.format(n_iter, test_index))
cv_accuracy.append(accuracy)
# 개별 iteration별 정확도를 합하여 평균 정확도 계산
print('\n## 평균 검증 정확도:', np.mean(cv_accuracy))
이런 방법으로 학습 데이터와 검증 데이터를 바꿔가며 학습과 평가를 여러번 수행한다.
5. Stratified K 폴드
Stratified K 폴드: 불균형한 분포도를 가지는 레이블 데이터 집합을 위한 k 폴드 방식
ex) 신용 카드 결제의 오류 발생률이라는 데이터가 있다고 가정해보자. 그런데 이때 실제로는 오류 발생률이 0.0001%에 불과한데 K폴드로 데이터를 나누는 과정에서 어떤 데이터셋에는 유독 오류 데이터가 많이 분포하여 해당 데이터의 오류 발생률은 0.1%가 될 수 있다. 이러한 경우 본래 의도와 다른 방향으로 학습이 이루어질 수 있다. 이러한 상황을 방지하기 위해 Stratified K 폴드를 사용한다.
kfold=KFold(n_splits=3)
n_iter =0
for train_index, test_index in kfold.split(iris_df):
n_iter +=1
label_train =iris_df['label'].iloc[train_index]
label_test =iris_df['label'].iloc[test_index]
print('## 교차 검증: {0}'.format(n_iter))
print('학습 레이블 데이터 분포:\n', label_train.value_counts())
print('검증 레이블 데이터 분포:\n', label_test.value_counts())
print('\n')
-> 붓꽃 데이터를 3개의 폴드로 분리한 위 결과 값을 보면 첫번째 폴드는 0,1에 대해서만 학습하고, 2에대해서 검증함.
나머지 데이터 셋을 보면 모두 서로 다른 두가지의 레이블에 대해서만 학습하고, 이와 무관한 나머지 하나의 레이블에 대해서는 평가를 진행하는 것을 볼 수 있다.
# Startified K 폴드로 수행시
* 유의사항
- Startified K 폴드는 레이블의 분포도를 고려해 데이터 폴드를 나누기 때문에
반드시!! .split()레이블 값을 인자로 넣어줘야 한다.
from sklearn.model_selection import StratifiedKFold
skf=StratifiedKFold(n_splits=3)
n_iter =0
for train_index, test_index in skf.split(iris_df,iris_df['label']):
n_iter +=1
label_train =iris_df['label'].iloc[train_index]
label_test =iris_df['label'].iloc[test_index]
print('## 교차 검증: {0}'.format(n_iter))
print('학습 레이블 데이터 분포:\n', label_train.value_counts())
print('검증 레이블 데이터 분포:\n', label_test.value_counts())
위의 결과 값을 보면, 0,1,2 에 대하여 균일하게 학습을 하고, 테스트를 진행하는 것을 볼 수 있다
Stratified K 폴드는 레이블 데이터 집합이 균형있는 분포를 가지게 해준다.
다시한번, Stratified K 폴드를 이용해 예측해보면?
dt_clf = DecisionTreeClassifier(random_state=156)
skfold = StratifiedKFold(n_splits=3)
n_iter=0
cv_accuracy=[]
# StratifiedKFold의 split( ) 호출시 반드시 레이블 데이터 셋도 추가 입력 필요
for train_index, test_index in skfold.split(features, label):
# split( )으로 반환된 인덱스를 이용하여 학습용, 검증용 테스트 데이터 추출
X_train, X_test = features[train_index], features[test_index]
y_train, y_test = label[train_index], label[test_index]
#학습 및 예측
dt_clf.fit(X_train , y_train)
pred = dt_clf.predict(X_test)
# 반복 시 마다 정확도 측정
n_iter += 1
accuracy = np.round(accuracy_score(y_test,pred), 4)
cv_accuracy.append(accuracy)
# 교차 검증별 정확도 및 평균 정확도 계산
print('\n## 교차 검증별 정확도:', np.round(cv_accuracy, 4))
print('## 평균 검증 정확도:', np.mean(cv_accuracy))
6. cross_val_score()
지금까지 교차검증을 수행한 과정을 살펴 보면 폴드 세트 설정, 학습/ 검증 데이터 추출, 반복적인 학습과 예측을 통해 예측 성능 반환으로 이루어졌다. 이러한 어떻게 보면 복잡한 과정을 한번에 실시해주는 아주 편리한 API가 있는데 바로 cross_val_score()이다. 아래 예제를 통해 cross_val_score()에 대해 보자.
* cross_val_score의 주요 인자
estimator(=dt_clf) : Classifier 알고리즘 또는 Regressor 알고리즘
X(=data) : feature 데이터 세트
y(=label) : 레이블 데이터 세트
scoring(='accuracy') : 예측 성능 평가 지표
cv(=3) : 폴드의 개수
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score , cross_validate
from sklearn.datasets import load_iris
import numpy as np
iris_data=load_iris()
dt_clf = DecisionTreeClassifier(random_state=156)
data=iris_data.data
label=iris_data.target
scores = cross_val_score(dt_clf, data, label, scoring='accuracy',cv=3)
print('교차 검증별 정확도:',np.round(scores, 4))
print('평균 검증 정확도:', np.round(np.mean(scores), 4))
cross_val_score는 cv로 지정된 횟수만큼 지정된 평가지표를 반환한다. 근데 반환된 결과값이 익숙하지 않나?
바로 이전에 실습한 Stratified K 폴드와 동일한 결과값을 보여준다. 그 이유는 바로 cross_val_score는 Classifier을 Stratified K 폴드 방식으로 수행하기 때문이다.
6. GridSearchCV
마지막 GridSearchCV
GridSearchCV: 교차검증과 최적의 하이퍼파라미터 튜닝을 한번에 진행해주는 API 이다.
하이퍼 파라미터란? 모델의 예측 성능을 향상 시키기 위해 조정해야할 중요한 인자
GridSearchCV 는 최적의 파라미터를찾아준다는 장점이 있지만, 시간이 오래걸린다는 단점이 있다.
*DataFrame 칼럼
split0_test_score : 첫번째 폴드의 예측결과
split1_test_score : 두번째 폴드의 예측결과
split2_test_score : 세번째 폴드의 예측결과
mean_test_score : 위에서 구한 예측결과의 평균
rank_test_score : 예측결과의 평균을 바탕으로 매긴 순위
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd
# 학습데이터와 테스트 데이터 분리
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target,
test_size=0.2, random_state=121)
dtree = DecisionTreeClassifier()
# 하이퍼파라미터들을 dictionary 형태로 설정
parameters = {'max_depth':[1, 2, 3], 'min_samples_split':[2,3]}
# 나올 수 있는 하이파라미터의 모든 조합(3X2가지)에 대하여 3개의 fold로 나누어 학습을 진행
grid_dtree=GridSearchCV(dtree, param_grid=parameters, cv=3, refit=True, return_train_score=True)
# 하이퍼 파라미터들을 순차적으로 학습/평가
grid_dtree.fit(X_train, y_train)
# GridSearchCV 결과는 cv_results_ 라는 딕셔너리로 저장됨. 이를 DataFrame으로 변환
scores_df = pd.DataFrame(grid_dtree.cv_results_)
scores_df[['params', 'mean_test_score', 'rank_test_score',
'split0_test_score', 'split1_test_score', 'split2_test_score']]
GridSearchCV에서 중요한 인자 중 하나는 바로 refit이라는 인자이다.
True라고 설정되어 있으면 최적의 성능의 하이퍼 파라미터로 모델을 학습시켜 best_estimator_로 저장한다.
그럼 이렇게 튜닝한 모델을 이전에 train_test_split()로 분리한 별도의 테스트 세트로 평가를 진행해보자.
이렇게 교차검증을 통해 모델을 튜닝하고 별도의 테스트세트로 모델을 평가하는 것이 일반적인 방법이다.
# GridSearchCV의 refit으로 이미 학습이 된 estimator 반환
estimator = grid_dtree.best_estimator_
# GridSearchCV의 best_estimator_는 이미 최적 하이퍼 파라미터로 학습이 됨
pred = estimator.predict(X_test)
print('테스트 데이터 세트 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))
'Data > 머신러닝' 카테고리의 다른 글
[파이썬머신러닝완벽가이드]03.평가(2) (0) | 2023.05.13 |
---|---|
[파이썬머신러닝완벽가이드]03.평가(1) (0) | 2023.05.06 |
[파이썬머신러닝완벽가이드]02.사이킷런으로 시작하는 머신러닝(2) (0) | 2023.04.28 |
[파이썬머신러닝완벽가이드]01.파이썬 기반의 머신러닝과 생태계 이해: 판다스 (1) | 2023.04.15 |
[파이썬머신러닝완벽가이드]01.파이썬 기반의 머신러닝과 생태계 이해: 넘파이 (0) | 2023.04.13 |