열심히 코딩 하숭!

사이킷런, Iris data_K Fold 검증, 데이터 인코딩, 스케일링 | 3주차 - 1, 2 | 파이썬 머신러닝 완벽가이드 본문

프로그래밍 언어/python

사이킷런, Iris data_K Fold 검증, 데이터 인코딩, 스케일링 | 3주차 - 1, 2 | 파이썬 머신러닝 완벽가이드

채숭이 2023. 1. 21. 17:05

 

* 해당 글은 inflearn의 강의 '[개정판] 파이썬 머신러닝 완벽가이드'를 정리한 글입니다.

 

 

 

회색 - 강의 제목

노란색, 주황색 - 강조

 

 


1일

 

사이킷런 소개와 머신러닝 분류 예측 모델 개요

 

 

사이킷런(scikit-learn)

- 쉽고 가장 python스러운 API를 제공함

- 머신러닝을 위한 매우 다양한 알고리즘과 개발을 위한 편리한 프레임워크, API 제공

- 주로 Numpy와 Scipy 기반 위에서 구축된 라이브러리

 

 

Feature(속성)

- 데이터 세트의 일반적인 속성

- 타겟값을 제외한 나머지 속성이 모두 Feature

 

 

레이블, 클래스, 타겟(값), 결정(값)

- 지도 학습 시 데이터의 학습을 위해 주어지는 정답 데이터

- 분류의 경우에는 이 결정값을 레이블 또는 클래스로 지칭

 


 

지도학습(Supervised Learning)

- 피처와 레이블 데이터를 기준으로 학습한 후 별도의 테스트 데이터 세트에서 미지의 레이블값을 예측

- 주어진 패턴을 학습 -> 테스트 데이터로 예측

학습데이터 / 테스트 데이터

 

Iris(붓꽃) 데이터

- 속성 총 4개 : Sepal length / Sepal width / Petal length / Petal width

- 분류할 품종(레이블) : Setosa / Vesicolor / Virginica

 

 

붓꽃 데이터 분류 예측 과정

1) 데이터 세트 분리 -> 데이터를 학습 데이터와 테스트 데이터로 분리

2) 모델 학습 -> 학습 데이터를 기반으로 ML 알고리즘을 적용

3) 예측 수행 -> 학습된 ML 모델을 이용해 테스트 데이터의 분류를 예측

4) 평가 -> 예측된 결과값과 테스트 데이터의 실제 결과값을 비교하여 ML 모델의 성능을 평가

 

 

 

 

첫번째 머신러닝 모델 만들어 보기 - 붓꽃(Iris) 품종 ,예측

 

 

사이킷런을 이용하여 붓꽃 데이터 품종 예측하기

 

사이킷런 버전 확인

# 사이킷런 버전 확인
import sklearn
print(sklearn.__version__)

결과

1.0.2

 

 

 

붓꽃 예측을 위한 사이킷런 필요 모듈 로딩

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier # 결정 트리 분류 모델
from sklearn.model_selection import train_test_split # 학습/테스트 데이터 분리

 

 

 

데이터 세트를 로딩

import pandas as pd

# 붓꽃 데이터 세트를 로딩합니다. 
iris = load_iris()

# iris.data는 Iris 데이터 세트에서 피처(feature)만으로 된 데이터를 numpy로 가지고 있습니다. 
iris_data = iris.data

# iris.target은 붓꽃 데이터 세트에서 레이블(결정 값) 데이터를 numpy로 가지고 있습니다. 
iris_label = iris.target
print('iris target값:', iris_label)
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)

결과

iris target값: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]
iris target명: ['setosa' 'versicolor' 'virginica']

 

 

학습 데이터와 테스트 데이터 세트로 분리

X_train, X_test, y_train, y_test = train_test_split(iris_data, iris_label, 
                                                    test_size=0.2, random_state=11)
# test_size : 0.2퍼센트의 데이터만 test 데이터로 변형해라
# random_state : 고정값으로 설정하면 됨

 

 

학습 데이터 세트로 학습(Train)수행

