AI/모두의 딥러닝

[Deep Learning : 딥러닝] 다중 분류 문제

LiDARian 2021. 6. 23. 18:10
반응형

다중 분류 문제 multi classification

여러개의 답 중 하나를 골라야하는 문제 - 다중 분류 문제(multi-classification)라고 합니다.

다중 분류 문제의 대표적인 예제인 'iris 품종 맞추기'를 해봅시다.

 

해당 예제의 데이터셋은 속성은 4개, 클래스가 3개인 데이터셋입니다.

# 파일 선택을 통해 예제 데이터를 내 컴퓨터에서 불러옵니다.
from google.colab import files
uploaded = files.upload()
my_data = 'iris.csv'

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.preprocessing import LabelEncoder

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

이렇게 주요 라이브러리를 import하고, 데이터셋을 관찰합시다.

# 실행할 때마다 같은 결과를 출력하기 위해 설정하는 부분입니다.
np.random.seed(3)
tf.random.set_seed(3)

# 불러온 데이터를 적용합니다. 
df = pd.read_csv(my_data, names = ["sepal_length", "sepal_width", "petal_length", "petal_width", "species"])
print(df.head())

속성은 4개, 클래스 1개로 구성된 데이터 셋입니다. 그리고 그 클래스의 원소의 개수가 3개입니다..


pairplot

pairplot은 데이터 전체를 한번에 보는 데 자주 사용됩니다.

 

https://seaborn.pydata.org/generated/seaborn.pairplot.html
https://pinkwink.kr/986
를 참고해서 아래의 문장을 해석해봅시다.

sns.pairplot(df, hue='species');
을 작성하면 종별 특성을 볼 수 있게 됩니다. hue에 표기된 사항은 서로 구분해서 색상을 칠합니다.

참고로 argument로 받은 species는 df = pd.read_csv()에서 인자로 받은 문자열 중 하나입니다.

# 그래프로 확인
sns.pairplot(df, hue='species');
plt.show()

초록, 주황, 파랑 모두 서로 다른 종입니다.


이와 같이 종에 따라서 다른 색으로 표시됩니다!


one-hot incoding

 

원핫인코딩(데이터를 0과 1로만 표현되도록 하는 과정)을 통해서 문자열 데이터를 비트처럼 다루도록 합시다.이래야 추후에 볼 softmax 활성화 함수를 이용할 수 있습니다.

 

데이터에 문자열이 있는 경우 numpy보다는 pandas를 이용하는 것이 좋습니다.

 

맨 처음 예제 데이터를 받았던,

df = pd.read_csv(my_data, names = ["sepal_length", "sepal_width", "petal_length", "petal_width", "species"])
print(df.head())

의 반환 자료형이 DataFrame이므로, values 메서드를 이용해서 각 축을 제외한 값만을 다룰 수 있습니다.
(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.values.html)

 

그리고 astype 메서드를 통해서 각 속성값의 자료형을 float으로 변환합니다.


클래스인 Y값 - 문자열을 숫자로 바꿔서 간편하게 다루는 것이 좋은데, 이를 sklearn LabelEncoder()를 이용합니다.
(https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html)


LabelEncoder()는 각 값을 0부터 n-1까지의 값으로 변환합니다.
LabelEncoder().fit()을 통해서 라벨을 입력하고, transform()을 통해서 인코딩된 결과를 내뱉습니다. [0,1,2]가 나옵니다.

예시 코드를 보여주자면

from sklearn.preprocessing import LabelEncoder

array = ['a', 'b', 'c']
le = LabelEncoder()

print(le.fit(array))

print(le.transform(array))

# ouput
LabelEncoder()
[0 1 2]

그리고 이를 tf.keras.utils.categorical()함수를 통해서 원핫인코딩을 마무리 짓습니다. [0 1 2]가 [[1,0,0],[0,1,0],[0,0,1]]이 됩니다.

from sklearn.preprocessing import LabelEncoder
import tensorflow as tf

array = ['a', 'b', 'c']
le = LabelEncoder()

print(le.fit(array))
print(le.transform(array))

Y_encoded = tf.keras.utils.to_categorical(Y)
print(Y_encoded)

# output
LabelEncoder()
[0 1 2]
[[1,0,0],[0,1,0],[0,0,1]]

원핫인코딩 과정을 이 예제에 적용하면,

# 데이터 분류
dataset = df.values
X = dataset[:,0:4].astype(float)
Y_obj = dataset[:,4]

# 문자열을 숫자로 변환
e = LabelEncoder()
e.fit(Y_obj)
Y = e.transform(Y_obj)
Y_encoded = tf.keras.utils.to_categorical(Y)

모델 컴파일

출력 값이 3개중 하나여야하므로 출력층의 노드 수를 3으로 해야합니다.


그리고 새로운 activation 함수인 softmax는 여러 개의 출력을 다룰 때 유용한 함수입니다. 출력의 총합이 1이 되도록 조정하는데, 이로인해 출력이 [1,0,0] 으로 나오면 1이 있는 인덱스가 딥러닝에 의한 답이라고 볼 수 있는 것입니다.

 

컴파일 함수에서도 오차함수를 categorical_crossentropy를 사용합니다.

categorical_crossentropy는 다중 분류에 더 적합한 오차함수입니다.

# 모델의 설정
model = Sequential()
model.add(Dense(16,  input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))

# 모델 컴파일
model.compile(loss='categorical_crossentropy',
            optimizer='adam',
            metrics=['accuracy'])

# 모델 실행
model.fit(X, Y_encoded, epochs=50, batch_size=1)

# 결과 출력
print("\n Accuracy: %.4f" % (model.evaluate(X, Y_encoded)[1]))

이 딥러닝의 결과는...

.
.
.
150/150 [==============================] - 0s 904us/step - loss: 0.1201 - accuracy: 0.9800
Epoch 44/50
150/150 [==============================] - 0s 939us/step - loss: 0.1156 - accuracy: 0.9667
Epoch 45/50
150/150 [==============================] - 0s 976us/step - loss: 0.1205 - accuracy: 0.9600
Epoch 46/50
150/150 [==============================] - 0s 918us/step - loss: 0.1142 - accuracy: 0.9667
Epoch 47/50
150/150 [==============================] - 0s 943us/step - loss: 0.1148 - accuracy: 0.9667
Epoch 48/50
150/150 [==============================] - 0s 947us/step - loss: 0.1099 - accuracy: 0.9667
Epoch 49/50
150/150 [==============================] - 0s 969us/step - loss: 0.1084 - accuracy: 0.9667
Epoch 50/50
150/150 [==============================] - 0s 997us/step - loss: 0.1112 - accuracy: 0.9533
5/5 [==============================] - 0s 3ms/step - loss: 0.1024 - accuracy: 0.9733

 Accuracy: 0.9733
반응형