KNN算法原理以及代码实现

 

一、KNN简述

KNN是比较经典的算法,也是是数据挖掘分类技术中最简单的方法之一。

KNN的核心思想很简单:离谁近就是谁。具体解释为如果一个实例在特征空间中的K个最相似(即特征空间中最近邻)的实例中的大多数属于某一个类别,则该实例也属于这个类别。

换个说法可能更好理解,比如一个一定范围的平面随机分布着两种颜色的样本点,在这个平面内有个实例点不知道它是什么颜色,因此通过它周边的不同颜色的点分布情况进行推测,假设取K=3,意思是在离这个实例点最近的样本点中去前三个最近的, 然后看这三个当中那种类别占比大,就判断该实例点属于那个类别的,当k=5的时候也一样这样判断,因此k的取值很关键,通常不会超过20。当然,因为每个样本有多个特征,因此实际工作中,这个‘平面’就是三维甚至是多维的,道理是一样的。如图:

二、KNN算法原理

在KNN中,通过计算对象间距离来作为各个对象之间的非相似性指标,避免了对象之间的匹配问题,在这里距离一般使用欧氏距离或曼哈顿距离:

对KNN算法的思想总结一下:就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类,其算法的描述为:

1)计算测试数据与各个训练数据之间的距离;

2)按照距离的递增关系进行排序;

3)选取距离最小的K个点;

4)确定前K个点所在类别的出现频率;

5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

 

三、KNN算法优缺点以及算法改进

优缺点:

1、简单,易于理解,是一个天然的多分类器;

2、不需要庞大的样本数据也可以完成一个简单的分类;

3、不需要训练和求解参数(既是优点也是缺点);

4、数据量大的时候,计算量也非常大(样本多,特征多);

5、不平衡样本处理能力差;

6、并没有学习和优化的过程,严格来说不算是机器学习。

改进:

进行加权平均,离得近的样本给予更大的权重,离得远的样本使其权重变小。

 

四、KNN代码实现

import numpy as np
import pandas as pd
import matplotlib.pylab as plt
data_=pd.read_csv('vehicle.csv')
print(data_)
feature=np.array(data_.iloc[:,0:2])  # 将参数与特征进行分离,返回数据类型为数组,这里只拿去前两列
#print(feature)
labels = data_['label'].tolist()   # 将'label'标签提取出来转换为列表类型,方便后续使用
#print(labels)

# 数据可视化
plt.scatter(data_['length'][data_['label']=='car'],data_['width'][data_['label']=='car'],c='y')  #先取length的数值,里面有car和truck的长度,再单独取label那一行为car的值
plt.scatter(data_['length'][data_['label']=='truck'],data_['width'][data_['label']=='truck'],c='r')  #先取width的数值,里面有car和truck的长度,再单独取label那一行为truck的值
#print(data_['length'])
#print(plt.show())

test = [4.7,2.1] # 待测样本

numSamples = data_.shape[0]  # 读取矩阵的长度,这里是读取第一维的长度# 运行结果:150
diff_= np.tile(test,(numSamples,1)) #这里表示test列表竖向重复150次,横向重复1一次,组成一个素组
# numpy.tile(A,B)函数:A=[4.7,2.1],B=(3,4),意思是列表A在行方向(从上到下)重复3次,在列放心(从左到右)重复4次
diff = diff_-feature  # 利用这里的实验值和样本空间里的每一组数据进行相减
squreDiff = diff**2   # 将差值进行平方
squreDist = np.sum(squreDiff,axis=1)  # 每一列横向求和,最后返回一维数组
distance = squreDist ** 0.5 
sorteDisIndices = np.argsort(distance)  # 排序
k=9  # k个最近邻
classCount = {}  # 字典或者列表的数据类型需要声明
label_count=[]   # 字典或者列表的数据类型需要声明
for i in range(k):
    voteLabel = labels[sorteDisIndices[i]]
    classCount[voteLabel] = classCount.get(voteLabel,0) + 1
    label_count.append(voteLabel)

from collections import Counter
word_counts = Counter(label_count)
top = word_counts.most_common(1)   # 返回数量最多的值以及对应的标签
#print(word_counts)
#print(top)


# 利用sklearn进行实现
import numpy as np
import pandas as pd
import matplotlib.pylab as plt
data_
=pd.read_csv('vehicle.csv') feature=np.array(data_.iloc[:,0:2]) # 将参数与特征进行分离,返回数据类型为数组,这里只拿去前两列 labels = data_['label'].tolist() # 将'label'标签提取出来转换为列表类型,方便后续使用 from sklearn.model_selection import train_test_split feautre_train,feautre_test,label_train,label_test=train_test_split(feature,labels,test_size=0.2) # 指出训练集的标签和特征以及测试集的标签和特征,0.2为参数,对测试集以及训练集按照2:8进行划分 from sklearn.neighbors import KNeighborsClassifier model=KNeighborsClassifier(n_neighbors= 9) model.fit(feautre_train,label_train) # 现在只需要传入训练集的数据 prediction=model.predict(feautre_test) #print(prediction) labels=['car','truck'] classes=['car', 'truck'] from sklearn.metrics import classification_report result_=classification_report(label_test,prediction,target_names = classes,labels=labels,digits=4) # target_names:类别;digits:int,输出浮点值的位数 print(result_)

 

posted @ 2019-06-12 16:01  编程小虾米  阅读(16453)  评论(2编辑  收藏  举报