코알못

파이썬 머신러닝 완벽 가이드 - 2장 본문

PYTHON

파이썬 머신러닝 완벽 가이드 - 2장

코린이s 2020. 10. 31. 20:34
728x90

2장 - 사이킷런으로 시작하는 머신러닝

# 사이킷런 소개와 특징

- 사이킷런은 파이썬 머신러닝 라이브러리


# 첫번째 머신러닝 만들어 보기 - 붓꽃 품종 예측하기

- 분류 (classification) 예제

- 지도학습(supervised learning) 예제

* 지도 학습이란? 데이터를 주고 학습을 시킴 <-> 비지도 학습

- 꽃잎의 길이 & 너비, 꽃받침의 길이 & 너비를 기반으로 꽃의 품종 예측

- sk-learn 명명 규칙

1) sklearn.datasets : 데이터 세트 생성모듈

2) sklearn.tree : 트리 기반 ML 알고리즘 클래스

3) sklearn.model_selection : 학습 , 검증, 예측 데이터로 분리, 학습 모델

- 예제

1) 붓꽃 품종 예측하기

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipynb


# 교차 검증

- Test 데이터를 분리 하지 않고, Train 데이터 만으로 학습하고 테스트 한다면 ? : 정확도 100%, but 학습 데이터에만 맞춰져 다른 데이터에는 맞지 않게됨 (과적합 발생 = overfitting)

- 과적합을 방지하기 위해 교차 검증 수행

- 교차 검증은 모의고사를 여러번 보는 것과 같다.

- 교차 검증 모델

 

1) K 폴드 교차 검증

- 가장 보편적인 교차 검증 기법

- 5 폴드 교차 검증 : 5번 평가 후 평가 점수의 평균을 낸다.

- 순서

1. 데이터 K등분

2. 1/K 인 데이터셋이 5개가 만들어 지며, 한개의 데이터셋을 검증 데이터로 사용 (K 번의 매 학습마다 검증 데이터셋을 K번 변경)

3. K 번의 정확도의 평균을 낸다.

- 그림

- 사용법

from sklearn.model_selection import KFold
kfold = KFold(n_splits=5)
for train_index, test_index in kfold.split(input_data):
      x_train, x_test = input_data[train_index], input_data[test_index]
      y_train, y_test = output_data[train_index], output_data[test_index]

- 예제

>> K 폴드 교차 검증 : 정확도 90%

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipyn

 

2) stratified K폴드

- 학습, 검증 데이터가 편향되어 들어가 있을 수 있다 > 이를 해결하기 위해 만들어짐

- 원본의 데이터 분포대로 학습, 검증 데이터를 분배

- 사용법

from sklearn.model_selection import StratifiedKFold
skfold = StratifiedKFold(n_splits=5)
for train_index, test_index in skfold.split(input_data, output_data):
    x_train, x_test = input_data[train_index], input_data[test_index]
    y_train, y_test = output_data[train_index], output_data[test_index]

- 예제

>> Stratified K 폴드 교차 검증  : 정확도 96% (K 폴드보다 높게 나옴)

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipynb

 

3) K 폴드 vs stratified K 폴드

- 분류에서는 stratified K 폴드를 주로 사용

- 회귀에서는 정답 데이터가 연속적인 값이기에 결정값 별로 분포를 정하는 의미가 없기에 stratified K 폴드를 사용할 수 없다. 

- 예제

>> K 폴드 vs stratified K 폴드 교차 검증 비교

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipynb

 

4) cross_val_score

- 교차 검증을 간편하게 해준다.

- 교차 검증을 위한 데이터를 나누고 , 학습을 시켜주고 , 정확도 리턴을 모두 한번에 해준다.

- 사용법

from sklearn.model_selection import cross_val_score
dt_class = DecisionTreeClassifier()
# 1 : 학습 모델 (여기서는 DecisionTreeClassifier)
# 2 : 입력 데이터
# 3 : 출력 데이터
# 4(scoring) : 성능지표 (accuracy : 정확도)
# 5(cv) : 교차 검증 수
scores = cross_val_score(dt_class, input_data, output_data, scoring='accuracy', cv=3)

- 예제

>> 간결해진 교차 검증 cross_val_score

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipynb

5) GridSearchCV

- 교차검증 + 하이퍼 파라미터 튜닝

* 하이퍼 파라미터(Hyper parameter) :  최고의 파라미터라는 뜻으로, 모델링할 때 사용자가 직접 세팅해주는 모델 성능에 영향을 주는 값

- 입력 파라미터에 데이터를 따로 받고 있지 않아 데이터는 나눠서 넣어줘야함.

- 최적의 파라미터 튜닝한 모델을 가져올 수 있다.

- 사용법

