1。KNN原理

K-Nearest Neighbors

很簡單,看圖就一目瞭然了。

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

綠色和藍色是已知資料,根據已知資料,我們想要知道,紅色的點屬於哪一類。

這是,我們選擇的方法是:看距離紅色最近的一個點(K=1)是屬於哪一類,或者看距離紅色最近的兩個個點(K=1)或三個點(K=3)是屬於哪一類,此時,我們需要在這些點裡做投票,看看這個區域內,哪個顏色的點數量多。

我們以K=3為例來看:

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

在選擇距離紅色點最近的三個點作為參考時,綠色佔兩個,藍色佔一個,這是,我們就將紅色歸為綠色一類。

這也告訴我了我們,K在通常情況下要選擇奇數,否則很容易出現兩種情況數量相等的情況(如K為4,可能會出現兩藍兩綠的情況)

2。KNN演算法

KNN具體的實現方法

1。特徵工程,Feature Engineering,把物體用向量、矩陣、張量的形式表示出來

2。標記號:每個物體的標籤

3。計算兩個物體之間的距離,最常用的就是歐式距離:

d = \sqrt{(x_{1}-y_{1})^{2}+(x_{2}-y_{2})^{2}+(x_{3}-y_{3})^{2}+...}

4。選擇合適的K

首先,要理解什麼是決策邊界(非常重要):

決策邊界決定線性分類器和非線性分類器。

決策邊界不可以過於陡峭(過擬合)

看一個小例子

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

根據距離橙/綠點的距離,填充背景。那麼很明顯,在右圖我們可以看到清晰的決策邊界。

用交叉驗證方法(Cross Validation)選擇K:

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

將所有資料分為訓練資料(綠色)和測試資料(橙色),預設為75%和25%,可以自行調整。

交叉驗證是將訓練資料再次分配,我們以5折為例,就是說將交叉資料分成五份,每次都選取不同的資料作為驗證資料(藍色)。

首先驗證K=1

每一組不同的驗證資料都會得出一個準確度,求得五組準確度的平均值,就是K=1情況下的準確度。

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

同理,當K=3時,方法同上,求出平均準確度

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

求出兩個準確度之後,看哪一個準確度更高,說明哪一個K值取得好。當然在實際中,交叉驗證的不會只有K=1K=3兩個值,經常都是交叉驗證很多個K值,取其中準確度最高的為我們需要的K值。

當資料量少的時候,可以適當增加折數。

切記:不能用測試資料(橙色)來調參(K)!!!!!!!!

5。其他需要注意的地方

特徵的縮放:特徵中量綱差距過大,導致其中一個或幾個特徵在計算中基本起不到作用,這是我們需要特徵的縮放。方法如下:

線性歸一化(Min-Max-Normalization):一般情況Min=0,Max=1

公式為:

x_{new}=\frac{x-min(x)}{max(x)-min(x)}

標準差標準化(Z-Score-Normalization):

公式為:

x_{new}=\frac{x-mean(x)}{std(x)}

,其中,mean(x)為平均值,std(x)為標準差

3。KNN程式碼

詳細請看註釋

1。 呼叫KNN函式來實現分類

資料採用的是經典的iris資料,是三分類問題

# 讀取相應的庫

from

sklearn

import

datasets

#sklearn是自帶的資料

from

sklearn。model_selection

import

train_test_split

#訓練測試分類

from

sklearn。neighbors

import

KNeighborsClassifier

#KNN模型

import

numpy

as

np

# 讀取資料 X, y

iris

=

datasets

load_iris

()

#讀取資料

X

=

iris

data

#四維向量,特徵

y

=

iris

target

#分類:三分類,結果為0,1,2。要拖到結果的最下面才能看到

print

X

y

#列印資料

