[監督學習] 分類(K近鄰算法)

以下是本人整理的機器學習-監督學習有關知識,詳細請看鏈接:

監督學習框架:思維導圖-python.

KNN算法

一:KNN算法的概述
  鄰近算法,或者說K最近鄰(kNN,k-NearestNeighbor)分類算法是數據挖掘分類技術中最簡單的方法之一。所謂K最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表,Cover和Hart在1968年提出了最初的鄰近算法。
  KNN是一種分類(lassification)算法,它輸入基於實例的學習(instance-based learning),屬於懶惰學習(lazy learning)即KNN沒有顯式的學習過程,也就是說沒有訓練階段,數據集事先已有了分類和特徵值,待收到新樣本後直接進行處理。與急切學習(eager learning)相對應。
  
  KNN是通過測量不同特徵值之間的距離進行分類。 
  
  具體過程:通過計算待分類數據點,與已有數據集中的所有數據點的距離。取距離最小的前K個點,根據“少數服從多數”的原則,將這個數據點劃分爲出現次數最多的那個類別。
  當涉及到KNN,網上會有關很多這類圖片,以下圖片便於大家理解。

在這裏插入圖片描述
  通過計算待分類點Xu 與樣本數據集合中每個點的距離,最近的K個樣本點大多數屬於紅色類別,所以待分類點Xu被分爲紅色。

二:KNN算法的過程
  1)計算測試數據與各個訓練數據之間的距離
  2)按照距離的遞增關係進行排序
  3)選取距離最小的K個點
  4)確定前K個點所在類別的出現頻率
  5)返回前K個點中出現頻率最高的類別作爲測試數據的預測分類

三:關於距離的計算
  距離 就是平面上兩個點的直線距離。關於距離的度量方法,常用的有:歐幾里得距離、餘弦值(cos), 相關度 (correlation), 曼哈頓距離 (Manhattan distance)等。
  兩個點或元組P1=(x1,y1)和P2=(x2,y2)的歐幾里得距離是
在這裏插入圖片描述
  當樣本點是n維時,距離公式可寫成:
在這裏插入圖片描述
四:關於K值的選取
  
  K值: 臨近數,即在預測目標點時取幾個臨近的點來預測。
 
K值得選取非常重要,因爲:
  (1)如果當K的取值過小時,一旦有噪聲得成分存在們將會對預測產生比較大影響,例如取K值爲1時,一旦最近的一個點是噪聲,那麼就會出現偏差,K值的減小就意味着整體模型變得複雜,容易發生過擬合;
  (2)如果K的值取的過大時,就相當於用較大鄰域中的訓練實例進行預測,學習的近似誤差會增大。這時與輸入目標點較遠實例也會對預測起作用,使預測發生錯誤。K值的增大就意味着整體的模型變得簡單; 
  K的取值儘量要取奇數,一般情況下,K值會傾向選取較小的值,並使用交叉驗證法選取最優K值。

Python實現過程

一:導入sklearn庫

sklearn中的K近鄰分類器在sklearn庫中,可以使sklearn.neighbors.KNeighborsClassifier 創建一個K近鄰分類器 。

from sklearn.neighbors import KNeighborsClassifier

主要參數有:

neigh = KNeighborsClassifier(n_neighbors= 3, weights = 'uniform', algorithm = 'auto') #設置最近的3個鄰居作爲分類的依據

n_ neighbors:用於指定分類器中K的大小(默認值爲5,注意與kmeans的區別)。
weights:設置選中的K個點對分類結果影響的權重(默認值爲平均權重“uniform”,可以選擇“distance"代表越近的點權重越高,或者傳入自己編寫的以距離爲參數的權重計算函數)。
algorithm:設置用於計算臨近點的方法,因爲當數據量很大的情況下計算當前點和所有點的距離再選出最近的k各點,這個計算量是很費時的,所以選項中有ball tree、kd_ tree和brute,分別代表不同的尋找鄰居的優化算法,默認值爲auto,根據訓練數據自動選擇。

二:案例一測試

嘗試使用K近鄰分類器,創建一組數據 x 和它對應的標籤 y,並訓練數據,通過對模型的訓練建立模型後,輸入測試集text = [[1.1], [2.1]],觀察這兩個測試點的結果。

from sklearn.neighbors import KNeighborsClassifier

X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]

neigh = KNeighborsClassifier(n_neighbors= 3, weights = 'uniform', algorithm = 'auto') # 設置最近的3個鄰居作爲分類的依據
neigh.fit(X, y) # 調用fit()函數,將訓練數據X和標籤y送入分類器進行學習

text = [[1.1], [2.1]] 
data = neigh.predict(text)
print(data)
print(neigh.score(X, y)) #返回評分

測試結果:

訓練結果: [0 1]
訓練結果評分: 1.0

