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


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


有監督學習--分類模型--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)

輸出結果:

(1504) (1501)

划分訓練集和測試集:

# 划分訓練集和測試集,第三個參數我們選取簡單交叉驗證,第四個參數表示隨機划分,第五個參數表示按照 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

輸出結果如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM