基於scikit-learn包實現機器學習之KNN(K近鄰)-完整示例


              基於scikit-learn包實現機器學習之KNN(K近鄰)

scikit-learn(簡稱sklearn)是目前最受歡迎,也是功能最強大的一個用於機器學習的Python庫件。它廣泛地支持各種分類、聚類以及回歸分析方法比如支持向量機、隨機森林、DBSCAN等等,由於其強大的功能、優異的拓展性以及易用性,目前受到了很多數據科學從業者的歡迎,也是業界相當著名的一個開源項目之一。

基於上一篇的k近鄰原理講解,我們這一片主要是利用相應的工具包實現機器學習,為了逐步掌握這樣成功的工具包,我們從簡單的KNN開始入手,其中scikit-learn就是一個不錯的選擇。

 

sklearn的安裝

首先我們需要安裝sklearn這個庫(由於您可以在我們的網頁上進行所有的實驗,所以您可以在之后再嘗試在您的電腦上安裝sklearn)。sklearn是Python的擴展庫,因此我們必須首先設置好Python運行環境。同時,由於sklearn基於Numpy和Scipy這兩個庫,我們也要首先安裝好它們。然后,我們便可以使用pipconda來自動安裝sklearn,具體方法如下:

# 安裝sklearn之前必須先安裝較新版本的Scipy與Numpy
# 使用pip安裝sklearn:
pip install -U scikit-learn
# 使用conda安裝sklearn:
conda install scikit-learn

安裝好sklearn之后,我們便可以在Python腳本中使用來自sklearn中的各種數據、功能函數等等

sklearn內置數據集

數據是機器學習的關鍵,在機器學習工作中我們需要花費大量的時間來采集和整理數據,合理且科學的數據是得到良好機器學習效果的關鍵。一般而言,一個分類問題的機器學習過程需要用到四塊數據內容,分別是:

  • 訓練數據,一般用train來表示
  • 訓練數據的分類屬性,一般用target來表示
  • 測試數據,一般用test來表示
  • 測試數據的真實分類屬性,用於評估分類器性能,一般用expected來表示

為了方便學習和測試機器學習中的各種內容,sklearn內置了各種有用的數據集,文本處理、圖像識別等具有代表性的問題的數據在sklearn中均有收集(對於初學者來說,不得不說很人性化)。

本文中用的鳶尾花數據集同樣可以在sklearn中的datasets模塊中找到。

KNN算法實現

不多說,直接先上代碼,后面再進行詳解。

 
        
#-*-coding:utf-8 -*-
from sklearn import datasets
#導入內置數據集模塊

from sklearn.neighbors import KNeighborsClassifier
#導入
sklearn.neighbors模塊中KNN類
import numpy as np
np.random.seed(0)
#設置隨機種子,不設置的話默認是按系統時間作為參數,因此每次調用隨機模塊時產生的隨機數都不一樣設置后每次產生的一樣
iris=datasets.load_iris()
#導入鳶尾花的數據集,iris是一個類似於結構體的東西,內部有樣本數據,如果是監督學習還有標簽數據
iris_x=iris.data
#樣本數據150*4二維數據,代表150個樣本,每個樣本4個屬性分別為花瓣和花萼的長、寬
iris_y=iris.target
#長150的以為數組,樣本數據的標簽
indices = np.random.permutation(len(iris_x))
#permutation接收一個數作為參數(150),產生一個0-149一維數組,只不過是隨機打亂的,當然她也可以接收一個一維數組作為參數,結果是直接對這個數組打亂
iris_x_train = iris_x[indices[:-10]]
#隨機選取140個樣本作為訓練數據集
iris_y_train = iris_y[indices[:-10]]
#並且選取這140個樣本的標簽作為訓練數據集的標簽
iris_x_test = iris_x[indices[-10:]]
#剩下的10個樣本作為測試數據集
iris_y_test = iris_y[indices[-10:]]
#並且把剩下10個樣本對應標簽作為測試數據及的標簽

knn = KNeighborsClassifier()
#定義一個knn分類器對象
knn.fit(iris_x_train, iris_y_train)
#調用該對象的訓練方法,主要接收兩個參數:訓練數據集及其樣本標簽

