멀리 보는 연습

머신러닝_iris 품종 분류 실습(K-Nearest Neighbors) 본문

빅데이터 분석 서비스/머신러닝

머신러닝_iris 품종 분류 실습(K-Nearest Neighbors)

푸실리 2021. 9. 4. 01:06

머신러닝 5가지 실습을 마치고, 대략 2주동안 캐글 대회를 진행 중이다. 전자 상거래 물품 배송 예측(분류)을 주제로 진행하고 있는데, 종료되면 이에 대한 후기도 올릴 예정이다. 지금 심정은 굉장히.. 암울.. 멘붕..정도랄까.. 알파벳을 배우자마자 영어 작문을 하는 기분이다. 그래도 열심히 해봐야지..

 

1.목표

- 붓꽃의 꽃잎 길이, 꽃잎 너비, 꽃받침 길이, 꽃받침 너비 특징을 활용해 3가지 품종을 분류해보자

 

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier # 하이퍼파라미터
from sklearn import metrics # 예측률

 

K-Nearest Neighbors 알고리즘?

 

한국어로 해석하면 가까운 이웃이다. 무슨 말이냐면, 새로운 데이터 포인트와 가장 가까운 훈련 데이터셋의 데이터 포인트를 찾아서 예측한다는 말이다. K값에 따라 가까운 이웃의 수가 결정된다. 분류와 회귀 모두 사용 가능하다. 

 

장점

  • 쉬운 모델, 쉬운 알고리즘과 이해
  • 튜닝할 hyperparameter 스트레스가 없음
  • 초기 시도해보기 좋은 시작점이 되는 모델

단점

  • 샘플 데이터가 늘어나면 예측시간도 늘어나기 때문에 매우 느려짐
  • pre-processing을 잘하지 않으면 좋은 성능을 기대하기 어려움
  • feature가 많은(수 백개 이상) 데이터셋에서는 좋은 성능을 기대하기 어려움
  • feature의 값이 대부분 0인 데이터셋과는 매우 안좋은 성능을 냄

kaggle과 현업에서는 더 좋은 대안들이 많기 때문에 자주 쓰이는 알고리즘은 아니라고 한다. 그래도 지금은 배우는 단계이기 때문에 열심히 해보는 중!

 

 

 

2. 데이터 수집 

from sklearn.datasets import load_iris # iris 데이터 가져오기

원래는 데이터 파일인 csv 혹은 xls 양식의 파일을 같이 업데이트 해두었는데, 이번 iris 데이터는 sklearn에 내장되어있는 데이터이기 때문에, 바로 불러오기만 하면 된다. 세상 편리하군!

 

 

iris_data = load_iris()
iris_data        # 딕셔너리 형태 {key : value}

...

iris_data.keys()

# data => 문제

iris_data['data']
# target => 답

iris_data['target']

 

 

# target_name => 답의 구체적 내용

iris_data['target_names']

# DESCR   -> Attributes : 속성(컬럼), class : 답

print(iris_data['DESCR'])

.. _iris_dataset: Iris plants dataset -------------------- **Data Set Characteristics:** :Number of Instances: 150 (50 in each of three classes) :Number of Attributes: 4 numeric, predictive attributes and the class :Attribute Information: - sepal length in cm - sepal width in cm - petal length in cm - petal width in cm - class: - Iris-Setosa - Iris-Versicolour - Iris-Virginica :Summary Statistics:

============== ==== ==== ======= ===== ====================

Min Max Mean SD Class Correlation

============== ==== ==== ======= ===== ====================

sepal length: 4.3 7.9 5.84 0.83 0.7826

sepal width: 2.0 4.4 3.05 0.43 -0.4194

petal length: 1.0 6.9 3.76 1.76 0.9490 (high!)

petal width: 0.1 2.5 1.20 0.76 0.9565 (high!)

============== ==== ==== ======= ===== ====================

:Missing Attribute Values: None

:Class Distribution: 33.3% for each of 3 classes.

:Creator: R.A. Fisher :Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)

:Date: July, 1988

The famous Iris database, first used by Sir R.A. Fisher. The dataset is taken from Fisher's paper. Note that it's the same as in R, but not as in the UCI Machine Learning Repository, which has two wrong data points. This is perhaps the best known database to be found in the pattern recognition literature. Fisher's paper is a classic in the field and is referenced frequently to this day. (See Duda & Hart, for example.) The data set contains 3 classes of 50 instances each, where each class refers to a type of iris plant. One class is linearly separable from the other 2; the latter are NOT linearly separable from each other.

.. topic:: References

- Fisher, R.A. "The use of multiple measurements in taxonomic problems" Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions to Mathematical Statistics" (John Wiley, NY, 1950).