[[

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

4。6

3。4

1。4

0。3

5。

3。4

1。5

0。2

4。4

2。9

1。4

0。2

4。9

3。1

1。5

0。1

5。4

3。7

1。5

0。2

4。8

3。4

1。6

0。2

4。8

3。

1。4

0。1

4。3

3。

1。1

0。1

5。8

4。

1。2

0。2

5。7

4。4

1。5

0。4

5。4

3。9

1。3

0。4

5。1

3。5

1。4

0。3

5。7

3。8

1。7

0。3

5。1

3。8

1。5

0。3

5。4

3。4

1。7

0。2

5。1

3。7

1。5

0。4

4。6

3。6

1。

0。2

5。1

3。3

1。7

0。5

4。8

3。4

1。9

0。2

5。

3。

1。6

0。2

5。

3。4

1。6

0。4

5。2

3。5

1。5

0。2

5。2

3。4

1。4

0。2

4。7

3。2

1。6

0。2

4。8

3。1

1。6

0。2

5。4

3。4

1。5

0。4

5。2

4。1

1。5

0。1

5。5

4。2

1。4

0。2

4。9

3。1

1。5

0。2

5。

3。2

1。2

0。2

5。5

3。5

1。3

0。2

4。9

3。6

1。4

0。1

4。4

3。

1。3

0。2

5。1

3。4

1。5

0。2

5。

3。5

1。3

0。3

4。5

2。3

1。3

0。3

4。4

3。2

1。3

0。2

5。

3。5

1。6

0。6

5。1

3。8

1。9

0。4

4。8

3。

1。4

0。3

5。1

3。8

1。6

0。2

4。6

3。2

1。4

0。2

5。3

3。7

1。5

0。2

5。

3。3

1。4

0。2

7。

3。2

4。7

1。4

6。4

3。2

4。5

1。5

6。9

3。1

4。9

1。5

5。5

2。3

4。

1。3

6。5

2。8

4。6

1。5

5。7

2。8

4。5

1。3

6。3

3。3

4。7

1。6

4。9

2。4

3。3

1。

6。6

2。9

4。6

1。3

5。2

2。7

3。9

1。4

5。

2。

3。5

1。

5。9

3。

4。2

1。5

6。

2。2

4。

1。

6。1

2。9

4。7

1。4

5。6

2。9

3。6

1。3

6。7

3。1

4。4

1。4

5。6

3。

4。5

1。5

5。8

2。7

4。1

1。

6。2

2。2

4。5

1。5

5。6

2。5

3。9

1。1

5。9

3。2

4。8

1。8

6。1

2。8

4。

1。3

6。3

2。5

4。9

1。5

6。1

2。8

4。7

1。2

6。4

2。9

4。3

1。3

6。6

3。

4。4

1。4

6。8

2。8

4。8

1。4

6。7

3。

5。

1。7

6。

2。9

4。5

1。5

5。7

2。6

3。5

1。

5。5

2。4

3。8

1。1

5。5

2。4

3。7

1。

5。8

2。7

3。9

1。2

6。

2。7

5。1

1。6

5。4

3。

4。5

1。5

6。

3。4

4。5

1。6

6。7

3。1

4。7

1。5

6。3

2。3

4。4

1。3

5。6

3。

4。1

1。3

5。5

2。5

4。

1。3

5。5

2。6

4。4

1。2

6。1

3。

4。6

1。4

5。8

2。6

4。

1。2

5。

2。3

3。3

1。

5。6

2。7

4。2

1。3

5。7

3。

4。2

1。2

5。7

2。9

4。2

1。3

6。2

2。9

4。3

1。3

5。1

2。5

3。

1。1

5。7

2。8

4。1

1。3

6。3

3。3

6。

2。5

5。8

2。7

5。1

1。9

7。1

3。

5。9

2。1

6。3

2。9

5。6

1。8

6。5

3。

5。8

2。2

7。6

3。

6。6

2。1

4。9

2。5

4。5

1。7

7。3

2。9

6。3

1。8

6。7

2。5

5。8

1。8

7。2

3。6

6。1

2。5

6。5

3。2

5。1

2。

6。4

2。7

5。3

1。9

6。8

3。

5。5

2。1

5。7

2。5

5。

2。

5。8

2。8

5。1

2。4

6。4

3。2

5。3

2。3

6。5

3。

5。5

1。8

7。7

3。8

6。7

2。2

7。7

2。6

6。9

2。3

6。

2。2

5。

1。5

6。9

3。2

5。7

2。3

5。6

2。8

4。9

2。

7。7

2。8

6。7

2。

6。3

2。7

4。9

1。8

6。7

3。3

5。7

2。1

7。2

3。2

6。

1。8

6。2

2。8

4。8

1。8

6。1

3。

4。9

1。8

6。4

2。8

5。6

2。1

7。2

3。

5。8

1。6

7。4

2。8

6。1

1。9

7。9

3。8

6。4

2。

6。4

2。8

5。6

2。2

6。3

2。8

5。1

1。5

6。1

2。6

5。6

1。4

7。7

3。

6。1

2。3

6。3

3。4

5。6

2。4

6。4

3。1

5。5

1。8

6。

3。

4。8

1。8

6。9

3。1

5。4

2。1

6。7

3。1

5。6

2。4

6。9

3。1

5。1

2。3

5。8

2。7

5。1

1。9

6。8

3。2

5。9

2。3

6。7

3。3

5。7

2。5

6。7

3。

5。2

2。3

6。3

2。5

5。

1。9

6。5

3。

5。2

2。

6。2

3。4

5。4

2。3

5。9

3。

5。1

1。8

]]

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

