分类 kNN

#coding=utf-8
from numpy import *
import operator
from os import listdir
import matplotlib
import matplotlib.pyplot as plt

#从文件当中读取内容,保存到矩阵当中
#因为文件当中有两部分内容,一部分是三个原因,另一部分是结果
def file2matrix(filename):
    fr=open(filename)
    numberOfLines=len(fr.readlines())#计算文件的行数
    returnMat=zeros((numberOfLines,3))#生成一个零矩阵
    classLabelVector=[]#生成一个序列,主要操作是切片
    fr=open(filename)
    index=0
    for line in fr.readlines():
        line=line.strip()#读取一行的内容
        listFromLine=line.split('\t')#将line分割成3个列
        returnMat[index,:]=listFromLine[0:3]#取前三个到切片放到第index行
        classLabelVector.append(int(listFromLine[-1]))#取最后一个追加到classLabelVector
        index+=1#index自加
    return returnMat,classLabelVector

#归一化数据
def autoNorm(dataSet):
    #获取每一列的最小值,也就是说结果是一个3维的数组,数组的元素
    #是每一列到最小值
    #如果0改为1,那么获取到的是每一行的最小值,也就是一个数组
    minVals=dataSet.min(0)
    maxVals=dataSet.max(0)#获取每一列的最大值
    ranges=maxVals-minVals
    normDataSet=zeros(shape(dataSet))#生成一个零矩阵

    #shape,显示一个矩阵的行列,如果没有[0],那么输出
    #(1000,3)也就是1000行,3列,
    # [0]表示第一个元素(行),[1]表示第二个元素(列)
    m=dataSet.shape[0]#获取行的行的数然后复制给m
    #tile是一个复制函数,将minVals复制
    #行的方向上复制m次你,列的方向上复制1次
    normDataSet=dataSet-tile(minVals,(m,1))
    normDataSet=normDataSet/tile(ranges,(m,1))
    return normDataSet,ranges,minVals


#绘图
def draw():
    fig=plt.figure()
    ax=fig.add_subplot(111)
    datingDataMat,datingLabels= file2matrix('datingTestSet.txt')
    ax.scatter(datingDataMat[:,0],datingDataMat[:,1],
           15.0*array(datingLabels),15.0*array(datingLabels))
    plt.show()

#分类
def classify0(inX, dataSet, labels, k):
    #获取到dataSet的行数量
    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()
    classCount={}
    for i in range(k):
        #获取到分类
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]



#识别过程
def datingClassTest():
    hoRatio=0.10
    #从文件当中读取txt文件,转化为矩阵
    datingDataMat,datingLabels=file2matrix('datingTestSet.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)

    m=normMat.shape[0]
    numTestVecs=int(m*hoRatio)
    errorCount=0.0
    #从1到100
    for i in range(numTestVecs):
        #第一个参数是待分类到矩阵
        #normMat[i,:]代表一个行,也就是矩阵的第i行的一位矩阵
        #normMat[numTestVecs:m,:]使用从100到1000行的矩阵去分类
        #datingLabels[numTestVecs:m]使用从100到1000行的结果去分类
        #3代表kNN当中的k
        classfierResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],
                                    datingLabels[numTestVecs:m],3)
        print "机器人认为的结果是%d,正确的答案是:%d"%(classfierResult,datingLabels[i])
        if(classfierResult!=datingLabels[i]):
            errorCount+=1.0
    print "错误律是:%f" %(errorCount/float(numTestVecs))

datingClassTest()

"""
最初错误原因
dataSet=file2matrix('datingTestSet.txt')
print dataSet#有两个返回值,会把后一个返回值追加到dataSet上面,构成元祖
print "*****************************"
datingDataMat,datingLabels=file2matrix('datingTestSet.txt')
print datingDataMat
print "*****************************"
print datingLabels
"""

 

posted @ 2013-09-28 11:42  yufenghou  阅读(498)  评论(0编辑  收藏  举报