k-邻近算法原理简述:
k-邻近算法就是通过计算待分类数据与样本数据间距离,获取样本中前k个(通常不大于20个)与待分类数据最相近的数据,然后再分类统计这个k个数据,把待分类数据归类到出现次数最多的分类中。
需要注意的是,
1、有时候需要根据特征数据在分类中所做的贡献大小,进行加权;
2、如果特征对分类的贡献相同,而特征值相差较大时,数值较大的会影响分类结果,此时需要对特征数据进行归一化处理。在数据处理方面,归一化是常用的预处理手段,归一化的方法也较多,在这里转载一篇关于归一化的博客,对归一化不了解的读者可以前往。 再谈机器学习中的归一化方法(Normalization Method)
线性归一化的python实现如下:
''' 归一化 ''' def autoNorm(dataSet): minValues = dataSet.min(0) maxValues = dataSet.max(0) ranges = maxValues - minValues normDataSet = zeros(shape(dataSet)) m = dataSet.shape[0] normDataSet = dataSet - tile(minValues, (m, 1)) normDataSet = normDataSet / tile(ranges, (m, 1)) return normDataSet, ranges, minValues
python3实现最简单的k-邻近算法:
from numpy import * import operator ''' group:样本数据 labels:样本数据所对应类别标签 ''' def createDataSet(): group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]) labels = ['A', 'A', 'B', 'B'] return group, labels ''' 定义k-邻近算法 ''' def classify0(inX, dataSet, labels, k): ''' :param inX: 待分类数据 :param dataSet: 样本数据 :param labels: 样本数据标签 :param k: 选取距离最小的点数 :return:待分类数据的类别 ''' ''' 计算欧氏距离 ''' #shape:numpy中的函数,获取数组、元组等长度 dataSetSize = dataSet.shape[0] # tile:numpy中的函数,构造数组 diffMat = tile(inX, (dataSetSize, 1)) - dataSet sqDiffMat = diffMat ** 2 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances ** 0.5 #argsort:numpy中的函数,排序并提取索引 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) #items():python3语法,python2需要用:iteritems() return sortedClassCount[0][0] if __name__ == "__main__": group, labels = createDataSet() print(classify0([0, 0], group, labels, 3))可以通过一下代码读取样本数据存储在文本中的情况:
''' 从文本中取数据 ''' def file2matrix(filename,num): ''' 注意:文档最后一行为标签数据 :param filename: 文件名称 :param num: 样本包含特征数 :return: 样本数组和标签 ''' fr = open(filename) arrayOfLines = fr.readlines() #将文本读取列表,注意与readline()的区别 numberOfLines = len(arrayOfLines) #获取文本行数 returnMat = zeros((numberOfLines, num)) classLabelVector = [] index = 0 for line in arrayOfLines: line = line.strip() #去回撤 listFromLine = line.sptrit('\t') #用\t将数据分割为元素列表 returnMat[index, :] = listFromLine[0: num] classLabelVector.append(int(listFromLine[-1])) index += 1 return returnMat, classLabelVector