1. 程式人生 > >Python高階--K-近鄰演算法(KNN)

Python高階--K-近鄰演算法(KNN)

K nearest neighbour
K-近鄰演算法採用測量不同特徵值之間的距離方法進行分類。
優點:精度高、對異常值不敏感、無資料輸入假定。
缺點:時間複雜度高、空間複雜度高。
適用資料範圍:數值型和標稱型。

這裡寫圖片描述

一、K-近鄰演算法(KNN)舉例

這裡寫圖片描述

1)工作原理

存在一個樣本資料集合,也稱作訓練樣本集,並且樣本集中每個資料都存在標籤,即我們知道樣本集中每一資料

與所屬分類的對應關係。輸人沒有標籤的新資料後,將新資料的每個特徵與樣本集中資料對應的
特徵進行比較,然後演算法提取樣本集中特徵最相似資料(最近鄰)的分類標籤。一般來說,我們
只選擇樣本資料集中前K個最相似的資料,這就是K-近鄰演算法中K的出處,通常*K是不大於20的整數。
最後 ,選擇K個最相似資料中出現次數最多的分類,作為新資料的分類*。

2)演算法例項

回到前面電影分類的例子,使用K-近鄰演算法分類愛情片和動作片。有人曾經統計過很多電影的打鬥鏡頭和接吻鏡頭,下圖顯示了6部電影的打鬥和接吻次數。假如有一部未看過的電影,如何確定它是愛情片還是動作片呢?我們可以使用K-近鄰演算法來解決這個問題。
這裡寫圖片描述

首先我們需要知道這個未知電影存在多少個打鬥鏡頭和接吻鏡頭,上圖中問號位置是該未知電影出現的鏡頭數圖形化展示,具體數字參見下表。

這裡寫圖片描述

即使不知道未知電影屬於哪種型別,我們也可以通過某種方法計算出來。首先計算未知電影與樣本集中其他電影的距離,如圖所示。這裡寫圖片描述

現在我們得到了樣本集中所有電影與未知電影的距離,按照距離遞增排序,可以找到K個距
離最近的電影。假定k=3,則三個最靠近的電影依次是California Man、He’s Not Really into Dudes、Beautiful Woman。K-近鄰演算法按照距離最近的三部電影的型別,決定未知電影的型別,而這三部電影全是愛情片,因此我們判定未知電影是愛情片。

3)歐幾里得距離(Euclidean Distance)

歐氏距離是最常見的距離度量,衡量的是多維空間中各個點之間的絕對距離。公式如下:
這裡寫圖片描述

二、在scikit-learn庫中使用k-近鄰演算法

  • 分類問題:from sklearn.neighbors import KNeighborsClassifier

  • 迴歸問題:from sklearn.neighbors import KNeighborsRegressor

三、簡單示例(分類)

給出一組資料(身高、體重、鞋子尺碼)判斷性別

分析:這是一個使用K-臨近演算法(KNN)的分類問題

1)建立訓練資料(特徵和結果)

1.訓練樣本的特徵

注意:這裡的特徵需要和結果一一對應

'''
X_train:訓練樣本的特徵(一列值)
y_train:訓練樣本的結果(標籤)
'''
# 傳入訓練資料  
#  身高,體重, 鞋碼
X_train = np.array([
    [177,73,42],
    [150,44,36],
    [177,63,41],
    [160,52,35],
    [165,70,40],
    [179,80,44],
    [156,40,36],
    [155,50,36]
])
# 一一傳入訓練資料的樣本結果
y_train = np.array(['male','female','male','female','male','male','female','female'])

2)建立 獲取分類的模型

KNeighborsClassifier(n_neighbors=5)
功能:實現k近鄰投票的分類器。

# n_neighbors:獲取最近的幾個  預設是5個
knn_c = KNeighborsClassifier(n_neighbors=5)

3)模型訓練

knn.fit(X, y)
功能:將訓練資料的特徵和結果傳入進行訓練
以X為訓練資料,y為目標值 擬合模型

'''
引數 X 是訓練資料的特徵
引數 y 是訓練資料的結果(標籤)
'''
knn_c.fit(X_train,y_train)

4)模型測試

knn.predict(X)
功能:通過訓練好的模型將測試資料傳入,返回測試結果
為提供的資料預測類標籤

knn_c.predict([
    [190,100,45],
    [150,35,32]
])

array(['male', 'female'], dtype='<U6')

5)得出結果

返回測試結果與實際資料符合實際情況,這就是K-近鄰演算法(KNN)處理分類問題

四、機器學習–鳶尾花(分類)

機器學習常用庫sklearn

scikit-learning 提供資料樣本,可以供我們研究機器學習模型

# 機器學習裡面包含的資料集
from sklearn import datasets

1)獲取訓練資料(特徵和結果)

使用load方法載入資料可以載入很多可供我們使用的資料
這裡我們使用鳶尾花資料

iris_data = datasets.load_iris()
iris_data

#這裡返回資料較多,我們拿出部分分析
# data:鳶尾花樣本,該樣本有四個特徵,表示 花萼長度 花萼寬度 花瓣長度 花瓣寬度
# target:表示鳶尾花的種類 0(setosa) 1(versicolor) 2(virginica)
{'data': array([[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],
        。。。
        [6.5, 3. , 5.2, 2. ],
        [6.2, 3.4, 5.4, 2.3],
        [5.9, 3. , 5.1, 1.8]]),
 'target': array([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]),}
        #還有一些描述的資訊

我們獲取的iris_data是一個字典型別的資料

1. 獲取訓練樣本特徵

data = iris_data.data        #訓練樣本的值
feature = iris_data.feature_names  #訓練樣本的值對應的名稱

2. 獲取訓練樣本結果

target = iris_data.target  # 所有樣本的目標值
target_names = iris_data.target_names  # 目標值對應的名稱

3. 將得到的資料繪製圖形

DataFrame(data).plot()

這裡寫圖片描述

畫圖研究前兩個特徵和分類之間的關係

(二維散點圖只能展示兩個維度)

1、這裡擷取前兩個特徵來展示

X_train = data[:,0:2]  # 訓練樣本的特徵
y_train = target  # 訓練樣本的結果
#目前取得樣本特徵和結果依舊是一一對應的關係

2、展示特徵和結果之間的關係

花萼長度為x, 花萼寬度為y 對所有樣本進行定位

我們使用點的顏色對其進行分類,散點圖引數c可以傳入一個數組,陣列我們可以用樣本的值使傳入的x, y對應的點得顏色與值一一對應,這樣就將圖中的點分為三類區分開

plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.xlabel('sepal length')  #設定x軸的標籤
plt.ylabel('sepal width')  #設定y軸的標籤

這裡寫圖片描述

2)建立 獲取分類的模型

建立分類模型

knn_c = KNeighborsClassifier(n_neighbors=5)

3)模型訓練

將訓練資料樣本特徵和結果放入模型訓練

knn_c.fit(X_train,y_train)

4)模型測試

將測試資料傳入訓練模型,返回訓練結果

knn_c.predict([
    [4.5,4.0],
    [7.5,3.0],
    [5.25,2.25]
])

array([0, 2, 1])

4)測試結果分析

測試資料的預測結果與實際結果相同

5)創造測試資料,測試模型結果

1、創造測試資料

先取到x軸線的範圍和y軸的範圍取到

# 為了全面,將資料的範圍稍微擴大一點
xmin = X_train[:,0].min()-0.5   
xmax = X_train[:,0].max()+0.5
ymin = X_train[:,1].min()-0.5
ymax = X_train[:,1].max()+0.5

將x軸的資料和y軸的資料每隔 0.01 取一份

# x軸範圍內要取遍
x = np.arange(xmin,xmax,0.01)
# y軸範圍內也要取遍
y = np.arange(ymin,ymax,0.01)
#我們拿到座標軸的資料之後,我們要拿到每個點的座標

