09_分類算法--k近鄰算法(KNN)、案例、歐氏距離、k-近鄰算法API、KNeighborsClassifier、及其裏面的案例(網絡資料+學習資料整理筆記)

1 分類算法–k近鄰算法(KNN)

定義:如果一個樣本在特徵空間中**k個最相似(即特徵空間中最鄰近)**的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別,則該樣本也屬於這個類別。

k-近鄰算法採用測量不同特徵值之間的距離來進行分類

優點:精度高、對異常值不敏感、無數據輸入假定。
缺點:計算複雜度高、空間複雜度高。
使用數據範圍:數值型和標稱型。

以下是《機器原理》中的關於KNN的介紹

K最近鄰(k-Nearest Neighbor,KNN)分類算法可以說是最簡單的機器學習算法了。它採用測量不同特徵值之間的距離方法進行分類。它的思想很簡單:如果一個樣本在特徵空間中的k個最相似(即特徵空間中最鄰近)的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別。
在這裏插入圖片描述
比如上面這個圖,我們有兩類數據,分別是藍色方塊和紅色三角形,他們分佈在一個上圖的二維中間中。那麼假如我們有一個綠色圓圈這個數據,需要判斷這個數據是屬於藍色方塊這一類,還是與紅色三角形同類。怎麼做呢?我們先把離這個綠色圓圈最近的幾個點找到,因爲我們覺得離綠色圓圈最近的纔對它的類別有判斷的幫助。那到底要用多少個來判斷呢?這個個數就是k了。如果k=3,就表示我們選擇離綠色圓圈最近的3個點來判斷,由於紅色三角形所佔比例爲2/3,所以我們認爲綠色圓是和紅色三角形同類。如果k=5,由於藍色四方形比例爲3/5,因此綠色圓被賦予藍色四方形類。從這裏可以看到,k的值還是很重要的。

該算法在分類時有個主要的不足是,當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本佔多數。因此可以採用權值的方法(和該樣本距離小的鄰居權值大)來改進。該方法的另一個不足之處是計算量較大,因爲對每一個待分類的文本都要計算它到全體已知樣本的距離,才能求得它的K個最近鄰點。目前常用的解決方法是事先對已知樣本點進行剪輯,事先去除對分類作用不大的樣本。該算法比較適用於樣本容量比較大的類域的自動分類,而那些樣本容量較小的類域採用這種算法比較容易產生誤分[參考機器學習十大算法]。

總的來說就是我們已經存在了一個帶標籤的數據庫,然後輸入沒有標籤的新數據後,將新數據的每個特徵與樣本集中數據對應的特徵進行比較,然後算法提取樣本集中特徵最相似(最近鄰)的分類標籤。一般來說,只選擇樣本數據庫中前k個最相似的數據。最後,選擇k個最相似數據中出現次數最多的分類。其算法描述如下:
1)計算已知類別數據集中的點與當前點之間的距離;
2)按照距離遞增次序排序;
3)選取與當前點距離最小的k個點;
4)確定前k個點所在類別的出現頻率;
5)返回前k個點出現頻率最高的類別作爲當前點的預測分類。

KNN做迴歸和分類的主要區別在於最後做預測時候的決策方式不同。KNN做分類預測時,一般是選擇多數表決法,即訓練集裏和預測的樣本特徵最近的K個樣本,預測爲裏面有最多類別數的類別。而KNN做迴歸時,一般是選擇平均法,即最近的K個樣本的樣本輸出的平均值作爲迴歸預測值。

1.1 一個例子弄懂k-近鄰

電影可以按照題材分類,每個題材又是如何定義的呢?那麼假如兩種類型的電影,動作片和愛情片。動作片有哪些公共的特徵?那麼愛情片又存在哪些明顯的差別呢?我們發現動作片中打鬥鏡頭的次數較多,而愛情片中接吻鏡頭相對更多。當然動作片中也有一些接吻鏡頭,愛情片中也會有一些打鬥鏡頭。所以不能單純通過是否存在打鬥鏡頭或者接吻鏡頭來判斷影片的類別。那麼現在我們有6部影片已經明確了類別,也有打鬥鏡頭和接吻鏡頭的次數,還有一部電影類型未知。
在這裏插入圖片描述
那麼我們使用K-近鄰算法來分類愛情片和動作片:存在一個樣本數據集合,也叫訓練樣本集,樣本個數M個,知道每一個數據特徵與類別對應關係,然後存在未知類型數據集合1個,那麼我們要選擇一個測試樣本數據中與訓練樣本中M個的距離,排序過後選出最近的K個,這個取值一般不大於20個。選擇K個最相近數據中次數最多的分類。那麼我們根據這個原則去判斷未知電影的分類
在這裏插入圖片描述
我們假設K爲3,那麼排名前三個電影的類型都是愛情片,所以我們判定這個未知電影也是一個愛情片。那麼計算距離是怎樣計算的呢?
在這裏插入圖片描述

