Day31 - 머신러닝(2). 22.10.11.화

류소리·2022년 10월 11일
0

머신러닝

목록 보기
2/14
post-thumbnail

[Model Selection] p98

학습/테스트 데이터 세트 분리 - train_test_split()

#학습/테스트 데이터 세트 분리 -train_test_split()

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

iris = load_iris()
dt_clf = DecisionTreeClassifier()
train_data = iris.data
train_label = iris.target
dt_clf.fit(train_data, train_label)

#학습 데아터 세트로 예측 수행
pred = dt_clf.predict(train_data)
print('예측 정확도 : ',accuracy_score(train_label, pred))
  • 정확도가 100% 예측한 이유는 이미 학습한 학습 데이터 세트를 기반으로 예측했기 때문이다.
  • 따라서 예측을 수행하는 데이터 세트는 학습을 수행한 학습용 데이터 세트가 아닌 전용의 테스트 데이터 세트여야한다.
  • 사이킷런의 train_test_split()를 통해 원본 데이터 세트에서 학습 및 테스트 데이터 세트를 쉽게 분리할 수 있습니다.

train_test_split()

  • 첫 번째 파라미터 피처 데이터 세트
  • 두 번째 파라미터 레이블 데이터 세트
  • 선택적 파라미터
    • test_size : 전체 데이터에서 학습용 데이터 세트 크기를 얼마로 샘플링할 것인가를 결정한다.
    • shuffle : 데이터를 분리하기 전에 데이터를 미리 섞을지를 결정한다.
    • random_state : random_state는 호출할 때마다 동일한 학습/테스트용 데이터 세트를 생성하기 위해 주어지는 난수 값.
  • 반환값은 튜플 형태다.
x_train, x_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target,test_size = 0.3, random_state = 121)

테스트 데이터 세트를 전체의 30%로, 학습 데이터 세트를 70%로 분리하겠습니다.


[데이터 전처리] p116

데이터 전처리는 ML 알고리즘만큼 중요합니다. ML 알고리즘은 데이터에 기반하고있기 때문에 어떤 데이터를 입력으로 가지느냐에 따라 결과도 크게 달라질 수 있습니다.
사이킷런의 ML 알고리즘을 적용하기 전에 데이터에 대해 미리 처리해야 할 기본 사항이 있습니다.

  1. 결손값은 허용되지 않는다.
    null값은 고정된 다른 값으로 변환해야 한다.
    null 값이 얼마 없다면 -> 피처의 평균값 등으로 간단하게 해결 가능하다.
    null 값이 많다면 -> 해당 피처를 drop 하는게 더 좋다.

  2. 문자열 값을 입력값으로 혀용하지 않습니다.
    모든 문자열 값은 인코딩돼서 숫자 형으로 변환해야 합니다. 문자열 피처는 일반적으로 카테고리형 피처와 텍스트형 피처를 의미합니다.

데이터 인코딩 p116

머신러닝을 위한 대표적인 인코딩 방식은 레이블 이코딩, 원-핫 인코딩이 있습니다.
레이블 인코딩은 카테고리 피처를 코드형 숫자 값으로 변환하는 것입니다.

레이블 인코딩

사이킷런의 레이블 인코딩은 LabelEncoder 클래스로 구현된다.

LabelEncoder를 객체로 생성한 후 fit()과 transform()을 호출해 레이블 인코딩을 수행합니다.

레이블 인코딩은 간단하게 문자열 값을 숫자형으로 카테고리 값으로 변환합니다.

하지만 레이블 인코딩이 일괄적인 숫자 값으로 변환 되면서 몇몇 ML 알고리즘에는 이를 적용할 경우 예측 성능이 떨어지는 경우가 발생할 수 있습니다. 이는 숫자 값의 경우 크고 작음에 대한 특성이 작용하기 때문입니다.

레이블 인코딩은 선형회귀와 같은 ML 알고리즘에는 적용하지 않아야 합니다. 트리 계열의 ML 알고리즘은 숫자의 이러한 특성을 반영하지 않으므로 레이블 인코딩도 별 문제가 없습니다.

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

# 레이블 인코딩
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()  # fit()과 transform()으로 인코딩 수행.
le.fit(items)
le.transform(items)

원-핫 인코딩

원-핫 인코딩은 피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시하는 방식입니다. 즉, 행 행태로 돼 있는 피처의 고유 값을 열 형태로 차원을 변환한 뒤, 고유 값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시합니다.(즉, 여러 개의 속성 중 단 한 개의 속성만 1로 표시)

사이킷런의 원-핫 인코딩은 OneHotEncoder 클래스로 구현된다.
입력값으로 2차원 데이터가 팔요하다.