拿到每個點對應的x,y座標

xx,yy = np.meshgrid(x,y)     # 將畫布上所有的點取遍

這裡寫圖片描述

xx.flatten(),yy.flatten()    # 將矩陣扁平化

(array([3.8 , 3.81, 3.82, ..., 8.38, 8.39, 8.4 ]),
 array([1.5, 1.5, 1.5, ..., 4.9, 4.9, 4.9]))

這裡寫圖片描述

# 把對應位置的兩個內容取出來 變成新的列表
X_test = np.c_[xx.flatten(),yy.flatten()] # 將平面上所有的點取遍 並 用來作為測試資料

array([[3.8 , 1.5 ],
       [3.81, 1.5 ],
       [3.82, 1.5 ],
       ...,
       [8.38, 4.9 ],
       [8.39, 4.9 ],
       [8.4 , 4.9 ]])

這裡寫圖片描述

2、使用剛剛訓練好的模型進行預測

y_ = knn_c.predict(X_test)  #預測後返回預測結果值

3、繪製測試結果圖形

根據特徵繪製樣本的兩個特徵 X_test[:,0],X_test[:,1]
根據模型預測的結果 y_
繪製樣本的顏色


plt.scatter(X_test[:,0],X_test[:,1],c=y_) 

這裡寫圖片描述

4、將訓練資料和自己建立的測試資料作比較

把真實的訓練資料也畫到圖上

plt.scatter(X_test[:,0],X_test[:,1],c=y_)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cmap0) #這裡的cmap給color設定顏色

這裡寫圖片描述

5、為影象制定顏色

需要匯入

from matplotlib.colors import ListedColormap
cmap0 = ListedColormap(['red','green','blue'])
# 將cmap0傳入上面的圖的效果

五、預測趨勢(迴歸)

導包

from sklearn.neighbors import KNeighborsRegressor

1)生成訓練樣本資料

1、種子生成器

功能:固定隨機數,多次執行,產生相同的隨機數
np.random.seed(0)

np.random.seed(0)
np.random.random()
nd = np.random.rand(40,1)  #  樣本 40行1列
nd

2、對生成的訓練資料排序np.sort

np.sort() 預設對最內層的資料進行排序 現在要對每一行進行排序 讓樣本從小到大排列
設定 np.sort(nd,axis=0)

對nd進行排序 然後放大5倍數

X_train = 5*np.sort(nd,axis=0)

3、訓練資料值

結果集 是一個一維陣列,所以在這裡要將他改變

y_train = np.sin(X_train).flatten()

2)繪製訓練資料

plt.scatter(X_train,y_train)

這裡寫圖片描述

3)新增噪聲

給y_train新增一些噪聲 讓x和y的關係不要那麼明確

我們的訓練資料為 40 行一列的資料,我們每隔4個給加一個隨機噪聲

1、製造噪聲

noise = np.random.random(size=10)/2
noise

array([0.2343256 , 0.48838054, 0.30242276, 0.36963179, 0.0195939 ,
       0.14140348, 0.06009828, 0.1480701 , 0.05936386, 0.15899159])

2、新增噪聲

每隔4個加一個噪聲

y_train[::4] += noise

2、新增噪聲後的圖形

plt.scatter(X_train,y_train)

這裡寫圖片描述

4)生成模型

from sklearn.neighbors import KNeighborsRegressor
# 獲取模型
knn = KNeighborsRegressor(n_neighbors=30)

5)訓練資料

把訓練資料傳入模型,
x:訓練樣本特徵
y:訓練樣本值

'''
# X_train是多行資料 有幾個樣本就有幾行 有幾個特徵就有幾列
# y_train 是一個一維的陣列 裡面直接裝著結果值
'''
knn.fit(X_train,y_train)

6)建立測試資料

把x範圍內的值取遍 然後用機器學習模型獲取y_
這裡的樣本資料為一列,所以繪圖時不用調整座標(相對於上面鳶尾花來說)。