2

# 把資料分成訓練資料和測試資料

X_train

X_test

y_train

y_test

=

train_test_split

X

y

random_state

=

2003

#2003是種子點,確保每次的訓練資料和測試資料是一樣的,如果不選種子點,每次生成的資料不一樣,無法判斷我們的訓練結果是否準確

# 構建KNN模型, K值為3、 並做訓練

clf

=

KNeighborsClassifier

n_neighbors

=

3

clf

fit

X_train

y_train

#fit函式,相當於把資料儲存下來,記憶體分配,不對資料進行訓練

KNeighborsClassifier

algorithm

=

‘auto’

leaf_size

=

30

metric

=

‘minkowski’

metric_params

=

None

n_jobs

=

None

n_neighbors

=

3

p

=

2

weights

=

‘uniform’

# 計算準確率

from

sklearn。metrics

import

accuracy_score

correct

=

np

count_nonzero

((

clf

predict

X_test

==

y_test

==

True

#accuracy_score(y_test, clf。predict(X_test))

print

“Accuracy is:

%。3f

%

correct

/

len

X_test

)))

Accuracy

is

0。921

2。從零開始自己寫一個KNN演算法

from

sklearn

import

datasets

from

collections

import

Counter

# 為了做投票

from

sklearn。model_selection

import

train_test_split

import

numpy

as

np

# 匯入iris資料

iris

=

datasets

load_iris

()

X

=

iris

data

y

=

iris

target

X_train

X_test

y_train

y_test

=

train_test_split

X

y

random_state

=

2003

def

euc_dis

instance1

instance2

):

“”“

計算兩個樣本instance1和instance2之間的歐式距離

instance1: 第一個樣本, array型

instance2: 第二個樣本, array型

”“”

# TODO

dist

=

np

sqrt

sum

((

instance1

-

instance2

**

2

))

return

dist

def

knn_classify

X

y

testInstance

k

):

“”“

給定一個測試資料testInstance, 透過KNN演算法來預測它的標籤。

X: 訓練資料的特徵

y: 訓練資料的標籤

testInstance: 測試資料,這裡假定一個測試資料 array型

k: 選擇多少個neighbors?

”“”

# TODO 返回testInstance的預測標籤 = {0,1,2}

#時間複雜度 O(N): N:number of samples

distances

=

euc_dis

x

testInstance

for

x

in

X

#若N很大,計算歐式距離消耗的測試時間非常大的時間,take forever~ (KNN的缺點)

#argsort: O(NlogN)

#如何最佳化? priority queue O(NlogK)

kneighbors

=

np

argsort

distances

)[:

k

count

=

Counter

y

kneighbors

])

#print(count)可以顯示出來每個樣本出現了多少次

return

count

most_common

()[

0

][

0

#取出出現最多的值

# 預測結果。

predictions

=

knn_classify

X_train

y_train

data

3

for

data

in

X_test

correct

=

np

count_nonzero

((

predictions

==

y_test

==

True

#accuracy_score(y_test, clf。predict(X_test))

print

“Accuracy is:

%。3f

%

correct

/

len

X_test

)))

Accuracy

is

0。921

3。KNN的決策邊界

import

matplotlib。pyplot

as

plt

import

numpy

as

np

from

itertools

import

product

from

sklearn。neighbors

import

KNeighborsClassifier

# 生成一些隨機樣本

n_points

=

100

X1

=

np

random

multivariate_normal

([

1

50

],

[[

1

0

],[

0

10

]],

n_points

X2

=

np

random

multivariate_normal

([

2

50

],

[[

1

0

],[

0

10

]],

n_points

X

=

np

concatenate

([

X1

X2

])

y

=

np

array

([

0

*

n_points

+

1

*

n_points

print

X

shape

y

shape

200

2

200

,)

# KNN模型的訓練過程

clfs

=

[]

neighbors

=

1

3

5

9

11

13

15

17

19

for

i

in

range

len

neighbors

)):

clfs

append

KNeighborsClassifier

n_neighbors

=

neighbors

i

])

fit

X

y

))

# 視覺化結果

x_min

x_max

=

X

[:,

0

min

()

-

1

X

[:,

0

max

()

+

1

y_min

y_max

=

X

[:,

1

min

()

-

1

X

[:,

1

max

()

+

1

xx

yy

=

np

meshgrid

np

arange

x_min

x_max

0。1

),

np

arange

y_min

y_max

0。1

))

#print(xx,yy),瞭解meshgrid函式

f

axarr

=

plt

subplots

3

3

sharex

=

‘col’

sharey

=

‘row’

figsize

=

15

12

))

for

idx

