이번에 해볼 것은 분류 문제로 유명한 데이터인 붓꽃(iris) 데이터를 활용하여 분류 예측 모델을 만들어보는 것입니다.
이때 사용할 모델은 분류 모델 중 가장 기초적이지만, 설명력이 높은 결정나무(Decision Tree)를 활용하는 것입니다.
1. 데이터 설명
데이터는 총 3 종류의 붓꽃(Versicolor / Setosa / Virginica) 품종에 대한 각 특징들이 기록되어 있습니다.
데이터의 일부분을 추출해서 보면 아래와 같이 나타낼 수 있습니다.
여기서 label은 붓꽃의 품종을 뜻하며, 0 : Versicolor / 1 : Setosa / 2 : Virginica 입니다.
각 품종과 함께 수집된 변수(features)는
a) sepal length : 꽃받침의 길이 (cm)
b) sepal width : 꽃받침의 넓이 (cm)
c) petal length : 꽃잎의 길이 (cm)
d) petal width : 꽃잎의 넓이 (cm)
입니다.
2. 결정나무 분류(Decision Classifier)를 활용한 분류모델 만들기
1) 필요한 라이브러리를 불러옵니다.
이번 분석에서 필요한 라이브러는
a) from sklearn.datasets import load_iris : 사이킷런(Scikit-Learn)에 내장된 iris 데이터
b) from sklearn.tree import DecisionTreeClassifier : 결정나무 분류기
c) from sklearn.model_selection import train_test_split
: 데이터를 모델 훈련용(train) 과 테스트(test) 용으로 나누는 라이브러리
d) import pandas as pd : 데이터 처리에 필요한 pandas 라이브러리
1
2
3
4
5
|
#필요한 라이브러리 불러오기
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
import pandas as pd
|
cs |
2) 다음은 데이터를 로드하고, 데이터에 대해 알아보는 과정을 거치겠습니다.
* 이때, iris.target 은 iris 데이터에서 label로 표현된 iris의 품종을 말합니다.
* 여기서 각 숫자는 위에서 언급했던 대로
0 : setosa / 1 : versicolor / 2 : virginica 입니다
1
2
3
4
5
6
7
8
9
10
|
# 붓꽃 데이터 세트를 로딩
iris = load_iris()
# scikit learn에 내장된 iris.data는 Iris 데이터 세트에서 피처(feature)만으로 된 데이터를 numpy로 가지고 있습니다.
iris_data = iris.data
# iris.target은 붓꽃 데이터 세트에서 레이블(결정 값) 데이터를 numpy로 가지고 있습니다.
iris_label = iris.target
print('iris target값:', iris_label)
print('iris target명:', iris.target_names)
|
cs |
3) 이제 array의 형태로 되어 있는 데이터를 pandas 라이브러리의 DataFrame 기능을 활용하여 데이터프레임으로 만들어줍니다.
1
2
3
4
|
# 붓꽃 데이터 세트를 자세히 보기 위해 DataFrame으로 변환합니다.
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)
iris_df['label'] = iris.target
iris_df.head(3)
|
cs |
1
|
iris_df.info()
|
cs |
info() 함수를 활용하면 데이터의 전체 정보를 쉽게 확인할 수 있습다.
데이터는 총 150개의 관측치 (entries)가 있으며
Column은 septal length / sepal width / petal length / petal width / label 로 구성되어 있습다.
Non-Null Count를 봤을때 모든 데이터는 결측치가 없으며
4개의 변수(features)는 데이터타입이 실수형인 float64이며
품종을 나타내는 label 은 데이터타입이 정수형인 int64 입니다.
4) 훈련용(train)과 테스트(test)용 데이터로 나누기
1
2
3
4
5
6
|
# 데이터를 train 과 test로 나누기
X_train, X_test, y_train, y_test = train_test_split(iris_data, iris_label,
test_size=0.2, random_state=11)
print("train 데이터의 갯수 : ", len(X_train))
print("test 데이터의 갯수 : ", len(X_test))
|
cs |
위 코드에서는 train_test_split 이라는 함수를 사용해서 데이터를 훈련용과 테스트용으로 나눕니다.
이때,
a) iris_data는 위에서 규정한대로 features로 구성된 데이터로 X(대문자 x / 행렬을 의미)로 표현하며,
b) iris_label은 붓꽃의 품종을 나타내는 열을 의미합니다.
c) test_size = 0.2 는 전체 데이터의 크기에서 테스트 데이터의 비율(0.2 = 20%)을 의미하며
d) random_state = 11 은 위에서 말한 비율대로 데이터를 나눌때 난수(random number)를 넣어서 분류하는 것을 의미합니다.
결과는 아래와 같으며
결국 총 150개의 데이터 중 20%인 30개가 test 데이터로 분류되고, 나머지 80%인 120개는 train 데이터로 분류됩니다.
5) 결정나무 분류기 생성
1
2
3
4
5
|
# DecisionTreeClassifier 객체 생성
dt_clf = DecisionTreeClassifier(random_state=11)
# 학습 수행
dt_clf.fit(X_train, y_train)
|
cs |
* 결정나무 분류기의 객체를 dt_clf로 생성하며
* 분류된 데이터를 넣어서 학습을 수행한다.
이때, 학습을 수행하여 모델을 만들기에 train 데이터를 사용합니다
6) 생성된 분류기를 통해서 test 데이터 예측
1
2
3
4
|
# 학습이 완료된 DecisionTreeClassifier 객체에서 테스트 데이터 세트로 예측 수행.
pred = dt_clf.predict(X_test)
from sklearn.metrics import accuracy_score
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))
|
cs |
a) 이제 X_test를 모델에 넣어서 예측값(predicion value)을 만듭니다.
* 이때 예측값이란, X(feautres)를 모델에서 나오는 leaf node를 활용해 각 관측치들이 어떤 종류의 붓꽃일지에 대한 확률을 구하고, 그 중 확률 값이 큰 쪽의 클래스를 택하는 것을 말합니다.
b) 다음은 사이킷런에서 accuracy_score(예측 정확도)를 도출해주는 함수를 불러오고, 이를 통해 예측의 정확도를 도출합니다.
도출된 예측의 정확도는 0.9333으로 93.33%의 정확도로 예측을 하였다는 것을 의미합니다.
그렇다면, 각 예측된 샘플은 어떤 과정을 거쳐 나오는지 알아보자
1
2
3
4
5
6
7
|
sample_index = 0 # 예측하고자 하는 샘플의 인덱스
sample = X_test[sample_index].reshape(1, -1)
predicted_class = dt_clf.predict(sample)
probability = dt_clf.predict_proba(sample)
print("예측 클래스:", predicted_class)
print("각 클래스에 대한 확률값:", probability)
|
cs |
위와 같이 예측하고자 하는 샘플(test 샘플)의 인덱스를 입력하고 모델에 넣고 각 확률을 구하면 아래와 같습니다.
이를 해석해보면
0번째의 인덱스 (파이썬은 첫번째 인덱스가 0부터 시작한다)의 test 데이터의 예측값은 2(Virginica) 이며,
[0. 0. 1.]의 첫번째 0은 Versicolor 일 확률이 0% 임을 / 두번째 0은 Setosa 일 확률이 0% 임을 / 세번째 0은 Virginica일 확률이 100%임을 나타내고,
이러한 과정을 거쳐 최종적으로 0번째 인덱스의 예측값이 2(Virginica)임을 확인할 수 있습니다.
7) 혼동행렬(Confusion Matrix)를 활용하여 결과 해석
사이킷런 패키지에서 내장된 confusion_matrix 함수를 활용해 함수를 만들것입니다.
이때, 시각화를 위해 seaborn 라이브러리와 matplotlib의 pyplot을 활용해서 결과를 혼동핼렬로 시각화 해봅시다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
# 예측 결과와 실제 레이블 비교
y_pred = dt_clf.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
# 클래스 이름 가져오기
class_names = iris.target_names
# 혼동 행렬 시각화
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", xticklabels=class_names, yticklabels=class_names)
plt.xlabel("Predicted Labels")
plt.ylabel("True Labels")
plt.title("Confusion Matrix")
plt.show()
|
cs |
결과는 위와 같이 나옵니다.
이를 해석해보면, 혼동행렬의 1x1 / 2x2 / 3x3 에 표시된 숫자는 실제 각 붓꽃의 품종을 결정나무 분류기 모델이 맞춘 결과를 의미합니다.
test 데이터에는 setosa가 총 9개 / versicolor 총 10개 / virginica가 총 11개(2 +9)개 있었으며
이 중 virginica의 경우에만 오분류된 경우가 있습니다.(3행 2열 )
즉, 전체 30개 중 2개 만 오분류 되었으며 나머지 28개는 제대로 분류되었습니다.
이를 정확도(Accuracy)의 정의에 의해 표현해보면, 93.33% (= 28/30 *100 ) 입니다.
8) 결정나무 분류 결과를 graphviz를 통해 시각화하기
이번에도 사이킷런에 내장된 export_graphviz를 통해 분류나무의 결과를 시각화 해보겠습니다.
코드는 아래와 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from sklearn.tree import export_graphviz
import graphviz
# Graphviz 시각화
dot_data = export_graphviz(dt_clf, out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True, rounded=True,
special_characters=True)
graph = graphviz.Source(dot_data)
graph.render("iris_decision_tree") # 그래프를 파일로 저장
graph.view() # 그래프 시각화
|
cs |
구글 코랩으로 실행할 경우, 좌측의 파일에 만들어진 그래프가 파일로 저장된다. 이를 다운로드 받아 실행해주면 됩니다.
결과는 아래와 같습니다.
해석
a) 93.33%의 정확도로 붓꽃의 품종을 분류해낸 결정나무 분류기가 가장 중요하게 생각한 변수는 petal width가 0.8cm보다 작거나 또는 큰지에 대해서 분류한 것이다.
b) 그 다음은 순서도에 나온대로 해석하면 된다.
c) 각 마지막에 나온 gini 는 Gini 계수를 의미하며 불순도(impurity)를 의미한다.
9) Gini 계수에 대한 설명
Gini 계수는 불순도(impurity)를 측정하기 위한 지표 중 하나로, 주로 의사결정 트리(Decision Tree)와 같은 분류 알고리즘에서 사용됩니다. 불순도란 데이터 집합 내에서 서로 다른 클래스의 데이터가 얼마나 혼합되어 있는지를 나타내는 지표로, 낮을수록 데이터가 한 클래스에 몰려 있는 것을 의미합니다.
Gini 계수는 0부터 1까지의 값을 가지며, 0에 가까울수록 불순도가 낮고, 1에 가까울수록 불순도가 높습니다. 다음과 같은 공식으로 계산됩니다
여기서 pi는 각 클래스 i에 속하는 데이터의 비율을 나타냅니다.
의사결정 트리의 분할 시, Gini 계수는 분할된 각 하위 그룹의 불순도를 계산하고, 이들의 가중 평균을 구함으로써 분할의 품질을 측정합니다. Gini 계수가 낮을수록 좋은 분할이라고 할 수 있습니다. 의사결정 트리에서 불순도를 최소화하도록 하는 분할을 선택하여 데이터를 잘 분류하는 결정을 내리는데 사용됩니다.
요약하면, Gini 계수는 분류 문제에서 의사결정 트리가 어떤 특성을 선택하여 데이터를 분할할 때, 얼마나 순수한 하위 그룹을 생성하는지를 나타내는 지표입니다.
'파이썬(Python), 머신러닝, 딥러닝' 카테고리의 다른 글
(머신러닝 with 파이썬) Model Selection / train_test_split, K-fold CV, Startifield K-fold CV, GridSearch CV (0) | 2023.08.16 |
---|---|
[데이터분석] 웹 크롤링(Web Crawling) 기초 (파이썬, 코랩) (0) | 2023.08.15 |
생성형 AI와 다른 인공지능의 차이점 (0) | 2023.04.23 |
(딥러닝 with 파이썬) k겹 교차검증(k-fold cross validation / k-fold cv) (0) | 2022.08.10 |
(딥러닝 with 파이썬) 아이리스(iris/분꽃) 데이터 다중분류 문제 (0) | 2022.08.05 |
댓글