《机器学习实战》-K邻近算法

K邻近算法

由于《机器学习实战》中用的是python2+,而我用的是python3+,所以在学习中产生了很多bug
又因为对各种函数不是太了解,每个都要具体查,很麻烦。
这里对每个函数都做了大致的注释,Bug也都改了。
拿来直接运行

话不多说,直接上代码,注释肯不好(望谅解)
KNN.py文件
from numpy import *
import operator
#功能****
##读取文件获得训练样本和标签##
def readfile(filename):
    #1读取文件,此时文件指针指向文件尾部
    #2获得样本数目/维度  以便建立矩阵
    #3建立样本数目*3的零矩阵  和 标签向量组
    #4重定向文件指针指向文件头
    #5循环遍历文件每行并储存到矩阵中
    fr=open(filename)
    train_num=len(fr.readlines())
    returnMat=zeros((train_num,3))
    class_label=[]
    fr=open(filename)
    index=0
    for line in fr.readlines():
        line=line.strip()
        line_list=line.split('\t')
        returnMat[index,:]=line_list[0:3]
        class_label.append(int(line_list[-1]))
        index+=1
    return returnMat,class_label
#功能****
#输入样本,训练样本,样本标签,选取最邻近值个数        
#输出标签
def classify(train_object,train_example,train_labels,k):
    #1先求出训练样本的维度
    #2再建立一个特征值数量行*1列的 矩阵保存输入样本
    #3把该样本与训练样本相减并平方,并用sum(axis=1)使行向量相加,再^1/2
    #如下公式根号下((x-y)^2)
    #4对求差后的向量进行排序,从小到大,以标签的所在列形式显示argsort()
    #5申明一个分类字典
    #6循环前k个距离差值,确定各个标签出现的频率
    #7使用get匹配,如果匹配且出现过则+1  
    #9返回匹配率最高的一个
    train_dem=train_example.shape[0]
    diff_mat=tile(train_object,(train_dem,1))
    diff_mat=(diff_mat-train_example)**2
    distance=diff_mat.sum(axis=1)**0.5
    dist_values=distance.argsort()
    label_class={}
    for i in range(k):
        votelabel=labels[dist_values[i]]
        label_class[votelabel]=label_class.get(votelabel,0)+1
    sortedClassCount=sorted(label_class.items(),
                            key=operator.itemgetter(1),
                            reverse=True)
    return sortedClassCount[0][0]
#功能***
#约会测试
def classifyPerson():
    #定义返回值列表
    #定义输入样本
    #用readfile读取文件,返回训练样本和标签
    #归一化训练样本
    #归一化输入样本*****输入样本-训练样本最小值)/训练样本范围
    #分类classify(归一化输入样本,训练样本,训练标签,k值)
    resultList=['一点也不喜欢','喜欢一点点','非常喜欢']
    percentTats=float(input("花费在游戏上的百分比"))
    ffMiles=float(input("每年的飞行里程数"))
    iceCream=float(input("每年吃的冰淇淋公升数"))
    datingDataMat,dataingLabels=readfile('datingTestSet2.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)
    inArr=array([ffMiles,percentTats,iceCream])
    classifierResult=classify((inArr-minVals)/ranges
                               ,normMat,dataingLabels,3)
    print("你可能:",resultList[classifierResult-1])
#功能****
#归一化特征值
#newVlaue=(oldValue-min)/(max-min)
#返回归一化矩阵,矩阵差值,矩阵每列最小值
def autoNorm(dataSet):
    #1获得每列最小值
    #2获得每列的范围
    #3建立一个数据集大小的零矩阵
    #4获取样本个数
    #5数据集减去每列最小的值(求出差)并保存到归一化矩阵
    #6归一化矩阵每个元素除以范围 得出真.归一化矩阵
    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))
    return normDataSet,ranges,minVals
#功能******
#把图片变成一组样本
#把32*32变成1*1024
def img2vector(filename):
    returnVect=zeros((1,1024))
    fr=open(filename)
    for i in range(32):
        lineStr=fr.readline()
        for j in range(32):
            returnVect[0,32*i+j]=int(lineStr[j])
    return returnVect
#功能******
#正确率测试
def datingClassTest():
    #定义挑选数据 这里定义挑选10%的数据
    #1readfile读取文件返回训练样本和训练标签
    #2归一化训练样本
    #3shape[0]取得样本数目后*0.1 定义挑选的数据量
    #4for遍历数据量
    #5取得测试数据与真实数据对比
    #6输出错误率
    hoRatio = 0.10      
    datingDataMat,datingLabels =readfile('datingTestSet2.txt')  
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify(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)))
    print(errorCount)
#功能*****
#手写识别
def handwritingClassTest():
    #定义样本标签
    #1读取文件夹内文件列表,并获取列表长度m(文件个数)
    #2声明一个m*1024的训练样本的0矩阵
    #3遍历样本
    #4{从文件名上分离出样本标签,并添加到样本标签列表中
    #5加载处理后1*1024的单个训练样本}
    #6读入输入样本文件夹内文件列表
    #7对每个输入样本做如下处理
    #8{取出输入样本标签值
    #9对每个输入样本classify后对比正确数
    #10输出错误率
    hwLabels=[]
    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)
    for i in range(mTest):
        fileNameStr=testFileList[i]
        fileStr=fileNameStr.split('.')[0]
        classNumStr=int(fileStr.split('_')[0])
        vectorUnderTest=img2vector('trainingDigits/%s'
                   %fileNameStr) 
        classifierResult=classify(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("\n错误总数是:%d"%errorCount)
    print("\n错误率是:%f"%(errorCount/float(mTest)))
    
    
    
    
    
    



猜你喜欢

转载自blog.csdn.net/qq_37633207/article/details/79134177