KNN模型笔记


一、KNN模型

KNN(K近邻)模型,不会预先生成一个分类或预测模型,用于新样本的预测,而是将模型的构建与未知数据的预测同时进行。
该算法对数据的分布特征没有任何要求。

1 核心思想

比较已知y值的样本与未知y值样本的相似度,然后寻找最相似的k个样本用作未知样本的预测。
算法主要任务:

  • 确定最近邻的个数k值;
  • 用于度量样本间相似性的指标。

2 k值的选择

k值的影响:

  • k值过于偏小,可能会导致模型的过拟合;
  • 反之,又可能会使模型进入欠拟合状态

为了获得最佳的k值,可以考虑三种解决方案

  • 第一种,设置k近邻样本的投票权重。通常可以将权重设置为距离的倒数;
  • 第二种,采用多重交叉验证法,该方法是目前比较流行的方案,其核心就是将k取不同的值,然后在每种值下执行m重的交叉验证,最后选出平均误差最小的k值;
  • 第三种,结合前两种方法,选出理想的k值。

3 相似度的度量方法

  • 欧氏距离
  • 曼哈顿距离
  • 余弦相似度
  • 杰卡德相似系数

3.1 欧氏距离

该距离度量的是两点之间的直线距离。公式如下(针对点A( x 1 , x 2 , . . . , x n ) x_1,x_2,...,x_n) x1,x2,...,xn)、B( y 1 , y 2 , . . . , y n y_1,y_2,...,y_n y1,y2,...,yn)):

d A , B = ( y 1 − x 1 ) 2 + ( y 2 − x 2 ) 2 + . . . + ( y n − x n ) 2 d_{A,B}=\sqrt{(y_1-x_1)^2+(y_2-x_2)^2+...+(y_n-x_n)^2} dA,B=(y1x1)2+(y2x2)2+...+(ynxn)2

3.2 曼哈顿距离

该距离也称为“曼哈顿街区距离”,度量的是两点在轴上的相对距离总和。公式如下(针对点A( x 1 , x 2 , . . . , x n ) x_1,x_2,...,x_n) x1,x2,...,xn)、B( y 1 , y 2 , . . . , y n y_1,y_2,...,y_n y1,y2,...,yn)):

d A , B = ∣ y 1 − x 1 ∣ + ∣ y 2 − x 2 ∣ + . . . + ∣ y n − x n ∣ d_{A,B}=|y_1-x_1|+|y_2-x_2|+...+|y_n-x_n| dA,B=y1x1+y2x2+...+ynxn

3.3 余弦相似度

该相似度其实就是计算两点所构成向量夹角的余弦值,夹角越小,则余弦值越接近于1,进而能够说明两点之间越相似。公式如下(针对点A( x 1 , x 2 , . . . , x n ) x_1,x_2,...,x_n) x1,x2,...,xn)、B( y 1 , y 2 , . . . , y n y_1,y_2,...,y_n y1,y2,...,yn)):

S i m i l a r i t y A , B = cos ⁡ θ = A ⃗ ⋅ B ⃗ ∣ ∣ A ⃗ ∣ ∣ ∣ ∣ B ⃗ ∣ ∣ Similarity_{A,B}=\cos \theta=\frac{\vec{A}·\vec{B}}{\mid\mid \vec{A}\mid \mid\mid\mid\vec{B}\mid\mid} SimilarityA,B=cosθ=A B A B
其中,点·代表两个向量之间的内积,符号‖‖代表向量的模,即l2正则。

3.4 杰卡德相似系数

该相似系数与余弦相似度经常被用于推荐算法,计算用户之间的相似性。 公式如下:
J ( A , B ) = ∣ A ⋂ B ∣ ∣ A ⋃ B ∣ J(A,B)=\frac{\mid A\bigcap B\mid}{\mid A \bigcup B\mid} J(A,B)=ABAB
其中,|A∩B|表示两个用户所购买相同商品的数量,|A∪B|代表两个用户购买所有产品的数量。

使用距离方法来度量样本间的相似性时,必须注意两点:

  • 一个是所有变量的数值化;
  • 另一个是防止数值变量的量纲影响,必须采用数据的标准化方法对其归一化,使得所有变量的数值具有可比性。

4 近邻样本的搜寻方法

近邻样本的搜寻方法:

  • 暴力搜寻法:需要全表扫描,只能适合小样本的数据集
  • KD树搜寻法:不需要全表扫描
  • 球树搜寻法:不需要全表扫描