from sklearn.model_selection import GridSearchCV
dt_class = DecisionTreeClassifier()
parameters = {'max_depth':[1,2,3], 'min_samples_split':[2,3]}
# 1: 모델 명 (여기서는 DecisionTreeClassifier)
# 2(param_grid) : (여기서는 DecisionTreeClassifier 에 들어가는)하이퍼 파라미터 리스트
# 3(cv) : 교차 검증 수
# 4(refit) : True 면 좋은 하이퍼 파라미터로 한번더 학습시킴 (default: True) 
grid_dtree = GridSearchCV(dt_class, param_grid=parameters, cv=3, refit=True)

- 예제

>> 교차검증 + 하이퍼 파라미터 튜닝 (GridSearchCV)

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipynb


# 데이터 전처리

- 어떤 입력을 가지냐에 따라 결과도 달라질 수 있어 전처리는 중요한 단계

- 결손값이 있으면 대체값으로 치환

1) 평균값 

2) null 값이 대부분이라면 drop

- 문자열로 된 필드는 사이킷 런에서 입력값으로 허용하지 않으므로 숫자로 변경이 필요. (데이터 인코딩)

1) 식별자 필드는 숫자로 변경하는 것 보다 제거하는게 낫다 (식별의 용도로 사용하고 분석에는 의미 없는값으로 예측 성능을 떨어트린다.)

- 전처리 종류

데이터 인코딩 레이블 인코딩 - 예) TV: 1 , 냉장고 : 2 , 전자레인지 : 3
* 주의점 : 01, 02 는 문자열이지 숫자가 아님.

- 숫자는 클수록 영향도가 크므로 인코딩된 값에 따라 성능이 바뀌어 선형회귀에서는 사용하면 안됨. 해당 


- 트리 계열 ML 알고리즘은 숫자의 이런 특성을 반영하지 않아 괜찮다.
원-핫 인코딩 - 예) tv, 냉장고, 전자레인지
> 1,0,0
> 0,1,0
> 0,0,1

- 해당 하는 값에만 1을 주고 나머지는 0으로 표기하는 기법 (숫자의 값이 클수록 가중치가 부여되는 이슈 보안)

- sklearn or pandas 이용
피처 스케일링과 정규화
* 피처 스케일링 : 다른 변수의 값 범위를 일정 수준으로 맞추는 작업
- 서로 다른 피처의 크기의 데이터를 동일 선상에 두고 비교하기 위해 스케일링 진헹


StandardScaler - StandardScaler는 평균은 0에 가까운값, 분산은 1에 가까운 가우시안 정규 분포를 가진 값으로 변경
MinMaxScaler - MinMaxScaler는 데이터를 0과 1사이 값으로 변환 (음수가 있다면 -1 ~ 1값으로 변경)
스케일링 유의 사항 - fit : 스케일링을 위한 기준 설정

- transform : 변환

- 잘못된 예) train data를 fit, transform  진행 후,
test data fit, transform 진행 하면 각각 스케일링 기준이 달라져서 정확한 예측이 불가능함.

-  올바른 예) train data 를 fit, transform 진행 후, test data transform 진행

1. 레이블 인코딩

from sklearn.preprocessing import LabelEncoder
items = ['TV', '냉장고', '전자레인지']
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print('인코딩 값 : {}'.format(labels))
print('인코딩 클래스 : {}'.format(encoder.classes_))
print('인코딩 값을 거꾸로 뒤집어서 디코드 : {}'.format(encoder.inverse_transform(list(reversed(labels)))))
# 인코딩 값 : [0 1 2]
# 인코딩 클래스 : ['TV' '냉장고' '전자레인지']
# 인코딩 값을 거꾸로 뒤집어서 디코드 : ['전자레인지' '냉장고' 'TV']

2. 원-핫 인코딩

- sklearn

from sklearn.preprocessing import OneHotEncoder
items = ['TV', '냉장고', '전자레인지','TV']
# 라벨 인코딩으로 숫자로 변환 후 1차원 > 2차원 변경 
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items)
print('데이터 차원\n{0} \n라벨 인코딩 데이터\n{1}'.format(labels.shape,labels))
labels = labels.reshape(-1,1)
print('------------')
print('데이터 차원\n{0} \n2차원으로 변형된 데이터\n{1}'.format(labels.shape,labels))
# 데이터 차원
# (4,) 
# 라벨 인코딩 데이터
# [0 1 2 0]
# ------------
# 데이터 차원
# (4, 1) 
# 2차원으로 변형된 데이터
# [[0]
#  [1]
#  [2]
#  [0]]

