04_有監督學習--分類模型--K 近鄰(kNN)

有監督學習--分類模型--K 近鄰(kNN)0.引入依賴1.數據的加載和預處理2.核心算法實現3.測試4.自動化測試python


有監督學習--分類模型--K 近鄰(kNN)

0.引入依賴

import numpy as np # 數值計算、矩陣運算、向量運算
import pandas as pd # 數值分析、科學計算

# 這裏直接引入 sklearn 裏的數據集 --> iris 鳶尾花
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split # 切分數據集爲訓練集和測試集
from sklearn.metrics import accuracy_score # 計算分類預測的準確率

1.數據的加載和預處理

iris = load_iris()
# iris # 字典
# type(iris) # sklearn.utils.Bunch

df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
# print(df)

df['class'] = iris.target
df['class'] = df['class'].map({0: iris.target_names[0], 1: iris.target_names[1], 2: iris.target_names[2]})
# df

df.describe()

輸出結果以下:算法

小測試:數組

x = iris.data
# x # x 是二維數組

# y = iris.target
# y # y 是一維數組,須要轉成二維數組

y = iris.target.reshape(-11# 變成 n 行 1 列的列向量
# y

print(x.shape, y.shape) # (150, 4) (150, 1)

輸出結果:app

(1504) (1501)

劃分訓練集和測試集:dom

# 劃分訓練集和測試集,第三個參數咱們選取簡單交叉驗證,第四個參數表示隨機劃分,第五個參數表示按照 y 的分佈等比例分割
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=35, stratify=y)

print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)

# 測試
# x_test = x_test[0].reshape(1, -1) # 將一維數組 x.test[0] 變爲 二維數組
# x_test.shape # (1, 4)
# print(x_train)
# print(x_test)
# np.sum(np.abs(x_train - x_test), axis=1)

# distances = np.array([2, 1, 5, 4, 3, 11, 15, 20, 9, 110])
# print(np.argsort(distances)) # [1 0 4 3 2 8 5 6 7 9]

# nn_index = np.argsort(distances)
# print(nn_index[0:3]) # [1 0 4]

# nn_y = y_train[nn_index[0:3]].ravel()

# print(nn_y) # [2 1 1]
# print(np.bincount(nn_y)) # [0 2 1]
# print(np.argmax(np.bincount(nn_y))) # 1

輸出結果:函數

(1054) (1051)
(454) (451)
 

2.核心算法實現

# 定義距離函數
# 曼哈頓距離的平方
def l1_distance(a, b): # 這裏要求:a 能夠是矩陣,b 必須是向量,且是行向量
    return np.sum(np.abs(a - b), axis=1# axis=1 表示將 sum 的運算結果保存成 1 列

# 歐式距離
def l2_distance(a, b): 
    return np.sqrt(np.sum((a - b) ** 2, axis=1))

# 分類器實現
class kNN(object):
    # 定義一個初始化方法,形式是 __init__ 是類的構造方法
    def __init__(self, n_neighbors=1, dist_func=l1_distance):
        self.n_neighbors = n_neighbors
        self.dist_func = dist_func

    # 定義模型的訓練方法
    def fix(self, x, y):
        self.x_train = x
        self.y_train = y

    # 定義模型的預測方法
    def predict(self, x):
        # 初始化預測分類數組
        y_pred = np.zeros((x.shape[0], 1), dtype=self.y_train.dtype)

        # 遍歷輸入的 x 數據點,取出每個數據點的序號 i 和數據 x_test
        for i, x_test in enumerate(x):
            # 計算 x_test 與各個訓練數據之間的距離
            distances = self.dist_func(self.x_train, x_test)

            # 獲得的距離按照由近到遠排序,取的是索引值
            nn_index = np.argsort(distances)

            # 選取最近的 k 個點,保存它們對應的分類類別
            nn_y = self.y_train[nn_index[0:self.n_neighbors]].ravel()

            # 統計類別中出現頻率最高的那個,賦值給 y_pred[i]
            y_pred[i] = np.argmax(np.bincount(nn_y))

        return y_pred

3.測試

# 定義一個 kNN 的實例
knn = kNN(n_neighbors=3)
# 訓練模型
knn.fix(x_train, y_train)
# 測試模型
y_pred = knn.predict(x_test)

# 求出預測的準確率
accuracy = accuracy_score(y_test, y_pred)
print('預測準確率:', accuracy)

輸出結果:學習

預測準確率: 0.9333333333333333

4.自動化測試

# 定義一個 kNN 的實例
knn = kNN()
# 訓練模型
knn.fix(x_train, y_train)

# 保存結果 list
result_list = []

# 針對不一樣的參數選取作預測
for p in [12]:
    knn.dist_func = l1_distance if p == 1 else l2_distance
    # 考慮不一樣的 k 取值
    for k in range(1102): # 1, 3, 5, 7, 9 注意:二元分類中咱們選取 k 爲奇數,可是本題中是三元分類,效果不明顯
        knn.n_neighbors = k
        # 傳入測試數據,測試模型
        y_pred = knn.predict(x_test)
        # 求出預測的準確率
        accuracy = accuracy_score(y_test, y_pred)
        result_list.append([k, 'l1_distance' if p == 1 else 'l2_distance', accuracy])

df = pd.DataFrame(result_list, columns=['k''距離函數''預測正確率'])
df

輸出結果以下:測試

相關文章
相關標籤/搜索