1.2 計算距離公式

兩個樣本的距離可以通過如下公式計算,又叫歐氏距離,比如說,a(a1,a2,a3),b(b1,b2,b3)
在這裏插入圖片描述

1.3 sklearn k-近鄰算法API

參考:https://www.jianshu.com/p/871884bb4a75

sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, metric=’minkowski’, metric_params=None,n_jobs=None, **kwargs)[source]
     1、n_neighbors:int,可選(默認=5),k_neighbors查詢默認使用的鄰居數,選擇最鄰近的數目k。
     2、weights:鄰近點的計算權重值,uniform代表各個點權重值相等。
          用於預測的權重函數。可選參數如下:
          A:‘uniform’:統一的權重. 在每一個鄰居區域裏的點的權重都是一樣的。
          B:'distance':權重點等於他們距離的倒數。使用此函數,更近的鄰居對於所預測的點的影響更大。
          C:[callable]:一個用戶自定義的方法,此方法接收一個距離的數組,然後返回一個相同形狀並且包含權重的數組。。
     3、algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可選用於計算最近鄰居的算法:‘ball_tree’將會使用 BallTree,‘kd_tree’將使用 KDTree。‘auto’將嘗試根據傳遞給fit方法的值來決定最合適的算法。 (不同實現方式影響效率)
     4、leaf_size(葉子數量):int,可選參數(默認爲30)、
         傳遞給BallTree或kTree的葉子大小,這會影響構造和查詢的速度,以及存儲樹所需的內存。
     5、p:Minkowski度量的指數參數。p = 1 代表使用曼哈頓距離 (l1),p = 2 代表使用歐幾里得距離(l2)
     6、metric:距離度量,點之間距離的計算方法。
     7、metric_params:額外的關鍵字度量函數。
     8、n_jobs:爲鄰近點搜索運行的並行作業數。

方法:

方法名 含義
fit(X,y) 使用X作爲訓練數據,y作爲目標值(類似於標籤)來擬合模型
get_params([deep]) 獲取估值器的參數。
kneighbors([X, n_neighbors, return_distance]) 查找一個或幾個點的K個鄰居。返回每個點的下標和到鄰居的距離。
kneighbors_graph([X,n_neighbors,mode]) 計算在X數組中每個點的k鄰居的(權重)圖
predit(X) 給提供的數據預測對應的標籤。
predict_proba(X) 返回測試數據X的概率估值。
score(X, y[, sample_weight]) 返回給定測試數據和標籤的平均準確值。
set_params(**params) 設置估值器的參數。

案例:

from sklearn.neighbors import KNeighborsClassifier

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

neigh = KNeighborsClassifier(n_neighbors=3)
neigh.fit(X,y)

print(neigh.predict([[1.1]]))
print(neigh.predict_proba([[0.9]]))

輸出結果:

[0]
[[0.66666667 0.33333333]]
fit(X,y)
使用X作爲訓練數據擬合模型,y作爲X的類別值。X,y爲數組或者矩陣

參數:
    X: {類似數組, 稀疏矩陣, BallTree, KDTree}
         待訓練數據。如果是數組或者矩陣,形狀爲 [n_samples, n_features],如果矩陣爲’precomputed', 則形狀爲[n_samples, n_samples]。
    y: {類似數組, 稀疏矩陣}
         形狀爲[n_samples] 或者 [n_samples, n_outputs]的目標值。

案例:

import numpy as np
from sklearn.neighbors import KNeighborsClassifier

neigh = KNeighborsClassifier(n_neighbors=3)

X = np.array([[1, 1], [1, 1.1], [0, 0], [0, 0.1]])
y = np.array([1,1,0,0])

print(neigh.fit(X,y))

輸出結果爲:

KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=None, n_neighbors=3, p=2,
                     weights='uniform')
get_params(deep=True)
    獲取估值器的參數。

參數:
    deep:boolean,可選參數
        如果爲True,則返回估值器的參數,以包含子目標的估值器。
返回值:
    params:Mapping string to any
        返回Map變量,內容爲[參數值:值,參數值:值,......]
kneighbors(X=None,n_neighbors=None,return_distance=True)
    查詢一個或幾個點的K個鄰居, 返回每個點的下標和到鄰居的距離。

參數:
    X: 類似數組, 形狀(n_query, n_features)或者(n_query, n_indexed) 。如果矩陣是‘precomputed’,形狀爲(n_query, n_indexed)
         帶查詢的一個或幾個點。如果沒有提供,則返回每個有下標的點的鄰居們。
    n_neighbors: int
         鄰居數量 (默認爲調用構造器時設定的n_neighboes的值).
    return_distance: boolean, 可選參數. 默認爲 True.
         如果爲 False,則不會返回距離

返回值:
    dist: array
         當return_distance =True時,返回到每個點的長度。
    ind: array
         鄰居區域裏最近的幾個點的下標。

例子:

from sklearn.neighbors import NearestNeighbors
samples = [[0., 0., 0.], [0., .5, 0.], [1., 1., .5]]

# n_neighbors = 1故只得到1個最近的點
neigh = NearestNeighbors(n_neighbors=1)
neigh.fit(samples)
# 找到的是samples離[1.,1.,1.]最近的點,第一個值是距離值,第二個值是samples中的座標值
print(neigh.kneighbors([[1.,1.,1.]]))
"""
輸出的是:
(array([[0.5]]), array([[2]], dtype=int64))
"""

如你所見返回值爲[[0.5]]和[[2]]。意思是此點是距離爲0.5並且是樣本中的第三個元素(下標從0開始)。你可以嘗試查詢多個點。

from sklearn.neighbors import NearestNeighbors
samples = [[0., 0., 0.], [0., .5, 0.], [1., 1., .5]]

# n_neighbors = 1故只得到1個最近的點
neigh = NearestNeighbors(n_neighbors=1)
neigh.fit(samples)

# 以下是查詢多個點的情況
X = [[0., 1., 0.], [1., 0., 1.]]
print(neigh.kneighbors(X,return_distance=False))
"""
輸出的是:
[[1]
 [2]]
"""
print(neigh.kneighbors(X,return_distance=True))
"""
輸出結果:
(array([[0.5       ],
       [1.11803399]]), array([[1],
       [2]], dtype=int64))
       
其中第一個array表示分別離[0., 1., 0.]、 [1., 0., 1.]的距離
array([[1],
       [2]], dtype=int64)   表示samples的下標值
"""
kneighbors_graph(X=None,n_neighbors=None,mode=’connectivity’)
計算在X數組中每個點的k鄰居的(權重)圖
參數:
    X: 類似數組, 形狀(n_query, n_features)。如果矩陣是‘precomputed’,形狀爲(n_query, n_indexed)
       一個或多個待查詢點。如果沒有提供,則返回每個有下標的點的鄰居們。
    n_neighbors: int
       鄰居數量。(默認爲調用構造器時設定的n_neighboes的值)。
    mode: {‘connectivity’, ‘distance’}, 可選參數
       返回矩陣數據類型: ‘connectivity’ 會返回10組成的矩陣。 in ‘distance’ 會返回點之間的歐幾里得距離。
   
    A:CSR格式的稀疏矩陣,形狀爲 [n_samples, n_samples_fit]
       n_samples_fit 是擬合過的數據中樣例的數量,其中 A[i, j] 代表i到j的邊的權重。

例子:

from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=2)
X=[[0],[3],[1]]
neigh.fit(X)
A = neigh.kneighbors_graph(X)
print(A.toarray())

輸出結果:

[[1. 0. 1.]
 [0. 1. 1.]
 [1. 0. 1.]]
predict(X)
給提供的數據預測相應的類別標籤
參數:
    X:類似數組, 形狀(n_query, n_features)。 如果矩陣是‘precomputed’,形狀爲(n_query, n_indexed)待測試樣例。
返回值:
    y: 形狀爲 [n_samples] 或者 [n_samples, n_outputs]的數組
    返回每個待測試樣例的類別標籤。