xmin = X_train.min()
xmax = X_train.max()
X_test = np.arange(xmin,xmax,0.01)

7)測試樣本值

注意,有一個特徵,傳入的樣本值應該為n行1列

y_ = knn.predict(X_test.reshape(-1,1))

8)繪圖顯示資料

plt.plot(X_test,y_,color='green',label='predict')  #設定顏色和圖示
plt.scatter(X_train,y_train,label='real',color='k')
plt.legend()  #顯示圖示

這裡寫圖片描述

六、人類動作識別

1) 資料儲存np.save(儲存路徑, 資料)

1)儲存*.npy資料檔案np.save

nd = np.array([1,2,3])
nd
# np.save方法可以把資料儲存到本地 引數 1.是路徑 2.是資料
np.save('./test',nd)  #這裡可以不輸入檔案字尾

2)載入*.npy資料檔案np.load(”檔案路徑”)

np.load('./test.npy') 

array([1, 2, 3])

2) 匯入訓練集和測試集

1、匯入資料

X_train = np.load('./data/x_train.npy')
y_train = np.load('./data/y_train.npy')

2、檢視資料資訊

X_train.shape

(7352, 561)  #資料有 7352行,561列
y_train.size

7352
Series(y_train).unique()

array([5, 4, 6, 1, 3, 2], dtype=int64)
'''
這裡訓練結果集代表的運動型別
    1:'walking',              #走
    2:'walking upstairs',     #上樓
    3:'walking downstairs',   #下樓
    4:'sitting',              #坐著
    5:'standing',             #站著
    6:'laying'                #躺著
'''

3、畫圖檢視各個特徵的圖形

我們隨機抽查 第100,200,300,400,500,600個樣本檢視訓練樣本的結果

n = 100
y_train[n]
labels[y_train[n]]

'walking'
------------------------
n = 200
y_train[n]
labels[y_train[n]]

'standing'
------------------------
n = 300
y_train[n]
labels[y_train[n]]

'walking downstairs'
------------------------
n = 400
y_train[n]
labels[y_train[n]]

'sitting'
------------------------
n = 500
y_train[n]
labels[y_train[n]]

'walking upstairs'
------------------------
n = 600
y_train[n]
labels[y_train[n]]

'laying'

我們可以看出抽取的這 6 個數據將全部型別的取出來,我們將這6個訓練樣本繪圖展示觀察

plt.figure(figsize=(20,10))  #設定畫布大小
for i in [1,2,3,4,5,6]:
    axes = plt.subplot(3,2,i)  #建立子畫布
    axes.plot(X_train[i*100],color=colors[i-1])  #在子畫布上畫圖
    axes.set_title(labels[y_train[i*100]])  設定子畫布的標題

這裡寫圖片描述

3) 訓練模型

1、建立訓練模型

knn = KNeighborsClassifier(n_neighbors=5)

2、訓練資料

傳入訓練資料與訓練結果

knn.fit(X_train,y_train)

3、

4、

4) 模型預測

y_ = knn.predict(X_test)

array([5, 5, 5, ..., 2, 2, 1], dtype=int64)

5) 預測準確率

1、自己計算

將預測值與測試值相等,得出預測正確的個數

y_ == y_test  # 獲取的是布林值的序列 相等的是True 不想等是False

array([ True,  True,  True, ...,  True,  True, False])

測試結果個數與預測結果個數

(y_ == y_test).sum()

2657

y_test.size

2947

兩者相乘

(y_ == y_test).sum() / y_test.size

0.9066847641669494

2、KNN自帶方法

機器學習模型 給我們提供了 打分的方法

# 引數 1.是測試集的特徵資料 2.是測試集的真實結果
# 把測試集的特徵資料傳入後 機器學習模型 會 計算得到預測結果y_
# 然後和傳入的真是結果 y_test 對比 返回準確率
knn.score(X_test,y_test)