机器学习-实现KNN算法

135 阅读3分钟

实现KNN算法前, 引入余弦相似度欧式距离

1.余弦相似度

  • 是从向量的角度看待数据
  • 向量间的余弦值越大, 向量越相似(数据越相似=》 也就是cos0°=1, 夹角为0°)

2.欧式距离

  • 是把数据看作欧式空间中的一个点
  • 计算欧式空间中两点之间的直线距离, 距离越小, 越相似

3.求两个向量的余弦

无标题.png

  • A * B: A向量与B向量的内积(点积)=》 两向量对应相乘在相加,结果为一个标量
  • |A| * |B|:A向量的模与B向量的模相乘, 向量A模=(x1²+y1²)的 平方根
  • cosθ= A * B / |A| * | B|
a = [1, 2]
b = [3, 4]
# a@b = 1*3+2*4, @=>点积,内积
# |a|= (1²+2²)**0.5
# 求向量的模, 也就是求二范数
np.linalg.norm(a)
#两向量的夹角
a1 = (a**2).sum()**0.5
b2 = (b**2).sum()**0.5
a@b/a1/b2 #两向量的余弦值
#同 a@b/np.linalg.norm(a)/np.linalg.norm(b)

4. 求欧式空间中两点的距离

无标题3.png

  • 两点的距离 = (x1-x2)²+(y1-y2)²和的平方根
a = [-2, 5]
b = [1, 3]
distance = (a-b)**2.sum()**0.5
#引入平行四边形法则, 把对应点, 看作是一个从原点出发的向量, ab两点的距离等同与 a向量-b向量的模
np.linalg.norm(a-b)

4.实现knn

from collections import Counter
from numpy as np
class CustomKNeighborsClassifier(object):
    def __init__(self, n_neighbors = 5):
        self.n_neighbors = n_neighbors
    
    def fit(self, X, y):
        self.X = X   # 测试集
        self.y = y   # 测试集的标签
   
   def predict(self, X):
       result = []
       for x in X:
           #求欧式距离
            distance = (self.X - x)**2.sum(asix=1)**0.5
           #获取距离最近的K个label的索引(假设self.X 传进来150个样本, 通过求x与150个样本的欧式距离, 产生150个结果)
            index = distance.algsort()[:self.neighbors] #先排序, 然后取前K个
            #获取对应的标签
            labels = self.y[index]
            #根据测试集中的标签, 计算匹配最多的标签,就是最后的结果标签
            finaly_label = Counter(labels).most_common(1)[0][0]
            result.append(finaly_label)
       retrun np.array(result)

5. 实现knn回归

from collections import Counter
from numpy as np
class CustomKNeighborsRegressor(object):
    def __init__(self, n_neighbors = 5):
        self.n_neighbors = n_neighbors
    
    def fit(self, X, y):
        self.X = X   # 测试集
        self.y = y   # 测试集的标签
   
   def predict(self, X):
       result = []
       for x in X:
           #求欧式距离
            distance = (self.X - x)**2.sum(asix=1)**0.5
           #获取距离最近的K个label的索引(假设self.X 传进来150个样本, 通过求x与150个样本的欧式距离, 产生150个结果)
            index = distance.algsort()[:self.neighbors] #先排序, 然后取前K个
            #获取对应的标签
            labels = self.y[index]
            #求标签和的均值,就是最后预测的结果
            finaly_label = labels.mean()
            result.append(finaly_label)
       retrun np.array(result)

6.使用

  • 使用一个房价数据集,并且切分数据
import panda as pd
from sklearn.model_selection import train_test_split
import numpy as np

datas = pd.read_csv(filepath_or_buffer="boston_house_prices.csv", skiprows=1)
X = datas.drop(columns=["MEDV"]).to_numpy
y = datas["MEDV"].to_numpy
#切分数据
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=0)

#实例化模型
knn = CustomKNeighborsRegressor(n_neighbors = 5)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
#评估模型
#MAE(平均绝对值误差)
abs(y_pred-y_test).mean()
#MSE(均方误差)
((y_pred-y_test)**2).mean()