[핸즈온 머신러닝] 3강 scikitLearn Classification를 공부하고 1편

2018. 7. 10. 23:52Python-이론/python-인공지능2

Classification


우선 공부하면서 사용할 예제 mnist를 가져와 봅시다. (환경은 주피터 노트북에서 하고 있어요)


Mnist

Mnist는 머신러닝의 헬로우 월드 같은 것 이라고 생각하면 된다. 이데이터는 고등학생과 미국 인구 조사국 직원들이 손으로 쓴 70,000개의 작은 숫자 이미지를 모은 데이터셋입니다.  각 데이터의 레이블은 1 ~ 10까지 어떤 숫자를 나타내는지 나와있다. 


1. MnistData 받기

1. 우선 scikit learn과 keras를 이용해서 Mnist데이터를 가져와보겠습니다. (필자는 scikit learn으로 데이터를 가져오는 일에서 오류가 발생했습니다.)


#keras from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 784) x_test = x_test.reshape(70000, 784) #shape(60000,28,28) trainData testData(10000, 28, 28)

#keras의 데이터를 scikitlearn에서 사용하기 위해선 배열을 28*28을 784로 바꾸어주어야한다.

#scikit learn from sklearn.datasets import fetch_mldata mnist = fetch_mldata('MNIST original') x_train, x_test, y_train, y_test = X[:60000],X[60000:], Y[:60000], Y[60000:] #shape(70000, 784)


Mnist모양


 이런식으로 데이터가 제공되는데 잘보면 맞추기가 어려울 거 같다. 

2. 이진분류기 훈련시키기 


이진 분류는 말그대로 뭐가 아니다 맞다로 구분하는 분류기입니다. 그럼 우리는 이데이터가 7이 맞는지 아닌지 구분하는 이진분류기를 만들어 보겠습니다. 


1. 우선 라벨 데이터를 7과 같다면 true가 나오는 조건으로 바꾸어 보겠습니다. 

y_train_7 = (y_train == 7)
y_test_7 = (y_test == 7)

2. 다음 확률적 경사하강법 분류기로 시작해보겠습니다. 


확률적 경사하강법이란? 

y = wx + b라는 함수 식이 있으면 가장 오차가 적게되는 w와 b를 구하는 방법이다. 일반 경사하강법은 전체 데이터 다 사용하지만 확률적 경사하강법은 몇가지의 데이터만 뽑아서 w, b를 구하는 방법입니다. 


아래와 같이 확률적 경사하강법을 사용할 수 있습니다.

from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(max_iter=5, random_state=42)#max_iter 최대로 통과할 수 있는 데이터의 수 #seed를 설정해주는 #것이다. sgd_clf.fit(y_train, y_train5)


예측해보기 

sgd_clf.predict([x_train[0]])

False라고 예측한다. y[0] 데이터는 0이었다. 


3. 성능 측정 

3.1 교차 검증을 사용한 정확도 측정 


교차검증 구현하기 

sickit learn에서 교차검증과 관련된 함수를 제공하고 있지만 제어 해주어야 할 특성이나 과정이 있다면 직접 구현해볼 수 도 있다. 


from sklearn.model_selection import StratifiedKFold
from sklearn.base import clone

skfolds = StratifiedKFold(n_splits=3, random_state=42)
# 직접생성
for train_index, test_index in skfolds.split(x_train, y_train5):
clone_clf = clone(sgd_clf)
x_train_folds = x_train[train_index]
y_train_folds = y_train5[train_index]
x_test_fold = x_train[test_index]
y_test_fold = y_train5[test_index]

clone_clf.fit(x_train_folds, y_train_folds)
y_pred = clone_clf.predict(x_test_fold)
n_correct = sum(y_pred == y_test_fold)
print(n_correct/len(y_pred))


# sickit learn에서 제공하는 함수 사용

from sklearn.model_selection import cross_val_score

cross_val_score(sgd_clf, x_train, y_train7, cv=3 ,scoring="accuracy")

0.9543022848857557

0.98075

0.9817990899544977 확률이 나온다. 


StrartifiedKFold(n_splits=3, random_state=42)는 계층적 샘플링을 통해서 각클래스별 일정한 폴드를 만들어준다. 

계층적 샘플링이란 만약 여자가 전체인구의 48% 남자가 52%이면 여자는 1000명의 예를 구할 때 여자는 520명, 남자는 480명으로 구하는 것이다. 그러면 각 클래스들이 각자 전부 대표할 수 있는 모집단이 만들어지는 것이다.  


model_selection의 clone은 데이터까지 복사하는 것이 아니라 model만 복사하는 함수이다. 



3.2 오차행렬을 사용해서 모델 평가하기 


교차 검증보다 더 좋은 방법인 오차행렬을 조사하는 것입니다. 기본적인 아이디어는 A라는 label(class)이여야 하는데 잘못분류되었는 개수를 세서 올바르게 분류한 것과 비교하는 것 입니다.  우선 이와 같은 기능을 사용하려면 예측값을 만들어야 합니다. 테스트 세트로 예측을 만들 수 있지만 사용하면 안됩니다. (테스트 세트는 마지막에 테스트하는 목적으로 사용) model_selection의 ross_val_predict 


from sklearn.model_selection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf, x_train, y_train5, cv=3)

cross_val_predict 평가 점수를 반환하지 않고 각 테스트폴드에서 얻은 예측결과를 반환해줍니다.  confusion_matrix를 사용해서 오차행렬을 만들어 보겠습니다. 


from sklearn.metrics import confusion_matrix
confusion_matrix(y_train7, y_train_pred)

반환값: array([[52221,  1514],

           [  644,  5621]], dtype=int64)

[0][0]는 7이 아닌 다른 숫자를 올바르게 판단한 경우 52221 TN (7이 아니지만 참이다.)  

[0][1]는 7이 아닌 숫자를 7이라고 판단한 경우 1514 FP (7이 아니지만 거짓이다.)

[1][0]는 7인 숫자를 7이 아니라고 판단한 경우 644 FN (7이지만 거짓이다.)

[1][1]는 7인 숫자를 올바르게 판단한 경우 5621 TP (7이다.)


판단할 점 

1. 정밀도 (참의 비율)


정밀도 = (TP/(FP+TP))


2. 재현율 (양성의 비율)


재현율 = (TP/(FN+TP))


나머지는 다음시간에 계속