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 |