目录
一、 KNN算法简介
kNN是一个基本而简单的分类算法,作为监督学习,那么KNN模型需要的是有标签的训练数据,对于新样本的类别由与新样本距离最近的k个训练样本点按照分类决策规则决定。
k近邻法(k-nearest neighbor, kNN)是一种基本的分类与回归方法;是一种基于有标签训练数据的模型;是一种监督学习算法。
基本做法的三个要点是:
第一,确定距离度量;
第二,k值的选择(找出训练集中与带估计点最靠近的k个实例点);
第三,分类决策规则。
具体可以分为以下步骤:
收集数据:可以使用任何方法。
准备数据:距离计算所需要的数值,最好是结构化的数据格式
分析数据:可以使用任何方法。
训练算法:此步骤不适用于k-近邻算法。
测试算法:计算错误率。
使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。
二、代码实现
2.1导入库numpy和operator:
import numpy as np
import operator
2.2收集和准备数据:
def Dataset():
group = np.array([[3,101],[2,100],[1,81],[101,10],[99,5],[98,2]])
labels = ['爱','爱','爱','动','动','动']
return group,labels
注:此处采用数组形式导入数据,并附上标签,同理还可用字典形式或者导入数据集文件等方式
2.3计算距离:
利用欧式距离公式:
def KNN(in_x, x_labels, y_labels, k):
x_labels_size = x_labels.shape[0]
distances = (np.tile(in_x, (x_labels_size, 1)) - x_labels) ** 2
ad_distances = distances.sum(axis=1)
sq_distances = ad_distances ** 0.5
ed_distances = sq_distances.argsort()
classdict = {}
# 选择距离最小的K个点
for i in range(k):
voteI_label = y_labels[ed_distances[i]]
classdict[voteI_label] = classdict.get(voteI_label, 0) + 1
sort_classdict = sorted(classdict.items(), key=operator.itemgetter(1), reverse=True)
return sort_classdict[0][0]
注:数据进行归一化后再用matplotlib会更加直观
2.4利用matplotlib进行数据分析
def simpleScatter(group, labels):
uniqueClass = np.unique(labels)
sns.color_palette("hsv", as_cmap=True)
colors = len(uniqueClass)
for i in range(colors):
xLabel = group[np.where(np.array(labels) == uniqueClass[i]), 0]
yLabel = group[np.where(np.array(labels) == uniqueClass[i]), 1]
plt.scatter(xLabel, yLabel, label=uniqueClass[i], alpha=0.8)
plt.title("散点图")
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='upper right')
plt.show()
完整代码:
import numpy as np
import operator
import matplotlib.pyplot as plt
import seaborn as sns
# 放置matplotlib中文乱码
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
def Dataset():
group = np.array([[3, 101], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
labels = ['爱', '爱', '爱', '动', '动', '动']
group = (group - group.min(0)) / (group.max(0) - group.min(0)) # 归一化
return group, labels
def KNN(in_x, x_labels, y_labels, k):
x_labels_size = x_labels.shape[0]
distances = (np.tile(in_x, (x_labels_size, 1)) - x_labels) ** 2
ad_distances = distances.sum(axis=1)
sq_distances = ad_distances ** 0.5
ed_distances = sq_distances.argsort()
classdict = {}
# 选择距离最小的K个点
for i in range(k):
voteI_label = y_labels[ed_distances[i]]
classdict[voteI_label] = classdict.get(voteI_label, 0) + 1
sort_classdict = sorted(classdict.items(), key=operator.itemgetter(1), reverse=True)
return sort_classdict[0][0]
def simpleScatter(group, labels):
uniqueClass = np.unique(labels)
sns.color_palette("hsv", as_cmap=True)
colors = len(uniqueClass)
for i in range(colors):
xLabel = group[np.where(np.array(labels) == uniqueClass[i]), 0]
yLabel = group[np.where(np.array(labels) == uniqueClass[i]), 1]
plt.scatter(xLabel, yLabel, label=uniqueClass[i], alpha=0.8)
plt.title("散点图")
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='upper right')
plt.show()
if __name__ == '__main__':
group, labels = Dataset()
test_x = [18, 90]
print('输入数据对应的类别是:{}'.format(KNN(test_x, group, labels, 3)))
simpleScatter(group, labels)