KNN算法的过程为:
若是数据特征中存在非数值的类型,必须採取手段将其量化为数值。
举个样例。若样本特征中包括颜色(红黑蓝)一项,颜色之间是没有距离可言的,可通过将颜色转换为灰度值来实现距离计算。
另外,样本有多个參数,每个參数都有自己的定义域和取值范围,他们对distance计算的影响也就不一样。如取值较大的影响力会盖过取值较小的參数。为了公平,样本參数必须做一些scale处理,最简单的方式就是全部特征的数值都採取归一化处置。
2、须要一个distance函数以计算两个样本之间的距离。
距离的定义有非常多。如欧氏距离、余弦距离、汉明距离、曼哈顿距离等等,关于相似性度量的方法可參考‘漫谈:机器学习中距离和相似性度量方法’。普通情况下,选欧氏距离作为距离度量,可是这是仅仅适用于连续变量。
在文本分类这样的非连续变量情况下,汉明距离能够用来作为度量。通常情况下。假设运用一些特殊的算法来计算度量的话,K近邻分类精度可显著提高,如运用大边缘近期邻法或者近邻成分分析法。
3,确定K的值
K是一个自己定义的常数,K的值也直接影响最后的预计,一种选择K值得方法是使用 
通过训练数据训练一个机器学习模型,然后利用測试数据測试其误差率。 
比如选择K=1,2,3,...
以下的Python程序是採用KNN算法的实例(计算欧氏距离。多数表决法决断):一个是採用KNN算法改进约会站点配对效果。还有一个是採用KNN算法进行手写识别。
约会站点配对效果改进的样例是依据男子的每年的飞行里程、视频游戏时间比和每周冰激凌耗量三个特征来推断其是否是海伦姑娘喜欢的类型(类别为非常喜欢、一般和讨厌),决策採用多数表决法。
因为三个特征的取值范围不同,这里採用的scale策略为归一化。
使用KNN分类器的手写识别系统 仅仅能识别数字0到9。
须要识别的数字使用图形处理软件,处理成具有同样的色 彩和大小 :宽髙是32像素X32像素的黑白图像。虽然採用文本格式存储图像不能有效地利用内存空间,为了方便理解,这里已经将将图像转换为文本格式。训练数据中每一个数字大概有200个样本。程序中将图像样本格式化处理为向量,即一个把一个32x32的二进制图像矩阵转换为一个1x1024的向量。
from numpy import *
import operator
from os import listdir
import matplotlib
import matplotlib.pyplot as plt
import pdb
def classify0(inX, dataSet, labels, k=3):
    #pdb.set_trace()
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort() #ascend sorted,
    #return the index of unsorted, that is to choose the least 3 item    
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# a dict with label as key and occurrence number as value
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    ‘‘‘descend sorted according to value, ‘‘‘
    return sortedClassCount[0][0]
def file2matrix(filename):
    fr = open(filename)
    #pdb.set_trace()
    L = fr.readlines()
    numberOfLines = len(L)         #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    classLabelVector = []                       #prepare labels return       
    index = 0
    for line in L:
        line = line.strip()
        listFromLine = line.split(‘\t‘)
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        #classLabelVector.append((listFromLine[-1]))
        index += 1
    fr.close()
    return returnMat,classLabelVector
def plotscattter():
    datingDataMat,datingLabels = file2matrix(‘datingTestSet2.txt‘)       #load data setfrom file
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax2 = fig.add_subplot(111)
    ax3 = fig.add_subplot(111)
    ax1.scatter(datingDataMat[:,0],datingDataMat[:,1],15.0*array(datingLabels),15.0*array(datingLabels))
    #ax2.scatter(datingDataMat[:,0],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
    #ax2.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
    plt.show()
    
    
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals
   
def datingClassTest(hoRatio = 0.20):
    #hold out 10%
    datingDataMat,datingLabels = file2matrix(‘datingTestSet2.txt‘)       #load data setfrom file
    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 "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
        if (classifierResult != datingLabels[i]): errorCount += 1.0
    print "the total error rate is: %.2f%%" % (100*errorCount/float(numTestVecs))
    print ‘testcount is %s, errorCount is %s‘ %(numTestVecs,errorCount)
def classifyPerson():
    ‘‘‘
    input a person , decide like or not, then update the DB
    ‘‘‘
    resultlist = [‘not at all‘,‘little doses‘,‘large doses‘]
    percentTats = float(raw_input(‘input the person\‘ percentage of time playing video games:‘))
    ffMiles = float(raw_input(‘flier miles in a year:‘))
    iceCream = float(raw_input(‘amount of iceCream consumed per year:‘))
    datingDataMat,datingLabels = file2matrix(‘datingTestSet2.txt‘)
    normMat, ranges, minVals = autoNorm(datingDataMat)
    normPerson = (array([ffMiles,percentTats,iceCream])-minVals)/ranges
    result = classify0(normPerson, normMat, datingLabels, 3)
    print ‘you will probably like this guy in:‘, resultlist[result -1]
    #update the datingTestSet
    print ‘update dating DB‘
    tmp = ‘\t‘.join([repr(ffMiles),repr(percentTats),repr(iceCream),repr(result)])+‘\n‘
    with open(‘datingTestSet2.txt‘,‘a‘) as fr:
        fr.write(tmp)
def img2file(filename):
    #vector = zeros(1,1024)
    with open(filename) as fr:
        L=fr.readlines()
    vector =[int(L[i][j]) for i in range(32) for j in range(32)]
    return array(vector,dtype = float)
        
def handwritingClassTest():
    hwLabels = []
    trainingFileList = listdir(‘trainingDigits‘)           #load the training set
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split(‘.‘)[0]     #take off .txt
        classNumStr = int(fileStr.split(‘_‘)[0])
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector(‘trainingDigits/%s‘ % fileNameStr)
    testFileList = listdir(‘testDigits‘)        #iterate through the test set
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split(‘.‘)[0]     #take off .txt
        classNumStr = int(fileStr.split(‘_‘)[0])
        vectorUnderTest = img2vector(‘testDigits/%s‘ % fileNameStr)
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
        print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)
        if (classifierResult != classNumStr): errorCount += 1.0
    print "\nthe total number of errors is: %d" % errorCount
    print "\nthe total error rate is: %f" % (errorCount/float(mTest))
if __name__ == ‘__main__‘:
    datingClassTest()
    #handwritingClassTest()
KNN算法学习包下载地址为:
(四)KNN回归
数据点的类别标签是连续值时应用KNN算法就是回归。与KNN分类算法过程同样。差别在于对K个邻居的处理上。KNN回归是取K个邻居类标签值得加权作为新数据点的预測值。加权方法有:K个近邻的属性值的平均值(最差)、1/d为权重(有效的衡量邻居的权重。使较近邻居的权重比較远邻居的权重大)、高斯函数(或者其它适当的减函数)计算权重= gaussian(distance) (距离越远得到的值就越小,加权得到更为准确的预计。K-近邻算法是分类数据最简单最有效的算法,其学习基于实例,使用算法时我们必须有接近实际数据的训练样本数据。K-近邻算法必须保存所有数据集,假设训练数据集的非常大,必须使用大量的存储空间。此外,因为必须对数据集中的每一个数据计算距离值,实际使用时可能非常耗时。
k-近邻算法的还有一个缺陷是它无法给出不论什么数据的基础结构信息,因此我们也无法知晓平均实例样本和典型实例样本具有什么特征。
本文作者Adan,来源于:机器学习经典算法具体解释及Python实现--K近邻(KNN)算法。转载请注明出处。
机器学习经典算法具体解释及Python实现--K近邻(KNN)算法
原文:http://www.cnblogs.com/blfbuaa/p/6815992.html