OneHotEncoder를 이용해 변환한 값이 희소(Sparse Matrix)행렬 형태이므로 이를 다시 toarray() 메서드를 이용해 밀집(Dense Matrix)행렬 로 변환해야 한다는 것이다.

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

import numpy as np
import pandas as pd

# 원핫 인코딩
from sklearn.preprocessing import OneHotEncoder

arr = np.array(items).reshape(-1, 1) #2차원 ndarray로 변환합니다.
ohe = OneHotEncoder()   #원-핫 인코딩을 적용합니다.
ohe.fit(arr)
ohe.transform(arr).toarray()  #torray()를 이용해 밀집 행렬로 변환.


[교차 검증] p100

  • 본고사를 치르기 전에 모의고사를 여러 번 보는 것

  • 대부분의 ML 모델의 성능 평가는 교차 검증 기반으로 1차 평가를 한 뒤에 최종적으로 테스트 데이터 세트에 적용해 평가하는 프로세스다.

  • ML에 사용되는 데이터 세트를 세분화해서 학습, 검증, 테스트 데이터 세트로 나눌 수 있다.

  • 훈련데이터: 모형 적합
    모수의 적합과 모수의 추정에 사용

  • 검증데이터: 모형 선택
    parameter tuning,변수 선택, 모형선택

  • 테스트데이터: 최종 평가
    모형 적합과 모형 선택이 끝난 후 최종 모형의 오류를 측정

  • 지도학습기가 하는 작업은 훈련데이터로부터 주어진 데이터에 대해 예측하고자 하는 값을 올바로 추측해내는 것이다.

이 목표를 달성하기 위해서는 훈련용 데이터 맞춤으로 만들어진 모형이 기존의 훈련 데이터에 나타나지 않았던 상황까지도 일반화하여 처리할 수 있어야 한다.

앞 에시에서는 학습하는 데 사용된 훈련 데이터를 가지고 모형의 성능을 평가했기 떄문에 공정하지 않다.

과적합의 취약한 약점을 가질 수 있습니다.

과적합은 모델이 학습 데이터만 과도하게 최적화되어, 실제 예측에 다른 데이터로 수행할 경우에는 예측 성능이 과도하게 떨어지는 것을 말합니다.

그런데 고정된 학습 데이터와 테스트 데이터로 평가를 하다보면 테스트 데이터만 최적의 성능을 발휘할 수 있도록 편향된 모델을 유도하는 경향이 생기게 됩니다.

결국은 해당 테스트 데이터만 과적합되는 학습 모델이 만들어져 다른 테스트용 데이터가 들어올 경우에는 성능이 저하됩니다. 이러한 문제점을 개선하기 위해 교차 검증을 이용해 다양한 학습과 평가를 수행합니다.

교차검증은 데이터 편중을 막기 위해서 별도의 여러 세트로 구성된 학습 데이터 세트와 검증데이터 세트에서 학습과 평가를 수행하는 것입니다.

각 세트에서 수행한 평가 결과에 따라 하이퍼 파리미터 튜닝 등의 모델 최적화를 더욱 손쉽게 할 수 있습니다.

K 폴드 교차 검증 (KFold) p101

  • 가장 보편적으로 사용되는 교차 검증의 기법입니다.
  • K개의 데이터 폴드 세트를 만들어서 K번만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행하는 방법
  • 5개의 폴드 세트로 분리
  1. 데이터 세트를 5등분 한다.
  2. 첫번째 반복에서는 처음부터 4개 등분을 학습 데이터 세트, 마지막 5번째 등분 하나를 검증 데이터 세트로 설정하고 학습 데이터 세트에서 학습 수행, 검증 데이터 세트에서 평가를 수행합니다.
  3. 첫번째가 끝나면 두번째 반복에서 다시 비슷한 학습과 평가 작업을 수행합니다.
    단, 이번에는 학습 데이터와 검증 데이터를 변경합니다.
  4. 학습 데이터 세트와 검증 데이터 세트를 점진적으로 변경하면서 마지막 5번째 까지 학습과 검증을 수행하는 것이 K 폴드 교차 방식이다.

사이킷런에서는 K폴드 교차 검증 프로세스를 구현하기 위해
KFold클래스와 stratifiedKFoid 클래스를 제공한다.

KFold -> split() 5개로 분리한다.
split()을 호출하면 학습용/검증용 데이터로 분할할 수 있는 인덱스를 반환한다.

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold

import pandas as pd
import numpy as np


iris = load_iris()              # 파일부르기
iris_data = iris.data
iris_label= iris.target         # data(정보)와 target(매치대상) 저장