- Duda, R.O., & Hart, P.E. (1973) Pattern Classification and Scene Analysis. (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218.

- Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System Structure and Classification Rule for Recognition in Partially Exposed Environments". IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. PAMI-2, No. 1, 67-71.

- Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule". IEEE Transactions on Information Theory, May 1972, 431-433.

- See also: 1988 MLC Proceedings, 54-64. Cheeseman et al"s AUTOCLASS II conceptual clustering system finds 3 classes in the data.

- Many, many more ...

 

# feature_names => 컬럼 이름

iris_data['feature_names']

데이터 셋 구성하기 >> 데이터프레임 형태로 만들기

 # iris_df = pd.DataFrame('문제값', columns = '컬럼 이름')
    
iris_df = pd.DataFrame(iris_data['data'], columns = iris_data['feature_names'])
iris_df

print(iris_df)

display(iris_df)

3. 전처리

- 문제와 답 분류

# 문제 

X = iris_df
# 답

y = iris_data['target']

- train(훈련셋)과 test(평가셋) 분리

iris_data['target'].shape

iris_df.shape

# 답을 확인해보면, 순서대로 정렬이 되어있기 때문에 절대 맞출 수 없는 오류가 존재함

X_train = X.iloc[:105, :]  # 훈련 문제
y_train = y[:105]          # 훈련 답
X_test = X.iloc[105:, :]   # 평가 문제
y_test = y[105:]           # 평가 답
y_test

sklearn.model_selection => train_test_split => 자동으로 섞어주는 함수

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state=0)

# 변수 선언                                               # test 비율       # 랜덤 숫자는 아무거나 넣기
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)

4. EDA

pd.plotting.scatter_matrix(iris_df, c = y, figsize=(15,15), marker='O', alpha = 1)  # alpha => 색 투명도

5. 모델링

model = KNeighborsClassifier(n_neighbors = 3)   # 하이퍼파라미터 3으로 설정

KNN 알고리즘은 n_neighbors의 갯수가 적을 때는 결정 경계가 매우 복잡해지고, 반대로 n_neighbors의 갯수가 많아지면 결정 경계가 단순해진다. 

  • n_neighbors 적어지면 -> model의 결정경계가 복잡 -> overfitting
  • n_neighbors 많아지면 -> model의 결정경계가 단순 -> underfitting

즉,  적절한 n_neighbors를 찾는 것이 이 modeling의 POINT!

 

 

model.fit(X_train, y_train)   # 훈련용 문제와 답

# 예측률 1

pre = model.predict(X_test)
pre

metrics.accuracy_score(pre, y_test)

0.9777777777777777

# 예측률 2

model.score(X_test, y_test)

0.9777777777777777

 

 

 

하이퍼파라미터 튜닝

- 모델링 시 => model = KNeighborsClassifier(n_neighbors = 3) 하이퍼파라미터 3으로 값 설정

 

test_list = []
train_list = []

for k in range(1, 80, 2) :  # 1부터 80까지 2씩 증가
    model = KNeighborsClassifier(n_neighbors= k) 
    model.fit(X_train, y_train)
    test.append(model.score(X_test, y_test))
    
    train.append(model.score(X_train, y_train))

test_list  # 하이퍼파라미터의 중요성!

[0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9777777777777777, 0.9555555555555556, 0.9777777777777777, 0.9555555555555556, 0.9555555555555556, 0.9555555555555556, 0.9333333333333333, 0.9111111111111111, 0.9111111111111111, 0.8888888888888888, 0.9111111111111111, 0.9111111111111111, 0.9111111111111111, 0.9333333333333333, 0.9111111111111111, 0.9111111111111111, 0.9111111111111111, 0.9111111111111111, 0.8444444444444444, 0.8444444444444444, 0.8666666666666667, 0.7333333333333333, 0.6888888888888889, 0.6666666666666666, 0.6666666666666666, 0.6666666666666666, 0.6888888888888889, 0.6666666666666666, 0.6444444444444445]

 

train_list

[1.0, 0.9619047619047619, 0.9714285714285714, 0.9714285714285714, 0.9619047619047619, 0.9619047619047619, 0.9619047619047619, 0.9619047619047619, 0.9619047619047619, 0.9619047619047619, 0.9523809523809523, 0.9523809523809523, 0.9523809523809523, 0.9428571428571428, 0.9428571428571428, 0.9428571428571428, 0.9523809523809523, 0.9333333333333333, 0.9333333333333333, 0.9428571428571428, 0.9428571428571428, 0.9428571428571428, 0.9333333333333333, 0.9238095238095239, 0.9238095238095239, 0.9238095238095239, 0.9142857142857143, 0.9142857142857143, 0.9238095238095239, 0.8761904761904762, 0.8761904761904762, 0.8952380952380953, 0.8476190476190476, 0.8285714285714286, 0.8095238095238095, 0.8, 0.8, 0.7904761904761904, 0.7904761904761904, 0.7904761904761904]

plt.figure(figsize = (7,7))
plt.plot(range(1, 80, 2), train_list, label = 'train')
plt.plot(range(1, 80, 2), test_list, label = 'test')
plt.legend() # 범주
plt.show()

# k=1, 모델의 복잡도 높아지고 => 과대적합 / train 정확도 1 일 때, test 0.97  훈련 정확도가 더 높으면 X
# test 정확도가 더 높을 때가 가장 일반화가 잘 되었다.

각종 모델 기법과 개념들이 머릿속에서 빙빙 꼬여버렸다. 복습을 하면 조금 나아지기는 하는데, 열심히 공부해야겠다는 생각이 든다. 수강생들은 모두 이해를 잘 하고 있을까? 1년 후의 나는 머신러닝을 더 친근하게 여기고 있을까? 2년 후의 나는? 정말 어려운 분야인 것 같다. 휘몰아치는 일정 속에서 잘 살아남아야겠다. 화이팅 : ) 

Comments