KNN分类算法

算法概述

KNN算法,也叫做K近邻算法,是机器学习中一种简单的分类算法。是一种监督学习算法 。

算法原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

算法推导

在这里插入图片描述
判断未知点(绿色)属于蓝色还是红色类别时,首先要确定K值,选择距离未知点最近的K个点,选择出现最高频率的点的类别作为未知点的类别。
K值的选择
K值选择过小,会出现与最近邻算法一样的问题,容易过拟合,会受数据噪声得影响
K值选择过大,容易发生欠拟合,对未知样本得判断不准确

算法流程——伪代码或者文字描述

Step.1–准备数据,分析数据,对数据进行预处理,归一化处理;
Step.2–划分训练集和测试集;
Step.3–计算未知样本和每个训练集样本的距离;
Step.4–设定参数,k值;
Step.5–将距离升序排列;
Step.6–选取距离最小的k个点;
Step.7–统计前k个最近邻样本点所在类别出现的次数;
Step.8–多数表决,选择出现频率最大的类别作为未知样本的类别。

算法实例——Python实现

电影类别分类

在这里插入图片描述
图形表示:

import matplotlib.pyplot as plt
fight=(3,2,1,101,99,98,18)
kiss=(104,100,81,10,5,2,90)
filmtype=(1,1,1,2,2,2,3)
plt.scatter(fight,kiss,c=filmtype)

在这里插入图片描述计算距离:
距离的表示方法有多种,这里用欧拉距离来表示,也就是两点间直线距离
d i s = ( x 0 − x 1 ) 2 + ( y 0 − y 1 ) 2 dis=\sqrt{(x_0-x_1)^2+(y_0-y_1)^2} dis=(x0x1)2+(y0y1)2

代码实现

#构建数据集
import numpy as np
import matplotlib.pyplot as plt
fight=[3,2,1,101,99,98]
kiss=[104,100,81,10,5,2]
filmtype=[1,1,1,2,2,2]
plt.scatter(fight,kiss,c=filmtype)
plt.xlabel('fight')
plt.ylabel('kiss')
plt.title("movie")
plt.show()
x=np.array([fight,kiss])
x=x.T
y=np.array(filmtype)

xx=np.array([18,90])#测试数据
dist=(((x-xx)**2).sum(1))**0.5#np求和公式,按行求和

sorteddist=dist.argsort()#返回排序后索引
k=4#确定K值
classcount={}

for i in range(k):#统计前K种电影类型出现次数
    votelabel=y[sorteddist[i]]
    classcount[votelabel]=classcount.get(votelabel,0)+1
maxtype=0
maxcount=-1
for key,value in classcount.items():
    if(value>maxcount):
        maxtype=key
        maxcount=value
print("电影类型",maxtype)

代码实现

封装成函数,方便日后调用

#封装成函数,方便日后调用
import numpy as np
def knn(inx,dataset,labels,k):
#inx 测试集
#dataset 训练集
#label 分类标签
#k 距离最近的k个点
    dist=(((dataset-inx)**2).sum(1))**0.5
    sorteddist=dist.argsort()
    classcount={}
    for i in range(k):#统计前K种电影类型出现次数
        votelabel=labels[sorteddist[i]]
        classcount[votelabel]=classcount.get(votelabel,0)+1
    maxtype=0
    maxcount=-1
    for key,value in classcount.items():
        if(value>maxcount):
            maxtype=key
            maxcount=value
    return maxtype

约会网站配对数据

根据三项特性,为海伦女士预测自己对约会男生的态度。
在这里插入图片描述
数据集:百度网盘自取
提取码:tept

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实现


# -*- coding: utf-8 -*-


#KNN算法进行约会网站数据匹配
#按照男生的三种特性:每年出行的里程数、玩游戏的时间比、每周吃冰淇凌公升数来预测
#海伦女士对该男生的态度:不喜欢、魅力一般、极具魅力
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']#设置图中可显示中文
plt.rcParams['axes.unicode_minus'] = False#设置图中可显示中文
def knn(inx,dataset,labels,k):#整体函数的功能是从前k个距离最近的点中找出出现次数最多的点,并返回其类型(海伦女士的态度)
#knn算法参数为
#inx 测试集
#dataset 训练例子
#label 分类标签
#k 距离最近的k个点
    dist=(((dataset-inx)**2).sum(1))**0.5#计算欧式距离
    sorteddist=dist.argsort()#按照出现次数排序,返回索引
    classcount={}#创建字典
    for i in range(k):#统计前K种电影类型出现次数
        votelabel=labels[sorteddist[i]]
        classcount[votelabel]=classcount.get(votelabel,0)+1#此votelabel类型的键值+1
    maxtype=0
    maxcount=-1
    for key,value in classcount.items():#遍历字典,也就是存前K个近的点
        if(value>maxcount):#比较找出类型出现最多的key 和values
            maxtype=key
            maxcount=value
    return maxtype
#文件出理函数
def file2matrix(filename):#文件读取数据
    fr=open(filename)#读取txt文件
    numberoflines=len(fr.readlines())#按行读取,numberoflines为行数
    returnmat=np.zeros((numberoflines,3))#创造一个与txt文件数据格式相同的空队列
    classlabelvector=[]#用来存数据的结果也就是下面的1,2,3
    fr=open(filename)#重新打开,指针复到初位
    index=0
    for line in fr.readlines():#遍历每一行
        line=line.strip()
        listfromline=line.split("\t")#按照文件中的空格划分出数据
        returnmat[index,:]=listfromline[0:3]#将数据赋值给列表returnmat
        #由于数据结果有三种情况,我们这里用1,2,3来代替数据中的结果
        if listfromline[-1]=="didntLike":
            classlabelvector.append(1)
        elif listfromline[-1]=="smallDoses":
            classlabelvector.append(2)
        elif listfromline[-1]=="largeDoses":
            classlabelvector.append(3)
        index+=1#没遍历一行index+1
    fr.close()#关闭文件
    return returnmat,classlabelvector#返回测试集和label