dt_clf = DecisionTreeClassifier()      # 의사결정 트리 
kfold = KFold(n_splits=5)

cv_accuracy = []

# KFold객체의 split( ) 호출하면 폴드 별 학습용, 검증용 테스트의 인덱스를 반환한다. %% 이거 중요함. 

for train_index, test_index  in kfold.split(iris_data): 
    
    # print(train_index, test_index)
    # print("---"*10)
    # kfold.split( )으로 반환된 인덱스를 이용하여 학습용, 검증용 테스트 데이터 추출
    
    X_train, X_test = iris_data[train_index], iris_data[test_index]
    y_train, y_test = iris_label[train_index],iris_label[test_index]

    
    dt_clf.fit(X_train , y_train)    
    pred = dt_clf.predict(X_test)
    
   
    accuracy = accuracy_score(y_test,pred)   
    cv_accuracy.append(accuracy)
 
    print("개별 검증 정확도: ", cv_accuracy)
    
print('평균 검증 정확도:', np.mean(cv_accuracy)) 

개별 검증 정확도: [1.0]
개별 검증 정확도: [1.0, 1.0]
개별 검증 정확도: [1.0, 1.0, 0.9]
개별 검증 정확도: [1.0, 1.0, 0.9, 0.9333333333333333]
개별 검증 정확도: [1.0, 1.0, 0.9, 0.9333333333333333, 0.7333333333333333]
평균 검증 정확도: 0.9133333333333333

[계층화 폴드 stratified KFold] p104

  • 불균형한 분포를 가진 레이블(결정 클래스) 데이터 집합을 위한 방식입니다.
    -불균형한 분포도를 가진 레이블 데이터 집합은 특정 레이블 값이 특이하게 많거나 매우 적어서 한쪽으로 분포가 치우친 것을 말합니다.

예를 들어 대출 사기 데이터를 예측한다고 가정해보자.
비록 사기 건수는 작지만 알고리즘이 대출 사기 예측하기 위한 중요한 피처 값을 가지고 있기 때문에 매우 중요한 데이터 세트입니다.
따라서 원본 데이터와 유사한 대출 사기 레이블 값의 분포를 학습/테스트 세트에도 유지하는 게 매우 중요하다.

-레이블 데이터 집합이 원본 데이터 집합의 레이블 분포를 학습 및 테스트 세트에 제대로 분배하지 못하는 경우의 문제를 해결해 줍니다.

  • KFold로 분할된 레이블 데이터 세트가 전체 레이블 값의 분포도를 반영하지 못하는 문제를 해결해 줍니다.-> 전체 레이블 반영함!!!
  • 원본 데이터의 레이블 분포도 특성을 반영한 학습 및 검증 데이터 세트를 만들 수 있으므로 왜곡된 레이블 데이터 세트에서는 반드시 stratified KFold이용해 교차 검증을 해야한다.
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold  #추가됨

iris = load_iris()
features = X = iris_data = iris.data
labels = y = iris_label = iris.target

dt_clf = DecisionTreeClassifier()
s_kfold = StratifiedKFold(n_splits=3)
cv_accuracy = [ ]

# 레이블 데이터 분포도에 따라 학습/검증 데이터를 나누기 때문에 split()메서드에 인자로 둘 다 들어가야 한다는 사실입니다.%% 이거 중요함!
# StratifiedKFold의 split() 호출시 반드시 레이블 데이터 세트도 추가 입력 필요.
for train_index, test_index in s_kfold.split(features, labels):
   
    # split()으로 반환된 인덱스를 이용해 학습용, 검증용 테스트 데이터 추출
    X_train, X_test = features[train_index], features[test_index]
    y_train, y_test = labels[train_index], labels[test_index]

    # 학습 및 예측
    dt_clf.fit(X_train, y_train)
    pred = dt_clf.predict(X_test)

    acc = accuracy_score(y_test, pred)
    cv_accuracy.append(acc)
    print("개별정확도:" , acc)

print("정확도 모음:",cv_accuracy) 
print(np.mean(cv_accuracy).round(4))

개별정확도: 0.98
개별정확도: 0.92
개별정확도: 0.98
정확도 모음: [0.98, 0.92, 0.98]
0.96

[교차 검증을 보다 간편하게 - cross_val_score( )]

사이킷런은 교차 검증을 좀 더 편리하게 수행할 수 있게 해주는 API를 제공한다.
대표적인 것이 cross_val_score()입니다.

KFold로 데이터를 학습하고 예측하는 코드를 보면

1.폴드 세트를 설정
2.for 루프에서 반복적으로 학습 및 테스트 데이터의 인덱스를 추출
3.반복적으로 학습과 예측을 수행하고 예측 성능을 반환

