【機器學習演算法】KNN鳶尾花種類預測案例和特徵預處理。全md文件筆記(已分享,附程式碼)

發表於2024-02-26

本系列文章md筆記(已分享)主要討論機器學習演算法相關知識。機器學習演算法文章筆記以演算法、案例為驅動的學習,伴隨淺顯易懂的數學知識,讓大家掌握機器學習常見演算法原理,應用Scikit-learn實現機器學習演算法的應用,結合場景解決實際問題。包括K-近鄰演算法,線性迴歸,邏輯迴歸,決策樹演算法,整合學習,聚類演算法。K-近鄰演算法的距離公式,應用LinearRegression或SGDRegressor實現迴歸預測,應用LogisticRegression實現邏輯迴歸預測,應用DecisionTreeClassifier實現決策樹分類,應用RandomForestClassifie實現隨機森林演算法,應用Kmeans實現聚類任務。

全套筆記和程式碼自取移步gitee倉庫: gitee倉庫獲取完整文件和程式碼

感興趣的小夥伴可以自取哦,歡迎大家點贊轉發~


共 7 章,44 子模組

K-近鄰演算法

學習目標

  • 掌握K-近鄰演算法實現過程
  • 知道K-近鄰演算法的距離公式
  • 知道K-近鄰演算法的超引數K值以及取值問題
  • 知道kd樹實現搜尋的過程
  • 應用KNeighborsClassifier實現分類
  • 知道K-近鄰演算法的優缺點
  • 知道交叉驗證實現過程
  • 知道超引數搜尋過程
  • 應用GridSearchCV實現演算法引數的調優

1.8 案例:鳶尾花種類預測—流程實現

1 再識K-近鄰演算法API

  • sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm='auto')

    • n_neighbors:

      • int,可選(預設= 5),k_neighbors查詢預設使用的鄰居數
    • algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’}

      • 快速k近鄰搜尋演算法,預設引數為auto,可以理解為演算法自己決定合適的搜尋演算法。除此之外,使用者也可以自己指定搜尋演算法ball_tree、kd_tree、brute方法進行搜尋,

        • brute是蠻力搜尋,也就是線性掃描,當訓練集很大時,計算非常耗時。
        • kd_tree,構造kd樹儲存資料以便對其進行快速檢索的樹形資料結構,kd樹也就是資料結構中的二叉樹。以中值切分構造的樹,每個結點是一個超矩形,在維數小於20時效率高。
        • ball tree是為了克服kd樹高緯失效而發明的,其構造過程是以質心C和半徑r分割樣本空間,每個節點是一個超球體。

2 案例:鳶尾花種類預測

2.1 資料集介紹

Iris資料集是常用的分類實驗資料集,由Fisher, 1936收集整理。Iris也稱鳶尾花卉資料集,是一類多重變數分析的資料集。關於資料集的具體介紹:

img

2.2 步驟分析

  • 1.獲取資料集
  • 2.資料基本處理
  • 3.特徵工程
  • 4.機器學習(模型訓練)
  • 5.模型評估

2.3 程式碼過程

  • 匯入模組
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
  • 先從sklearn當中獲取資料集,然後進行資料集的分割
  
  
# 1.獲取資料集
  
  
iris = load_iris()

  
  
# 2.資料基本處理
  
  
  
  
# x_train,x_test,y_train,y_test為訓練集特徵值、測試集特徵值、訓練集目標值、測試集目標值
  
  
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22)
  • 進行資料標準化

    • 特徵值的標準化
  
  
# 3、特徵工程:標準化
  
  
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
  • 模型進行訓練預測
  
  
# 4、機器學習(模型訓練)
  
  
estimator = KNeighborsClassifier(n_neighbors=9)
estimator.fit(x_train, y_train)
  
  
# 5、模型評估
  
  
  
  
# 方法1:比對真實值和預測值
  
  
y_predict = estimator.predict(x_test)
print("預測結果為:\n", y_predict)
print("比對真實值和預測值:\n", y_predict == y_test)
  
  
# 方法2:直接計算準確率
  
  
score = estimator.score(x_test, y_test)
print("準確率為:\n", score)

1.9 練一練

同學之間討論剛才完成的機器學習程式碼,並且確保在自己的電腦是哪個執行成功

