본문 바로가기
머신러닝 딥러닝

0910 k-nearest Neighbor (KNN) 'K - 최근접 이웃'

by 대금부는개발자 2021. 9. 10.
SMALL

0910 k-nearest Neighbor (KNN)  'K - 최근접 이웃'

상당히 간단한 machine learning 알고리즘

NN 앞에 K(숫자)로 몇 개의 이웃이 있는지 정해줘요.

그림에서 지정된 범위의 이웃 중 어떤 색이 더 많은지 분류해서 색을 결정.

KNN은 학습과정이 없어요→  model based learning이 아니에요.

KNN → instance based learning(lazy model)

 

그러면 regression 경우(모델이 연속적인 값을 예측) 예측할 수 있나요?? 이것도 가능해요!!

 

단점(어려운 점)

1. K값을 어떻게 설정?

최적의 k값이 어떤 값인지 구할 계산식이 없어서 몰라요 → 찾아야 해요

 

2. 거리측정은 어떻게 할까? 

1) 최단거리 직선 →  유클리디안 거리(Euclidean Distance) 

2) 직선(사선은 x) →  맨해튼 거리(Manhattan distance)

3) 분산과 공분산 이용 → 마할라노비스 거리(Mahalanobis distance)

 

알아내기 위해 노동집약적 작업이 필요!

 

KNN의 약점

모든 점에 대한 거리를 다 계산해야 해요. → 계산량이 많아요(속도가 느려요)

 

현업에서 쓰나요?? 많이 써요!!

k=1 인경우 성능이 좋아요.

 

코드로 알아보아요!

 

import numpy as np

import pandas as pd

from scipy import stats  # zscore을 이용한 이상치 검출 작업을 위해 사용

from sklearn.neighbors import KNeighborsRegressor # ozone량의 NaN값을 예측하기 위해서

from sklearn.preprocessing import MinMaxScaler # Normalization 처리를 위해

import warnings

warnings.filterwarnings(action='ignore')   # warning 출력되지 않게 설정

# from sklearn.model_selection import  train_test_split 

# keras로 구현하기 때문에 keras의 train, validation 분리 기능을 이용해서 학습할 거예요!



# 1.raw data loading

df =pd.read_csv('/content/drive/MyDrive/ozone/ozone.csv')

# display(df)

 

x_data = df[['Solar.R''Wind''Temp']]   #df

t_data = df['Ozone']                       #Series

 

# 2. 독립변수에 대한 결측치를 찾아내서 각 column의 median 값으로 대체

# x_data.columns  리스트 형태로 나와요

# nanmedian 결치를 제거하고 나머지 값에 대한 중윗값을 알려줘요!

# [x_data[col].isnull()],해당 칼럼에 대한 인덱싱

for col in x_data.columns:   #모든 칼럼에 대해 반복 처리

  col_median = np.nanmedian(x_data[col]) # 각 column의 NaN을 제외한 중윗값을 알아내요!

  x_data[col].loc[x_data[col].isnull()] = col_median  # column에 대한 nan column만 뽑아요, 거기의 값을 중윗값으로 세팅

 

# 3. 독립변수에 이상치를 검출해서 mean으로 처리할 거예요!  

zscore_threshold=1.8

# outlier 빼고 나머지 값들의 평균을 구해 outlier 대체

for col in x_data.columns:

  outlier=x_data[col][np.abs(stats.zscore(x_data[col])) > zscore_threshold]

  col_mean = np.mean(x_data.loc[~x_data[col].isin(outlier), col])

  # print(col_mean)

  x_data.loc[x_data[col].isin(outlier), col] = col_mean

 

# 4. 종속변수에 대한 이상치는 mean으로 처리할 거예요! 

#    => 오존 예제에서 종속변수에 대한 이상치는 없어요!     



# 5. 정규화 처리를 먼저 진행

scaler_x = MinMaxScaler()

scaler_t = MinMaxScaler()

 

scaler_x.fit(x_data.values)

scaler_t.fit(t_data.values.reshape(-1,1))   #fit() 함수는 인자로 2차원 데이터가 들어가야 해요!

 

x_data_norm = scaler_x.transform(x_data)

t_data_norm = scaler_t.transform(t_data.values.reshape(-1,1)).ravel() 

#label은 1차원이기 때문에 정규화를 위해 차원 변환, 정규화 끝나고 다시 1차원으로

 

# 6. 종속변수에 대한 결측치 처리를 KNN을 이용한 Imputation으로 처리해요.

# KNN을 학습해야 하니까 train data와 label data에서 nan을 제외하고 가져와야 해요!

# np.isnan(t_data_norm) NaN만 true로 나와요 우리는 NaN이 아닌 게 필요. 종속변수에 NaN을 뺄 거예요! ~

# 행에 대해 boolean indexing을 하니까 NaN이 아닌 학습용 데이터만 나와요.

train_x_data_norm = x_data_norm[~np.isnan(t_data_norm)]

train_t_data_norm = t_data_norm[~np.isnan(t_data_norm)]

 

knn_regressor = KNeighborsRegressor(n_neighbors=2)     # Regressor이니 때문에 홀수 짝수 상관없어요.

knn_regressor.fit(train_x_data_norm,train_t_data_norm) # KNN 모델 완성

 

# NNN을 이용해서 prediction(종속변수가 NaN인 것들에 대해)

knn_predict = knn_regressor.predict(x_data_norm[np.isnan(t_data_norm)])

t_data_norm[np.isnan(t_data_norm)] = knn_predict

 

x_data_norm

t_data_norm


array([0.23952096, 0.20958084, 0.06586826, 0.10179641, 0.08383234,

...

0.07784431, 0.10179641, 0.11377246])

 

# 기존에도 ozone data를 이용해서 python구현, sklearn구현, tensorflow구현을 다 했었어요!

# sklearn의 결과와 약간 다른 예측치를 보인 걸로 기억해요!

 

from sklearn.linear_model import LinearRegression

from tensorflow.keras import Sequential

from tensorflow.keras.layers import  Flatten, Dense

from tensorflow.keras.optimizers import SGD

 

test_data = [[3101580]]   # Solar.R, Wind, Temp

 

# sklearn 구현

model = LinearRegression()

model.fit(x_data_norm,t_data_norm)

result = model.predict(scaler_x.transform(test_data))    # 1차원

 

print(scaler_t.inverse_transform(result.reshape(-1,1)))  # 2차원 변형 

#[[38.75927452]]



# tensorflow 2.x 구현

keras_model = Sequential()

 

#input_shape=() 들어오는 독립변수 입력

keras_model.add(Flatten(input_shape=(3,)))

keras_model.add(Dense(1, activation='linear')) #output layer

 

keras_model.compile(optimizer=SGD(learning_rate=1e-2),

                    loss ='mse'#설정

 

keras_model.fit(x_data_norm,

                t_data_norm,

                epochs=5000,

                verbose=0)

keras_result = keras_model.predict(scaler_x.transform(test_data))

 

print(scaler_t.inverse_transform(keras_result.reshape(-1,1)))

#[[38.598263]] sklearn과 거의 비슷해요.





 

 

LIST

'머신러닝 딥러닝' 카테고리의 다른 글

0914 MNIST_ keras  (0) 2021.09.14
0914 titanic_keras  (0) 2021.09.14
0910 Regression 정리  (0) 2021.09.10
0909 Tensor flow 2.x, keras in tensor 2.x  (0) 2021.09.09
0909 multinomial classification - MNIST  (0) 2021.09.09

댓글