cross_val_score()는 이런 일련의 과정을 한꺼번에 수행해주는 API입니다.

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 = 클래스 의미함.
  • X = 피처 데이터 세트
  • y = 레이블 데이터 세트
  • scoring = 예측 성능 평가 지표를 기술
  • cv = 교차 검증 폴드 수를 의미
from sklearn.model_selection import cross_val_score, cross_validate 
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier 

iris = load_iris()
data = feateures = x = iris_data = iris.data
label = labels = y = iris_label = iris.target
df_clf = DecisionTreeClassifier()

# 성능 지표는 "정확도" , 교차 검증 세트는 3개.
scorse=cross_val_score(df_clf, data, label, scoring = "accuracy", cv = 3 )
scorse

array([0.98, 0.94, 0.98])
np.mean(scorse).round(4) -> 0.9667

  • cross_val_score()는 cv로 지정된 횟수만큼 scoring 파라미터로 지정된 평가 지표로 평가 결과값을 배열로 반환합니다. 그리고 일반적으로 이를 평균해 평가 수치로 사용합니다.
  • cross_val_score()는 단 하나의 평가 지표만 가능하지만, cross_validate()는 여러 개의 평가 지표를 반환할 수 있다.
  • cross_val_score()는 내부적으로 stratified KFold를 이용하기 때문이다.

[교차 검증과 최적 하이퍼 파라미처 튜닝을 한 번에 (GridSearchCV) p111]

: grid는 격자라는 뜻, 촘촘하게 파라미터를 입력하면서 테스트를 하는 방식이다.

사이킷런은 GridSearchCV API를 이용해 Classifier나 Regression와 같은 알고리즘에 사용되는 하이퍼 파라미터를 순차적으로 입력하면서 최적의 파라미터를 도출할 수 있는 방안을 제공한다.
하이퍼 파라미터는 머신러닝 알고리즘을 구성하는 주요 구성 요소이며, 이 값을 조정해 알고리즘의 예측 성능을 개선할 수 있습니다.

  • Grid search(격자탐색)은 모델 파라미터에 넣을 수 있는 값들을 순차적으로 입력한 뒤에 가장 높은 성능을 보이는 파라미터들을 찾는 탐색 방법

  • 하이퍼 파라미터(초매개변수)란
    모델을 생성할 때, 사용자가 직접 설정하는 변수가 사전적 정의이다.
    랜덤 포레스트 모델에서는 트리의 개수, 트리의 깊이는 몇까지 할 것인지 딥러닝 모델에서는 layer의 개수, 에폭(학습횟수)의 수 등이 된다.
    딥러닝에서 파라미터는 가중치이므로 기존의 파라미터를 하이퍼파라미터라 한다.

GridSearchCV 클래스의 생성자 주요 파라미터

  • estimator : classifier, regressor, pipeline이 사용될 수 있습니다.

  • pram_grid : key+ 리스트 값을 가지는 딕셔너리가 주어집니다. estimator의 튜닝을 위해 파라미터명과 사용될 여러 파라미터 값을 지정합니다. -> 파라미터의 조합

  • scoring : 예측 성능을 측정할 평가 방법을 지정합니다. 보통은 사이킷런의 성능 평가 지표를 지정하는 문자열 (예:정확도의 경우 "accuracy")로 지정하나 별도의 성능 평가 지표 함수도 지정할 수 있습니다. ->(정확도,최소오차)

  • cv : 교차 검증을 위해분할되는 학습/테스츠 세츠의 개수를 지정합니다. ->교차 검증의 개수를 지정합니다.

  • refit : 디포르가 True 이며 True로 생성 시 가장 최적의 하이퍼 파라미터를 찾은 뒤 입력된 estimator 객체를 해당 하이퍼 파라미터로 재학습시킵니다.

## GridSearchCV
# p111

grid_parameters = {"max_depth ": [1,2,3],"min_samples_split":[2,3]}

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV, train_test_split

# 데이터를 로딩하고 학습 데이터와 테스트 데이터 분리
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data,iris.target, test_size = 0.2, random_state = 121)

df_clf = DecisionTreeClassifier()

### 파라미터를 딕셔너리 행태로 설정
grid_parameters = {"max_depth": [1,2,3],"min_samples_split":[2,3]}

import pandas as pd