總結

  • 在本案例中,具體完成內容有:
  • 使用視覺化載入和探索資料,以確定特徵是否能將不同類別分開。
  • 透過標準化數字特徵並隨機抽樣到訓練集和測試集來準備資料。
  • 透過統計學,精確度度量進行構建和評估機器學習模型。
  • k近鄰演算法總結
  • 優點:
  * **簡單有效**
  * **重新訓練的代價低**
  * **適合類域交叉樣本**
     * KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對於類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更為適合。

  * **適合大樣本自動分類**
     * 該演算法比較適用於樣本容量比較大的類域的自動分類,而那些樣本容量較小的類域採用這種演算法比較容易產生誤分。

  • 缺點:
  * **惰性學習**
     * KNN演算法是懶散學習方法(lazy learning,基本上不學習),一些積極學習的演算法要快很多

  * **類別評分不是規格化**
     * 不像一些透過機率評分的分類

  * **輸出可解釋性不強**
     * 例如決策樹的輸出可解釋性就較強

  * **對不均衡的樣本不擅長**
     * 當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本佔多數。該演算法只計算“最近的”鄰居樣本,某一類的樣本數量很大,那麼或者這類樣本並不接近目標樣本,或者這類樣本很靠近目標樣本。無論怎樣,數量並不能影響執行結果。可以採用權值的方法(和該樣本距離小的鄰居權值大)來改進。

  * **計算量較大**
     * 目前常用的解決方法是事先對已知樣本點進行剪輯,事先去除對分類作用不大的樣本。






1.10 交叉驗證,網格搜尋

1 什麼是交叉驗證(cross validation)

交叉驗證:將拿到的訓練資料,分為訓練和驗證集。以下圖為例:將資料分成4份,其中一份作為驗證集。然後經過4次(組)的測試,每次都更換不同的驗證集。即得到4組模型的結果,取平均值作為最終結果。又稱4折交叉驗證。

1.1 分析

我們之前知道資料分為訓練集和測試集,但是為了讓從訓練得到模型結果更加準確。做以下處理

  • 訓練集:訓練集+驗證集
  • 測試集:測試集

1.2 為什麼需要交叉驗證

交叉驗證目的:為了讓被評估的模型更加準確可信

問題:那麼這個只是對於引數得出更好的結果,那麼怎麼選擇或者調優引數呢?

2 什麼是網格搜尋(Grid Search)

通常情況下,有很多引數是需要手動指定的(如k-近鄰演算法中的K值),這種叫超引數。但是手動過程繁雜,所以需要對模型預設幾種超引數組合。每組超引數都採用交叉驗證來進行評估。最後選出最優引數組合建立模型。

3 交叉驗證,網格搜尋(模型選擇與調優)API:

  • sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)

    • 對估計器的指定引數值進行詳盡搜尋
    • estimator:估計器物件
    • param_grid:估計器引數(dict){“n_neighbors”:[1,3,5]}
    • cv:指定幾折交叉驗證
    • fit:輸入訓練資料
    • score:準確率
    • 結果分析:

      • bestscore__:在交叉驗證中驗證的最好結果
      • bestestimator:最好的引數模型
      • cvresults:每次交叉驗證後的驗證集準確率結果和訓練集準確率結果

4 鳶尾花案例增加K值調優

  • 使用GridSearchCV構建估計器
  
  
# 1、獲取資料集
  
  
iris = load_iris()
  
  
# 2、資料基本處理 -- 劃分資料集
  
  
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
  
  
# 3、特徵工程:標準化
  
  
  
  
# 例項化一個轉換器類
  
  
transfer = StandardScaler()
  
  
# 呼叫fit_transform
  
  
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
  
  
# 4、KNN預估器流程
  
  
  
  
#  4.1 例項化預估器類
  
  
estimator = KNeighborsClassifier()

  
  
