본문 바로가기
Study/Machine learning,NLP

머신러닝(2)-Classification(1)

by 왕방개 2024. 2. 28.

1.분류

1)개요

=>데이터를 가지고 어떤 결정을 해야 하는 문제를 접하는 경우에 결정해야 하는 Target이 이미 알려진 범주형인 경우

이미 알려져 있으므로 지도 학습(Supervised Learning)

=>분류의 유형은 이진 분류(Binary) 와 다중 분류( Multiclass) 로 분류하기도 하고 선형 분류 (linear) 와 비선형(polynomial)로 나누기도 합니다.

=>sklearn의 분류기들은 예측하기 위한 함수로 2가지를 사용

predict:분류 결과

predict_proba:각 클래스에 대한 확률 (확률이 가장 높은 결과가 predict 의 결과)

 

2)분류 알고리즘

=>판별 분석

=>랜덤 분류

=>KNN
=>SVM(support vector machine)

=>나이브 베이즈

=>로지스틱 회귀

=>결정 트리

=>최소 근접

=>신경망

=>앙상블

 

2.MNIST 데이터

1)개요

=>0부터 9까지의 숫자이미지 70000개로 이루어진 데이터로 레이블이 존재

=>sklearn을 이용해서 다운로드 받으면 data 속성에 feature 가 존재하고 target 속성으로 레이블 제공

 

2)MNIST 데이터 가져오기

from sklearn.datasets import fetch_openml

mnist = fetch_openml('mnist_784',version=1,as_frame=False)

X,y=mnist['data'],mnist['target']

print(X.shape)
print(y.shape)

 

3)이미지 불러오기

#이미지 데이터 1개 가져오기
some_digit = X[0]

#이미지를 다시 2차원으로 변경
some_digit_image = some_digit.reshape(28,28)

#출력
plt.imshow(some_digit_image,cmap =mpl.cm.binary)
plt.axis('off')
plt.show()
# extra code – this cell generates and saves Figure 3–2

def plot_digit(image_data):
    image = image_data.reshape(28, 28)
    plt.imshow(image, cmap="binary")
    plt.axis("off")
    
plt.figure(figsize=(9, 9))
for idx, image_data in enumerate(X[:100]):#100개의 이미지값 출력
    plt.subplot(10, 10, idx + 1)
    plot_digit(image_data)
plt.subplots_adjust(wspace=0, hspace=0)
plt.show()

 

4)훈련 데이터와 테스트 데이터 분리

print(y.dtype) #object로 되있음
y=y.astype(np.uint8)
print(y.dtype)
#훈련데이터로 6만개를 사용하고 테스트데이터로 1만개로 사용하도록 분리
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]

3.이진분류

1)이진분류를 위한 데이터 준비

=>타겟이 True 또는 False

=>이진 분류는 맞다 틀리다를 구분하는 것

=>레이블의 값을 True 와 False 로 생성

5가 맞는지 여부로 레이블을 수정

 

2)sklearn.linear_model의 SGDClassifier

=>확률적 경사 하강법(Stochastic Gradient Descent - SGD:경사 하강법은 타겟을 찾아갈 때 한 번에 찾아가지 않고 학습률(learning rate)라는 값을 이용해 작게 분할해서 타겟을 찾아가는 방)을 사용하는 분류 모델 클래스

=>매우 큰 데이터세트를 효율적으로 처리하는 모델

=>한 번에 하나씩 샘플을 처리하기 때문에 온라인 학습(실시간으로 데이터가 주어지는 형태의 학습)에 잘 들어맞습니다.

=>하이퍼 파라미터

max_iter: 최대 수행 횟수

tol:손실로 이 값보다 손실의 값이 작으면 훈련을 중지

random_state

from sklearn.linear_model import SGDClassifier
#sgd는 mini_batch기법을 사용해 계산속도가 빨라서 같은시간이면 많은 step가능
sgd_clf = SGDClassifier(max_iter=1000,tol=1e-3,random_state=42)#동일한 순서로 학습<->random_state=None
sgd_clf.fit(X_train, y_train_5)

 

 

3)분류의 평가 지표

=>오차 행렬(Confusion Matrix): 정답이 True 와 False 로 나누어져 있고, 예측한 값이 분류결과도 True 와 False 로 나누어서 표로 만든 형태

=>Confusion_matrix라는 함수를 이용해서 오차 행렬을 만들 수 있음