# DecisionTreeClassifier 객체 생성 
dt_clf = DecisionTreeClassifier(random_state=11)

# 학습 수행 
dt_clf.fit(X_train, y_train) # 학습용 데이터, 타겟을 입력

결과

DecisionTreeClassifier(random_state=11)
 

 

테스트 데이터 세트로 예측(Predict) 수행

# 학습이 완료된 DecisionTreeClassifier 객체에서 테스트 데이터 세트로 예측 수행. 
pred = dt_clf.predict(X_test)

pred

결과

array([2, 2, 1, 1, 2, 0, 1, 0, 0, 1, 1, 1, 1, 2, 2, 0, 2, 1, 2, 2, 1, 0,
       0, 1, 0, 0, 2, 1, 0, 1])

 

 

 

예측 정확도 평가

from sklearn.metrics import accuracy_score # 정확도를 평가해주는 API
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred))) # test데이터의 타겟값과 실제 예측값을 비교

결과

예측 정확도: 0.9333
 
 

 

 

 

사이킷런의 기반 프레임 워크 익히기 - 주요 API/모듈 및 내장 예제 데이터 세트 소개

 

 

Estimator와 fit(), predict()

- Estimator가 분류와 회귀의 최상위 부모 class라고 생각하면 됨

- 분류와 회귀 모두 학습은 fit() / 예측은 predict()로 시행된다

 

 

 

사이킷런의 주요 모듈

- 알고있기

 

 

 

사이킷런 내장 예제 데이터 셋 - 분류 및 회귀용

- 제공해주는 데이터 셋을 사용하여 분류, 회귀를 진행해볼 수 있음

 

 

 

내장 예제 데이터 셋 구성

- data : 피쳐 데이터셋

- feature_names : data의 name column 들

- target : label을 값으로 표시

- target_names : target 값들이 뜻하는 이름을 나타냄

 

 

사이킷런 내장 예제 데이터

 

데이터 불러오기

from sklearn.datasets import load_iris

iris_data = load_iris()
print(type(iris_data)) # Bunch라는 타입은 파이썬의 딕셔너리와 비슷하다고 보면 됨

결과

<class 'sklearn.utils.Bunch'>

 

Keys 출력

keys = iris_data.keys()
print('붓꽃 데이터 세트의 키들:', keys)

결과

붓꽃 데이터 세트의 키들: dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])

 

- 키는 보통 data, target, target_name, feature_names, DESCR로 구성돼 있음

- 개별 키가 가리키는 의미는 다음과 같다

  • data : 피처의 데이터 세트
  • target : 분류 시 레이블 값, 회귀일 때는 숫자 결괏값 데이터 세트
  • target_names : 개별 레이블의 이름
  • feature_names : 피처의 이름
  • DESCR : 데이터 세트에 대한 설명과 각 피처의 설명
 
 

데이터 확인

print('\n feature_names 의 type:',type(iris_data.feature_names))
print(' feature_names 의 shape:',len(iris_data.feature_names))
print(iris_data.feature_names)

print('\n target_names 의 type:',type(iris_data.target_names))
print(' feature_names 의 shape:',len(iris_data.target_names))
print(iris_data.target_names)

print('\n data 의 type:',type(iris_data.data))
print(' data 의 shape:',iris_data.data.shape)
print(iris_data['data'])

print('\n target 의 type:',type(iris_data.target))
print(' target 의 shape:',iris_data.target.shape)
print(iris_data.target)

결과

 feature_names 의 type: <class 'list'>
 feature_names 의 shape: 4
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

 target_names 의 type: <class 'numpy.ndarray'>
 feature_names 의 shape: 3
['setosa' 'versicolor' 'virginica']

 data 의 type: <class 'numpy.ndarray'>
 data 의 shape: (150, 4)
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]
(생략...)
 [6.3 2.5 5.  1.9]
 [6.5 3.  5.2 2. ]
 [6.2 3.4 5.4 2.3]
 [5.9 3.  5.1 1.8]]

 target 의 type: <class 'numpy.ndarray'>
 target 의 shape: (150,)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]

 

 

 

