機器學習入門之KNN算法和交叉驗證與超參數搜索(三)
文章目錄
- 機器學習入門之KNN算法和交叉驗證與超參數搜索(三)
- 一、KNN算法-分類
- 1. 樣本距離判斷
- 明可夫斯基距離
- 2. KNN 算法原理
- 3. KNN 的缺點
- 4. KNN 的 API
- 5. 使用 sklearn 實現 KNN 示例
- 6. 模型保存與加載
- 二、模型選擇與調優:交叉驗證與超參數搜索
- 1. 交叉驗證
- (1) 保留交叉驗證(HoldOut)
- (2) K-折交叉驗證(K-fold)
- (3) 分層 K-折交叉驗證(Stratified K-fold)
- (4) 其他驗證方法
- (5) API 示例
- 2. 超參數搜索(網格搜索,Grid Search)
- 3. sklearn API
- 4. 示例:鳶尾花分類
一、KNN算法-分類
1. 樣本距離判斷
KNN 算法中,樣本之間的距離是判斷相似性的關鍵。常見的距離度量方式包括:
明可夫斯基距離
- 歐式距離:明可夫斯基距離的特殊情況,公式為 (\sqrt{\sum_{i=1}^{n}(x_i - y_i)^2})。
- 曼哈頓距離:明可夫斯基距離的另一種特殊情況,公式為 (\sum_{i=1}^{n}|x_i - y_i|)。
2. KNN 算法原理
K-近鄰算法(K-Nearest Neighbors,簡稱 KNN)是一種基于實例的學習方法。其核心思想是:如果一個樣本在特征空間中的 k 個最相似(最鄰近)樣本中的大多數屬于某個類別,則該樣本也屬于這個類別。例如,假設我們有 10000 個樣本,選擇距離樣本 A 最近的 7 個樣本,其中類別 1 有 2 個,類別 2 有 3 個,類別 3 有 2 個,則樣本 A 被認為屬于類別 2。
3. KNN 的缺點
- 計算量大:對于大規模數據集,需要計算測試樣本與所有訓練樣本的距離。
- 維度災難:在高維數據中,距離度量可能變得不那么有意義。
- 參數選擇:需要選擇合適的 k 值和距離度量方式,這可能需要多次實驗和調整。
4. KNN 的 API
class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, algorithm='auto')
- 參數:
n_neighbors
:用于 kneighbors 查詢的近鄰數,默認為 5。algorithm
:找到近鄰的方式,可選值為{'auto', 'ball_tree', 'kd_tree', 'brute'}
,默認為'auto'
。
- 方法:
fit(X, y)
:使用 X 作為訓練數據和 y 作為目標數據。predict(X)
:預測提供的數據,返回預測結果。
5. 使用 sklearn 實現 KNN 示例
以下是一個使用 KNN 算法對鳶尾花進行分類的完整代碼示例:
# 用 KNN 算法對鳶尾花進行分類
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier# 1)獲取數據
iris = load_iris()
print(iris.data.shape) # (150, 4)
print(iris.feature_names) # ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(iris.target.shape) # (150,)
print(iris.target) # [0 0 0 ... 2 2 2]
print(iris.target_names) # ['setosa' 'versicolor' 'virginica']# 2)劃分數據集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)# 3)特征工程:標準化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)# 4)KNN 算法預估器
estimator = KNeighborsClassifier(n_neighbors=7)
estimator.fit(x_train, y_train)# 5)模型評估
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("直接比對真實值和預測值:\n", y_test == y_predict)
score = estimator.score(x_test, y_test)
print("準確率為:\n", score) # 0.9473684210526315
6. 模型保存與加載
使用 joblib
可以方便地保存和加載模型:
import joblib# 保存模型
joblib.dump(estimator, "my_knn.pkl")# 加載模型
estimator = joblib.load("my_knn.pkl")# 使用模型預測
y_test = estimator.predict([[0.4, 0.2, 0.4, 0.7]])
print(y_test)
以下是整理后的 Markdown 格式內容:
二、模型選擇與調優:交叉驗證與超參數搜索
1. 交叉驗證
交叉驗證是評估模型性能的重要方法,常見的交叉驗證技術包括:
(1) 保留交叉驗證(HoldOut)
- 原理:將數據集隨機劃分為訓練集和驗證集,通常比例為 70% 訓練集和 30% 驗證集。
- 優點:簡單易行。
- 缺點:
- 不適用于不平衡數據集。
- 一部分數據未參與訓練,可能導致模型性能不佳。
(2) K-折交叉驗證(K-fold)
- 原理:將數據集劃分為 K 個大小相同的部分,每次使用一個部分作為驗證集,其余部分作為訓練集,重復 K 次。
- 優點:充分利用數據,模型性能更穩定。
- 缺點:計算量較大。
(3) 分層 K-折交叉驗證(Stratified K-fold)
- 原理:在每一折中保持原始數據中各個類別的比例關系,確保每個折疊的類別分布與整體數據一致。
- 優點:適用于不平衡數據集,驗證結果更可信。
(4) 其他驗證方法
- 留一交叉驗證:每次只留一個樣本作為驗證集。
- 蒙特卡羅交叉驗證:隨機劃分訓練集和測試集,多次重復。
- 時間序列交叉驗證:適用于時間序列數據。
(5) API 示例
from sklearn.model_selection import StratifiedKFoldstrat_k_fold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
indexs = strat_k_fold.split(X, y)for train_index, test_index in indexs:X_train, X_test = X[train_index], X[test_index]y_train, y_test = y[train_index], y[test_index]
2. 超參數搜索(網格搜索,Grid Search)
網格搜索是一種自動尋找最佳超參數的方法,通過遍歷所有可能的參數組合來找到最優解。
3. sklearn API
from sklearn.model_selection import GridSearchCVGridSearchCV(estimator, param_grid, cv=5)
- 參數:
estimator
:模型實例。param_grid
:超參數的網格,例如{"n_neighbors": [1, 3, 5, 7, 9, 11]}
。cv
:交叉驗證的折數,默認為 5。
- 屬性:
best_params_
:最佳參數。best_score_
:最佳模型的交叉驗證分數。best_estimator_
:最佳模型實例。cv_results_
:交叉驗證結果。
4. 示例:鳶尾花分類
以下是一個使用 KNN 算法對鳶尾花進行分類的完整代碼示例,結合了分層 K-折交叉驗證和網格搜索:
from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler# 加載數據
iris = load_iris()
X = iris.data
y = iris.target# 初始化分層 K-折交叉驗證器
strat_k_fold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)# 創建 KNN 分類器實例
knn = KNeighborsClassifier()# 網格搜索與交叉驗證
param_grid = {"n_neighbors": [1, 3, 5, 7, 9, 11]}
grid_search = GridSearchCV(knn, param_grid, cv=strat_k_fold)
grid_search.fit(X, y)# 輸出結果
print("最佳參數:", grid_search.best_params_) # {'n_neighbors': 3}
print("最佳準確率:", grid_search.best_score_) # 0.9553030303030303
print("最佳模型:", grid_search.best_estimator_) # KNeighborsClassifier(n_neighbors=3)
通過分層 K-折交叉驗證和網格搜索,我們可以找到最優的超參數,從而提高模型的性能。