ch2_kNN

作者: hxc_422 | 来源:发表于2018-08-22 20:05 被阅读0次

    from numpy import *

    import operator

    from os import listdir

    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

    '''KNN算法的伪代码

    对未知类别属性的数据集中的每个点依次执行以下操作:

    (1)计算已知类别数据集中的点与当前点之间的距离

    (2)按照距离递增次序排序

    (3)选取与当前点距离最小的k个点

    (4)确定前k个点所在类别的出现频率

    (5)返回前k个点出现频率最高的类别作为当前点的预测分类'''

    def classify0(inX, dataSet, labels, k): #默认输入4个参数,inX表示用于分类的输入向量;dataSet为训练样本集;labels为标签向量;k表示用于选择最近邻居的数目

    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() #将得到的欧氏距离阵列,这种numpyarray从小到大排列,并提取原本的index

    classCount = {} #建立分类字典

    for i in range(k):

    voteIlabel = labels[sortedDistIndicies[i]] #逐次查找最小的index对应的类标签

    classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #如果字典classCount中有voteIlabel类则返回该值+1否则返回0+1

    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),reverse=True) #提取classCount中的项,提取其中的值倒叙排列,并返回一个排好的字典

    return sortedClassCount[0][0] #返回第一个项的键(数量最大的值对应的键)

    '''约会网站上使用k近邻算法,该函数输入为文件名字字符串,输出为训练样本矩阵和类标签向量

    (1)收集数据:提供文本文件

    (2)准备数据

    (3)分析数据:使用matplotlib画二维散点图

    (4)训练算法:此步骤不适用于k近邻算法

    (5)测试算法

    (6)使用算法'''

    def file2matrix(filename):

    fr = open(filename)

    arrayOflines = fr.readlines()

    numberOfLines = len(arrayOflines) #得到文件的行数

    returnMat = zeros((numberOfLines,3)) #创建返回Numpy的矩阵

    classLabelVector = [] #创建文本类标签向量的list

    index = 0

    for line in arrayOflines: #解析文件数据到列表

    line = line.strip() #截取掉所有回车字符

    listFromLine = line.split('\t') #使用tab字符(\t)将整行数据截取为元素列表

    returnMat[index,:] = listFromLine[0:3] #选取前三个元素储存到特征矩阵中。

    classLabelVector.append(int(listFromLine[-1])) #最后一列存储到向量classLabelVector中,处理对象说明为整型否则按字符串处理

    index += 1

    return returnMat, classLabelVector

    '''分析数据使用Matplotlib制作原始数据的散点图

    >>>reload(kNN)

    >>>datingDataMat,datingLabels = kNN.file2matrix('datingTestSet.txt')

    >>>datingDataMat

    >>>datingLabels[0:20]

    >>>import matplotlib

    >>>import matplotlib.pyplot as plt

    >>>fig = plt.figure()

    >>>ax = fig.add_subplot(111)

    >>>ax.scatter(datingDataMat[:,1], datingDataMat[:,2])

    >>>plt.show()

    '''

    '''归一化数值,由于数据取值范围不同,当相同权重时,同种不同组数据若相差影响最终结果过大,会有所偏差,

    再次引入归一化数值的方法,将所有数据取值范围变为0-1之间。

    计算公式:新的数值=(原始数值-最小值)/(最大值-最小值)'''

    def autoNorm(dataSet):

    minVals = dataSet.min(0) #将每列数据中最小的数字放入变量minVals。参数(0)表示:在列维度求值,(1)表示在行维度求

    maxVals = dataSet.max(0) #同理最大数字放入maxVals

    ranges = maxVals - minVals

    normDataSet = zeros(shape(dataSet))

    m = dataSet.shape[0] #得到数据集中共有多少行数据

    normDataSet = dataSet - tile(minVals, (m,1)) #计算公式的分子:数值-最小值

    normDataSet = normDataSet/tile(ranges, (m,1)) #计算公式的分母:最大值-最小值

    return normDataSet, ranges, minVals

    '''在autoNorm函数中,将每列的最小值放到minVals,最大值放到maxVals计算最大最小差值。min(0)中参数0表示,函数可以从列维度

    中选取最小值。最后函数返回一个新的矩阵,为归一化结果。

    设特征值矩阵1000x3,而minVals和ranges都为1x3,用tile()解决这个问题。'''

    #测试算法

    def datingClassTest():

    hoRatio = 0.10

    datingDataMat,datingLabels = file2matrix('datingTestSet.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("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 : %f" % (errorCount/float(numTestVecs)))

    '''使用kNN构造手写数字识别系统。

    (1)收集数据:提供文本文件

    (2)准备数据:编写函数classify0(), 将图像格式转换为分类器使用的list格式

    (3)分析数据:在Python命令提示符中检查数据,确保符合要求

    (4)训练算法:

    (5)测试算法:使用提供的部分数据集作为测试样本,测试样本与非测试样本区别在于

    测试样本是已经完成分类的数据,如果预测分类与实际类别不同,则标记为错误

    (6)使用算法:本例没有完成'''

    def img2vector(filename): #将图像转化为向量的函数

    returnVect = zeros((1,1024)) #初始化一个1x1024的向量

    fr = open(filename) #读取文件

    for i in range(32): #将32x32的原始图像转化为1x1024的向量

    lineStr = fr.readline()

    for j in range(32):

    returnVect[0,32*i+j] = int(lineStr[j])

    return returnVect #返回得到的向量

    '''测试算法,使用k-近邻算法识别手写数字,img2vector将数据处理成分类器可以识别的模式,

    handwritingClassTest函数是检测分类器执行结果。listdir是os库中的函数,可以列出给定目录的文件名'''

    def handwritingClassTest():

    hwLabels = [] #hwLabels类型为list用来记录标签

    trainingFileList = listdir('trainingDigits') #测试集数据文件名,要作为标签使用

    m = len(trainingFileList)

    trainingMat = zeros((m,1024)) #初始化矩阵

    for i in range(m):

    fileNameStr = trainingFileList[i] #遍历所有标签

    fileStr = fileNameStr.split('.')[0]

    classNumStr = int(fileStr.split('_')[0]) #这两步表示将数据本来类别名从文件名中提取出来

    hwLabels.append(classNumStr) #标签集增加

    trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr) #得到最终训练结果

    testFileList = listdir('testDigits') #测试集文件名开始

    errorCount = 0.0 #初始化错误数

    mTest = len(testFileList) #得到测试集个数

    errorList = {} #用字典记录分类器分类错误的图像及错误结果

    for i in range(mTest):

    fileNameStr = testFileList[i] #遍历测试集

    fileStr = fileNameStr.split('.')[0] #得到测试集标签

    classNumStr = int(fileStr.split('_')[0]) #用于验证精度

    vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)

    classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3) #分类器本体

    #print("the clasifier came back with : %d, the real answer is: %d" % (classifierResult, classNumStr))

    if (classifierResult != classNumStr): #若分类器结果与读取的测试集结果不相等

    errorCount += 1.0 #错误数增加1

    errorList[fileStr] = classifierResult

    print("the total number of error is : %d" % errorCount)

    errorRate = errorCount/float(mTest)

    print("the total error rate is : %f" % errorRate) #用总错误数/总测试集个数表示精度

    print("the error list is :", end = ' ')

    print(errorList)

    相关文章

      网友评论

          本文标题:ch2_kNN

          本文链接:https://www.haomeiwen.com/subject/qmiyiftx.html