# 원-핫 인코딩으로 변환
oh_encoder = OneHotEncoder()
oh_encoder.fit(labels)
oh_labels = oh_encoder.transform(labels)
print('원-핫 인코딩 데이터\n{0}'.format(oh_labels.toarray()))
print('원-핫 인코딩 데이터 차원\n{0}'.format(oh_labels.shape))
# 원-핫 인코딩 데이터
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]
#  [1. 0. 0.]]
# 원-핫 인코딩 데이터 차원
# (4, 3)

- pandas

import pandas as pd
df = pd.DataFrame({'item':items})
df
#item
#0	TV
#1	냉장고
#2	전자레인지
#3	TV

# 겟 더미스 사용시 쉽게 one-hot encoding 이 가능하다.
pd.get_dummies(df)
#item_TV	item_냉장고	item_전자레인지
#0	1	0	0
#1	0	1	0
#2	0	0	1
#3	1	0	0

3. StandardScaler

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(input_df)
iris_scaled = scaler.transform(input_df) # numpy 로 리턴

# dataframe 으로 변경
iris_scaled_df = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)

print('평균값\n{}'.format(iris_scaled_df.mean()))
print('분산값\n{}'.format(iris_scaled_df.var()))
# 평균값
# 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
# 분산값
# sepal length (cm)    1.006711
# sepal width (cm)     1.006711
# petal length (cm)    1.006711
# petal width (cm)     1.006711
# dtype: float64

4. MinMaxScaler

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(input_df)
iris_scaled = scaler.transform(input_df)# numpy 로 리턴

# dataframe 으로 변경
iris_scaled_df = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)

print('최소값\n{}'.format(iris_scaled_df.min()))
print('최대값\n{}'.format(iris_scaled_df.max()))
# 최소값
# sepal length (cm)    0.0
# sepal width (cm)     0.0
# petal length (cm)    0.0
# petal width (cm)     0.0
# dtype: float64
# 최대값
# sepal length (cm)    1.0
# sepal width (cm)     1.0
# petal length (cm)    1.0
# petal width (cm)     1.0
# dtype: float64

5. 스케일링 유의사항

- 잘못된 스케일링 예시
- train , test 스케일링된 값이 다름.

import numpy as np
# fit, transform 은 2차원 이상 데이터만 가능하여 2차원으로 변환후 진행
# reshape(-1,1) : -1은 행수 지정하지 않음, 1열 > 보통 2차원으로 변경시 사용
train_arr = np.arange(0,11).reshape(-1,1)
test_arr = np.arange(0,6).reshape(-1,1)

scaler = MinMaxScaler()
scaler.fit(train_arr)
train_scaled = scaler.transform(train_arr)

# reshape(-1) : 1차원으로 변경할때 쓰는 방법
print('원본 train 데이터 : {}'.format(train_arr.reshape(-1)))
print('변환 된 train 데이터 : {}'.format(train_scaled.reshape(-1)))
# 원본 train 데이터 : [ 0  1  2  3  4  5  6  7  8  9 10]
# 변환 된 train 데이터 : [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]

scaler = MinMaxScaler()
scaler.fit(test_arr)
test_scaled = scaler.transform(test_arr)

# reshape(-1) : 1차원으로 변경할때 쓰는 방법
print('원본 test 데이터 : {}'.format(test_arr.reshape(-1)))
print('변환 된 test 데이터 : {}'.format(test_scaled.reshape(-1)))
# 원본 test 데이터 : [0 1 2 3 4 5]
# 변환 된 test 데이터 : [0.  0.2 0.4 0.6 0.8 1. ]

- 올바른 스케일링 예시

train_arr = np.arange(0,11).reshape(-1,1)
test_arr = np.arange(0,6).reshape(-1,1)

scaler = MinMaxScaler()
scaler.fit(train_arr)
train_scaled = scaler.transform(train_arr)

# reshape(-1) : 1차원으로 변경할때 쓰는 방법
print('원본 train 데이터 : {}'.format(train_arr.reshape(-1)))
print('변환 된 train 데이터 : {}'.format(train_scaled.reshape(-1)))
# 원본 train 데이터 : [ 0  1  2  3  4  5  6  7  8  9 10]
# 변환 된 train 데이터 : [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]

test_scaled = scaler.transform(test_arr)
# reshape(-1) : 1차원으로 변경할때 쓰는 방법
print('원본 test 데이터 : {}'.format(test_arr.reshape(-1)))
print('변환 된 test 데이터 : {}'.format(test_scaled.reshape(-1)))
# 원본 test 데이터 : [0 1 2 3 4 5]
# 변환 된 test 데이터 : [0.  0.1 0.2 0.3 0.4 0.5]

 


# 타이타닉 생존자 예측 예제

- 전체 코드

:: github.com/works-code/Python-Machine-Learning-Complete-Guide/blob/main/1_ML_Scikit-learn.ipynb

728x90
Comments