타겟 클래스의 레이블과 예측 클래스의 레이블을 대입해주면 됩니다.

예측 클래스의 레이블은 cross_val_predict(분류기,피처,레이블,cv=교차검증횟수)을 호출해서 만들 수 있습니다.

 

=>이전 데이터와 분류기를 이용해서 오차 행렬 생성

from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix

#training을 통한 예측 성능 측정을 하기 위해 예측 value와 실제 value 비교 
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
#오차 행렬 생성
confusion_matrix(y_train_5,y_train_pred)

 

=>Accuracy(정확도)

-True를 True 로 또는 False를 False로 예측한 비율

-옳은 경우를 고려하는 지표

(TP+TN)/(TP+FN+FP+TN)

-정확도는 가장 직관적으로 모델의 성능을 평가할 수 있는 지표

-정확도를 사용할 때 타겟의 비율을 확인해야합니다.

타겟의 비율이 어느 정도 고르게 분포되어 있다면 고려할 수 있는 평가 지표이지만 타겟의 비율이 고르지 않다면 다른 지표를 사용해야 할 수 도 있음

-어느 곳의 날씨가 99일은 맑고 1일은 비가 오는 경우 무조건 맑다고 예측하면 정확도가 99%

비가 오는 하루가 중요한 의미를 갖는다면 정확도는 올바른 평가 지표가 아닐 수 있습니다.

 

=>Recall(재현율)

-True 를 True라고 예측한 비율

(TP) /(TP+FN)

-sensitivity (민감도) 또는 hit rate라고도 부름

-실제 날씨가 맑은 데 맑다고 예측한 비율

 

=>Precision(정밀도)

-True라고 예측한 것 중에 True인 것의 비율

(TP)/(TP+FP)

 

-날씨가 맑다 했는데 실제로 맑은 비율

-정밀도와 재현율은 같이 사용하는 경우가 많습니다.

 

=>F1 score

-Precision과 Recall의 조화 평균

F1score = 2*((Precision*Recall)/(Precision + Recall))

-F1 score은 Target의 비율이불균형 구조인 경우 모델의 성능 지표로 많이 이용

 

=>sklearn.metrics 에서는 이러한 지표를 계산해주는 API 제공

대입해야 하는 데이터는 실제 값과 예측한 값의 배열입니다.

 

=>보통의 경우 F1 score 가 좋으면 성능이 좋은 분류기라고 하지만 상황에 따라서는 다른 지표 사용을 고려

-감시 카메라를 이용해서 도둑을 잡아내는 분류기를 훈련시킨다고 하면 정확도가 낮더라도 재현율이 좋은 것이 좋은 분류기가 될 수 있습니다.

 

-어린 아이에게 동영상을 추천하는 시스템의 경우는 어린 아이에게 성인이 볼 영상을 추천을 하면 안됩니다.

이런 경우에는 안전한 것들만 추천을 해주어야 하므로 정밀도가 높은 것이 좋은 분류기가 될 수 있습니다.

 

-일반적으로 정밀도를 올리면 재현율이 떨어지고 재현율을 높이면 정밀도가 떨어지게 됩니다.

이를 정밀도 와 재현율의 trade-off 라고 합니다.

 

=>평가 지표 계산

from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score

print("정확도:",accuracy_score(y_train_5,y_train_pred))
print("정밀도:",precision_score(y_train_5,y_train_pred))
print("재현율:",recall_score(y_train_5,y_train_pred))
print("F1score:",f1_score(y_train_5,y_train_pred))

 

=>ROC 곡선

 

-Receiver Operation Characteristic(ROC- 수신기 조작 특성) 곡선 이진 분류에서 널리 사용되는 도구

-거짓양성비율(FPR)에 대한 진짜 양성(TPR) 비율(재현율)의 곡선

-거짓 양성 비율은 잘못분류된 음성의 비율로 1에서 음성으로 정확하게 분류한 음성 샘플 비율을 진짜 음성 비율을 뺀 값

-음성으로 정확하게 분류한 비율을 특이도(Specificity) 라고 하는데 ROC 곡선은 재현율에 대한 1- 특이도 그래프

-이 값이 1에 가까우면 좋은 모델이라고 하고 0.5 에 가까우면 나쁜 모델(Random Model)이라고 합니다.

-roc_auc_score 라는 API를 이용해서 구할 수 있음

