Knn算法实现

一、题目要求

KNN(K Near Neighbor):k个最近的邻居,即每个样本都可以同他最接近的k个邻居来代表。
KNN算法是一种分类算法,该算法思想是一个样本与数据集中的k个样本最相似,如果k个样本的大多数属于某一个类别,则该样本也属于这个类别。

二、算法分析

在选择两个实例相似性时,一般是用的欧式距离:

对于k值的选择,如果选择较小的K值,就相当于用较小的邻域中的训练实例进行预测,学习的近似误差会减小,只有与输入实例较近的训练实例才会对预测结果起作用,单缺点是学习的估计误差会增大,预测结果会对近邻的实例点分成敏感。如果邻近的实例点恰巧是噪声,预测就会出错。换句话说,K值减小就意味着整体模型变复杂,分的不清楚,就容易发生过拟合。
如果选择较大K值,就相当于用较大邻域中的训练实例进行预测,其优点是可以减少学习的估计误差,但近似误差会增大,也就是对输入实例预测不准确,K值得增大就意味着整体模型变的简单。

三、代码分析

导入项目所需的包,以及定义训练集、测试集和所需的k值

import math
import random
import matplotlib.pyplot as plt

data_train=[]

data_test=[]
k_near_by=5
limit=math.ceil(k_near_by/2)

制作数据的函数,在训练集中数据被分为5类,每类个10组数据,再在测试集中添加30组测试数据,所有数据都由随机生成。

def make_data():
    """
    制作数据
    """
    for p in range(1,5):
        x=random.random()*20
        y=random.random()*20
        for i in range(10):
            x_shift=random.random()*5
            y_shift=random.random()*5
            data_train.append([x+x_shift,y+y_shift,p])
    for p in range(30):
        x=random.random()*20
        y=random.random()*20
        data_test.append([x,y,0])

这里我们还可以通过skitlearn的包导入鸢尾花的数据进行数据的制作

	def make_data_from_iris():
    """
    从数据集中导入鸢尾花数据
    """
    iris_dataset = load_iris()
    iris_data_train=iris_dataset['data'][::5]
    iris_tag_train=iris_dataset['target'][::5]
    iris_data_tag_train=[]
    for i in range(30):
        iris_data_tag_train=[iris_data_train[i][0],iris_data_train[i][1],iris_tag_train[i]]
        data_train.append(iris_data_tag_train)
    iris_data_test=iris_dataset['data'][1::15]
    iris_tag_test=iris_dataset['target'][1::15]
    iris_data_tag_test=[]
    for i in range(10):
        iris_data_tag_test=[iris_data_test[i][0],iris_data_test[i][1],0]
        data_test.append(iris_data_tag_test)
        data_test_origin.append(iris_data_tag_test)

计算距离函数,返回欧式距离的平方

def dis(a,b):
    """
    a,b传入列表 格式为:[x,y,*]
    计算距离
    """
    return ((a[0]-b[0])**2+(a[1]-b[1])**2)

当传入一个数据时,获取它的第一个元素,用于获取在标签时获取距离

def takefirst(elem):
    return elem[0]

分类函数,将传入的数据分类并附上标签,先将训练集的数据转换为一个字典,并将每个数据分类的个数更新为字典对应键的值

def make_tag(t):
    """
    t:传入列表 格式为[x,y,0]
    分类标签,标签为0表示不分类
    """
    
    min_dix=[]
    for i in data_train:
        min_dix.append([dis(i,t),i[2]])
    min_dix.sort(key=takefirst)
    tag_dact={}
    for i in range(k_near_by):
        if min_dix[i][1] not in tag_dact:
            tag_dact.update({min_dix[i][1]:1})
        else:
            tag_dact[min_dix[i][1]]+=1
    for kv in tag_dact.items():
        if kv[1] > limit:
            return kv[0]
    return 0

调用函数并进行分类,调用matplotlib将散点图画出

make_data()
for i in range(len(data_test)):
    data_test[i][2]=make_tag(data_test[i])
"""
可视化部分
"""
point_dict={
    0 : 'H',#错误
    1 : '.',
    2 : ',',
    3 : 'o',
    4 : 'v',
    5 : '^',
    6 : '<',
}
color_dict={
    0 : 'y',  # 错误
    1 : 'b',
    2 : 'c',
    3 : 'g',
    4 : 'k',
    5 : 'm',
    6 : 'r',
}

plt.figure(1,dpi=80)
ax1=plt.subplot(221)
ax2=plt.subplot(222)
ax3=plt.subplot(223)

for i in data_train :
	plt.sca(ax1)
	plt.scatter(i[0],i[1],c=color_dict[i[2]],marker=point_dict[i[2]])
for i in data_train :
	plt.sca(ax3)
	plt.scatter(i[0],i[1],c=color_dict[i[2]],marker=point_dict[i[2]])

for i in data_test :
	plt.sca(ax2)
	plt.scatter(i[0],i[1],c=color_dict[i[2]],marker=point_dict[i[2]])
for i in data_test :
	plt.sca(ax3)
	plt.scatter(i[0],i[1],c=color_dict[i[2]],marker=point_dict[i[2]])
plt.show()
exit(0)

四、运行结果

在这里插入图片描述

五、总结分析

Knn算法是机器学习中用于分类的基本算法,不是只考虑最近的点,而是通过该点周围的一定数量的邻居点,并通过邻居点的类别来判断改点的类别。Knn算法k值的选择十分重要,k值较小,说明整体模型变复杂,预测结构会对邻近的干扰产生较大的误差,容易发生过拟合;而k值较大时,说明整体模型变简单,使得对输入实例预测不准确,容易产生欠拟合。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值