kNN學習筆記
一、kNN基礎
二、什麼是機器學習
三、超參數
四、數據歸一化
五、總結
一、kNN基礎
實現簡單
使用的數學知識少
適合入門
- 簡單的來講,KNN算法就是找出x最近鄰的k個樣本,k個樣本中,找出與之特徵相似樣本的數量最多的類別,然後將x分入該類別。
- 以上圖爲例,設k = 3,即找出與藍色的點最詳盡的三個點,很顯然,最近的三個點都爲紅色的點,那麼該藍色的點就位紅色這一類。相應的,如果藍色點的最近的三個點中有兩個點爲紅色,一個爲藍色,則仍然歸類爲紅色一類,反之亦然。
二、什麼是機器學習
- 輸入訓練數據集,在機器學習算法訓練生成模型,輸入樣例到模型之後得到預測的輸出結果
* - knn是一個不需要訓練過程的算法
- knn是特殊的,是沒有模型的算法
- 爲了和其它算法統一,可以說訓練集本身就是模型
- 訓練數據集、測試數據集
-
訓練得到的模型能夠直接在真實環境中使用
- 問題:
-
模型如果很差會造成真實損失
-
真實環境中不能拿到真實的label(target)
- 因此需要訓練數據集合測試數據集分離:
-
使用封裝好的train_test_split,或者十折交叉驗證(10-fold cross validation)
# 一個demo
# 導入封裝好了knn算法
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
from sklearn.model_selection import train_test_split
knn_clf = KNeighborsClassifier(n_neighbors = 3) #這裏的n_neighbors = 3即前面講到的k = 3
iris = datasets.load_iris() #獲取鳶尾花的數據
#用X、y來接受鳶尾花的特徵值和類別
X = iris.data
y = iris.target
#將數據分爲訓練集和測試集
X_train, x_test, y_train, y_test = train_test,split(X, y, test_size = 0.2)
#做模型訓練
knn_clf.fit(X_train, y_train)
#數據預測
y_predict = knn_clf.predict(X_test)
#滿足預測結果與實際結果相同的率,即預測成功率
rate = sum(y_predict == y_test)/y_test
#同上一列所達到的目的一樣
knn_clf.score(X_test, y_test)
#也可以使用accuracy_score來評價預測成功率
from sklearn.metrics import accuracy_score
accuracy_score(y_predict, y_test)
三、超參數
在機器學習的上下文中,超參數是在開始學習過程之前設置值的參數,而不是通過訓練得到的參數數據。通常情況下,需要對超參數進行優化,給學習機選擇一組最優超參數,以提高學習的性能和效果。
-
簡單的來說,超參數就是爲了來提高學習的性能和效果。
-
超參數:在算法運行前需要決定的參數
-
模型參數:算法過程中學習的參數
尋找好的參數:
領域知識
經驗數值
- 這就涉及了一些問題,怎麼找到最好的超參數呢?以尋找最好的k爲例:
# 可以寫在上一個代碼示例後面
best_score = 0.0
best_k = -1
# 在1-11之間尋找最好的k
for k in range(1, 11):
knn = KNeighborsClassifier(n_neighbors = k)
knn.fit(X_train, y_train)
score = knn.score(X_test, y_test)
if score > best_score:
best_score = score
best_k = k
print("best_k = ", best_k)
print("best_k = ", best_score)
-
上例只考慮了k的最好值,還有其它的超參數類型:例如:下圖中的sample最近鄰的三個點都有相應的weight,三個點中,有兩個爲藍色一類的,一個綠色,但是綠色的權重100 > 50+40,所以算上權重的話,sample應該歸爲綠色一類。代碼可以試着自己寫一下。
-
曼哈頓距離:每個維度上的差值的絕對值之和
歐拉距離:每個維度上的差值的平方之和的平方根
閔可夫斯基距離: 每個維度上的距離絕對值的p次方之和的p次方根
- 你可以思考一下閔可夫斯基距離中的p可否作爲一個超參數
- 事實上,在尋找各超參數或者模型參數的過程中,不需要自己不斷地遍歷。可以使用網格搜索(Grid Search)
param_grid = [
{
'weights':['uniform'],
'n_neighbors':[i for i in range(1,11)]
},
{
'weights':['distance'],
'n_neighbors': [i for i in range(1,11)],
'p': [i for i in range(1,6)]
}
]
from sklearn.model_selection import GridSearchCV
grid_search = GridSearchCV(knn, param_grid)
gsCV = grid_search.fit(X_train , y_train)
print(gsCV)
#
四、數據歸一化
爲什麼要進行數據歸一化呢?以下圖所示:(該圖的數據爲我現場寫的,僅作爲解釋,可能會有誤解)對如下數據做處理,X2的參數中數據明顯偏大,分類過程受到X2的影響明顯會更大,但是其中一項數據對結果的影響更大,肯定會影響到最終預測的準確率,所以做標準歸一化操作很重要,要避免某一項或某幾項會明顯影響結果的情況。
X1 | X2 | y |
---|---|---|
7 | 100 | 1 |
9 | 76 | 0 |
8 | 83 | 1 |
- 這裏給出以下兩種方式:
-
最值歸一化: 把所有的數據映射到0-1之間
使用於分佈有明顯邊界的情況;受到outlier影響較大
缺點:不能解決數據偏值很大的數據
例如:大部分的數據的值都在100以內,有小部分的重要數據在500以上,最值歸一化就難以處理,即若在預測時需要預測500以上的數據,那麼由於數據量少,預測結果就不準確 -
均值方差歸一化:將所有數據歸一到均值爲0方差爲1的分佈中
數據分佈沒有明顯的邊界;有可能存在極端數據值真實環境很有可能無法得到所有測試數據的均值和方差
對數據的歸一化也是算法的一部分,所以測試數據進行歸一化時,需要用到測試數據的均值和方差,(X_test - mean_train)/std_train, 要保存測試數據值的均值和方差,給測試訓練集使用
- 於是引入scikit-learn中的standardScaler方法:
from sklearn.preprocessing import StandardScaler
stand = StandardScaler()
stand.fit(X_train)
#打印出均值和方差
print(stand.mean_)
print(stand.scale_)
#將X_train轉化爲均值爲0,方差爲1的形式
X_train = stand.transform(X_train)
print(X_trian)
X_test_t = stand.transform(X_test)
#對現在的數據進行訓練並看最終的預測成功率
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, y_train)
knn.score(X_test, y_test)
五、總結
- knn 可以解決分類問題,天然地可以解決多分類問題且思想簡單
- knn也可以解決迴歸問題:可以瞭解KNeighborsRegressor方法
- 缺點:
- 最大缺點:效率低下。如果訓練集有m個樣本,n個特徵,則預測一個新的數據,需要O(m*n)。優化:使用KD-Tree,Ball-Tree
- 高度數據相關
- 預測結果具有不可解釋性
* (維數災難)隨着維度的增加,看似很近的兩個點之間的距離越來越大
* 解決方法:降維 PCA方法