1. 程式人生 > >機器學習系列演算法1:KNN

機器學習系列演算法1:KNN

思路:空間上距離相近的點具有相似的特徵屬性。

執行流程:

  •1. 從訓練集合中獲取K個離待預測樣本距離最近的樣本資料;
  •2. 根據獲取得到的K個樣本資料來預測當前待預測樣本的目標屬性值 

三要素:K值選擇/距離度量(歐式距離)/決策選擇(平均值/加權平均)

Knn問題:資料量大,計算量較大;解決方案:kd-tree

kd-tree:計算方差,根據方差大的劃分

 

虛擬碼實現:

import numpy as np
from collections import defaultdict


class myknn:

    def fit(self, X, Y, k):
        self.train_x = X
        self.train_y = Y
        self.k = k

    def predict(self, X):
        predict_labels = []
        for x in X:
            # 1. 從訓練資料中獲取K個和當前待預測樣本x最相似的樣本
            neighbors = self.fetch_k_neighbors(x)
            # 2. 將這K個最相似的樣本中出現次數最多的類別作為預測值
            predict_label = self.calc_max_count_label(neighbors)
            # 3. 將當前樣本的預測值新增到臨時的列表中
            predict_labels.append(predict_label)

        return predict_labels

    def fetch_k_neighbors(self, x):
        distances = []
        for neighbor in self.train_x:
            dis = np.sqrt(np.sum((np.array(x) - neighbor) ** 2))
            distances.append(dis)
        neighbors_y_distances = [[neighbor, y, dis] for neighbor, y, dis in zip(self.train_x, self.train_y, distances)]

        k_neighbors_y = sorted(neighbors_y_distances, key=lambda x: x[2])[:self.k]
        return k_neighbors_y

    def calc_max_count_label(self, neighbors):
        y_count = defaultdict(int)
        for neighbor, y, _ in neighbors:
            y_count[y] += 1
        max_count_label = sorted(y_count.items(), key=lambda x: x[1], reverse=True)[0][0]
        return max_count_label


a = myknn()
X = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12],
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
Y = [1, 2, 3, 2, 1, 2, 3]
k = 3
a.fit(X, Y, k)
print(a.predict([[7, 8, 9], ]))
sklearn 實現:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import os

if not os.path.exists('models'): 
    os.mkdir('models')
base_path = './models/'  #模型儲存路徑

from sklearn.datasets import load_iris    #load 鳶尾花資料
from sklearn.model_selection import train_test_split  #資料分割
from sklearn.neighbors import KNeighborsClassifier  #knn分類器
from sklearn.externals import joblib   #持久化

data = pd.read_csv('iris.data', header=None)

print(data.head())
X = data.loc[:, :3] #前4列為特徵資料
Y = data[4]  #最後一列為目標資料  
print(X.head())

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=22)

'''
    def __init__(self,
            n_neighbors=5,   #鄰居數目
            weights='uniform',  #uniform 等權重/distance
            algorithm='auto', #暴力計算和kd-tree
            leaf_size=30,  #構建kd-tree 允許的最大葉子節點
            p=2,    #距離公式
            metric='minkowski', #預設歐式距離
            metric_params=None,
            n_jobs=None,  #開啟多少個執行緒計算
            **kwargs):'''

algo = KNeighborsClassifier(n_neighbors=3)
algo.fit(X_train, Y_train)
print('準確率:{}'.format(algo.score(X_train, Y_train)))

# 持久化
joblib.dump(value=algo, filename=base_path + 'knn.pkl')

機器學習開發流程:

# 1. 資料載入

# 2. 資料的清洗、處理

# 3. 訓練資料和測試資料的劃分

# 4. 特徵工程

# 5. 模型物件構建

# 6. 模型訓練

# 7. 模型效果評估

# 8. 模型持久化
"""
持久化的方式主要三種:
-1. 將模型持久化為二進位制的磁碟檔案。
-2. 將模型引數持久化到資料庫中。
-3. 使用模型對所有資料進行預測,並將預測結果儲存到資料庫中。
"""

&n