機器學習“傻瓜式”理解(4)KNN算法(數據處理以及超參數)

數據處理以及超參數的理解

首先我們需要瞭解到,我們在進行機器學習的過程中尋求的不是讓訓練處的在現有的數據集上達到最佳,而是我們需要讓其在真實環境中達到最佳的效果。在上一節中我們將全部的數據集全部用於訓練模型中,對於我們所訓練出的模型無法知道其具體的準確度便投入真實環境使用,這樣的做法極具風險性,而且我們也不推薦。
解決方案:機器學習最常用的解決方案便是實現測試集和訓練集的相互分離(此方法仍具有侷限性,後續會補充)。具體的操作方式是:將全部數據集的80%當做訓練數據集,訓練出來模型後我們通過另外20%的數據(稱其爲測試數據集)來驗證所訓練出來模型的準確度。
實現代碼封裝:

import numpy as np

def train_test_split(X,y,test_train = 0.2,seed = None):
    '''check'''
    assert X.shape[0] == y.shape[0],\
            "the size must be valid"
    assert 0.0 <= test_train <= 1.0,\
            "the ratio must be in 0-1"

    if seed:
        np.random.seed(seed)

    shuffle_index= np.random.permutation(len(X))

    test_ratio = test_train
    test_size = int(len(X) * test_ratio)

    test_indexes = X[:test_size]
    train_indxes = X[test_size:]

    X_train = X[train_indxes]
    X_test = X[test_indexes]

    y_train = y[train_indxes]
    y_test = y[test_indexes]

    return X_train,X_test,y_train,y_test

KNN中的超參數:

首先明確一個概念,何爲超參數?我們需要在機器學習中傳入的參數便是指的是超參數。KNN中的超參數便是K,這是KNN中我們需要關注的第一個超參數。
思考一個問題,加上K=3,距離最近的三個點之間的每個類別佔1/3,我們如何確定是屬於哪一個類別?如同下圖所示:
在這裏插入圖片描述
如上我們便引出了第二個超參數weights.
另外,我們在計算預測點和我們數據點之間的距離時使用的是歐拉距離,但是觀察下圖後你會發現:
在這裏插入圖片描述
我們便得到了超參數p。

如何才能尋找到最好的超參數?

有兩個解決方案:
①我們可以採用經驗數值,例如KNN算法中我們使用經驗數值K=5,
②網格搜索策略尋找最優參數。
問題:何爲最好的超參數?
我們需要一個評判標準,分類算法的評判標準便是模型準確度(accuracy)。
其實現代碼如下:(在庫中metrics中)

import numpy as np

def accuracy_score(y_true,y_predict):
    '''check'''
    assert y_true.shape[0] == y_predict.shape[0],\
            "the size must be valid"
    return int((np.sum(y_true == y_predict) / len(y_true)) * 100)

使用sklearn中提供的真實數據集,通過網格搜索實現尋找最優的超參數:

1.手動尋找

先進行數據的處理:

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
'''使用sklearn的手寫數字集'''
digits = datasets.load_digits()
X = digits.data
y = digits.target
X_train,X_test,y_train,y_test = train_test_split(X,y)

分爲兩種情況:
①尋找最優的超參數K和method(即是否考慮權重信息)

from sklearn.neighbors import KNeighborsClassifier
best_k = -1
best_score = 0.0
best_method = ""
best_p = ""

'''1.尋找最優的超參數K和weight'''
'''uniform:不考慮預測點與數據點的距離,distance正好相反'''
for method in ["uniform","distance"]:
    for k in range(1,11):
        knn_cif = KNeighborsClassifier(n_neighbors = k)
        knn_cif.fit(X_train,y_train)
        knn_score = knn_cif.score(X_test,y_test)
        if knn_score > best_score:
            best_score = knn_score
            best_k = k
            best_method = method


'''得出結果'''
print("考慮的方法",best_method)
print("使用的k值",best_k)
print("得出的精準度爲",best_score)

運行結果如下:
result
②尋找最優的超參數K和P(此時不需要考慮method,因爲若需要考慮P,則默認method=‘distance’)

for k in range(1,11):
    for p in range(1,6):
        knn_cif = KNeighborsClassifier(n_neighbors = k,weights="distance",p = p)
        knn_cif.fit(X_train,y_train)
        knn_score = knn_cif.score(X_test,y_test)
        if knn_score > best_score:
            best_score = knn_score
            best_k = k
            best_p = p


'''得出結果'''
print("考慮的P值",best_p)
print("使用的k值",best_k)
print("得出的精準度爲",best_score)

運行結果如下:
result2
補充:
模型參數:我們在機器學習過程中學到的參數,KNN算法中是沒有模型參數的,後面我們講到的線性迴歸和邏輯迴歸具有模型參數。

2.Sklearn中提供的網格搜索工具
from sklearn.model_selection import GridSearchCV
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)]
    }
]

knn_cif = KNeighborsClassifier()
'''
參數介紹:n_jobs,使用處理的電腦內核的個數,默認爲1,表示使用一個內核,爲-1表示使用全部內核
        verbose:表示學習過程中輸出信息,一般爲2,數越大,輸出信息越詳細
'''
grid_search = GridSearchCV(knn_cif,param_grid,n_jobs = -1,verbose = 2)
grid_search.fit(X_train,y_train)
print("最優結果:",grid_search.best_params_)

運行過程以及結果顯示:
proandresult

數據的歸一化處理

我這裏不長篇大論概述,我繪製了一張圖,通過下圖便可初步瞭解數據的歸一化:
歸一化
在這裏插入圖片描述
Sklearn中的歸一化處理:
分爲兩個步驟:fit->tranform
在這裏插入圖片描述
歸一化的封裝代碼:

import numpy as np

class StandardScaler:
    def __init__(self):
        self.mean_ = None
        self.std_ = None

    def fit(self,X):
        '''according to X get mean and std'''
        '''check'''
        assert X.ndim == 2,"the dimension must be 2"

        self.mean_ = np.array([np.mean[:,i] for i in range(0,X.shape[1])])
        self.std_ = np.array([np.std[:,i] for i in range(0,X.shape[1])])

        return self
    def transform(self,X):
        '''check'''
        assert self.mean_ is not None and self.std_ is not None,\
                "fit before transform"
        assert X.ndim == 2,"the dimension must be 2"
        assert X.shape[1] == len(self.mean_),\
                "the value must be valid"

        resX = np.empty(shape=X.shape,dtype=float)
        for col in range(X.shape[1]):
            resX[:,col] = (X[:,col] - self.mean_[col]) / self.std_[col]

        return resX

sklearn中的使用和封裝類似
總結:
在這裏插入圖片描述

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