机器学习——KNN算法

Posted by Kaka Blog on June 18, 2021

简介

KNN(K-Nearest Neighbors)算法是当前主流的分类算法之一,最初有Cover和Hart于1968年提出。

基本思想

有那么一堆已经知道类别的数据,当有一个新数据进入时,依次计算这个数据和每个训练数据的距离,然后挑出离这个数据最近的K个点,看看这个K个点属于什么类型,然后用少数服从多数的原则,给新数据归类。

算法实现

实现步骤

  1. 构建训练数据集(数据标准化);
  2. 计算训练数据集中的点与当前点的距离;
  3. 按照距离递增排序;
  4. 选取距离与当前距离最小的K个点;
  5. 确定前K个点中所在类别的出现概率;
  6. 返回前K个点中出现概率最高的类别作为当前点的分类。

Python代码实现:

import numpy as np
import operator

def createDataSet():
	"""
	构造训练数据,产生4条训练样本,group为样本属性,labels为分类标签
	"""
	group = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
	labels = ['A', 'A', 'B', 'B']
	return group, labels

def classify(inX, dataSet, labels, k):
	"""
	简单KNN分类
	:param inX: 待分类向量
	:param dataSet: 训练样本集
	:param labels: 训练样本标签
	:param k: K值
	:return:
	"""
	dataSetSize = dataSet.shape[0] # 训练样本个数
	diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # 计算训练样本和待分类样本的数值差值
	sqDiffMat = diffMat ** 2 # 差值的平方
	sqDistances = sqDiffMat.sum(axis=1) # 平方和
	distances = sqDistances ** 0.5 # 平方和开方
	sortedDistIndicies = distances.argsort() # 返回升序排列后的索引
	classCount = {}
  # 统计前K个样本中各标签出现次数
	for i in range(k):
		voteIlabel = labels[sortedDistIndicies[i]]
		classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
	sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
	print(sortedClassCount)
	# 按标签次数排序,返回次数最多的标签
	return sortedClassCount[0][0]

if __name__ == '__main__':
	group, labels = createDataSet()
	print(classify([0.9, 0.9], group, labels, 2))
  # 最终输出类别为A

优缺点

优点

  • KNN算法思想简单,非常人容易实现;
  • 有新样本要加入训练集时,无需重新训练;

缺点

  • 分类速度慢,因为每次分类新样本时,都要和所有的训练样本进行计算比较,时间复杂度和储存空间会随着训练集规模和特征维数的增大而增加。
  • 各属性权重相同,当样本分布不均匀时,会影响准确率;
  • K值不好确定

参考