# 4.2 模型選擇與調優——網格搜尋和交叉驗證
  
  
  
  
# 準備要調的超引數
  
  
param_dict = {"n_neighbors": [1, 3, 5]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
  
  
# 4.3 fit資料進行訓練
  
  
estimator.fit(x_train, y_train)
  
  
# 5、評估模型效果
  
  
  
  
# 方法a:比對預測結果和真實值
  
  
y_predict = estimator.predict(x_test)
print("比對預測結果和真實值:\n", y_predict == y_test)
  
  
# 方法b:直接計算準確率
  
  
score = estimator.score(x_test, y_test)
print("直接計算準確率:\n", score)
  • 然後進行評估檢視最終選擇的結果和交叉驗證的結果
print("在交叉驗證中驗證的最好結果:\n", estimator.best_score_)
print("最好的引數模型:\n", estimator.best_estimator_)
print("每次交叉驗證後的準確率結果:\n", estimator.cv_results_)
  • 最終結果
比對預測結果和真實值:
 [ True  True  True  True  True  True  True False  True  True  True  True
  True  True  True  True  True  True False  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True]
直接計算準確率:
 0.947368421053
在交叉驗證中驗證的最好結果:
 0.973214285714
最好的引數模型:
 KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform')
每次交叉驗證後的準確率結果:
 {'mean_fit_time': array([ 0.00114751,  0.00027037,  0.00024462]), 'std_fit_time': array([  1.13901511e-03,   1.25300249e-05,   1.11011951e-05]), 'mean_score_time': array([ 0.00085751,  0.00048693,  0.00045625]), 'std_score_time': array([  3.52785082e-04,   2.87650037e-05,   5.29673344e-06]), 'param_n_neighbors': masked_array(data = [1 3 5],
             mask = [False False False],
       fill_value = ?)
, 'params': [{'n_neighbors': 1}, {'n_neighbors': 3}, {'n_neighbors': 5}], 'split0_test_score': array([ 0.97368421,  0.97368421,  0.97368421]), 'split1_test_score': array([ 0.97297297,  0.97297297,  0.97297297]), 'split2_test_score': array([ 0.94594595,  0.89189189,  0.97297297]), 'mean_test_score': array([ 0.96428571,  0.94642857,  0.97321429]), 'std_test_score': array([ 0.01288472,  0.03830641,  0.00033675]), 'rank_test_score': array([2, 3, 1], dtype=int32), 'split0_train_score': array([ 1.        ,  0.95945946,  0.97297297]), 'split1_train_score': array([ 1.        ,  0.96      ,  0.97333333]), 'split2_train_score': array([ 1.  ,  0.96,  0.96]), 'mean_train_score': array([ 1.        ,  0.95981982,  0.96876877]), 'std_train_score': array([ 0.        ,  0.00025481,  0.0062022 ])}

1.11 案例2:預測facebook簽到位置

1 資料集介紹

FBlocationä"ç"

資料介紹:將根據使用者的位置,準確性和時間戳預測使用者正在檢視的業務。

train.csv,test.csv 
row_id:登記事件的ID
xy:座標
準確性:定位準確性 
時間:時間戳
place_id:業務的ID,這是您預測的目標
官網:https://www.kaggle.com/navoshta/grid-knn/data

2 步驟分析

  • 對於資料做一些基本處理(這裡所做的一些處理不一定達到很好的效果,我們只是簡單嘗試,有些特徵我們可以根據一些特徵選擇的方式去做處理)

    • 1 縮小資料集範圍 DataFrame.query()
    • 2 選取有用的時間特徵
    • 3 將簽到位置少於n個使用者的刪除
  • 分割資料集
  • 標準化處理
  • k-近鄰預測

3 程式碼過程

  • 1.獲取資料集
  
  
# 1、獲取資料集
  
  
facebook = pd.read_csv("./data/FBlocation/train.csv")
  • 2.基本資料處理
  
  
# 2.基本資料處理
  
  
  
  
# 2.1 縮小資料範圍
  
  
facebook_data = facebook.query("x>2.0 & x<2.5 & y>2.0 & y<2.5")
  
  
# 2.2 選擇時間特徵
  
  
time = pd.to_datetime(facebook_data["time"], unit="s")
time = pd.DatetimeIndex(time)
facebook_data["day"] = time.day
facebook_data["hour"] = time.hour
facebook_data["weekday"] = time.weekday
  
  
# 2.3 去掉簽到較少的地方
  
  
place_count = facebook_data.groupby("place_id").count()
place_count = place_count[place_count["row_id"]>3]
facebook_data = facebook_data[facebook_data["place_id"].isin(place_count.index)]
  
  
# 2.4 確定特徵值和目標值
  
  
x = facebook_data[["x", "y", "accuracy", "day", "hour", "weekday"]]
y = facebook_data["place_id"]
  
  
# 2.5 分割資料集
  
  
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)
  • 特徵工程--特徵預處理(標準化)
  
  
# 3.特徵工程--特徵預處理(標準化)
  
  
  
  
# 3.1 例項化一個轉換器
  
  
transfer = StandardScaler()
  
  
# 3.2 呼叫fit_transform
  
  
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
  • 機器學習--knn+cv
  
  
# 4.機器學習--knn+cv
  
  
  
  
# 4.1 例項化一個估計器
  
  
estimator = KNeighborsClassifier()
  
  
# 4.2 呼叫gridsearchCV
  
  
param_grid = {"n_neighbors": [1, 3, 5, 7, 9]}
estimator = GridSearchCV(estimator, param_grid=param_grid, cv=5)
  
  
# 4.3 模型訓練
  
  
estimator.fit(x_train, y_train)
  • 模型評估
  
  
# 5.模型評估
  
  
  
  
# 5.1 基本評估方式
  
  
score = estimator.score(x_test, y_test)
print("最後預測的準確率為:\n", score)

y_predict = estimator.predict(x_test)
print("最後的預測值為:\n", y_predict)
print("預測值和真實值的對比情況:\n", y_predict == y_test)

  
  
# 5.2 使用交叉驗證後的評估方式
  
  
print("在交叉驗證中驗證的最好結果:\n", estimator.best_score_)
print("最好的引數模型:\n", estimator.best_estimator_)
print("每次交叉驗證後的驗證集準確率結果和訓練集準確率結果:\n",estimator.cv_results_)

未完待續, 同學們請等待下一期

全套筆記和程式碼自取移步gitee倉庫: gitee倉庫獲取完整文件和程式碼

感興趣的小夥伴可以自取哦,歡迎大家點贊轉發~

相關文章