from sklearn.metrics import roc_auc_score

print("ROC score:",roc_auc_score(y_train_5,y_train_pred))

 

4)RandomForest Classifier 를 활용한 분류

=>예측하는 방법이 다른데 이 클래스는 예측한 클래스를 리턴하는 것이 아니고 predict_proba 함수를 이용해서 각 범주에 대한 확률 값을 리턴합니다.

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_predict


#모델 생성
forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf,X_train,y_train_5,cv=3,
                                   method='predict_proba')
#훈련을 하고 예측을 하게 되면 확률을 리턴합니다.
print(y_probas_forest[1])
#예측 - 양성 클래스의 확
y_scores_forest = y_probas_forest[:,1]
print(y_probas_forest[1])
#y_scores_forest를 가지고 평가 지표를 구해야함
print(roc_auc_score(y_train_5,y_scores_forest))
#Random Forest 을 이용한 모델의 ROC 값이 이전 모델보다 높게 나옴

 

5)교차 검증

=>여러 개의 fold로 나누어서 모델을 생성해서 훈련한 후 평가 지표를 얻어서 평균을 구하기도 합니다.

from sklearn.model_selection import cross_val_score

#3번 수행해서 정확도를 출력
cross_val_score(sgd_clf, X_train, y_train_5,cv=3,scoring='accuracy')

 

4.다중분류(Multiclass classification)

1)개요

=>둘 이상의 클래스를 구별하는 작업

=>SGD,RandomForest,Naive Bayes 알고리즘은 여러 개의 범주를 직접 처리할 수 있지만 Logistic Regression, Support Vector Machine 같은 알고리즘은 이진 분류만 가능

이진 분류기를 여러 개 결합하면 다중 분류가 가능합니다.

 

2)이진분류 알고리즘을 이용한 다중 분류

=>OvR(One -versus- the -Rest)

-범주의 개수만큼 이진 분류기를 만들어서 가장 높은 결정 점수를 가진 분류기로 선택

숫자 분류기라면 숫자는 0부터 9까지 10개가 있으므로 0 부터 9까지 분류할 수 있는 분류기를 10개 만들어서 각 숫자에 해당하는 확률을 구해서 그 확률 중에서 가장 높은 것을 선택

 

=>OvO(One-Versus-One)

-두가지로 분류하는 이진 분류기를 모두(범주 개수 * 범주 개수-1)/2 생성한 후 가장 많이 양성으로 분류된 범주를 선택

0/1 ,0/2 ,0/3, ......... 8/9 까지 만들어서 가장 많이 분류된 클래스를 선택

 

=>sklearn 에서는 다중 클래스 분류에 이진 분류 알고리즘만 사용하는 분류기를 선택하면 알아서 자동으로 알고리즘을 선택

강제로 알고리즘을 선택할 수도 있습니다.

 

3)SVM을 이용하는 다중 분류

SVM은 이진 분류기 : 기본적으로 다중 분류를 하지 못함

이 분류기를 이용해서 다중 분류를 위한 데이터를 학습시키면 스스로 알고리즘을 선택해서 다중 분류결과를 예측할 수 있음

from sklearn.svm import SVC

#모델 생성
svm_clf =SVC(random_state=42)

#훈련
svm_clf.fit(X_train[:1000],y_train[:1000])

#예측
svm_clf.predict([some_digit])

 

=>점수를 확인해 다른 점수가 높은게 뭐가 있을지 파악

#여러 개의 분류기를 생성한 후 각각의 분류기를 가지고 예측을 해서 점수를 배정
#이 점수가 가장 높은 클래스를 선택
some_digit= X[0]
some_digit_scores = svm_clf.decision_function([some_digit])
print(some_digit_scores)

some_digit=X[1]
some_digit_scores = svm_clf.decision_function([some_digit])
print(some_digit_scores)

#이 점수나 확률은 확인을 할 필요가 있습니다.

 

=>강제로 알고리즘을 설정

#강제로 알고리즘을 선택
from sklearn.multiclass import OneVsRestClassifier

ovr_clf = OneVsRestClassifier(SVC(random_state=42))
ovr_clf.fit(X_train[:1000],y_train[:1000])

some_digit= X[0]
print(ovr_clf.predict([some_digit]))

 

4)스케일링을 적용했을 떄의 정확도

=>특별한 경우가 아니면 스케일링 하고 나서의 정확도가 높

