ML) KNN - K-Nearest Neighbor Regression

dothouse·2024년 1월 31일
0

ML

목록 보기
2/9

0. K-Nearest Neighbor Regression

  • 주변의 가장 가까운 K개의 샘플을 통해 값을 예측하는 방식이다.

  • 가장 간단한 방식으로는 K개 샘플의 평균을 통해 예측

  • knn과의 차이
    -> KNN은 클래스로 분류 / K-NN Regression(K-최근접 이웃 회귀)은 '숫자'를 가지고 예측

1. 분석준비

✅ 모델의 score -> R2R^2

  • 기본적으로 회귀모델이기 때문에 두 변수간의 설명력은 R2R^2(결정계수)로

1) 기본

import numpy as np
import matplotlib.pyplot as plt


from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split

from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

iris = load_iris()
iris['feature_names']

iris = iris.data[:, ::2]

iris.data[:, ::2] -> sepal length (cm), petal length (cm)

2) train / test set 나누기


X_train, X_test, y_train, y_test = train_test_split(iris[:,0], iris[:, 1], test_size=0.25)

print(X_train.shape, y_train.shape)

(112, ) (112,) 이 형태는 1차원 형태
scikit-learn은 2차원 형태가 필요해서 2차원으로 reshape

X_train = X_train.reshape(-1,1)
y_train = y_train.reshape(-1,1)
X_test = X_test.reshape(-1,1)
y_test = y_test.reshape(-1,1)

print(X_train.shape, y_train.shape)

(112, 1) (112, 1)

2. 분석

1) 표준화 이전


knr.fit(X_train, y_train)
knr.score(X_train, y_train)

-> 0.8550470788787142

knr.fit(X_train, y_train)
knr.score(X_test, y_test)
- >0.6902890455963961
  • mae (mean_absolute_error) 계산
from sklearn.metrics import mean_absolute_error

test_prediction = knr.predict(X_test)
# 테스트 세트에 대한 평균 절댓값 오차를 계산
mae = mean_absolute_error(y_test, test_prediction)
print(mae)
# -> 0.6342105263157893

2) 표준화

knr_zscore = Pipeline([('scaler', StandardScaler()),
                      ('knn', KNeighborsRegressor(n_neighbors = 3))])
    
    
knr_zscore.fit(X_train, y_train)
knr_zscore.score(X_train, y_train)             
# -> 0.8544279810124895

knr_zscore.fit(X_train, y_train)
knr_zscore.score(X_test, y_test)
# -> 0.6902890455963961

test_prediction = knr_zscore.predict(X_test)
# 테스트 세트에 대한 평균 절댓값 오차를 계산합니다
mae = mean_absolute_error(y_test, test_prediction)
print(mae)
# -> 0.6342105263157893

✅ 표준화 이전과 표준화 한 R2R^2 / mae 값의 변화는 없다

  • 표준화를 하더라도 scale만 변한 것이지, 두 변수간의 관계의 변화는 없기 때문

3. 모델평가하기

from sklearn.metrics import mean_squared_error, r2_score
knr.n_neighbors = 5
knr.fit(X_train, y_train)
knr.score(X_train, y_train)

y_pred = knr.predict(X_test)
print("Mean Squared Error:", mean_squared_error(y_test, y_pred))
print("R-squared:", r2_score(y_test, y_pred))

모델 결과
Mean Squared Error: 0.8336736842105261
R-squared: 0.6902890455963961

1) MSE - Mean Squared Error

  • MSE는 예측값과 실제값의 차이(error)를 제곱한 값들의 평균
  • MSE 값이 작을수록 예측 정확도가 높다

2) R2R^2 - 결정계수

  • 0 ~ 1의 값을 지니며, 1에 가까울수록 모델의 설명력이 높다.
  • 이 모델이 전체 분산의 약 69%를 설명한다.

3) train set / test set 비교하기

R2R^2
train_set -> 0.8550470788787142
test_set -> 0.6902890455963961

✅ Train-set이 Test-set에 비해 score가 높다

이는 과적합(overfitting)이 의심된다.
-> k 값을 변화시켜서 다시 모델 훈련 필요

4. GridSearchCV


from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV

k_range = np.arange(2,30)

pipeline = Pipeline([('scaler', StandardScaler()),
                    ('knr', KNeighborsRegressor())])

params = {
    'knr__n_neighbors':k_range
}

gs = GridSearchCV(pipeline,
                 param_grid=params,
                 scoring='r2', #regression 에서는 r2
                 cv=5, # cv = fold 수 / default = 3
                 n_jobs=-1)

gs.fit(X_train, y_train)

print('params', gs.best_params_)
print('score', gs.best_score_)
print('estimator', gs.best_estimator_)

✅ 결과값
params-> {'knr__n_neighbors': 25}
score -> 0.8130095429239035

-> k = 25로 바꿔서

5. hyperparmeter 변경


final_k = gs.best_params_['knr__n_neighbors']


knr.n_neighbors = final_k
knr.fit(X_train, y_train)
knr.score(X_train, y_train)
knr.score(X_test, y_test)

test_prediction = knr.predict(X_test)
mae = mean_absolute_error(y_test, test_prediction)
print(mae)

knr.score(X_train, y_train) -> 0.7953232963290435
knr.score(X_test, y_test) -> 0.7784565830389936

train-settest-set의 score 차이 감소

R2R^2 값이 낮은 문제

  • 앞으로 reqularization 공부하고, 모델 적합도를 올려보자
profile
새로운 길

0개의 댓글