实现KNN算法前, 引入余弦相似度和欧式距离
1.余弦相似度
- 是从向量的角度看待数据
- 向量间的余弦值越大, 向量越相似(数据越相似=》 也就是cos0°=1, 夹角为0°)
2.欧式距离
- 是把数据看作欧式空间中的一个点
- 计算欧式空间中两点之间的直线距离, 距离越小, 越相似
3.求两个向量的余弦
- 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. 求欧式空间中两点的距离
- 两点的距离 = (x1-x2)²+(y1-y2)²和的平方根
a = [-2, 5]
b = [1, 3]
distance = (a-b)**2.sum()**0.5
#引入平行四边形法则, 把对应点, 看作是一个从原点出发的向量, a与b两点的距离等同与 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()