其中n_ neighbors設置爲3,即使用最近的3個鄰居作爲分類的依據,其他參數保持默認值,並將創建好的實例賦給變量neigh。調用fit()函數,將訓練數據X和標籤y送入分類器進行學習。neigh.fit(X, y)

輸入測試點 [1.1],K近鄰分類器通過計算該樣本]與訓練數據的距離,取0,1,2這3個鄰居作爲依據,根據“投票法”最終將樣本分爲類別0。
同理,輸入測試點 [2.1],模型輸出類別爲1。
並最終可返回對模型的評分。

三:案例二測試

使用sklearn庫中原有的鳶尾花數據進行分析,鳶尾花數據集 excel 展示可以點擊下面鏈接查看。

鳶尾花數據展示: 數據-圖片.

鳶尾花數據集每個樣本有4個特徵,共有0、1、2三種樣本,交叉驗證數據後成訓練模型,輸入測試集 text 進行模型驗證。

# -*- coding: utf-8 -*-
# @Time    : 2020/4/8 16:22
# @Author  : Zudy
# @FileName: course4.py

'''
1.機器學習-監督學習(分類)
   運用鳶尾花數據集 實現 KNN 算法
'''

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris # 導入鳶尾花訓練集
from sklearn.model_selection import cross_val_score # 導入計算交叉檢驗值的函數cross_val_score


# 將鳶尾花數據賦值給變量iris
iris = load_iris()
data = iris.data # 鳶尾花數據作爲特徵,
target = iris.target # 鳶尾花數據作爲目標結果[0,1,2],


neigh = KNeighborsClassifier(n_neighbors= 3)  # 創建K近鄰分類器, 設置 K=3
cross_val_score(neigh, data, target, cv = 10) # 使用10折交叉驗證

neigh.fit(data, target) # fit()訓練模型
text = [
    [5.1, 3.5, 1.4, 0.2],
    [7., 3.2, 4.7, 1.4],
    [5.9, 3., 5.1, 1.8]]
pre_text_KNN = neigh.predict(text) # KNN 函數預測

print('運用 KNN近鄰分類 預測分類結果:',pre_text_KNN)

測試結果:

運用 KNN近鄰分類 預測分類結果: [0 1 2]

四:交叉驗證獲取最佳-K值

這裏使用交叉驗證法選取最優K值,一般情況下,K會傾向選取較小的值。

思路:通過遍歷一定長度的數據,取不同的k值,用列表接收不同k值訓練的分數,選取第一次分數最高的k值,即爲最佳的k值。

# -*- coding: utf-8 -*-
# @Time    : 2020/4/2 13:55
# @Author  : Zudy
# @FileName: course_text.py

'''
1.使用sklearn的cross_val_score進行交叉驗證
    1.1 交叉驗證用於評估模型的預測性能,尤其是訓練好的模型在新數據上的表現,可以在一定程度上減小過擬合。
    1.2 還可以從有限的數據中獲取儘可能多的有效信息。
2. 使用交叉檢驗的方法可以用於任何帶參數的模型預測,選取合適的參數 K'''

from sklearn import datasets   # 鳶尾花數據集
from sklearn.model_selection import train_test_split,cross_val_score   # 劃分數據 交叉驗證
from sklearn.neighbors import KNeighborsClassifier  # KNN模型
import matplotlib.pyplot as plt


iris = datasets.load_iris()       # 加載sklearn的鳶尾花數據集
x = iris.data        # 數據集
y = iris.target       # 每行數據所對應的標籤

# 這裏以1/3的來劃分數據
train_X, test_X, train_y, test_y = train_test_split(x, y, test_size=1/3, random_state=3)
# 訓練集訓練結果  train_X, train_y
# 測試集測試結果  test_X, test_y


k_range = range(1,41)  # k值的取值範圍
cv_scores = []    # 用來放每個模型的分數結果值
for k in k_range:
   # 改變KNN聚類的參數n_neighborsd的值,來選取合適的KNN模型的k
   neigh = KNeighborsClassifier(n_neighbors = k)
   score = cross_val_score(neigh, train_X, train_y, cv = 10, scoring = 'accuracy')
   cv_scores.append(score.mean())

plt.plot(k_range, cv_scores, 'ko-')
plt.xlabel('K值')
plt.ylabel('Accuracy')
plt.show()

通過圖像可以觀察最佳K值,最佳K=3。
在這裏插入圖片描述

在實際進行KNN模型訓練時,我們可以發現K值過小時,相當於使用較小的鄰域進行預測,如果鄰居恰好是噪聲點,會導致過擬合。隨着K值不斷增大,模型的精確度先增後減,第一次到達最大精確值是K=3,隨着K值超過7時,距離較遠的樣本也會對預測起作用,導致預測錯誤,模型不精確度開始呈下降趨勢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章