predict_proba(X)
返回測試數據X的概率估值。
參數:
    X:類似數組, 形狀(n_query, n_features)。 如果矩陣是‘precomputed’,形狀爲(n_query, n_indexed) 的待測樣例。
返回值:
    p:形狀爲[n_samples,n_classes]的數組,或者是n_outputs列表。
    輸入樣例的類別概率估值。其中類別根據詞典順序排序。
score(X,y,sample_weight=None)
返回給定測試數據和標籤的平均準確度。在多標籤分類中,返回的是各個子集的準確度。
參數:
    X:類似數組,形狀爲(n_samples,n_features)待測試樣例。
 
    y:類似數組,形狀爲(n_samples)或者(n_samples,n_outputs)
        X對於的正確標籤

    sample_weight:類似數組,形狀爲[n_samples],可選參數。待測試的權重。

返回值:
    score:float
         self.predict(X)關於y的平均準確率。
set_params(**params)
設置估值器的參數。

此方法在單個估值器和嵌套對象(例如管道)中有效。

返回值:
              self

使用到sklearn.neighbors.KNeighborsClassifier的案例
Classifier comparison : https://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html#sphx-glr-auto-examples-classification-plot-classifier-comparison-py
在這裏插入圖片描述
Plot the decision boundaries of a VotingClassifier:https://scikit-learn.org/stable/auto_examples/ensemble/plot_voting_decision_regions.html#sphx-glr-auto-examples-ensemble-plot-voting-decision-regions-py
在這裏插入圖片描述

Digits Classification Exercise : https://scikit-learn.org/stable/auto_examples/exercises/plot_digits_classification_exercise.html#sphx-glr-auto-examples-exercises-plot-digits-classification-exercise-py

Nearest Neighbors Classification: https://scikit-learn.org/stable/auto_examples/neighbors/plot_classification.html#sphx-glr-auto-examples-neighbors-plot-classification-py
在這裏插入圖片描述

1.4 k-近鄰算法案例分析

本案例使用最著名的"鳶尾"數據集,該數據集曾經被Fisher用在經典論文中,目前作爲教科書般的數據樣本預存在Scikit-learn的工具包中。

from sklearn.datasets import load_iris
#使用加載器讀取數據並存入變量iris
iris = load_iris()

#查驗數據規模
print(iris.data.shape)

#查看數據說明(這是一個好習慣)
print(iris.DESCR)

通過上述代碼對數據的查驗以及數據本身的描述,我們瞭解到Iris數據集共有150朵鳶尾數據樣本,並且均勻分佈在3個不同的亞種;每個數據樣本有總共4個不同的關於花瓣、花萼的形狀特徵所描述。由於沒有制定的測試集合,因此按照慣例,我們需要對數據進行隨即分割,25%的樣本用於測試,其餘75%的樣本用於模型的訓練。

由於不清楚數據集的排列是否隨機,可能會有按照類別去進行依次排列,這樣訓練樣本的不均衡的,所以我們需要分割數據,已經默認有隨機採樣的功能。

對Iris數據集進行分割

# 用於獲取鳶尾花的數據集
from sklearn.datasets import load_iris
#數據切分
from sklearn.model_selection import train_test_split
# 標準化的庫
from sklearn.preprocessing import StandardScaler

#使用加載器讀取數據並存入變量iris
iris = load_iris()

#查驗數據規模
print(iris.data.shape)

#查看數據說明(這是一個好習慣)
print(iris.DESCR)

# 對iris數據集進行分割
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,test_size=0.25,random_state=42)

# 對特徵數據進行標準化
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.fit_transform(X_test)

K近鄰算法是非常直觀的機器學習模型,我們可以發現K近鄰算法沒有參數訓練過程,也就是說,我們沒有通過任何學習算法分析訓練數據,而只是根據測試樣本訓練數據的分佈直接作出分類決策。因此,K近鄰屬於無參數模型中非常簡單一種。

# 用於獲取鳶尾花的數據集
from sklearn.datasets import load_iris
#數據切分
from sklearn.model_selection import train_test_split
# 標準化的庫
from sklearn.preprocessing import StandardScaler
# K近鄰算法
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report
from sklearn.model_selection import GridSearchCV