학습과 테스트 데이터 세트의 분리

 

학습 데이터 세트

- 머신러닝 알고리즘의 학습을 위해 사용

- 데이터의 속성들과 결정값(레이블)값 모두를 가지고 있음

- 학습 데이터를 기반으로 머신러닝 알고리즘의 데이터 속성과 결정값의 패턴을 인지하고 학습

 

테스트 데이터 세트

- 테스트 데이터 세트에서 학습된 머신러닝 알고리즘을 테스트 

- 속성 데이터만 머신러닝 알고리즘에 제공하며, 머신러닝 알고리즘은 제공된 데이터를 기반으로 결정값 예측

- 테스트 데이터는 학습 데이터와 별도의 데이터 세트로 제공되어야 함

 

 

sklearn.model_selection의 train_test_split() 함수

X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, 
                                                    test_size=0.3, random_state=121)
  • test_size : 전체 데이터에서 테스트 데이터 세트의 크기를 얼마로 샘플링할 것인가를 결정. 디폴트 값은 0.25
  • train_size : test_size의 train버전. 통상적으로 test_size를 많이 사용하기 때문에 train_size는 잘 안 쓰임
  • shuffle : 데이터를 분리하기 전에 미리 섞을지를 결정함. 디폴트 값은 True -> 데이터를 분산시켜 좀 더 효율적으로 학습 및 테스트 데이터 세트를 만드는 데에 사용됨
  • random_state : 호출할 때마다 동일한 학습/테스트용 데이터 세트를 생성하기 위해 주어지는 난수 값

 

 train_test_split() 예제

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
​
dt_clf = DecisionTreeClassifier( )
iris_data = load_iris()
​
X_train, X_test,y_train, y_test= train_test_split(iris_data.data, iris_data.target, 
                                                    test_size=0.3, random_state=121)
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))

결과

예측 정확도: 0.9556
 
 
 

넘파이 ndarray 뿐만 아니라 판다스 DataFrame/Series도 train_test_split()으로 분할 가능

import pandas as pd

iris_df = pd.DataFrame(iris_data.data, columns=iris_data.feature_names)
iris_df['target']=iris_data.target
iris_df.head()

결과

----

ftr_df = iris_df.iloc[:, :-1] # feature 데이터 추출
tgt_df = iris_df.iloc[:, -1] # target 데이터 추출
X_train, X_test, y_train, y_test = train_test_split(ftr_df, tgt_df, 
                                                    test_size=0.3, random_state=121)
print(type(X_train), type(X_test), type(y_train), type(y_test))

결과

<class 'pandas.core.frame.DataFrame'> <class 'pandas.core.frame.DataFrame'> <class 'pandas.core.series.Series'> <class 'pandas.core.series.Series'>

----

 
dt_clf = DecisionTreeClassifier( )
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))

결과

예측 정확도: 0.9556
 

 

 

교차검증 - K-Fold와 Stratified K-Fold의 이해

 

 

교차검증 개념

- 학습데이터를 다시 분할

- 학습 데이터 / 평가를 위한 검증데이터로 나눔

 

 

K 폴드 교차 검증

- 아래와 같이 K개로 만든 폴드 세트를 각각 학습, 검증하여

- 최종적으로 평균값으로 평가

- 일반 K 폴드임

 

 

Stratified K 폴드

- 불균형한 분포도를 가진 레이블 데이터 집합을 위한 방식

- 예를 들어) 2만건의 데이터 중에 레이블값 1을 가진 데이터의 개수가 100개에 불과할 경우

- 학습 데이터와 검증 데이터 세트가 가지는 레이블 분포도가 유사하도록 검증 데이터 추출

 

 


 

 

일반 K 폴드 예제

 

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold # K Fold 클래스

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])

n_iter = 0

# 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)
    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))

 

결과

붓꽃 데이터 세트 크기: 150

