#!/usr/bin/env python3

k_NN(k-최근접 이웃) Regression


k-NN 회귀모델을 알아보겠습니다.
k-NN regression의 동작환경은 다음과 같습니다.

import mglearn

import matplotlib.pyplot as plt

mglearn.plots.plot_knn_regression(n_neighbors=1)
plt.show()

n_neighbors=1 일때 algorithm

x축에 3개의 테스트 데이터를 녹색 별로 표시합니다.
최근접 이웃을 한 개만 사용할 때 예측은 가장 가까운 데이터 포인트의 값으로 인식합니다.

다음은 이웃의 수가 3일 때 knn algorithm의 동작 환경입니다.
mglearn.plots.plot_knn_regression(n_neighbors=3)
plt.show()

n_neighbors=3 일때 algorithm

마찬가지로 3개의 녹색 테스트 데이터를 기준으로 가장 이웃한 3개의 최근접 데이터 포인트를 구합니다.
그리고 나서 각 데이터포인트사이의 거리의 역수를 가중치로 타겟 값을 산정합니다.


이해를 돕기위해 인위적 데이터를 사용하여 k-NN Regression을 사용해보겠습니다.
from mglearn.datasets import make_wave
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor

x, y = make_wave(n_samples=40)

x_train, x_test, y_train, y_test = \
  train_test_split(x, y, 
                   random_state=0, test_size=0.3)

knn_reg = KNeighborsRegressor(n_neighbors=3, n_jobs=-1) n_jobs = 사용할 코어의 수, -1 => 모든 코어 사용
knn_reg.fit(x_train, y_train)

print('{:.3f}'.format(knn_reg.score(x_test, y_test)))
# 0.697


1차원 데이터 셋이므로 시각화가 가능하므로 n_neighbors의 값에 따라 어떻게 변하는지 확인해보겠습니다.
import numpy as np
_, axes = plt.subplots(1, 3)

line = np.linspace(-5, 5, num=1000)
line = line.reshape(-1, 1)