def knniris():
    """
    鳶尾花分類
    :return: None
    """

    # 1、數據集獲取和分割
    lr = load_iris()

    x_train, x_test, y_train, y_test = train_test_split(lr.data, lr.target, test_size=0.25)

    # 2、進行標準化

    std = StandardScaler()

    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)

    # 3、estimator流程
    knn = KNeighborsClassifier()

    # 4、得出模型
    knn.fit(x_train,y_train)

    # 5、進行預測或得出精度(得出x_test所屬的分類)
    y_predict = knn.predict(x_test)
    print(y_predict)
    """
    結果:[1 0 1 2 2 2 2 2 0 1 1 0 0 2 2 0 1 2 2 1 2 2 1 0 1 0 0 0 2 1 1 2 0 2 0 0 2 2]
    """

    score = knn.score(x_test,y_test)
    print(score)
    """
    結果爲:0.9473684210526315
    """

    #===============================================================
    print("===============================================================")
    # 通過網格搜索,n_neighbors爲參數列表
    param = {"n_neighbors": [3, 5, 7]}

    gs = GridSearchCV(knn, param_grid=param, cv=10)

    # 建立模型
    gs.fit(x_train, y_train)

    # print(gs)

    # 預測數據

    print(gs.score(x_test, y_test))

    # 分類模型的精確率和召回率

    # print("每個類別的精確率與召回率:",classification_report(y_test, y_predict,target_names=lr.target_names))

    return None

if __name__ == "__main__":
    knniris()

輸出結果:

[1 0 0 1 2 2 1 0 0 1 1 1 0 1 2 0 1 2 1 1 0 2 2 1 0 0 0 0 0 2 2 0 2 1 2 1 1 2]
0.9736842105263158
===============================================================
D:\installed\Anaconda3\lib\site-packages\sklearn\model_selection\_search.py:814: DeprecationWarning: The default of the `iid` parameter will change from True to False in version 0.22 and will be removed in 0.24. This will change numeric results when test-set sizes are unequal.
  DeprecationWarning)
0.9736842105263158

案例2:Facebook-K-近鄰預測用戶簽到位置案例
在這裏插入圖片描述
在這裏插入圖片描述
數據格式:
在這裏插入圖片描述

from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
import pandas as pd

def knncls():
    """
    K-近鄰預測用戶簽到位置
    :return:None
    """
    # 讀取數據
    data = pd.read_csv("train.csv")

    # print(data.head(10))

    # 處理數據
    # 1、縮小數據,查詢數據曬訊
    data = data.query("x > 1.0 &  x < 1.25 & y > 2.5 & y < 2.75")

    # 處理時間的數據
    time_value = pd.to_datetime(data['time'], unit='s')

    print(time_value)

    # 把日期格式轉換成 字典格式
    time_value = pd.DatetimeIndex(time_value)

    # 構造一些特徵
    data['day'] = time_value.day
    data['hour'] = time_value.hour
    data['weekday'] = time_value.weekday

    # 把時間戳特徵刪除
    data = data.drop(['time'], axis=1)

    print(data)

    # 把簽到數量少於n個目標位置刪除
    place_count = data.groupby('place_id').count()

    tf = place_count[place_count.row_id > 3].reset_index()

    data = data[data['place_id'].isin(tf.place_id)]

    # 取出數據當中的特徵值和目標值
    y = data['place_id']

    x = data.drop(['place_id'], axis=1)

    # 進行數據的分割訓練集合測試集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

    # 特徵工程(標準化)
    std = StandardScaler()

    # 對測試集和訓練集的特徵值進行標準化
    x_train = std.fit_transform(x_train)

    x_test = std.transform(x_test)

    # 進行算法流程 # 超參數
    knn = KNeighborsClassifier()

    # # fit, predict,score
    # knn.fit(x_train, y_train)
    #
    # # 得出預測結果
    # y_predict = knn.predict(x_test)
    #
    # print("預測的目標籤到位置爲:", y_predict)
    #
    # # 得出準確率
    # print("預測的準確率:", knn.score(x_test, y_test))

    # 構造一些參數的值進行搜索
    param = {"n_neighbors": [3, 5, 10]}

    # 進行網格搜索
    gc = GridSearchCV(knn, param_grid=param, cv=2)

    gc.fit(x_train, y_train)

    # 預測準確率
    print("在測試集上準確率:", gc.score(x_test, y_test))
    print("在交叉驗證當中最好的結果:", gc.best_score_)
    print("選擇最好的模型是:", gc.best_estimator_)
    print("每個超參數每次交叉驗證的結果:", gc.cv_results_)

    return None