iris_y_predict = knn.predict(iris_x_test)
#調用該對象的測試方法,主要接收一個參數:測試數據集
probility=knn.predict_proba(iris_x_test)  
#計算各測試樣本基於概率的預測
neighborpoint=knn.kneighbors(iris_x_test[-1],5,False)
#計算與最后一個測試樣本距離在最近的5個點,返回的是這些樣本的序號組成的數組
score=knn.score(iris_x_test,iris_y_test,sample_weight=None)
#調用該對象的打分方法,計算出准確率

print('iris_y_predict = ')
print(iris_y_predict)
#輸出測試的結果

print('iris_y_test = ')
print(iris_y_test)
#輸出原始測試數據集的正確標簽,以方便對比
print 'Accuracy:',score  
#輸出准確率計算結果
print 'neighborpoint of last test sample:',neighborpoint
 
print 'probility:',probility
***********************************
結果輸出:
iris_y_predict =
[1 2 1 0 0 0 2 1 2 0]
iris_y_test =
[1 1 1 0 0 0 2 1 2 0]
Accuracy: 0.9
neighborpoint of last test sample: [[ 75  41  96  78 123]]
probility: [[ 0.   1.   0. ]
        [ 0.   0.4  0.6]
        [ 0.   1.   0. ]
        [ 1.   0.   0. ]
        [ 1.   0.   0. ]
        [ 1.   0.   0. ]
        [ 0.   0.   1. ]
        [ 0.   1.   0. ]
        [ 0.   0.   1. ]
        [ 1.   0.   0. ]]

基於此,KNN算法實現已經徹底完成了,當然,我們還是需要稍微再解讀一下,上面所說的主要兩個對象的方法,一個是fit()方法,一個是predict()方法,我說的主要接受兩個參數,並不是說只接受兩個參數或者一個參數,而是說其他參數都有默認值,且是內部參數,這里我們詳細解讀。KNeighborsClassifier是一個類,它集成了其他的NeighborsBase, KNeighborsMixin,SupervisedIntegerMixin, ClassifierMixin。這里我們暫時不管它。主要看它的幾個主要的方法。當然有的方法是其從父類那里集成過來的。

__init__()   初始化函數(構造函數) 它主要有一下幾個參數:

  n_neighbors=5           

int 型參數    knn算法中指定以最近的幾個最近鄰樣本具有投票權,默認參數為5

  weights='uniform'       

str參數        即每個擁有投票權的樣本是按什么比重投票,'uniform'表示等比重投票,'distance'表示按距離反比投票,[callable]表示自己定義的一個函數,這個函數接收一個

距離數組,返回一個權值數組。默認參數為‘uniform’

  algrithm='auto'           

str參數       即內部采用什么算法實現。有以下幾種選擇參數:'ball_tree':球樹、'kd_tree':kd樹、'brute':暴力搜索、'auto':自動根據數據的類型和結構選擇合適的算法。默認情況下是‘auto’。暴力搜索就不用說了大家都知道。具體前兩種樹型數據結構哪種好視情況而定。KD樹是對依次對K維坐標軸,以中值切分構造的樹,每一個節點是一個超矩形,在維數小於20時效率最高--可以參看《統計學習方法》第二章。ball tree 是為了克服KD樹高維失效而發明的,其構造過程是以質心C和半徑r分割樣本空間,每一個節點是一個超球體。一般低維數據用kd_tree速度快,用ball_tree相對較慢。超過20維之后的高維數據用kd_tree效果反而不佳,而ball_tree效果要好,具體構造過程及優劣勢的理論大家有興趣可以去具體學習。

  leaf_size=30               

int參數      基於以上介紹的算法,此參數給出了kd_tree或者ball_tree葉節點規模,葉節點的不同規模會影響數的構造和搜索速度,同樣會影響儲樹的內存的大小。具體最優規模是多少視情況而定。

  matric='minkowski'     