#1 교차 검증 정확도 :1.0, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#1 검증 세트 인덱스:[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29]
[ 30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47
  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65
  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83
  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101
 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
 138 139 140 141 142 143 144 145 146 147 148 149]

#2 교차 검증 정확도 :0.9667, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#2 검증 세트 인덱스:[30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
 54 55 56 57 58 59]
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  60  61  62  63  64  65
  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83
  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101
 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
 138 139 140 141 142 143 144 145 146 147 148 149]

#3 교차 검증 정확도 :0.8667, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#3 검증 세트 인덱스:[60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
 84 85 86 87 88 89]
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53
  54  55  56  57  58  59  90  91  92  93  94  95  96  97  98  99 100 101
 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
 138 139 140 141 142 143 144 145 146 147 148 149]

#4 교차 검증 정확도 :0.9333, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#4 검증 세트 인덱스:[ 90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107
 108 109 110 111 112 113 114 115 116 117 118 119]
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53
  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71
  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89
 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
 138 139 140 141 142 143 144 145 146 147 148 149]

#5 교차 검증 정확도 :0.7333, 학습 데이터 크기: 120, 검증 데이터 크기: 30
#5 검증 세트 인덱스:[120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
 138 139 140 141 142 143 144 145 146 147 148 149]
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53
  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71
  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89
  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107
 108 109 110 111 112 113 114 115 116 117 118 119]

## 평균 검증 정확도: 0.9

 

 

Stratified K 폴드 예제

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
from sklearn.tree import DecisionTreeClassifier

iris = load_iris()
features = iris.data
label = iris.target
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)
    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)
    
# 교차 검증별 정확도 및 평균 정확도 계산 
print('\n## 교차 검증별 정확도:', np.round(cv_accuracy, 4))
print('## 평균 검증 정확도:', np.mean(cv_accuracy))1}, 학습 데이터 크기: {2}, 검증 데이터 크기: {3}'
          .format(n_iter, accuracy, train_size, test_size))
    print('#{0} 검증 세트 인덱스:{1}'.format(n_iter,test_index))
    cv_accuracy.append(accuracy)
    
# 교차 검증별 정확도 및 평균 정확도 계산 
print('\n## 교차 검증별 정확도:', np.round(cv_accuracy, 4))
print('## 평균 검증 정확도:', np.mean(cv_accuracy))

 

결과

#1 교차 검증 정확도 :0.98, 학습 데이터 크기: 100, 검증 데이터 크기: 50
#1 검증 세트 인덱스:[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  50
  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66 100 101
 102 103 104 105 106 107 108 109 110 111 112 113 114 115]

#2 교차 검증 정확도 :0.94, 학습 데이터 크기: 100, 검증 데이터 크기: 50
#2 검증 세트 인덱스:[ 17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  67
  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82 116 117 118
 119 120 121 122 123 124 125 126 127 128 129 130 131 132]

#3 교차 검증 정확도 :0.98, 학습 데이터 크기: 100, 검증 데이터 크기: 50
#3 검증 세트 인덱스:[ 34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  83  84
  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 133 134 135
 136 137 138 139 140 141 142 143 144 145 146 147 148 149]

## 교차 검증별 정확도: [0.98 0.94 0.98]
## 평균 검증 정확도: 0.9666666666666667

 

 


 

 

 

2일

 

 

교차검증 성능평가 cross_val_score()와 하이퍼 파라미터 튜닝을 위한 GridSearchCV

 

 

cross_val_score()

- K 폴드 세트 추출, 학습/예측, 평가를 한 번에 수행할 수 있음

 

 

예제

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score 
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

# 성능 지표는 정확도(accuracy) , 교차 검증 세트는 3개 
# Stratified K Fold임
scores = cross_val_score(dt_clf , data , label , scoring='accuracy',cv=3) # cv: K값
print(scores, type(scores))
print('교차 검증별 정확도:',np.round(scores, 4))
print('평균 검증 정확도:', np.round(np.mean(scores), 4))

 

결과

[0.98 0.94 0.98] <class 'numpy.ndarray'>
교차 검증별 정확도: [0.98 0.94 0.98]
평균 검증 정확도: 0.9667

 

 

 

