또자의 코딩교실

[스마트인재개발원] 근본중의 근본) iris 데이터를 활용한 KNN 분류실습 본문

코딩공부/머신러닝 & 딥러닝

[스마트인재개발원] 근본중의 근본) iris 데이터를 활용한 KNN 분류실습

또자자 2021. 12. 8. 17:37

이번 포스팅에서는 iris데이터를 이용한 knn 분류문제를 실습코드와 함께 알아보자.


image source : https://sebastianraschka.com/Articles/2015_pca_in_3_steps.html

아아! iris머신러닝의 향기로운 붓꽃향이란!

무려 1988년에 수집된 이 데이터는 많은 머신러닝 입문자들에게 필수로 거쳐가는 코스일만큼

머신러닝을 실습하기에 사용되는 가장 흔한 데이터이다. 따라서 sklearn library에서 import를 통해 불러올 수 있다.

 

iris데이터를 이용한 KNN분류 실습에서는 꽃들의 Sepal, Petal등의 세부적인 개체의 속성들을 통해

3개~ 4개 여개 중의 붓꽃의 품종(species)를 맞추는 다중 분류의 문제이다.

0 : setosa 품종
1 : versicolor 품종
2 : virginica 품종

iris 데이터에는 약 150여개의 data가 존재한다. 

지금부터 파이썬 코드와 함께 iris data의 머신러닝을 시작해보자.


 

from sklearn.datasets import load_iris
import numpy as np

iris=load_iris() #iris 데이터를 딕셔너리 형태로 보여줌

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#iris 데이터 내 구분되는 특징(column)들의 이름을 확인할 수 있다.
iris['feature_names']


#최종 품종. (=정답) 범주형 데이터를 컴퓨터가 학습이 가능하도록 숫자로 바꿔준 모습
iris['target'] 
#품종들의 이름을 확인할 수 있다.
iris['target_names']

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#pandas 데이터 프레임형태로 머신러닝의 문제 데이터 만들기

X1 = pd.DataFrame(iris['data'], columns=iris['feature_names'])

#머신러닝의 답 데이터 만들기
y1 = pd.Series(iris['target'], name='class') 
y1

#shape함수를 통해 만든 데이터의 모양 확인하기
X1.shape, y1.shape

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#train data와 test data구분하기
# train_test_split : 특성데이터와 라벨데이터를 자동으로 훈련용, 테스트용 두가지로 나눠준다. 
from sklearn.model_selection import train_test_split

X1_train, X1_test, y1_train, y1_test = train_test_split(X1,y1,
                                                       test_size = 0.3,
                                                       random_state = 0) 
# random_state 는 재현가능(for reproducibility)하도록 난수의 초기값을 설정해주는 것이며, 아무 숫자나 넣어주면 됩니다
# X1, y1들에 들어가는 데이터들을 적절히 섞어주게 된다. 추가로 사용하는 옵션 test_size = test data의 비율을 지정

X1_train.shape, X1_test.shape, y1_train.shape, y1_test.shape

이제 간단한 데이터 전처리를 끝내고 iris 데이터들을 학습용과 테스트용으로 나누게 되었다.

따라서 이제 선택적 EDA(시각화)를 통해 데이터 분포를 알아보자.

산점도 매트릭스(scatter matrix)를 활용해 확인해보자.

다음은 산점도 매트릭스를 확인하는 코드이다.

pd.plotting.scatter_matrix(X1, c=y1, figsize=(15, 15), marker='o', hist_kwds={'bins':20},s=50, alpha=0.8)

다음은 코드를 통해 산출된 산점도 매트릭스이다. 

총 16개의 산점도가 나올것 각자 자기 자신을 곱한 것은 의미가 없어서 히스토그램이 대신 채워지게 된다.

산점도 매트릭스를 그릴 시, 지정할 수 있는 세부 설정

c = color.
- y1=0번 컬러, 1번 컬러, 2번 컬러 대로 다른 색으로 매칭됨

figsize= matrix 크기 지정

marker= 점의 모양 지정

hist_kwds = hist_kwds 명령어 안에서 bins라는 옵션을 조율.
- 산점도에 보면 각자 매칭되는 애들끼리 분포를 확인할 수 있게 할때 분포를 확인하는게 의미가 없을 경우, 히스토그램을 display 할 시, 히스토그램의 옵션으로 'bins' : 20 = bins 영역에서 히스토그램에 표시하는 막대기의 갯수를 20개로 지정해주겠다는 뜻.

alpha=투명도
#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#모델 선택
knn_model = KNeighborsClassifier(n_neighbors=7) 
# k를 지정해서 이웃간 거리를 잴때 짝수형이라면 애매하게 길이가 같은 경우가 많아 홀수형으로 해주는 경우가 많음

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#모델 학습 - train데이터로 진행
knn_model.fit(X1_train, y1_train)

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#모델 학습 - test 데이터로 진행
knn_model.score(X1_test, y1_test)

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#모델 예측 - 임의의 데이터로 진행
knn_model.predict([[5, 2.9, 1, 0.2]])

# >> array([0])의 뜻 : target_names(=label)안에서 0번째 이름

이후 하이퍼 파라미터튜닝을 진행하여 최적의 예측값을 찾을 수 있다.

 

하이퍼 파라미터 튜닝(Hyper Parameter Tunning)은

KNN 모델의 경우, X1의 갯수만큼 k를 돌리는 반복문을 쓰는 방식으로 하이퍼 파라미터 튜닝을 진행한다.

KNN 모델 설정시 세부적으로 설정해 줄 수 있는 변수인 이웃(n_neighbor)의 수를

X1 train data의 전체범위로 하여 이웃의 수가 얼마일때 가장 정확도가 높은지 검증하는 방식으로

matplotlib.pyplot 라이브러리를 통해 시각화 하여 그래프를 해석한다.

 

다음은 iris data의 하이퍼파라미터 튜닝을 진행했던 코드이다.

sklearn.metrics.accuracy_score
import sklearn.metrics

#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#리스트 지정 후 반복문을 통해 하이퍼파라미터 튜닝
train_acc = []
test_acc =[]
for n in range(1, 106, 2): #X1의 갯수인 105개만큼 k를 돌리자!
    #1, 3, 5, 7 ....
    model = KNeighborsClassifier(n_neighbors=n)
    model.fit(X1_train, y1_train)
    
    train_pred = model.predict(X1_train)
    train_acc.append(metrics.accuracy_score(train_pred, y1_train))
    
    test_pred = model.predict(X1_test)
    test_acc.append(metrics.accuracy_score(test_pred, y1_test))
    
#ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#그래프를 통해 하이퍼파라미터 튜닝결과 시각화 
plt.figure(figsize=(10, 10))
plt.plot(range(1,106,2), train_acc, label='train')
plt.plot(range(1,106,2), test_acc, label='test')

plt.legend()
plt.show()

코드 실행결과 후 시각화한 결과는 다음과 같다.

가장 적합한 파라미터는 10 이하의 6~9 구간 중 홀수의 수인 7으로 예측할 수 있다.

왜냐하면 train data가 test data보다 높은 구간에 존재하지 않으며,

파라미터값의 데이터 전후로 기울기가 급격하게 변화하지 않기 때문이고

홀수를 쓰는 이유는 이웃간 거리를 잴때 짝수형이라면 애매하게 길이가 같은 경우가 많아 홀수형으로 해주는 경우가 많기 때문이다.

 

Parameter인 n_neighbors 값을 7로 설정하여 예측한 결과는 97.7%의 정확성을 보인다.

Comments