4.1 KD树搜寻法

K-Dimension Tree,K表示训练集中包含的变量个数。其最大的搜寻特点:先利用所有已知类别的样本点构造一棵树模型,然后将未知类别的测试集应用在树模型上,实现最终的预测功能。
KD树搜寻法的两个重要步骤

  • KD树的构造
  • KD树的搜寻

缺点:该方法在搜寻分布不均匀的数据集时,效率会下降很多。

4.2 球树搜寻法

球树搜寻法能够解决KD树的缺陷,是因为球树将KD树中的超矩形体换成了超球体,没有了“角”,就不容易产生模棱两可的区域。
优缺点:与KD树的思想非常相似,所不同的是,球树的最优搜寻路径复杂度提高了,但是可以避免很多无谓样本点的搜寻

球树搜寻法的两个重要步骤

  • 球树的构造
  • 球树的搜寻

5 KNN模型实例

Python中的sklearn的子模块neighbors中有关KNN算法的类:KNeighborsClassifier类(分类)和KNeighborsRegressor类(预测)。

KNeighborsClassifier(
n_neighbors=5,
weights=‘uniform’, # ‘uniform’,表示所有近邻样本的投票权重一样;如果为’distance’,则表示投票权重与距离成反比
algorithm=‘auto’, #‘ball_tree’,则表示使用球树搜寻法; ‘kd_tree’,则表示使用KD树搜寻法; ‘brute’,则表示使用暴力搜寻法
leaf_size=30, # 用于指定球树或KD树叶子节点所包含的最小样本量
p=2,
metric=‘minkowski’, # 用于指定距离的度量指标
metric_params=None,
n_jobs=None,
**kwargs,
)

以下以分类问题为例:

# 导入第三方库
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score # 交叉验证

# 读入数据
kdata = pd.read_excel(r'Knowledge.xlsx')
# --------------------构造训练集和测试集------------------------
x_columns = kdata.columns[:-1]
y_column = kdata.columns[-1]
X_train,X_test,y_train,y_test = train_test_split(kdata[x_columns],
                                                 kdata[y_column],
                                                 test_size=0.25,
                                                 random_state=111)
#-------------------使用十折交叉验证寻找最优k值-----------------
# 设置待测试的不同k值
K = np.arange(1,np.int(np.log2(kdata.shape[0])))
accuracy = [] # 用于存储不同k值10折后的模型平均准确率
for k in K:
    # 使用十折交叉验证比对不同k值的预测准确率
    cv_result = cross_val_score(KNeighborsClassifier(n_neighbors=k,
                                                     weights='distance'),
                               X_train,y_train,cv=10,scoring='accuracy')
    accuracy.append(cv_result.mean())
# -------------------可视化准确率结果-----------------------------
# 挑选出准确率最大值对应的下标
k_max_index = np.array(accuracy).argmax()
# 中文和负号的正常显示
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
plt.rcParams['axes.unicode_minus']= False
plt.plot(K,accuracy)
plt.scatter(K,accuracy)
plt.text(K[k_max_index],accuracy[k_max_index],'最佳k值为{}'.format(K[k_max_index]))
plt.show()

在这里插入图片描述

# ---------------- 根据最佳k值 构建模型-----------------------
model = KNeighborsClassifier(n_neighbors=K[k_max_index],weights='distance')
model.fit(X_train,y_train)
y_pre = model.predict(X_test)
# 构建混淆矩阵
cross_matrix = pd.crosstab(y_pre,y_test)
# 将混淆矩阵构造成数据框,并加上字段名和行名称,用于行或列的含义说明
cross_matrix = pd.DataFrame(cross_matrix)
# 绘制热力图
sns.heatmap(cross_matrix, annot = True,cmap = 'GnBu')
# 添加x轴和y轴的标签
plt.xlabel(' 真实值')
plt.ylabel(' 预测值')
# 图形显示
plt.show()

在这里插入图片描述

# ----------------- 模型评估报告 -------------------------
print(metrics.classification_report(y_test,y_pre))
类别precisionrecallf1-scoresupport
High1.000.960.9827
Low0.821.000.9033
Middle0.960.860.9129
Very Low1.000.750.8612
accuracy0.92101
macro avg0.950.890.91101
weighted avg0.930.920.92101
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

积跬步,慕至千里

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值