# param_grid의 하이퍼 파라미터를 3개의 train, test set fold로 나누어 테스트 수행 설정.
### refit = True가 default임. True이면 가장 좋은 파라미터 설정으로 재학습시킴.
grid_tree =GridSearchCV(df_clf, param_grid = grid_parameters, cv =3, refit = True)
  • params 칼럼에는 수행할 때마다 적용된 개별 하이퍼 파라미터값을 나타냅니다.
  • ranl_test_score는 하이퍼 파라미터별로 성능이 좋은 score 순위를 나타냅니다. 1이 가장 뛰어난 순위이며, 이때의 파라미터가 최적의 하이퍼 파라미터입니다.
  • mean_test_score는 개별 하이퍼 파라미터별로 CV의 폴딩 테스트 세트에 대해 총 수행한 평가 평균값입니다.
grid_tree.best_params_

->gridtree.best_params
{'max_depth': 3, 'min_samples_split': 2}


피처 스케일링 (Feature Scaling) p122

: 단위가 다른걸 같게 맞춰준다.
서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업을 피처 스케일링이라고 한다. 대표적인 방법으로 표준화와 정규화가 있습니다.

표준화는 데이터의 피처 각각이 평균이 0이고 분산이 1인 가우시안 정규 분포를 가진 값으로 변환하는 것을 의미한다.

정규화는 서로 다른 피처의 크기를 통일하기 위해 크기를 변환해주는 개념이다.
이 변수를 모두 동일한 크기 단위로 비교하기 위해 값을 모두 최소 0 ~ 최대 1의 값으로 변환하는 것입니다. 즉, 개별 데이터의 크기를 모두 똑같은 단위로 변경하는 것입니다.

먼저 사이킷런에서 제공하는 대표적인 피처 스케일링 클래스인 StandarScaler와 MinMaxScaler를 알아보겠습니다.

표준화 (StandardScaler) p123

:데이터의 피처 각각이 평균이 0이고 분산이 1인 가우시안 정규 부포를 가진 값으로 변환하는 것을 의미한다.

StandardScaler은 앞에서 설명한 표준화를 쉽게 지원하는 클래스이다.
개별 평균을 0, 분산이 1로 변환해 준다.

StandardScaler를 이용해 각 피처를 한 번에 표준화해 변환해겠다.
StandardScaler 객체를 생성한 후에 fit()과 transform() 메서드에 변환 대상 피처 데이터 세트를 입력하고 호출하면 간단하게 변화됩니다.

표준화 식 : x-mu/sigma

#(1) apply 사용을 위해 pd.DataFrame!!

#새롭게 데이터 불러오기
iris=load_iris()
iris_df=iris.data

#데이터프레임 만들기
iris_df= pd.DataFrame(iris_df)

#표준화 함수 생성
def standardize(x):
    return (x-x.mean())/ x.std()

#평균값 확인
iris_df.apply(standardize).mean()

0 -5.684342e-16
1 -7.815970e-16
2 -2.842171e-16
3 -3.789561e-16
dtype: float64

#(2)StandardScaler 클래스 만들기  
#p123~p124

# StandardScaler 불러오기
from sklearn.preprocessing import StandardScaler

# iris 새롭게 다시 불러주기
iris=load_iris()
iris_df=iris.data

# StandardScaler()객체 생성
scaler = StandardScaler()

# StandardScaler로 데이터 세트 변환. fit()과 transform() 호출.
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)

iris_scaled

정규화 (minmaxscaler) p125

:서로 다른 피처의 크기를 통일하기 위해 크기를 변환해주는 개념이다.
이 변수는 모두 동일한 크기의 단위로 비교하기 위래 값을 모두 최소 0 ~ 최대 1의 값을 변환하는 것입니다. 즉, 개별 데이터의 크기를 모두 똑같은 단위로 변경하는 것입니다. minmaxscaler는

오류 모음 ㅎㅎ

  • (1) 'numpy.ndarray' object has no attribute 'apply'
    : apply는 데이터프레임에 사용하는 함수이다. 따라서 데이터값을 데이터프레임에 넣어야 한다.

정리 출처 : https://kibua20.tistory.com/194[모바일 SW 개발자가 운영하는 블로그:티스토리]

Panda dataframe을 엑셀의 매크로 함수처럼 각 열에 대한 연산을 하는 방법입니다.  Pandas의 apply()를 사용하고 이는  가장 많이 사용하고 강력한 기능입니다.

  • 기존의 Column 값을 연산하여 신규 Column을 추가하는 경우: df.apply(func, axis =1)  axis=0은 row이고, axis=1은 column입니다.
  • Row 값을 추가하는 경우에는 df.loc[] = df.apply(func, axis =0)으로 추가합니다. 
  • Column과 Row은 바꾸는 경우 df.transpose() 함수를 사용합니다.
profile
새싹 빅테이터 개발자

0개의 댓글