KNN

1.KNN:
knn算法( k nearest neighbor也叫K临近算法)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
2.KNN三要素:
(1)***K 值***的选择会对算法的结果产生重大影响。K值较小意味着只有与输入实例较近的训练实例才会对预测结果起作用,但容易发生过拟合;如果 K 值较大,优点是可以减少学习的估计误差,但缺点是学习的近似误差增大,这时与输入实例较远的训练实例也会对预测起作用,使预测发生错误。
在实际应用中,K 值一般选择一个较小的数值,通常采用交叉验证的方法来选择最优的 K 值。随着训练实例数目趋向于无穷和 K=1 时,误差率不会超过贝叶斯误差率贝叶斯误差率的2倍,如果K也趋向于无穷,则误差率趋向于贝叶斯误差率。
(2)***分类决策***多数表决法:多数表决法和我们日常生活中的投票表决是一样的,少数服从多数,是最常用的一种方法。
加权表决法:有些情况下会使用到加权表决法,比如投票的时候裁判投票的权重更大,而一般人的权重较小。所以在数据之间有权重的情况下,一般采用加权表决法
(3)***距离度量***一般采用Lp 距离,当p=2时,即为欧氏距离,在度量之前,应该将每个属性的值规范化,这样有助于防止具有较大初始值域的属性比具有较小初始值域的属性的权重过大。
距离度量,说白了就是距离计算公式。常见的距离计算公式有如下:
1).曼哈顿距离
2).欧氏距离
3).余弦距离
4).皮尔逊相关系数
5).杰卡德距离与杰卡德相关系数
6).闵可夫斯基距离
7).切比雪夫距离
8).汉明距离
9).莱文斯坦距离
交叉验证方法
Hold-Out: 随机从最初的样本中选出部分,形成交叉验证数据,而剩余的就当做训练数据。 一般来说,少于原本样本三分之一的数据被选做验证数据。常识来说,Holdout 验证并非一种交叉验证,因为数据并没有交叉使用。
K-foldcross-validation:K折交叉验证,初始采样分割成K个子样本,一个单独的子样本被保留作为验证模型的数据,其他K-1个样本用来训练。交叉验证重复K次,每个子样本验证一次,平均K次的结果或者使用其它结合方式,最终得到一个单一估测。这个方法的优势在于,同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次,10折交叉验证是最常用的。
Leave-One-Out Cross Validation:正如名称所建议, 留一验证(LOOCV)意指只使用原本样本中的一项来当做验证资料, 而剩余的则留下来当做训练资料。 这个步骤一直持续到每个样本都被当做一次验证资料。 事实上,这等同于 K-fold 交叉验证是一样的,其中K为原本样本个数。
算法步骤
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
在这里插入图片描述

代码实现

import matplotlib.pyplot as plt
import matplotlib
from math import sqrt

#############################初始化数据集###################################
data_A = [[1,2],[3.2,4],[4,7],[5.2,3],[7,4.1]]#数据集A
data_B = [[2.2,5.5],[4.2,2],[5,5],[6.3,7]]#数据集B
test_data = [[4.5,4.5]]#测试集
len_A = len(data_A)
len_B = len(data_B)

############################计算距离并排序####################################
distance_A = []#与A类数据之间的距离
distance_B = []#与B类数据之间的距离
distance = []#全部距离
#计算距离(使用欧氏距离)
for i in range(len_A):
    d = sqrt((test_data[0][0]-data_A[i][0])**2+(test_data[0][1]-data_A[i][1])**2)
    distance_A.append(d)
for i in range(len_B):
    d = sqrt((test_data[0][0]-data_B[i][0])**2+(test_data[0][1]-data_B[i][1])**2)
    distance_B.append(d)
#由小到大排序(此处使用冒泡排序)
distance = distance_A + distance_B
for i in range(len(distance)-1):
    for j in range(len(distance)-i-1):
        if distance[j] > distance[j+1]:
            distance[j],distance[j+1]=distance[j+1],distance[j]
print("距离所有A类数据的距离为:")
print(distance_A)
print("距离所有B类数据的距离为:")
print(distance_B)
print()
print("对所有的距离升序排序:")
print(distance)
print()

######################按K最近领对测试集进行分类##################################
K = 5#这里默认K值为5,也可以自行更改
number_A = 0
number_B = 0
#定义删除函数,避免对同一个数据重复计算
def delete(a,b,ls):
    for i in range(b):
        if ls[i]==a:
            ls.pop(i)
            break
#找出与测试数据最接近的K个点
for i in range(K):
    if distance[i] in distance_A:
        number_A += 1
        delete(distance[i],len(distance_A),distance_A)
        continue
    if distance[i] in distance_B:
        number_B += 1
        delete(distance[i],len(distance_B),distance_B)
        continue
print("最终结果:")
print("距离待测数据最近的K={:}个数据中,A类数据有{:}个,B类数据有{:}个".format(K,number_A,number_B))
if number_A > number_B:
    print("所以K={:}时,待测数据划分为A类".format(K))
else:
    print("所以K={:}时,待测数据划分为B类".format(K))

#################################画图##########################################
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
for i in range(len_A):#A类,用红色三角形表示
    if i!=len_A-1:
        plt.plot(data_A[i][0],data_A[i][1],'bo',marker='^',color='red')
    else:
        plt.plot(data_A[i][0],data_A[i][1],'bo',marker='^',label='A',color='r')
    #使用if..else...是为了避免在图形中重复出现多个标签
for i in range(len_B):#B类,用蓝色正方形表示
    if i!=len_B-1:
        plt.plot(data_B[i][0],data_B[i][1],'bo',marker='s',color='blue')
    else:
        plt.plot(data_B[i][0],data_B[i][1],'bo',marker='s',label='B',color='b')
plt.plot(test_data[0][0],test_data[0][1],'bo',label='待测数据',color='g')#测试集
plt.xlim(0,10)
plt.ylim(0,10)
plt.legend()
plt.show()

在这里插入图片描述
输出结果:
距离所有A类数据的距离为:
[4.301162633521313, 1.3928388277184118, 2.5495097567963922, 1.6552945357246849, 2.5317977802344327]
距离所有B类数据的距离为:
[2.5079872407968904, 2.5179356624028344, 0.7071067811865476, 3.080584360149872]

对所有的距离升序排序:
[0.7071067811865476, 1.3928388277184118, 1.6552945357246849, 2.5079872407968904, 2.5179356624028344, 2.5317977802344327, 2.5495097567963922, 3.080584360149872, 4.301162633521313]

最终结果:
距离待测数据最近的K=5个数据中,A类数据有2个,B类数据有3个
所以K=5时,待测数据划分为B类

算法优缺点
优点:精度高、对异常值不敏感、无数据输入假定。KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。
缺点:样本分布不均衡时,如果一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值