基於scikit-learn包實現機器學習之KNN(K近鄰)-完整樣本,scikit-learnknn
基於scikit-learn包實現機器學習之KNN(K近鄰)
scikit-learn(簡稱sklearn)是目前最受歡迎,也是功能最強大的一個用於機器學習的Python庫件。它廣泛地支援各種分
類、聚類以及迴歸分析方法比如支援向量機、隨機森林、DBSCAN等等,由於其強大的功能、優異的拓展性以及易用性,目
前受到了很多資料科學從業者的歡迎,也是業界相當著名的一個開源項目之一。
基於上一篇的k近鄰原理講解,我們這一片主要是利用相應的工具包實現機器學習,為了逐步掌握這樣成功的工具包,我們
從簡單的KNN開始入手,其中scikit-learn就是一個不錯的選擇。
sklearn的安裝
首先我們需要安裝sklearn這個庫(由於您可以在我們的網頁上進行所有的實驗,所以您可以在之後再嘗試在您的電腦上
安裝sklearn)。sklearn是Python的擴充庫,因此我們必須首先設定好Python運行環境。同時,由於sklearn基於Numpy和
Scipy這兩個庫,我們也要首先安裝好它們。然後,我們便可以使用pip或conda來自動安裝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內建了各種有用的資料集,文本處理、Image Recognition等具有代表性的
問題的資料在sklearn中均有收集(對於初學者來說,不得不說很人性化)。
本文中所介紹的用於KNN的鳶尾花資料集同樣可以在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()Function Compute的結果記性計算的。
其實該函數並不是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的其他方法。