GridSearchCV

- 교차 검증과 최적 하이퍼 파라미터 튜닝을 한 번에!

- 하이퍼 파라미터란? : Classifier나 Regressor와 같은 알고리즘에 사용되는 파라미터

- 파라미터 튜닝이란? : 최적의 파라미터를 도출시키는 방법

→ 숫자를 지정하면 경우의 수를 따져서 하나하나 test 해보고 최적의 파라미터를 찾아냄

→여기에서 max_depth이랑 min_samples_split의 경우  

 

 

예제

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

# 데이터를 로딩하고 학습데이터와 테스트 데이터 분리
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()

### parameter 들을 dictionary 형태로 설정
parameters = {'max_depth':[1, 2, 3], 'min_samples_split':[2,3]} 
# 무조건 data 값은 리스트[] 형태로 들어가야 함
import pandas as pd

# param_grid의 하이퍼 파라미터들을 3개의 train, test set fold 로 나누어서 테스트 수행 설정.  
### refit=True 가 default 임. -> True이면 가장 좋은 파라미터 설정으로 재 학습 시킴.  
grid_dtree = GridSearchCV(dtree, param_grid=parameters, cv=3, refit=True, return_train_score=True)

# 붓꽃 Train 데이터로 param_grid의 하이퍼 파라미터들을 순차적으로 학습/평가 .
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']]

 

print('GridSearchCV 최적 파라미터:', grid_dtree.best_params_)
print('GridSearchCV 최고 정확도: {0:.4f}'.format(grid_dtree.best_score_))

# refit=True로 설정된 GridSearchCV 객체가 fit()을 수행 시 
# 학습이 완료된 Estimator를 내포하고 있으므로 predict()를 통해 예측도 가능. 
pred = grid_dtree.predict(X_test)
print('테스트 데이터 세트 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))

 

결과

GridSearchCV 최적 파라미터: {'max_depth': 3, 'min_samples_split': 2}
GridSearchCV 최고 정확도: 0.9750
테스트 데이터 세트 정확도: 0.9667

 

-> estimator를 반환해서 사용할 수도 있음

# 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)))

결과

테스트 데이터 세트 정확도: 0.9667
 
 

 

 

데이터 전처리 - 인코딩

 

 

데이터 전처리(Preprocessing) 과정 개요

- 데이터 클린징 : 불필요한 데이터 처리

- 결손값 처리 (Null/NaN 처리)

- 데이터 인코딩(레이블, 원-핫 인코딩) : 문자열 값들은 다 숫자로 바꿔줘야 함

- 데이터 스케일링 : 단위에 따라 다른 값들을 공통적으로 스케일링 해주기

- 이상치 제거 : 평균에서 많이 동떨어진 데이터 처리

- Feature 선택, 추출 및 가공 : Feature를 가공, 처리

 

 

데이터 인코딩

- 머신러닝 알고리즘에 쓰이는 모든 데이터는 숫자형으로 표현되어야 함

- 문자형 카테고리 속성은 모두 숫자값으로 변환/인코딩 되어야 함

 

 

레이블(Label) 인코딩

- 숫자값으로 변환

- 문제점: 문자열 데이터에 숫자가 부여되므로, 알고리즘이 각 데이터 간에 크기 차이가 있는 것으로 오해할 수 있음

                 → 원-핫 인코딩으로 해결

 

 

레이블(Label) 인코딩 사용 방법

- LableEncoder 클래스 사용 

- fit()과 transform()을 이용하여 변환

 

from sklearn.preprocessing import LabelEncoder

items=['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서']

# LabelEncoder를 객체로 생성한 후 , fit( ) 과 transform( ) 으로 label 인코딩 수행. 
encoder = LabelEncoder()
encoder.fit(items)                 # -> 고유한 값들을 인지함
labels = encoder.transform(items)
print('인코딩 변환값:',labels)

결과

인코딩 변환값: [0 1 4 5 3 3 2 2]

 

 

print('인코딩 클래스:',encoder.classes_) # 0 ~ 5 순서대로
print('디코딩 원본 값:',encoder.inverse_transform([4, 5, 2, 0, 1, 1, 3, 3]))

결과

인코딩 클래스: ['TV' '냉장고' '믹서' '선풍기' '전자렌지' '컴퓨터']
디코딩 원본 값: ['전자렌지' '컴퓨터' '믹서' 'TV' '냉장고' '냉장고' '선풍기' '선풍기']
 
 

 

 

원-핫(One-hot) 인코딩

- 피처 값의 유형에 따라 새로운 피처를 추가해 고유값에 해당하는 컬럼에만 1을 표시하고 나머지 컬럼에는 0을 표시

 

 

원-핫(One-hot) 인코딩 사용 방법

방법1. 

- OneHotEncoder 클래스 사용

- fit()과 transform()을 이용하여 변환

- 인자로 2차원 ndarray 입력 필요

- Sparse 배열 형태로 변환되므로 toarray()를 적용하여 다시 Dense 형태로 변환되어야 함

 

# 1. sklearn에 있는 OneHotEncoder

from sklearn.preprocessing import OneHotEncoder
import numpy as np

items=['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서']

# 2차원 ndarray로 변환합니다. 
items = np.array(items).reshape(-1, 1)

# 원-핫 인코딩을 적용합니다. 
oh_encoder = OneHotEncoder()
oh_encoder.fit(items)
oh_labels = oh_encoder.transform(items)

# OneHotEncoder로 변환한 결과는 희소행렬(Sparse Matrix)이므로 toarray()를 이용하여 밀집 행렬(Dense Matrix)로 변환. 
print('원-핫 인코딩 데이터')
print(oh_labels.toarray())
print('원-핫 인코딩 데이터 차원')
print(oh_labels.shape)

결과

원-핫 인코딩 데이터
[[1. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0.]]
원-핫 인코딩 데이터 차원
(8, 6)

 

 

방법2.

- pd.get_dummies(DataFrame)을 이용

 

#2. get_dummies 함수 

import pandas as pd

df = pd.DataFrame({'item':['TV','냉장고','전자렌지','컴퓨터','선풍기','선풍기','믹서','믹서'] })
pd.get_dummies(df)

결과

 


 

 

데이터 전처리 - 스케일링

 

 

피처 스케일링

- 데이터 마다 가지는 척도가 달라서 이를 통일시켜줄 필요가 있음

 

 

표준화

- 평균이 0이고 분산이 1인 가우시안 정규 분포를 가진 값으로 변환

- 수식: (x값 - 평균값) / (표준편차)

 

 

정규화

- 서로 다른 피처의 크기를 통일하기 위해 크기를 변환해주는 개념

- 아래의 식은 0 ~ 1 사이로 변환

 

사이킷런에서 피처 스케일링

- StandardScaler : 평균이 0이고 분산이 1인 정규 분포 형태로 변환

- MinMaxScaler : 데이터 값을 0과 1 사이의 범위로 변환 (음수값이 있으면 -1 ~ 1 사이로 변환)

 

- 선형회귀 또는 SVM의 경우, 피처 스케일링의 영향을 많이 받음

- 근데 하면 좋으니까 거의 다 해주는 게 좋음!

 

 

 

 StandardScaler 예제

from sklearn.datasets import load_iris
import pandas as pd
# 붓꽃 데이터 셋을 로딩하고 DataFrame으로 변환합니다. 
iris = load_iris()
iris_data = iris.data
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)

print('feature 들의 평균 값')
print(iris_df.mean())
print('\nfeature 들의 분산 값')
print(iris_df.var())

 

결과

feature 들의 평균 값
sepal length (cm)    5.843333
sepal width (cm)     3.057333
petal length (cm)    3.758000
petal width (cm)     1.199333
dtype: float64

feature 들의 분산 값
sepal length (cm)    0.685694
sepal width (cm)     0.189979
petal length (cm)    3.116278
petal width (cm)     0.581006
dtype: float64

 

 

-----

 

 

from sklearn.preprocessing import StandardScaler

# StandardScaler객체 생성
scaler = StandardScaler()
# StandardScaler 로 데이터 셋 변환. fit( ) 과 transform( ) 호출. 
# -> fit_transform()함수 사용해도 됨 (but, 유의 필요)
scaler.fit(iris_df) # ndarray 뿐만 아니라 dataframe과도 잘 어울림
iris_scaled = scaler.transform(iris_df)

#transform( )시 scale 변환된 데이터 셋이 numpy ndarry로 반환되어 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature 들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature 들의 분산 값')
print(iris_df_scaled.var())

 

결과

feature 들의 평균 값
sepal length (cm)   -1.690315e-15
sepal width (cm)    -1.842970e-15
petal length (cm)   -1.698641e-15
petal width (cm)    -1.409243e-15
dtype: float64

feature 들의 분산 값
sepal length (cm)    1.006711
sepal width (cm)     1.006711
petal length (cm)    1.006711
petal width (cm)     1.006711
dtype: float64

 

 

 

 StandardScaler 예제

from sklearn.preprocessing import MinMaxScaler

# MinMaxScaler객체 생성
scaler = MinMaxScaler()
# MinMaxScaler 로 데이터 셋 변환. fit() 과 transform() 호출.  
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)

# transform()시 scale 변환된 데이터 셋이 numpy ndarry로 반환되어 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature들의 최소 값')
print(iris_df_scaled.min())
print('\nfeature들의 최대 값')
print(iris_df_scaled.max())

 

결과

feature들의 최소 값
sepal length (cm)    0.0
sepal width (cm)     0.0
petal length (cm)    0.0
petal width (cm)     0.0
dtype: float64

feature들의 최대 값
sepal length (cm)    1.0
sepal width (cm)     1.0
petal length (cm)    1.0
petal width (cm)     1.0
dtype: float64

 

 

 

Scaler를 이용하여 학습 데이터와 테스트 데이터에 fit(), transform(), fit_transform() 적용 시 유의사항

- train 데이터와 test 데이터의 min, max가 다르게 될 경우 척도가 달라지기 때문에

- train과 test에서의 Scale된 데이터 값이 달라짐

 

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)

 

 

# 최소값 0, 최대값 1로 변환하는 MinMaxScaler객체 생성
scaler = MinMaxScaler()
# fit()하게 되면 train_array 데이터의 최소값이 0, 최대값이 10으로 설정.  
scaler.fit(train_array)
# 1/10 scale로 train_array 데이터 변환함. 원본 10-> 1로 변환됨.
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))

결과

원본 train_array 데이터: [ 0  1  2  3  4  5  6  7  8  9 10]
Scale된 train_array 데이터: [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]

 

# 앞에서 생성한 MinMaxScaler에 test_array를 fit()하게 되면 원본 데이터의 최소값이 0, 최대값이 5으로 설정됨 
scaler.fit(test_array)
# 1/5 scale로 test_array 데이터 변환함. 원본 5->1로 변환.  
test_scaled = scaler.transform(test_array)
# train_array 변환 출력
print('원본 test_array 데이터:', np.round(test_array.reshape(-1), 2))
print('Scale된 test_array 데이터:', np.round(test_scaled.reshape(-1), 2))

결과

원본 test_array 데이터: [0 1 2 3 4 5]
Scale된 test_array 데이터: [0.  0.2 0.4 0.6 0.8 1. ]

 

 

-> 아래와 같이 test array에 Scale 변환을 할 때는 반드시 fit()을 호출하지 않고, transform()만으로 변환해야 함

scaler = MinMaxScaler()
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))

# !!! test_array에 Scale 변환을 할 때는 반드시 fit()을 호출하지 않고 transform() 만으로 변환해야 함. 
test_scaled = scaler.transform(test_array)
print('\n원본 test_array 데이터:', np.round(test_array.reshape(-1), 2))
print('Scale된 test_array 데이터:', np.round(test_scaled.reshape(-1), 2))