이번 포스팅은 이전 포스팅에 이어
다중분류(Multiclass Classification)에 대해서
파ㅎ쳐보겠습니다.
해당 포스팅을 참고해서 학습하겠습니다.
https://yhyun225.tistory.com/14
분류 (3) - 다중 분류(Multiclass Classification)
이진 분류(Binary Classification)는 타깃의 값이 어떤 기준에 대하여 참(True) 또는 거짓(False)의 값을 가졌습니다. 다중 분류(Multiclass Classification)의 경우 타깃이 가질 수 있는 값이 3개 이상입니다. 타깃
yhyun225.tistory.com
1. 다중분류 파헤치기
이진분류는 분류의 예측의 종류가 0, 1 두가지였다면
다중분류는 분류의 예측의 종류가 3가지 이상인 분류방식입니다.
다중분류를 더 자세히 설명하자면
여기서는 예측값이 가질 수 있는 값이 3개 이상입니다.
예측값에 대응되는 데이터의 종류를
클래스(class) 혹은 레이블(label)이라고 합니다.
이진분류의 예측값이 0,1이었다면
다중분류는 0,1,2,3 이렇게 4개의 클래스 혹은 레이블을
갖게 되겠네요.
1)One Hot Encoding
One Hot Encoding은
분류 종류(클래스)를
0과 1로 변경해주는 인코딩 방식입니다.
예를들어 분류할 데이터가
1,3,5,6 이라는 4가지 분류 종류라고 하면
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
의 형태로 변경해줍니다.
1은 [1 0 0 0]
3은 [0 1 0 0]
5는 [0 0 1 0]
6은 [ 0 0 0 1]
으로 각 클래스에 체크를 해줍니다.
출력값(y)가
이 과정을 거쳐야 모델이
softmax를 거친 예측값과 결과를 비교하며 학습이 가능합니다.
2) Softmax 함수
이진분류 모델의 activation(활성화)모델은
sigmoid함수였죠?
Softmax함수는 다중분류 모델의 activation함수입니다.
sigmoid를 일반화 한 것이 softmax라고 합니다.
일반화라는 개념은 잘 모르겠지만,
시그모이어 함수는 입력 값을 하나 받아서
0~1사이의 값을 만들어준다고 했을때,
소프트맥스는 다수의 입력 값을
0~1사이의 값으로 만들어주도록
개념을 확장한 것이라고 생각되네요.
추가로 이 값들의 합이 1이 되도록 만들어 준다고합니다.
아래의 식을 보면 3개 클래스를 갖는
입력값을 받았고
소프트맥스 함수를 거치면서
해당 값들의 결과를
3개의 합이 1이 되도록 각 수치를 생성해줬습니다.
마치 확률처럼요.
즉, 정리해보면 소프트맥스 함수를 통과하면
합이 1이 되는 0~1사이의 수치로 변경 해주고 어느 것이 예측값에
가까운지 판단하기가 더 좋게 변환되네요.
3) Categorical Cross-Entropy (범주형 교차엔트로피)
Categorical CrossEntropy는 다중분류의 손실함수입니다.
yi는 hot one encoder로 변경한 출력값이고
ai는 예측 즉 확률값입니다.
n 은 분류의 개수 즉, 클래스의 개수입니다.
만약 클래스의 개수가 3개, 출력값이 [0 0 1] 이고
softmax를 거친 예측값이 [0.3 0.2 0.5]라면
해당 식에 적용해서 계산해보면
0log0.3 - 0log 0.2 - 1log0.5 이므로
로스값은 -1log0.5 = 0.301029... 가 됩니다.
2. 사용해보기
다중분류 데이터인
Scikitlearn의 load_wine 데이터를 가져와보겠습니다.
pandas의 value_counts()를 사용하거나
numpy의 unique를 사용해서 클래스(레이블 or 데이터의 종류)와 개수를 확인할 수 있습니다.
import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
datasets = load_wine()
x = datasets.data
y = datasets.target
print(x.shape, y.shape) #(178, 13) (178,)
print(pd.value_counts(y)) #클래스 확인
# unique, counts = np.unique(y, return_counts=True)
# print(unique , counts)
그리고 onehot Encoder를 사용해서 데이터를 one hot 데이터로 변경해줍니다.
변경 방법은 3가지가 있습니다.
1. keras to_categorical() 함수
2. pandas의 get_dummies() 함수
3.scikit learn OneHotEncoder() 클래스의 fit_transform()함수
그런데 각 각의 데이터 형태가 다르니
상황에 따라 사용하면 좋을 듯 합니다.
특히 keras의 to_categorical()함수는 배열로 반환해서 그런지
[3 4 6]이런값이면
7(가장 큰 값의 +1)개 클래스의 one hot 데이터가 만들어집니다...
이 데이터는 [0001000] [0000100] [0000001] 이렇게 생성되는거죠..
(몰라서 고생을 했습니다)
또, 사이킷런 OneHotEncoder는 변경 값 데이터형을 행렬로 만들어서 넣어줘야합니다!!
(이것도 고생했습니다..)
from keras.utils import to_categorical
from sklearn.preprocessing import OneHotEncoder
#one hot encoder
#1. keras
ohe_y_keras = to_categorical(y)
#2. pandas
ohe_y_pandas = pd.get_dummies(y)
#3. scikitlearn
y = y.reshape(-1,1)
ohe_y_sklearn = OneHotEncoder(sparse=False).fit_transform(y)
print(ohe_y_sklearn)
print(ohe_y_sklearn.shape)
새로 사용한 파라미터가 나왔습니다.
train_test_split()의 stratify 입니다.
해당 포스팅에서는 어떻게 사용하는지 몰랐는데
이제 사용하네요!
https://aigaeddo.tistory.com/12
9. 데이터) Scikit-Learn "train_test_split" 사용해서 데이터 쪼개보기
안녕하세요. 오늘은 Scikit Learn 의 train_test_split 함수를 이용해서 데이터를 쪼개보겠습니다. 일단 사이킷런(Scikit Learn)이 무엇인지 알아야겠죠? 1. Scikit Learn 사이킷 런이란 머신러닝을 위한 데이터
aigaeddo.tistory.com
클래스의 적절한 분배를 해주도록 도와주는 파라미터입니다!
한가지에 몰리지 않게 분배해주는거죠.
다중분류에서는 중요한 파라미터입니다.
x_train, x_test, y_train, y_test = train_test_split(x, ohe_y_sklearn, train_size= 0.72, random_state=123,
stratify=ohe_y_sklearn)
이후 모델을 구성해줍니다.
여기서 저희가 공부한 'softmax'가 나왔네요!
모델의 마지막 레이어에
activation 함수로서 지정해주었습니다.
from keras.models import Sequential
from keras.layers import Dense
#모델 구현
model = Sequential()
model.add(Dense(64, input_dim = 13))
model.add(Dense(32))
model.add(Dense(16))
model.add(Dense(3, activation='softmax'))
그 뒤에 compile에 다중분류모델의 손실함수인
"categorical_crossentropy"를
설정해주었습니다.
metrics는 'accuracy' 를 넣어주었습니다.
#컴파일 훈련
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
history = model.fit(x_train, y_train, epochs=550, batch_size=1, validation_split=0.2, verbose=1)
처음에 one hot encoding을 하면서
데이터를 [1 2 3 4] -> [1 0 0 0] [ 0 1 00] [0 0 1 0] [0 0 0 1]
이렇게 변경해서 softmax의 예측값과 비교할 수 있도록 변경해 주었잖아요.
그리고 softmax를 거친 예측값도 [0.6 0.1 0.1 0.1][0.1 0.6 0.1 0.1][0.1 0.1 0.6 0.1][0.1 0.1 0.1 0.6]
이런식으로 나오구요.
이 값들 중 가장 큰 값에 해당하는 클래스(분류된 예측값)로 반환하기 위해서
numpy의 argmax()라는 함수를 반드시 사용해 줘야합니다.
(axis = 1은 한 행 단위 비교)
#예측 평가
loss = model.evaluate(x_test, y_test)
y_predict = np.argmax(model.predict(x_test), axis=1) #데이터 중 가장 큰 값의 클래스 반환
y_test_argmax = np.argmax(y_test, axis=1) # np.argmax( ) 중요!
accuracy_score도 찍어보고
from sklearn.metrics import accuracy_score
acc_score = accuracy_score(y_test_argmax, y_predict)
print("acc score :", acc_score)
시각화도 해보겠습니다.
evaluate loss, val_loss, val_acc 세가지를
비교해보겠습니다.
import matplotlib.pyplot as plt
plt.figure(figsize=(9,6))
plt.plot(history.history['loss'], color = 'red', label = 'red', marker = '.')
plt.plot(history.history['val_loss'], color = 'green', label = 'val_loss', marker = '.')
plt.plot(history.history['val_acc'], color = 'blue', label = 'val_acc', marker = '.')
plt.title("multiclass classification")
plt.legend(loc = 'upper right')
plt.show()
val_loss의 형태와
loss와 val_loss의 차이, 정확도의 형태를 확인하고 싶었는데
그래프 그리는 방식을
더 공부해봐야겠습니다.
이상으로 다중분류에 대해서
학습하고 정리하는 시간을 가졌습니다.
수업시간에 잘 정리가 되지 않았는데
그래도 머릿속에 조금은 이해가 갔습니다
틀린점 있으면 지적 부탁드립니다!
'인공지능 개발하기 > Machine Learning' 카테고리의 다른 글
[Tensorflow] 22. 데이터 스케일링(Data Scaling) (0) | 2024.01.20 |
---|---|
[Tensorflow] 21. 범주형 데이터(Categorical Data)를 수치형 데이터(Numeric data)로 변환하기 (0) | 2024.01.20 |
[Tensorflow] 19. 이진분류(Binary Classification) (0) | 2024.01.13 |
[Tensorflow] 18. keras EarlyStopping() 사용해보기 (2) | 2024.01.13 |
[Tensorflow] 17. loss 값 시각화 해보기 (1) | 2024.01.13 |