dataingdatamat,datinglabels=file2matrix("datingTestSet.txt")#调用函数处理txt文件,注意,应将代码与txt文件保存在同一目录下,否则就用txt文件的系统路径
#分析数据
#两两分析,此处分析的为里程数与游戏时间
plt.scatter(dataingdatamat[:,0],dataingdatamat[:,1],c=datinglabels)
plt.xlabel(" 里程数")
plt.ylabel("游戏时间")
plt.figure(1)
plt.show()
##两两分析,此处分析的为里程数与每周吃冰淇淋公升数
#plt.scatter(dataingdatamat[:,0],dataingdatamat[:,2],c=datinglabels)
#plt.xlabel(" 里程数")
#plt.ylabel("每周吃冰淇淋公升数")
#plt.figure(2)
#plt.show()
##两两分析,此处分析的为游戏时间与每周吃冰淇淋公升数
#plt.scatter(dataingdatamat[:,1],dataingdatamat[:,2],c=datinglabels)
#plt.xlabel(" 游戏时间")
#plt.ylabel("每周吃冰淇淋公升数")
#plt.figure(3)
#plt.show()
#由于里程数的数据过大,导致剩余的两个特征的参考价值不大
#进行数据归一化操作(0-1归一化)
#(x-x_min)/(x_max-x_min)
#按照列进行归一化
def autonorm(dataset):#0-1归一化函数,由于有一些数据的范围较大,比重较大,所以做0-1归一化处理
    #0-1归一化步骤
    minvals=dataset.min(0)
    maxvals=dataset.max(0)
    normdataset=np.zeros(dataset.shape)
    normdataset=(dataset-minvals)/(maxvals-minvals)
    return normdataset

dataset=autonorm(dataingdatamat)
m=0.8#表示选出前80%的数据用做训练集
datasize=dataset.shape[0]
trainsize=int(m*datasize)#训练集数量
testsize=int((1-m)*datasize)#测试集数量
d=5#选择分类数目,就是分成几类
error=0#记录测试错误的个数
for i in range(testsize):
    result=knn(dataset[trainsize+i-1,:],dataset[0:trainsize,:],datinglabels[0:trainsize],d)#循环调用上面的knn函数,将每个测试例子带入验证其正确性
    if result!=datinglabels[trainsize+i-1]:#判断通过knn函数得到的结果,是否与真正的结果相同
        error=error+1
print("学习比例:",m*100,"%")
print("测试比例:",100-100*m,"%")
print("错误率",error/testsize)#输出分类错误率



鸢尾花卉分类

在这里插入图片描述
数据集:鸢尾花(iris)数据集
提取码:gs5i
打乱处理过后的数据集:鸢尾花(iris)数据集2
提取码:w7qq

代码实现

import numpy as np
import matplotlib.pyplot as plt
import KKNNF as k
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def file2matrix(filename):#文件读取数据
    fr=open(filename)
    numberoflines=len(fr.readlines())#z指针迭代问题,需要重新打开文件
#    print(numberoflines)
    returnmat=np.zeros((numberoflines,4))
    classlabelvector=[]
    fr=open(filename)#z指针迭代问题,需要重新打开文件
    index=0
    for line in fr.readlines():
        line=line.strip()
#        print(line)
        listfromline=line.split(",")
        if len(listfromline)==1:
            break
#        print(len(listfromline))
#        print(listfromline)
        returnmat[index,:]=listfromline[0:4]
        if listfromline[-1]=="Iris-setosa":
            classlabelvector.append(1)
        elif listfromline[-1]=="Iris-versicolor":
            classlabelvector.append(2)
        elif listfromline[-1]=="Iris-virginica":
            classlabelvector.append(3)
        index+=1
    fr.close()
    return returnmat,classlabelvector#返回测试集和label
dataingdatamat,datinglabels=file2matrix("C:\\Users\\98306\\Desktop\\iris2.txt")
def autonorm(dataset):#0-1归一化函数
    minvals=dataset.min(0)
    maxvals=dataset.max(0)
    normdataset=np.zeros(dataset.shape)
    normdataset=(dataset-minvals)/(maxvals-minvals)
    return normdataset
dataset=autonorm(dataingdatamat)
m=0.8
datasize=dataset.shape[0]
trainsize=int(m*datasize)
testsize=int((1-m)*datasize)
d=50
error=0
for i in range(testsize):
    result=k.knn(dataset[trainsize+i-1,:],dataset[0:trainsize,:],datinglabels[0:trainsize],d)
    if result!=datinglabels[trainsize+i-1]:
        error=error+1
print("错误率",error/testsize)

在这里插入图片描述

算法评价

了解KNN算法的优势和劣势,可以帮助我们在选择学习算法的时候做出更加明智的决定。那我们就来看看KNN算法都有哪些优势以及其缺陷所在!
KNN算法优点
1.简单易用,相比其他算法,KNN算是比较简洁明了的算法。即使没有很高的2.数学基础也能搞清楚它的原理。
3.模型训练时间快,上面说到KNN算法是惰性的,这里也就不再过多讲述。
4.预测效果好。
5.对异常值不敏感
6.多分类
KNN算法缺点
1.对内存要求较高,因为该算法存储了所有训练数据
2.预测阶段可能很慢
3.对不相关的功能和数据规模敏感

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chp的博客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值