from sklearn.linear_model import SGDClassifier

#SGD 분류기 생성
sgd_clf = SGDClassifier(max_iter = 1000,tol = 1e-3 , random_state=42)
#훈련
sgd_clf.fit(X_train,y_train)
#교차 검증을 수행
cross_val_score(sgd_clf,X_train, y_train,cv=3,scoring='accuaracy')

위는 스케일링을 안하고 측정한 정확도 ,아래는 스케일링 후의 정확도

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))
cross_val_score(sgd_clf,X_train_scaled, y_train,cv=3,scoring='accuaracy')

 

5)평가 지표

#오차 행렬
y_train_pred = cross_val_predict(sgd_clf , X_train_scaled, y_train , cv=3)

conf_mx = confusion_matrix(y_train,y_train_pred)
print(conf_mx)

=>오차 행렬을 확인해서 어떤 부분에서 오류가 많이 발생하는지 확인

오류가 많이 발생하는 부분이 있다면 그에 해당하는 데이터를 더 수집해서 좀 더 정확한 모델을 만드는 것을 고려하거나 이미지 데이터의 경우는 전처리를 수행해서 보정을 하기도 합니다.

 

5.다중 레이블 분류

1) 개요

=>분류기가 샘플 별로 여러 개의 결과를 출력하는 경우

=>이미지에서 객체를 탐지하는 경우 하나의 객체를 탐지하는 것이 아닌 여러 개의 객체를 탐지해야하는 경우 나 얼굴에서 얼굴의 각 부위를 탐지하는 경우 등에 사용

=>이런 경우에는 타겟을 다중 배열로 만들어야 합니다

 

2)다중 레이블 분류

# 다중 레이블 생성
y_train_large = (y_train > 7)
y_train_odd = (y_train % 2 == 1)
y_multilabel = np.c_[y_train_large , y_train_odd]
print(y_multilabel[0])

from sklearn.neighbors import KNeighborsClassifier

knn_clf =KNeightborsClassifier()
#훈련을 할 때 여러 개의 label 인 묶인 타겟을 설정하면 다중 레이블 분류
knn_clf.fit(X_train , y_multilabel)
some_digit =X[0] #5번 클래스
print(knn_clf.predict([some_digit])

6.판별 분석(Discriminant Analysis)

1)개요

=>2개 이상의 모집단에 추출된 표본들이 지니고 있는 정보를 이용해서 이 표본들이 어느 모집단에 추출된 것인지를 결정해 줄 수 있는 기준을 찾는 분석

 

=>은행에서 부동산 담보 대출을 하고자 하는 경우 이 고객이 대출을 상환할 것인가 아니면 상환하지 않을 것인가를 판별하는 경우 은행에서는 기존의 대출을 상환하지 않은 고객들의 특성과 대출을 상환한 고객의 특성을 별도로 만들어두고 고객의 특성이 어느 쪽에 더 가까운 것인지를 파악할 수 있을텐데 이러한 분석이 판별 분석입니다

 

=>초창기에는 LDA(Linear Discriminant Analysis - 선형 판별 분석) 을 많이 사용했는데 최근에는 신경망등이 등장하면서 사용 빈도가 낮아졌는데 아직도 LDA는 다른 머신러닝 알고리즘의 기반 알고리즘으로 사용되고 있음

 

=>전체 표본의 크기가 독립 변수의 개수보다 3배 이상 많아야 합니다.

 

2)LDA

=>내부 제곱 합에 대한 사이 제곱합의 비율을 최대화 하는 것이 목적

그룹 내부의 제곱합은 적게 그리고 그룹과 그룹사이의 제곱합은 크게 만드는 알고리즘

클러스터링의 기반이 되는 방법

 

=>sklearn.discriminant.LinearDiscriminantAnalysis 클래스를 이용해서 구현

 

 

7.Dummy Classifier

=>랜덤하게 분류

=>타겟의 비율을 보고 그대로 랜덤하게 예측하는 방식

 

 

 

 

'Study > Machine learning,NLP' 카테고리의 다른 글

머신러닝(5) - Regression(2)  (0) 2024.03.05
머신러닝(4)-Regression(1)  (0) 2024.03.04
머신러닝(3)-Classification(2)  (0) 2024.02.29
머신러닝(1)  (1) 2024.02.27
이미지 데이터 다루기  (0) 2024.02.20