clf

tt

in

zip

product

([

0

1

2

],

0

1

2

]),

clfs

‘KNN (k=

%d

)’

%

k

for

k

in

neighbors

]):

Z

=

clf

predict

np

c_

xx

ravel

(),

yy

ravel

()])

Z

=

Z

reshape

xx

shape

axarr

idx

0

],

idx

1

]]

contourf

xx

yy

Z

alpha

=

0。4

axarr

idx

0

],

idx

1

]]

scatter

X

[:,

0

],

X

[:,

1

],

c

=

y

s

=

20

edgecolor

=

‘k’

axarr

idx

0

],

idx

1

]]

set_title

tt

plt

show

()

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

#K=1 不平緩,陡峭,不穩定

#K越大,決策邊界越平滑smooth

4。KNN迴歸

import

pandas

as

pd

import

matplotlib

import

matplotlib。pyplot

as

plt

import

numpy

as

np

import

seaborn

as

sns

#預測二手車價格

#讀取資料

df

=

pd

read_csv

‘data。csv’

df

# data frame

#清洗資料

# 把顏色獨熱編碼

df_colors

=

df

‘Color’

str

get_dummies

()

add_prefix

‘Color: ’

# 把型別獨熱編碼

df_type

=

df

‘Type’

apply

str

str

get_dummies

()

add_prefix

‘Type: ’

# 新增獨熱編碼資料列

df

=

pd

concat

([

df

df_colors

df_type

],

axis

=

1

# 去除獨熱編碼對應的原始列

df

=

df

drop

([

‘Brand’

‘Type’

‘Color’

],

axis

=

1

df

# 資料轉換

matrix

=

df

corr

()

f

ax

=

plt

subplots

figsize

=

8

6

))

sns

heatmap

matrix

square

=

True

plt

title

‘Car Price Variables’

Text

0。5

1。0

‘Car Price Variables’

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

#sns。pairplot(df[[‘Construction Year’, ‘Days Until MOT’, ‘Odometer’, ‘Ask Price’]], size=2)

#plt。show()

from

sklearn。neighbors

import

KNeighborsRegressor

from

sklearn。model_selection

import

train_test_split

from

sklearn

import

preprocessing

from

sklearn。preprocessing

import

StandardScaler

import

numpy

as

np

X

=

df

[[

‘Construction Year’

‘Days Until MOT’

‘Odometer’

]]

y

=

df

‘Ask Price’

values

reshape

-

1

1

X_train

X_test

y_train

y_test

=

train_test_split

X

y

test_size

=

0。3

random_state

=

41

X_normalizer

=

StandardScaler

()

# N(0,1)

X_train

=

X_normalizer

fit_transform

X_train

X_test

=

X_normalizer

transform

X_test

y_normalizer

=

StandardScaler

()

y_train

=

y_normalizer

fit_transform

y_train

y_test

=

y_normalizer

transform

y_test

knn

=

KNeighborsRegressor

n_neighbors

=

2

#K=2

knn

fit

X_train

y_train

ravel

())

#Now we can predict prices:

y_pred

=

knn

predict

X_test

y_pred_inv

=

y_normalizer

inverse_transform

y_pred

y_test_inv

=

y_normalizer

inverse_transform

y_test

# Build a plot

plt

scatter

y_pred_inv

y_test_inv

plt

xlabel

‘Prediction’

plt

ylabel

‘Real value’

# Now add the perfect prediction line

diagonal

=

np

linspace

500

1500

100

plt

plot

diagonal

diagonal

‘-r’

plt

xlabel

‘Predicted ask price’

plt

ylabel

‘Ask price’

plt

show

()

print

y_pred_inv

機器學習入門(2)KNN原理與KNN迴歸(附程式碼)

[1199。 1199。 700。 899。]

knn

KNeighborsRegressor(algorithm=‘auto’, leaf_size=30, metric=‘minkowski’,

metric_params=None, n_jobs=None, n_neighbors=2, p=2,

weights=‘uniform’)

pred = knn。predict(X_test)

pred

array([ 1。36676513, 1。36676513, -0。68269804, 0。13462294])

from sklearn。metrics import mean_absolute_error

mean_absolute_error(y_pred_inv, y_test_inv)

175。5

from sklearn。metrics import mean_squared_error

mean_squared_error(y_pred_inv, y_test_inv)

56525。5

y_pred_inv

array([1199。, 1199。, 700。, 899。])

y_test_inv

array([[1300。],

[1650。],

[ 650。],

[ 799。]])

如果有興趣,可以關注我的公眾號(圈圈小姐),程式設計小白不定期分享自己的學習成果(以及生活旅行和德語小知識點),大家一起進步~~