'파이썬 머신러닝 완벽가이드 > [2장] 사이킷런으로 시작하는 머신러닝' 카테고리의 다른 글
인코딩, 스케일링, 로그변환 익히기 (0) | 2023.01.25 |
---|---|
사이킷런 기본 익히기, 교차검증 익히기 (0) | 2023.01.23 |
인코딩, 스케일링, 로그변환 익히기 (0) | 2023.01.25 |
---|---|
사이킷런 기본 익히기, 교차검증 익히기 (0) | 2023.01.23 |
데이터 전처리
범주형 변수를 처리하는 데이터 인코딩, 서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업인 스케일링에 대해 알아본다. 더 다양하고 구체적인 데이터 전처리는 '데이터 전처리' 카테고리를 참고한다.
데이터 인코딩
사이킷런의 머신러닝 알고리즘은 문자열 값을 입력값으로 허용하지 않는다. 그래서 모든 문자열 값은 인코딩돼서 숫자 형으로 변환해야 한다. 여기서 문자열 피처는 범주형 변수, 코드화된 범주형 변수를 의미한다.
1) 레이블 인코딩(Label encoding)
from sklearn.preprocessing import LabelEncoder
items = ['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '선풍기', '믹서', '믹서']
# LabelEncoder를 객체로 생성한 후, fit()과 transform()으로 레이블 인코딩 수행
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print('인코딩 변환값:', labels)
# 문자열 값이 어떤 숫자 값으로 인코딩됐는지 확인 -> LabelEncoder 객체의 classes_
print('인코딩 클래스:', encoder.classes_)
# TV:0, 냉장고:1, 믹서:2, 선풍기:3, 전자레인지:4, 컴퓨터:5
# 인코딩된 값을 다시 디코딩 -> LabelEncoder 객체의 inverse_transform()
print('디코딩 원본값:', encoder.inverse_transform([4, 5, 2, 0, 1, 1, 3, 3]))
레이블 인코딩은 간단하게 문자열 값을 숫자형 값으로 변환하지만 숫자 값의 대소관계가 작용하기 때문에 몇몇 ML 알고리즘에서 예측 성능이 떨어지는 경우가 발생할 수 있다.
예를들어 냉장고가 1, 믹서가 2로 변환되면, 1보다 2가 더 큰 값이므로 특정 ML 알고리즘에서 가중치가 더 부여되거나 더 중요하게 인식할 가능성이 발생한다. 하지만 냉장고와 믹서의 숫자 변환 값은 단순 코드이지 숫자 값에 따른 순서나 중요도로 인식돼서는 안된다.
이러한 특성 때문에 레이블 인코딩은 선형회귀와 같은 ML 알고리즘에는 적용X, 트리 계열의 ML 알고리즘은 숫자의 이러한 특성을 반영하지 않으므로 레이블 인코딩도 별문제가 없음
→레이블 인코딩의 이러한 문제점을 해결하기 위한 인코딩 방식이 "원-핫 인코딩"
2) 원-핫 인코딩(One-Hot Encoding)
원-핫 인코딩은 피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 컬럼에만 1을 표시하고 나머지 컬럼에는 0을 표시하는 방식
●주의점: 입력값으로 2차원 데이터가 필요, OneHotEncoder를 이용해 변환한 값이 희소행렬(sparse matrix) 형태이므로 이를 다시 toarray() 메서드를 이용해 밀집행렬(dense matrix)로 변환해야 함
from sklearn.preprocessing import OneHotEncoder
import numpy as np
items = ['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '선풍기', '믹서', '믹서']
# 2차원 ndarray로 변환
items = np.array(items).reshape(-1,1)
# OneHotEncoder를 객체로 생성한 후, fit()과 transform()으로 원-핫 인코딩 수행
oh_encoder = OneHotEncoder()
oh_encoder.fit(items)
oh_labels = oh_encoder.transform(items)
# OneHotEncoder로 변환한 결과는 희소행렬이므로 toarray()를 이용해 밀집행렬로 변환
print('원-핫 인코딩 데이터')
print(oh_labels.toarray())
print('원-핫 인코딩 데이터 차원')
print(oh_labels.shape)
판다스에는 원-핫 인코딩을 더 쉽게 지원하는 get_dummies()가 있음
import pandas as pd
df = pd.DataFrame({'items':['TV', '냉장고', '전자레인지', '컴퓨터', '선풍기', '선풍기', '믹서', '믹서']})
pd.get_dummies(df)
스케일링
스케일링은 서로 다른 피처의 값 범위를 일정한 수준으로 맞추는 작업으로 대표적인 방법인 표준화, 정규화가 있음
●표준화(Standardization)
표준화는 데이터의 피처 각각이 평균이 0이고 분산이 1인 가우시안 정규분포를 가진 값으로 변환하는 것
●정규화(Normalization)
정규화는 서로 다른 피처의 크기를 통일하기 위해 크기를 모두 최소 0 ~ 최대 1의 값으로 변환하는 것
사이킷런에서 제공하는 스케일링 클래스인 StandardScaler, MinMaxScaler를 알아보자!
1) StandardScaler
표준화를 쉽게 지원하는 클래스로, 개별 피처를 평균이 0이고, 분산이 1인 가우시안 정규분포를 가진 값으로 변환
(Scaler 클래스의 fit(), transform()은 2차원 이상 데이터만 가능하다!!)
from sklearn.datasets import load_iris
import pandas as pd
# 붓꽃 데이터 세트를 로딩
iris = load_iris()
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
print('feature들의 평균값')
print(iris_df.mean())
print('\nfeature들의 분산값')
print(iris_df.var())
from sklearn.preprocessing import StandardScaler
# StandardScaler 객체 생성
scaler = StandardScaler()
# StandardScaler로 데이터 세트 변환. fit()과 transform() 호출
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
# transform()시 스케일 변환된 데이터 세트가 ndarray로 반환돼 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(iris_scaled, columns=iris.feature_names)
print('feature들의 평균값')
print(iris_df_scaled.mean())
print('\nfeature들의 분산값')
print(iris_df_scaled.var())
2) MinMaxScaler
정규화를 쉽게 지원하는 클래스로, 서로 다른 피처의 크기를 통일하기 위해 데이터값을 0과 1 사이의 범위 값으로 변환(음수 값이 있으면 -1에서 1값으로 변환)
(Scaler 클래스의 fit(), transform()은 2차원 이상 데이터만 가능하다!!)
from sklearn.preprocessing import MinMaxScaler
# MinMaxScaler 객체 생성
scaler = MinMaxScaler()
# MinMaxScaler로 데이터 세트 변환. fit()과 transform() 호출
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
# transform()시 스케일 변환된 데이터 세트가 ndarray로 반환돼 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(iris_scaled, columns=iris.feature_names)
print('feature들의 최솟값')
print(iris_df_scaled.min())
print('\nfeautre들의 최댓값')
print(iris_df_scaled.max())
참고로 MinMaxScaler 객체에서 feature_range 인자를 활용해 데이터값의 범위를 조정할 수 있음
★학습 데이터와 테스트 데이터의 스케일링 변환 시 유의점★
fit()은 데이터 변환을 위한 기준 정보를 기억하고 transform()은 이렇게 설정된 정보를 이용해 데이터를 변환함
그런데 학습 데이터 세트와 테스트 데이터 세트에 이 fit()과 transfrom()을 적용할 때 주의가 필요하다.
→다른 전처리 객체도 마찬가지임!!!(SimpleImputer, KNNImputer 등등)
Scaler 객체를 이용해 학습 데이터 세트로 fit()과 transform()을 적용하면 테스트 데이터 세트로는 다시 fit()을 수행하지 않고 학습 데이터 세트로 fit()을 수행한 결과를 이용해 transform() 변환을 적용해야 한다.
즉, 학습 데이터로 fit()이 적용된 스케일링 기준 정보를 그대로 테스트 데이터에 적용해야 하며, 그렇지 않고 테스트 데이터로 다시 새로운 스케일링 기준 정보를 만들게 되면 학습 데이터와 테스트 데이터의 스케일링 기준 정보가 서로 달라지기 때문에 올바른 예측 결과를 도출하지 못한다.
아래 예시를 통해 테스트 데이터에 fit()을 적용할 때 어떠한 문제가 발생하는지 알아보자~
from sklearn.preprocessing import MinMaxScaler
import numpy as np
# 학습 데이터는 0부터 10까지, 테스트 데이터는 0부터 5까지 값을 가지는 데이터 세트로 생성
# Scaler 클래스의 fit(), transform()은 2차원 이상 데이터만 가능하므로 reshape(-1,1)로 차원 변경
train_array = np.arange(0,11).reshape(-1,1)
test_array = np.arange(0,6).reshape(-1,1)
# MinMaxScaler를 이용해 학습 데이터 변환
scaler = MinMaxScaler() # MinMaxScaler 객체에 별도의 feature_range 파라미터 값을 지정하지 않으면 0~1 값으로 변환
scaler.fit(train_array)
train_scaled = scaler.transform(train_array)
print('원본 train_array 데이터:', np.round(train_array.reshape(-1), 2))
print('Scale된 train_array 데이터:', np.round(train_scaled.reshape(-1), 2))
# MinMaxScaler를 이용해 테스트 데이터 변환
scaler.fit(test_array)
test_scaled = scaler.transform(test_array)
print('원본 test_array 데이터:', np.round(test_array.reshape(-1), 2))
print('Scale된 test_array 데이터:', np.round(test_scaled.reshape(-1), 2))
출력 결과를 확인하면 학습 데이터와 테스트 데이터의 스케일링이 맞지 않음을 알 수 있다. 테스트 데이터의 경우 최솟값 0, 최댓값 5이므로 1/5로 스케일링된다. 따라서 원본값 1은 0.2로 원본값 5는 1로 변환이 된다. 앞서 학습 데이터는 스케일링 변환으로 원본값 2가 0.2로 원본값 10이 1로 변환됐다.
→머신러닝 모델은 학습 데이터를 기반으로 학습되기 때문에 반드시 테스트 데이터는 학습 데이터의 스케일링 기준에 따라야 하며, 테스트 데이터의 1 값은 학습 데이터와 동일하게 0.1 값으로 변환돼야 한다. 따라서 테스트 데이터에 다시 fit()을 적용해서는 안되며 학습 데이터로 이미 fit()이 적용된 Scaler 객체를 이용해 transform()으로 변환해야 한다.
다음은 맞는 방법인 테스트 데이터에 fit()을 호출하지 않고 학습 데이터로 fit()을 수행한 MinMaxScaler 객체의 transform()을 이용해 데이터를 변환해보자
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(train_array)
train_scaled = scaler.transform(train_array)
test_scaled = scaler.transform(test_array)
print('원본 train_array 데이터:', np.round(train_array.reshape(-1), 2))
print('Scale된 train_array 데이터:', np.round(train_scaled.reshape(-1), 2))
print('\n원본 test_array 데이터:', np.round(test_array.reshape(-1), 2))
print('Scale된 test_array 데이터:', np.round(test_scaled.reshape(-1), 2))
스케일링 변환 시 유의할 점을 요약하면
첫째, 가능하다면 전체 데이터의 스케일링 변환을 적용한 뒤 학습과 테스트 데이터로 분리
둘째, 1이 여의치 않다면 테스트 데이터 변환 시에는 fit()을 적용하지 않고 학습 데이터로 이미 fit()된 Scaler 객체를 이용해 transform()으로 변환
전처리와 데이터 분할 - 인프런 | 질문 & 답변
선생님, 안녕하세요. 스케일링 파트를 보다가 의문점이 생겨서 문의 드렸습니다. 가능하다면 전체 데이터의 스케일링 변환을 적용한 뒤 학습/테스트 데이터로 분리 하라고 하셨는데 스케일링
www.inflearn.com
로그변환
●log변환은 왜곡된 분포를 가진 피처를 비교적 정규분포에 가깝게 변환 → 변수 치우침을 해결하는 대표적인 처리 방법
●log변환은 로그를 취하는 순간 그 수는 진수가 되어버리니 값이 작아지기 때문에 큰 수치를 같은 비율의 작은 수치로 변환하기 때문에 데이터 분포도의 왜곡을 상당 수준 개선
●넘파이의 log1p() 함수를 이용하여 적용이 가능
로그변환과 스케일링의 차이
딱 정해서 말씀드리면, 개별 feature, 또는 target의 분포도가 skew가 심하면 log 변환을 합니다. Standard Scaler는 일반적으로 선형기반의 머신러닝의 입력 (전체) 데이터들에 대해서 다 적용합니다. 보통 scaling은 전체 feature들에(카테고리성 피처 제외) 다 적용합니다.
Skew가 심하면 로그 변환, 전체 데이터의 스케일링을 표준 정규 분포 형태로 맞추고 싶다면 Standard Scaler를 적용합니다(선형 기반의 머신러닝의 입력에서 MinMax나 Standard scaler를 선호는 합니다)
타이타닉 생존자 예측 실습 (0) | 2023.01.28 |
---|---|
사이킷런 기본 익히기, 교차검증 익히기 (0) | 2023.01.23 |
지도학습이란?
지도학습은 명확한 정답이 주어진 데이터를 먼저 학습한 뒤 미지의 정답을 예측하는 방식
이때 학습을 위해 주어진 데이터 세트를 학습 데이터 세트, 머신러닝 모델의 예측 성능을 평가하기 위해 별도로 주어진 데이터 세트를 테스트 데이터 세트로 지칭함
하이퍼 파라미터란?
하이퍼 파라미터는 머신러닝 알고리즘별로 최적의 학습을 위해 직접 입력하는 파라미터들을 통칭하며, 하이퍼 파라미터를 통해 머신러닝 알고리즘의 성능을 튜닝할 수 있음
붓꽃 품종 예측하기
추후에 배우게 될 의사결정트리(Decision Tree)를 활용해 붓꽃의 품종을 분류하는 모델을 만들어 머신러닝의 흐름을 파악해보자!
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 붓꽃 데이터 세트 로딩
iris = load_iris()
# 피처와 레이블
iris_data = iris.data
iris_label = iris.target
학습 데이터로 학습된 모델이 얼마나 뛰어난 성능을 가지는지 평가하기 위해 학습/테스트 데이터 분리함
# 학습/테스트 데이터 분리
x_train, x_test, y_train, y_test = train_test_split(iris_data, iris_label,
test_size=0.2, random_state=11)
# DecisionTreeClassifier 객체 생성
dt_clf = DecisionTreeClassifier(random_state=11)
# 학습
dt_clf.fit(x_train, y_train)
# 예측
pred = dt_clf.predict(x_test)
# 평가
print('예측 정확도:{0:.4f}'.format(accuracy_score(y_test, pred)))
예측 정확도:0.9333
사이킷런 프레임워크 익히기(지도학습:분류, 회귀)
●사이킷런은 ML 모델 학습을 위해 fit(), 학습된 모델의 예측을 위해 predict() 메서드 제공
●분류 알고리즘은 Classifier, 회귀 알고리즘은 Regressor로 지칭 → 두 개를 합쳐서 Estimator라고 부름
●cross_val_score와 같은 평가함수, GridSearchCV와 같은 하이퍼 파라미터 튜닝을 지원하는 클래스는 Estimator를 인자로 받음
사이킷런의 주요 모듈
Model Selection 모듈 소개
1. 학습/테스트 데이터 세트 분리 - train_test_split()
sklearn.model_selection의 train_test_split()함수
●첫 번째 파라미터로 피처 데이터 세트 입력
●두 번째 파라미터로 레이블 데이터 세트 입력
●test_size: 전체 데이터에서 테스트 데이터 세트 크기를 얼마로 샘플링할 것인가를 결정함. 디폴트는 0.25, 즉 25%임
●train_size: 전체 데이터에서 학습용 데이터 세트 크기를 얼마로 샘플링할 것인가를 결정함. test_size parameter를 통상적으로 사용하기 때문에 train_size는 잘 사용되지 않음
●shuffle: 데이터를 분리하기 전에 데이터를 미리 섞을지를 결정함, 디폴트는 True임
●random_state: 호출할 때마다 동일한 학습/테스트용 데이터 세트를 생성하기 위해 주어지는 난수값임, train_test_split()은 호출 시 무작위로 데이터를 분리하므로 random_state를 지정하지 않으면 수행할 때마다 다른 학습/테스트 용 데이터를 생성함
하지만 이 방법 역시 과적합(Overfitting)이라는 약점이 존재함
여기서 과적합이란 모델이 학습 데이터에만 과도하게 최적화되어, 실제 예측을 다른 데이터로 수행할 경우에는 예측 성능이 과도하게 떨어지는 경우를 말함, 즉 고정된 학습 데이터로 학습하고 고정된 테스트 데이터를 통해 모델의 성능을 확인하고 수정하는 과정을 반복하면, 결국 내가 만든 모델은 테스트 데이터에만 잘 동작하는 모델이 된다. 이 경우에는 테스트 데이터에 과적합되어 다른 실제 데이터를 가지고 예측을 수행하면 엉망인 결과가 나와버림
→ 이를 해결하기 위해 교차검증을 사용
2. 교차검증
간략하게 설명하자면 본고사를 치르기 전에 모의고사를 여러 번 보는 것임. 즉, 본고사가 테스트 데이터 세트에 대해 평가하는 거라면 모의고사는 교차검증에서 많은 학습과 검증 세트에서 알고리즘 학습과 평가를 수행하는 것
(원칙적으로 train_test_split으로 학습과 테스트 데이터 세트로 분리 후 학습 데이터를 학습과 검증 데이터 세트로 나눠 1차 평가)
→교차검증은 별도의 여러 세트로 구성된 학습 데이터 세트와 검증 데이터 세트에서 학습과 평가를 수행하는 것
⇛ML모델의 성능 평가는 교차 검증 기반으로 1차 평가를 한 뒤 최종적으로 테스트 데이터 세트에 적용해 평가하는 프로세스이다.
(iris데이터는 데이터 세트가 적기 때문에 교차검증이 어떻게 적용되는지를 살펴보기 위해서 학습 데이터에서 검증 데이터 세트를 안나누고 전체 데이터 세트로 교차검증을 수행했다. GridSearchCV는 원칙대로 적용)
1) K 폴드 교차검증
K 폴드 교차검증은 가장 보편적으로 사용되는 교차검증 기법으로, K개의 데이터 폴드 세트를 만들어서 K번만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행하는 방법
→K개의 예측 평가를 구했으면 이를 평균해서 K 폴드 평가 결과로 반영
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
iris = load_iris()
features = iris.data
label = iris.target
dt_clf = DecisionTreeClassifier(random_state=156)
# 5개의 폴드 세트로 분리하는 KFold 객체와 폴드 세트별 정확도를 담을 리스트 객체 생성
kfold = KFold(n_splits=5)
cv_accuracy = []
n_iter = 0 # for loop시 몇 번 반복했는지 확인하기 위해 n_iter 객체 생성
# KFold 객체의 split()를 호출하면 학습용, 검증용 테스트 데이터로 분할할 수 있는 인덱스를 array로 반환
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)
# 평가(정확도)
accuracy = np.round(accuracy_score(y_test, pred), 4)
# 폴드 세트별 정확도를 담을 리스트 객체에 정확도 추가
cv_accuracy.append(accuracy)
n_iter += 1
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))
# split()이 어떤 값을 실제로 반환하는지 확인해 보기 위해 검증 데이터 세트의 인덱스도 추출해봄
print('#{0} 검증 세트 인덱스:{1}'.format(n_iter, test_index))
# 개별 iteration별 정확도를 합하여 평균 정확도 계산
print('\n## 평균 검증 정확도:', np.mean(cv_accuracy))
2) Stratified K 폴드
Stratified K 폴드는 불균형한 분포도를 가진 레이블 데이터 집합을 위한 K 폴드 방식
→Stratified K 폴드는 원본 데이터의 레이블 분포를 먼저 고려한 뒤 이 분포와 동일하게 학습과 검증용 테스트 데이터를 분배
StratifiedKFold를 사용하는 방법은 KFold를 사용하는 방법과 비슷하다. 단 하나 큰 차이는 StratifiedKFold는 레이블 데이터 분포도에 따라 학습/검증용 테스트 데이터를 나누기 때문에 split() 메서드에 인자로 피처 데이터 세트뿐만 아니라 레이블 데이터 세트도 반드시 필요함
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
import numpy as np
iris = load_iris()
features = iris.data
label = iris.target
dt_clf = DecisionTreeClassifier(random_state=156)
# 3개의 폴드 세트로 분리하는 StratifiedKFold 객체와 폴드 세트별 정확도를 담을 리스트 객체 생성
skfold = StratifiedKFold(n_splits=3)
cv_accuracy = []
n_iter = 0 # for loop시 몇 번 반복했는지 확인하기 위해 n_iter 객체 생성
# StratifiedKFold 객체의 split()를 호출하면 학습용, 검증용 테스트 데이터로 분할할 수 있는 인덱스를 array로 반환
# StratifiedKFold의 split() 호출시 반드시 레이블 데이터 세트도 추가 입력 필요
for train_index, test_index in skfold.split(features, label):
# skfold.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)
# 평가(정확도)
accuracy = np.round(accuracy_score(y_test, pred), 4)
# 폴드 세트별 정확도를 담을 리스트 객체에 정확도 추가
cv_accuracy.append(accuracy)
n_iter += 1
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))
# split()이 어떤 값을 실제로 반환하는지 확인해 보기 위해 검증 데이터 세트의 인덱스도 추출해봄
print('#{0} 검증 세트 인덱스:{1}'.format(n_iter, test_index))
# 개별 iteration별 정확도를 합하여 평균 정확도 계산
print('\n## 평균 검증 정확도:', np.round(np.mean(cv_accuracy), 4))
그럼 KFold와 StratifiedKFold는 언제 써야 할까?
사이킷런은 교차검증을 좀 더 편리하게 수행할 수 있게 해주는 API를 제공함 → cross_val_score()
3) cross_val_score()
cross_val_score(estimator, X, y=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch='2*n_jobs') → 이 중 estimator, X, y, scoring, cv가 주요 파라미터임
●estimator: 사이킷런의 분류 알고리즘 클래스인 Classifier 또는 회귀 알고리즘 클래스인 Regressor를 의미
●X: 피처 데이터 세트
●y: 레이블 데이터 세트
●scoring: 예측 성능 평가 지표
●cv: 교차검증 폴드 수
⇛cross_val_score()는 분류 문제인 경우 Stratified K 폴드 방식으로 작동하고, 회귀 문제인 경우 K 폴드 방식으로 작동
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
import numpy as np
iris = load_iris()
features = iris.data
label = iris.target
dt_clf = DecisionTreeClassifier(random_state=156)
# 성능 지표는 정확도(accuracy), 교차검증 세트는 3개
scores = cross_val_score(dt_clf, features, label, scoring='accuracy', cv=3)
print('교차검증별 정확도:', np.round(scores, 4))
print('평균 검증 정확도:', np.round(np.mean(scores), 4))
4) 교차검증과 최적의 하이퍼파라미터 튜닝을 한번에 - GridSearchCV
사이킷런은 GridSearchCV를 이용해 분류와 회귀 알고리즘에 사용되는 하이퍼 파라미터를 순차적으로 입력하면서 편리하게 최적의 하이퍼파라미터를 도출할 수 있는 방안을 제공(최적의 하이퍼파라미터를 교차검증을 통해 추출)
<GridSearchCV의 주요 파라미터>
●estimator: 사이킷런의 분류 알고리즘 클래스인 Classifier 또는 회귀 알고리즘 클래스인 Regressor를 의미
●param_grid: key + 리스트 값을 가지는 딕셔너리가 주어짐. estimator의 튜닝을 위해 하이퍼파라미터명과 사용될 여러 하이퍼파라미터 값을 지정
●scoring: 예측 성능 평가 지표
●cv: 교차검증 폴드 수
●refit: 디폴트가 True이며 True로 생성시 최적의 하이퍼파라미터를 찾은 뒤, 입력된 estimator 객체를 해당 하이퍼파라미터로 재학습시킴
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
# 데이터를 로딩하고 학습 데이터와 테스트 데이터 분리
iris = load_iris()
features = iris.data
label = iris.target
x_train, x_test, y_train, y_test = train_test_split(features, label, test_size=0.2, random_state=121)
dtree = DecisionTreeClassifier()
# 파라미터를 딕셔너리 형태로 설정
parameters = {'max_depth':[1,2,3], 'min_samples_split':[2,3]}
grid_dtree = GridSearchCV(dtree, param_grid=parameters, scoring='accuracy', cv=3) # 디폴트로 refit=True
grid_dtree.fit(x_train, y_train)
# cv=3을 돌면서, 하이퍼파라미터 조합을 다 적용시켜서 그중 최적의 하이퍼파라미터 값
print('GridSearchCV 최적 파라미터:', grid_dtree.best_params_)
# cv=3을 돌면서, 하이퍼파라미터 조합을 다 적용시켜서 그중 최적의 하이퍼파라미터 값의 평가 결과 값
print('GridSearchCV 최고 정확도:', grid_dtree.best_score_)
from sklearn.metrics import accuracy_score
# GridSearchCV의 refit=True로 최적의 하이퍼파라미터로 학습된 estimator 반환
estimator = grid_dtree.best_estimator_
# 최적의 하이퍼파라미터로 학습된 estimator를 이용해 테스트 데이터 세트에 대해 예측 및 평가
pred = estimator.predict(x_test)
print('테스트 데이터 세트 정확도:{0:.4f}'.format(accuracy_score(y_test, pred)))
검증 세트의 최고 정확도 0.975보다 테스트 데이터 세트 정확도가 0.9667로 약간 낮게 나왔다. (검증 세트보다 약간 낮게 나오는게 일반적)→ 정확도 차이가 0.975보다 엄청 작게 나온게 아니므로 과적합이 없다고 판단
일반적인 머신러닝 모델 적용 방법은 학습 데이터를 GridSearchCV를 이용해 최적 하이퍼파라미터 튜닝을 수행한 뒤에 별도의 테스트 세트에서 이를 평가한다.
타이타닉 생존자 예측 실습 (0) | 2023.01.28 |
---|---|
인코딩, 스케일링, 로그변환 익히기 (0) | 2023.01.25 |