if __name__ == "__main__":
    knncls()

輸出結果爲:

600        1970-01-01 18:09:40
957        1970-01-10 02:11:10
4345       1970-01-05 15:08:02
4735       1970-01-06 23:03:03
5580       1970-01-09 11:26:50
                   ...        
29100203   1970-01-01 10:33:56
29108443   1970-01-07 23:22:04
29109993   1970-01-08 15:03:14
29111539   1970-01-04 00:53:41
29112154   1970-01-08 23:01:07
Name: time, Length: 17710, dtype: datetime64[ns]
E:/workspace/numpy/sklearn/03_KNeighborsClassifier.py:165: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  data['day'] = time_value.day
E:/workspace/numpy/sklearn/03_KNeighborsClassifier.py:166: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  data['hour'] = time_value.hour
E:/workspace/numpy/sklearn/03_KNeighborsClassifier.py:167: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  data['weekday'] = time_value.weekday
            row_id       x       y  accuracy    place_id  day  hour  weekday
600            600  1.2214  2.7023        17  6683426742    1    18        3
957            957  1.1832  2.6891        58  6683426742   10     2        5
4345          4345  1.1935  2.6550        11  6889790653    5    15        0
4735          4735  1.1452  2.6074        49  6822359752    6    23        1
5580          5580  1.0089  2.7287        19  1527921905    9    11        4
            ...     ...     ...       ...         ...  ...   ...      ...
29100203  29100203  1.0129  2.6775        12  3312463746    1    10        3
29108443  29108443  1.1474  2.6840        36  3533177779    7    23        2
29109993  29109993  1.0240  2.7238        62  6424972551    8    15        3
29111539  29111539  1.2032  2.6796        87  3533177779    4     0        6
29112154  29112154  1.1070  2.5419       178  4932578245    8    23        3
[17710 rows x 8 columns]
D:\installed\Anaconda3\lib\site-packages\sklearn\model_selection\_split.py:657: Warning: The least populated class in y has only 1 members, which is too few. The minimum number of members in any class cannot be less than n_splits=2.
  % (min_groups, self.n_splits)), Warning)
在測試集上準確率: 0.4189125295508274
在交叉驗證當中最好的結果: 0.39344262295081966
選擇最好的模型是: KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=None, n_neighbors=10, p=2,
                     weights='uniform')
每個超參數每次交叉驗證的結果: {'mean_fit_time': array([0.01545823, 0.00547051, 0.00598311]), 'std_fit_time': array([1.04693174e-02, 4.82320786e-04, 2.78949738e-05]), 'mean_score_time': array([0.36103368, 0.38176703, 0.47072983]), 'std_score_time': array([0.02695775, 0.01324654, 0.02192879]), 'param_n_neighbors': masked_array(data=[3, 5, 10],
             mask=[False, False, False],
       fill_value='?',
            dtype=object), 'params': [{'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 10}], 'split0_test_score': array([0.34967218, 0.37308773, 0.39541055]), 'split1_test_score': array([0.35561923, 0.37695002, 0.39143585]), 'mean_test_score': array([0.35261665, 0.375     , 0.39344262]), 'std_test_score': array([0.00297338, 0.00193105, 0.00198726]), 'rank_test_score': array([3, 2, 1])}

1.5 實例流程

1、數據集的處理
2、分割數據集
3、對數據集進行標準化
4、estimator流程進行分類預測

1.6 問題

1、k值取多大?有什麼影響
k值取很小:容易受異常點影響
k值取很大:容易受最近數據太多導致比例變化

1.7 k-近鄰算法優缺點

1、優點
    1.1 簡單,易於理解,易於實現,無需估計參數,無需訓練
2、缺點
    2.1 懶惰算法,對測試樣本分類時的計算量大,內存開銷大。
    2.2 必須指定K值,K值選擇不當則分類精度不能保證
3、使用場景:小數據場景,幾千~幾萬樣本,具體場景具體業務去測試

1.8 k-近鄰算法實現

加快搜索速度——基於算法的改進KDTree,API接口裏面有實現。

1.9 k近鄰算法作業:

1、通過k-近鄰算法對生物物種進行分類——鳶尾花(load_iris)
在這裏插入圖片描述
在這裏插入圖片描述

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