str或者距離度量對象   即怎樣度量距離。默認是閔氏距離,閔氏距離不是一種具體的距離度量方法,它可以說包括了其他距離度量方式,是其他距離度量的推廣,具體各種距離度量只是參數p的取值不同或者是否去極限的不同情況,具體大家可以參考這里,講的非常詳細                                

  

  p=2                         

int參數       就是以上閔氏距離各種不同的距離參數,默認為2,即歐氏距離。p=1代表曼哈頓距離等等

  metric_params=None                

距離度量函數的額外關鍵字參數,一般不用管,默認為None

  n_jobs=1                

int參數       指並行計算的線程數量,默認為1表示一個線程,為-1的話表示為CPU的內核數,也可以指定為其他數量的線程,這里不是很追求速度的話不用管,需要用到的話去看看多線程。

 

fit()                     

訓練函數,它是最主要的函數。接收參數只有1個,就是訓練數據集,每一行是一個樣本,每一列是一個屬性。它返回對象本身,即只是修改對象內部屬性,因此直接調用就可以了,后面用該對象的預測函數取預測自然及用到了這個訓練的結果。其實該函數並不是KNeighborsClassifier這個類的方法,而是它的父類SupervisedIntegerMixin繼承下來的方法。

 

predict()               

預測函數   接收輸入的數組類型測試樣本,一般是二維數組,每一行是一個樣本,每一列是一個屬性返回數組類型的預測結果,如果每個樣本只有一個輸出,則輸出為一個一維數組。如果每個樣本的輸出是多維的,則輸出二維數組,每一行是一個樣本,每一列是一維輸出。

 

predict_prob()      

基於概率的軟判決,也是預測函數,只是並不是給出某一個樣本的輸出是哪一個值,而是給出該輸出是各種可能值的概率各是多少接收參數和上面一樣返回參數和上面類似,只是上面該是值的地方全部替換成概率,比如說輸出結果又兩種選擇0或者1,上面的預測函數給出的是長為n的一維數組,代表各樣本一次的輸出是0還是1.而如果用概率預測函數的話,返回的是n*2的二維數組,每一行代表一個樣本,每一行有兩個數,分別是該樣本輸出為0的概率為多少,輸出1的概率為多少。而各種可能的順序是按字典順序排列,比如先0后1,或者其他情況等等都是按字典順序排列。

 

score()                

計算准確率的函數,接受參數有3個。 X:接收輸入的數組類型測試樣本,一般是二維數組,每一行是一個樣本,每一列是一個屬性。y:X這些預測樣本的真實標簽,一維數組或者二維數組。sample_weight=None,是一個和X第一位一樣長的各樣本對准確率影響的權重,一般默認為None.輸出為一個float型數,表示准確率。內部計算是按照predict()函數計算的結果記性計算的。其實該函數並不是KNeighborsClassifier這個類的方法,而是它的父類KNeighborsMixin繼承下來的方法。

kneighbors()          

計算某些測試樣本的最近的幾個近鄰訓練樣本。接收3個參數。X=None:需要尋找最近鄰的目標樣本。n_neighbors=None,表示需要尋找目標樣本最近的幾個最近鄰樣本,默認為None,需要調用時給出。return_distance=True:是否需要同時返回具體的距離值。返回最近鄰的樣本在訓練樣本中的序號。其實該函數並不是KNeighborsClassifier這個類的方法,而是它的父類KNeighborsMixin

繼承下來的方法。

下面舉一個簡單例子讓大家稍微看看,(其實上面的例子已經很具體形象了):

Examples
--------
>>> X = [[0], [1], [2], [3]]
>>> y = [0, 0, 1, 1]
>>> from sklearn.neighbors import KNeighborsClassifier
>>> neigh = KNeighborsClassifier(n_neighbors=3)
>>> neigh.fit(X, y)
>>> print(neigh.predict([[1.1]]))
[0]
>>> print(neigh.predict_proba([[0.9]]))
[[ 0.66666667 0.33333333]]
以上講解關於sklearn中的knn算法基本講解完了,不知道大家是否學會了呢?以上部分除了sklearn背景介紹,后面的部分為原創,希望大家共同學習共同
進步,后續會繼續更新sklearn的其他方法。



 

 

 

 

  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM