아무것도 모르는 공대생의 지식 탐험기
모두의 딥러닝 10일차 (ch.12) 본문
다중 분류 뮨제 해결하기
다중 분류 문제 해결하기 - 아이리스 품종 예측
1. 다중 분류 문제란?
딥러닝을 이용한 분류 문제는 크게 이항 분류(binary classification)와 다중 분류(multi-class classification)로 나뉜다.
- 이항 분류: 두 개의 클래스(예: 스팸 메일 여부)를 예측하는 문제
- 다중 분류: 세 개 이상의 클래스 중 하나를 예측하는 문제
이번에는 대표적인 다중 분류 문제인 아이리스(Iris) 품종 예측 문제를 다룰 것이다. 아이리스 데이터셋은 꽃잎의 길이, 너비, 꽃받침의 길이, 너비 등의 속성을 이용해 세 가지 품종(Setosa, Versicolor, Virginica)을 예측하는 문제이다.
아이리스 데이터셋 구성
꽃받침 길이 | 꽃받침 너비 | 꽃잎 길이 | 꽃잎 너비 | 품종 |
5.1 | 3.5 | 1.4 | 0.2 | Setosa |
4.9 | 3.0 | 1.4 | 0.2 | Setosa |
4.7 | 3.2 | 1.3 | 0.2 | Setosa |
4.6 | 3.1 | 1.5 | 0.2 | Setosa |
5.0 | 3.6 | 1.4 | 0.2 | Setosa |
2. 데이터 분석 및 시각화
2.1 데이터 불러오기
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 아이리스 데이터 불러오기
df = pd.read_csv("./data/iris.csv")
2.2 데이터 관계 분석 - Pairplot 활용
Pairplot은 각 속성 간 관계를 시각적으로 분석하는 데 유용하다.
sns.pairplot(df, hue='species')
plt.show()
이 그래프를 통해 각 품종별 데이터 분포를 확인할 수 있다. 품종 간 차이가 명확한 속성(예: 꽃잎 길이, 꽃잎 너비)이 있는 경우 해당 속성이 분류에 중요한 역할을 한다.
3. 데이터 전처리 - 원-핫 인코딩
딥러닝 모델은 숫자 데이터만 처리할 수 있기 때문에, 문자열 형태의 클래스(Species)를 숫자로 변환하는 과정이 필요하다.
3.1 Label Encoding 적용
from sklearn.preprocessing import LabelEncoder
# 데이터 분류
dataset = df.values
X = dataset[:,0:4].astype(float)
Y_obj = dataset[:,4]
# 문자열을 숫자로 변환
encoder = LabelEncoder()
encoder.fit(Y_obj)
Y = encoder.transform(Y_obj)
이렇게 변환하면 품종이 다음과 같이 숫자로 매핑된다:
- Setosa → 0
- Versicolor → 1
- Virginica → 2
3.2 One-Hot Encoding 적용
그런데 이렇게 단순히 정수형 숫자로 변환하면 모델이 숫자 간 크기 관계(2 > 1 > 0)를 학습할 가능성이 있다. 이를 방지하기 위해 원-핫 인코딩(One-Hot Encoding)을 적용한다.
import tensorflow as tf
# 원-핫 인코딩 적용
Y_encoded = tf.keras.utils.to_categorical(Y)
변환 후 데이터는 다음과 같은 벡터 형태가 된다:
Setosa | Versicolor | Virginica |
1 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
4. 소프트맥스(Softmax) 함수 적용
소프트맥스 함수(Softmax Function)는 출력값을 확률 분포 형태로 변환하는 활성화 함수이다. 즉, 모델이 각 클래스에 속할 확률을 출력하도록 만든다.
소프트맥스 함수의 주요 특징:
- 출력값의 총합이 1
- 가장 큰 확률을 가진 클래스를 선택
- 각 클래스 확률을 강조하며 정규화
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# 모델 설정
model = Sequential()
model.add(Dense(16, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))
출력층의 노드 수를 3으로 설정한 이유는 세 개의 클래스를 예측해야 하기 때문이다.
5. 모델 학습 및 평가
5.1 모델 컴파일
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
- categorical_crossentropy: 다중 분류 문제에 적합한 오차 함수
- Adam 옵티마이저: 가중치 조정을 최적화하는 알고리즘
- 정확도(accuracy) 평가 지표 사용
5.2 모델 학습
model.fit(X, Y_encoded, epochs=50, batch_size=1)
- epochs=50: 데이터를 50번 반복 학습
- batch_size=1: 한 번에 하나의 샘플을 학습
5.3 모델 평가
# 결과 출력
print("\n Accuracy: %.4f" % (model.evaluate(X, Y_encoded)[1]))
6. 결과 해석 및 최적화 방향
아이리스 품종 분류 모델을 학습한 후, 정확도가 약 97% 정도 나온다. 하지만 더 높은 성능을 원한다면 다음과 같은 방법을 고려할 수 있다:
- 더 많은 데이터 사용: 데이터가 많을수록 모델이 더 정확해진다.
- 하이퍼파라미터 튜닝: 학습률 조정, 레이어 수 변경, 활성화 함수 변경 등
- 정규화 기법 적용: 과적합 방지를 위해 드롭아웃(Dropout) 사용
7. 결론
이번 실습을 통해 다중 분류 문제에서의 주요 개념과 전처리 방법을 익혔다:
- 다중 분류 문제에서는 원-핫 인코딩이 필수
- 출력층 활성화 함수로 소프트맥스(Softmax) 사용
- 손실 함수는 categorical_crossentropy 적용
- Adam 옵티마이저를 이용해 학습 최적화