KNN算法 代码详细解释

   《机器学习实战》

   K-近邻算法采用测量不同特征值之间的距离方法进行分类。适用数据范围:数值型和标称型。

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

代码及注释:

#分类器

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]  # 计算矩阵的行数
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet  # 第一个维度重复1次,第二个维度重复dataSetSize次
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)  # 矩阵的每一行相加
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()  # argsort()函数返回的是distances元素从小到大排列后相应元素的索引。如a=array([2,1,5,3]),a.argsort() 的结果为:[1,0,3,2]
    classCount = {}  # 分类标签字典  标签:标签出现次数
    for i in range(k):  # 选择距离最小的K个点
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1  #字典的get(key,default)方法  返回字典中key对应的值,若key在字典中不存在,则返回default的值
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)  # 排序 sort() 在本地排序,不返回副本;sorted() 返回副本,原始输入不变
    return sortedClassCount[0][0]
    # iteritems()返回的是一个迭代器
    # sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
    # 第一个参数是可迭代对象,后面的参数都有默认值。cmp,比较的函数,具有两个参数,参数的值从可迭代对象中取,规则为:大于则返回1,小于则返回-1,等于则返回0
    # key,用来进行比较的元素,只有一个参数,参数取自可迭代对象,指定可迭代对象中的一个元素来进行排序。itemgetter()用于获取对象指定维的数据,参数为序号
    # reverse,排序规则,reverse = True  降序 , reverse = False 升序


# 文件数据读取

def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()  # 读取文件所有内容
    # .readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。另一方面,.readline() 每次只读取一行,
    # 通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()
    numberOfLines = len(arrayOLines)  # 得到文件行数
    returnMat = zeros((numberOfLines, 3))
    classLabelVector = []  # 分类标签向量
    index = 0  # 行索引号
    for line in arrayOLines:
        line = line.strip()
        # s.strip(rm) s为字符串,rm为要删除的字符序列。 删除s字符串中开头结尾处rm字符。rm为空时,默认删除空白符(‘\n’,‘\r’,‘\t’‘ ’)如a='  123',a='\t123',a='123\r\n'
        # a.strip()的结果都为123    s.lstrip(rm) 删除s字符串中开头处rm字符 ; s.rstrip(rm) 删除s字符串中结尾处rm字符
        listFromLine = line.split('\t')  # split()将一个字符串分裂成多个字符串组成的列表
        returnMat[index, :] = listFromLine[0:3]  # 将数据前三列提取出来
        classLabelVector.append(listFromLine[-1])  # 将数据最后一列标签提取出来
        index += 1
    return returnMat, classLabelVector
split()函数
语法:str.split(str="",num=string.count(str))[n]
参数说明:
str:表示为分隔符,默认为空格,但是不能为空('')。若字符串中没有分隔符,则把整个字符串作为列表的一个元素
num:表示分割次数。如果存在参数num,则仅分隔成 num+1 个子字符串,并且每一个子字符串可以赋给新的变量
[n]:表示选取第n个分片
如:>>>str="hello boy<[www.doiido.com]>byebye"
>>>str.split("[")[1].split("]")[0]
结果为:'www.doiido.com'

#  数据归一化处理

def autoNorm(dataSet):  # 数据归一化处理
    minValues = dataSet.min(0)  # 参数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


#  分类器测试

def datingClassTest():
    hoRatio = 0.10  # 取10%的数据作为测试集  90%的数据作为训练集
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m * hoRatio)  # 测试集数据量
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], \
                                     datingLabels[numTestVecs:m], 3)
        print "分类器结果:%d, 实际值 :%d" \
              % (int(classifierResult), int(datingLabels[i]))
        if (classifierResult != datingLabels[i]): errorCount += 1.0
    print "错误率:%f" % (errorCount / float(numTestVecs))

#  分类综合程序

def classifyPerson():
    resultList = ['一点也不喜欢', '有点喜欢', '非常喜欢']
    ffMiles = float(raw_input("Frequent flier miles earned per year? "))
    percentTats = float(raw_input("Percentage of time spent playing video games? "))
    iceCream = float(raw_input("Liters of ice cream consumed per year? "))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')  # 读取数据
    normMat, ranges, minVals = autoNorm(datingDataMat)  # 归一化特征值
    inArr = array([ffMiles, percentTats, iceCream])
    classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)  # 分类器
    print "你喜欢这个人的程度:", resultList[int(classifierResult) - 1]


  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值