for i, ax in zip([1, 3, 9], axes.ravel()):
    knn_reg = KNeighborsRegressor(n_neighbors=i, n_jobs=-1)
    knn_reg.fit(x_train, y_train)

    prediction = knn_reg.predict(line)
    ax.plot(line, prediction, label='model predict', c='k'
    ax.scatter(x_train, y_train, marker='^', c='darkred', label='train target')
    ax.scatter(x_test, y_test, marker='v', c='darkblue', label='test target')
    
    train_score = knn_reg.score(x_train, y_train)
    test_score = knn_reg.score(x_test, y_test)
    ax.set_title('k={}\ntest score={:.3f}\ntrain score={:.3f}'.format(i, train_score, test_score))
    ax.set_xlabel('feature')
    ax.set_ylabel('target')
axes[0].legend(loc=2)
plt.show()

n_neighbors 값에 따라 최근접 이웃 회귀로 만들어진 예측 회귀 비교

이웃을 하나만 사용할 때는 훈련 세트의 각 데이터 포인트가 모든 선을 통과합니다. 이 것은 너무 복잡하게 모델이 짜여져 있는 것을 말하며 실제로 예측할 때는 그 결과가 좋지 못합니다. 반대로 이웃을 많이 사용할 수록 훈련 데이터에는 잘 안맞을 수 있지만 높은 정확도를 얻게 됩니다.


k-NN은 이해하기 매우 쉬운 모델입니다. 그러나 수백 개 이상의 많은 특성을 가진 데이터 셋에는 잘 동작하지 않으며 특성값이 0이 많은 데이터셋이는 잘 작동하지 않습니다.
또한 예측이 느리고, 많은 특성을 처리하는 능력이 부족하여 현업에서는 잘 쓰지 않습니다.
KNeighborsRegressor와 KNeighborsClassifier의 객체를 생성할 때 'metric' parameter를 사용하여 거리 측정 방식을 변경할 수 있습니다. 'metric' parameter의 기본값은 'minkowski', 거듭제곱의 크기를 정하는 parameter느 'p'입니다.
metric='minkowski', p=2는 metric='euclidean'과 같습니다.



참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido


'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Lasso  (0) 2018.03.13
Ridge  (0) 2018.03.12
LinearRegression  (0) 2018.03.12
#!/usr/bin/env python3

k_NN(k-최근접 이웃)  Classifier[1]


분석을 위해 iris데이터를 로드합니다.

from sklearn.datasets import load_iris


iris = load_iris()



iris데이터의 형태는 다음의 코드로 확인할 수 있습니다.

print('''iris's key ==> {}'''.format(iris.keys()))

# iris's key ==> dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])


print('''iris's shape ==> {}'''.format(iris.data.shape))

# iris's shape ==> (150, 4)


print('''iris's data의 처음 6행 ==> \n{}'''.format(iris.data[:6]))

# iris's data의 처음 6행 ==> 

# [[5.1 3.5 1.4 0.2]

#  [4.9 3.  1.4 0.2]

#  [4.7 3.2 1.3 0.2]

#  [4.6 3.1 1.5 0.2]

#  [5.  3.6 1.4 0.2]

#  [5.4 3.9 1.7 0.4]]


print('''iris's feature names ==> \n{}'''.format(iris.feature_names))

# iris's feature names ==> 

# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']



머신러닝 데이터학습을 위해 데이터를 분할합니다. 이 방법은 앞으로도 계속 사용합니다.

from sklearn.model_selection import train_test_split


x_train, x_test, y_train, y_test = \

  train_test_split(iris.data, iris.target,

                   test_size=0.3, random_state=0)



이제 데이터를 분할했으니 머신러닝을 사용할 때입니다.

이번 포스팅에서는 가장 기본적인 KNN 최근접이웃 머신러닝을 사용합니다.

머신러닝 algorithm을 사용하기 위해서는 학습시킬 데이터를 fitting해야합니다.

from sklearn.neighbors import KNeighborsClassifier


# n_neighbors는 가장 가까운 이웃을 몇개를 고를지에 대한 parameter며

# n_jobs는 사용할 코어의 갯수 입니다. -1이면 모든 코어를 사용합니다.

knn = KNeighborsClassifier(n_neighbors=1, n_jobs=-1)

knn.fit(x_train, y_train)



sample data를 만들어 확인해보겠습니다.

import numpy as np


# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

x_sample = np.array([[5, 2.9, 1, 0.2]])

prediction = knn.predict(x_sample)

results = {p:n for p, n in zip(prediction, iris.target_names[prediction])}

print('sample test ==> {}'.format(results))

# sample test ==> {0: 'setosa'}

knn(n_neighbors=1)를 이용하여 sample test 예측했을 때는 'setosa'라고 결과를 냈습니다.



이제 위에서 분할한 test data로 예측하면

prediction = knn.predict(x_test)

results = [iris.target_names[p] for p in prediction]

print('results의 처음 6개 ==> {}'.format(results[:6]))

# results의 처음 6개 ==> ['virginica', 'versicolor', 'setosa', 'virginica', 'setosa', 'virginica']


bins = np.bincount(prediction)

count = {n:c for n, c in zip(iris.target_names, bins)}

print('test 결과의 빈도수 ==> {}'.format(count))

# test 결과의 빈도수 ==> {'setosa': 16, 'versicolor': 17, 'virginica': 12}



정확도는 2가지 방법으로 구할 수 있습니다.

KNeighborsClassifier의 score메소드를 이용하거나 직접 계산하는 방법입니다.

print('score 메소드 이용 ==> {:.3f}'.format(knn.score(x_test, y_test)))

# score 메소드 이용 ==> 0.978


y_pred = knn.predict(x_test)

print('numpy 이용 ==> {:.3f}'.format(np.mean(y_pred == y_test)))

# numpy 이용 ==> 0.978



훈련 데이터를 시각화 해보겠습니다.

pandas를 이용할 것이기 때문에 훈련 데이터를 DataFrame으로 변환하고

열이름은 featre_names를 사용하겠습니다.

import pandas as pd

import matplotlib.pyplot as plt

import matplotlib


matplotlib.rc('font', family='AppleGothic') # 한글출력

plt.rcParams['axes.unicode_minus'] = False # 축 - 표시


iris_df = pd.DataFrame(x_train, columns=iris.feature_names)

pd.scatter_matrix(iris_df,

                  c=y_train, # 색깔로 구분할 데이터

                  hist_kwds={'bins':30}, # 히스토그램

                  marker='o', # marker

                  s=20, # size

                  alpha=0.5) # 투명도

plt.show()


pandas를 이용한 scatter_matrix

이 그래프를 통해 훈련데이터의 개괄적인 정보를 한번에 파악할 수 있습니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido


'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Random Forest  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12

+ Recent posts