机器学习---KNN案例

1、相亲案例

import numpy as np
import operator
#matplotata 测试数据集的某行,  dataSet 训练数据集 ,labels 训练数据集的类别,k k的值
def classify(normData,dataSet,labels,k):
    dataSetSize = dataSet.shape[0]
#     print 'dataSetSize 长度 =',dataSetSize
    #当前点到所有点的坐标差值
    diffMat = np.tile(normData, (dataSetSize,1)) - dataSet
    #对每个坐标差值平方
    sqDiffMat = diffMat ** 2
    #对于二维数组 sqDiffMat.sum(axis=0)指定对数组b对每列求和,sqDiffMat.sum(axis=1)是对每行求和
    sqDistances = sqDiffMat.sum(axis = 1)
    #欧式距离 最后开方
    distance = sqDistances ** 0.5
    #argsort() 将x中的元素从小到大排序,提取其对应的index 索引,返回数组
    sortedDistIndicies = distance.argsort()
#     classCount保存的K是魅力类型   V:在K个近邻中某一个类型的次数
    classCount = {}
    for i in range(k):
        #获取对应的下标的类别
        voteLabel = labels[sortedDistIndicies[i]]
        #给相同的类别次数计数
        classCount[voteLabel] = classCount.get(voteLabel,0) + 1
    sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

def file2matrix(filename):
    fr = open(filename)
#     readlines:是一次性将这个文本的内容全部加载到内存中(列表)
    arrayOflines = fr.readlines()
    numOfLines = len(arrayOflines)
#     print "numOfLines = " , numOfLines
    #numpy.zeros 创建给定类型的矩阵  numOfLines 行 ,3列
    returnMat = np.zeros((numOfLines,3))
    classLabelVector = []
    index = 0
    for line in arrayOflines:
        #去掉一行的头尾空格
        line = line.strip()
        listFromline = line.split('\t')
        returnMat[index,:] = listFromline[0:3]
        classLabelVector.append(int(listFromline[-1]))
        index += 1
    return returnMat,classLabelVector
'''
    将训练集中的数据进行归一化
    归一化的目的:
        训练集中飞行公里数这一维度中的值是非常大,那么这个纬度值对于最终的计算结果(两点的距离)影响是非常大,
        远远超过其他的两个维度对于最终结果的影响
    实际约会姑娘认为这三个特征是同等重要的
    下面使用最大最小值归一化的方式将训练集中的数据进行归一化
'''
#将数据归一化
def autoNorm(dataSet):
#     dataSet.min(0)   代表的是统计这个矩阵中每一列的最小值     返回值是一个矩阵1*3矩阵
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    #dataSet.shape[0] 计算行数, shape[1] 计算列数
    m = dataSet.shape[0]1列
    normDataSet = dataSet - np.tile(minVals,(m,1))
    normDataSet = normDataSet / np.tile(ranges,(m,1))
    return normDataSet,ranges,minVals
def datingClassTest():
    hoRatio = 0.1
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
    #将数据归一化
    normMat,ranges,minVals = autoNorm(datingDataMat)
    # m 为行数 = 1000
    m = normMat.shape[0]
#     print 'm =%d 行'%m
    #取出100行数据测试
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        #normMat[i,:] 取出数据的第i行,normMat[numTestVecs:m,:]取出数据中的100行到1000行 作为训练集,datingLabels[numTestVecs:m] 取出数据中100行到1000行的类别,4是K
        classifierResult = classify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],4)
        print '模型预测值: %d ,真实值 : %d' %(classifierResult,datingLabels[i])
        if (classifierResult != datingLabels[i]):
            errorCount += 1.0
    errorRate = errorCount / float(numTestVecs)
    print '正确率 : %f' %(1-errorRate)
    return 1-errorRate

def classifyperson():
    resultList = ['没感觉', '看起来还行','极具魅力']
    input_man= [30000,3,0.1]
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
    normMat,ranges,minVals = autoNorm(datingDataMat) 
    result = classify((input_man - minVals)/ranges,normMat,datingLabels,3)   
    print '你即将约会的人是:' ,  resultList[result-1]                             
if __name__ == '__main__':
    acc = datingClassTest()
    if(acc > 0.9):
        classifyperson()

调用python 中 Scikit-learn 实现KNN算法:

from sklearn.neighbors import NearestNeighbors
import numpy as np
from KNNDateOnHand import *

datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
normMat,ranges,minVals = autoNorm(datingDataMat)
t作为训练集拟合模型 
nbrs = NearestNeighbors(n_neighbors=3).fit(normMat)  
input_man= [30000,3,2]
#数据归一化
S = (input_man - minVals)/ranges
#找到当前点的K个临近点,也就是找到临近的3个点
distances, indices = nbrs.kneighbors(S)
print indices  
print distances 
# classCount   K:类别名    V:这个类别中的样本出现的次数
classCount = {}
for i in range(3):应的索引的类别号
    voteLabel = datingLabels[indices[0][i]]
    classCount[voteLabel] = classCount.get(voteLabel,0) + 1
sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
resultList = ['没感觉', '看起来还行','极具魅力']
print resultList[sortedClassCount[0][0]-1]

2、KNN文本分类案例

import os
import numpy as np
from KNNDateOnHand import classify
方法将每个文件中32*32的矩阵数据,转换到1*1024一行中 
def img2vector(filename):
    #创建一个1行1024列的矩阵
    returnVect = np.zeros((1,1024))
    #打开当前的文件
    fr = open(filename)
    #每个文件中有32行,每行有32列数据,遍历32个行,将32个列数据放入1024的列中
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])
    return returnVect

def IdentifImgClassTest():
    hwLabels = []
    #读取训练街 TrainData目录下所有的文件和文件夹
    trainingFileList = os.listdir('TrainData')           
    m = len(trainingFileList)
    #zeros((m,1024)) 返回一个m行 ,1024列的矩阵,默认是浮点型的
    trainingMat = np.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('TrainData/%s' % fileNameStr)
    #读取测试集数据
    testFileList = os.listdir('TestData')         
    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('TestData/%s' % fileNameStr)
        classifierResult = classify(vectorUnderTest, trainingMat, hwLabels, 3)
        print "识别出的数字是: %d, 真实数字是: %d" % (classifierResult, classNumStr)
        if (classifierResult != classNumStr): 
            errorCount += 1.0
    print "\n识别错误次数 %d" % errorCount
    errorRate = errorCount/float(mTest)
    print "\n正确率: %f" % (1-errorRate)

if __name__ == '__main__':
    IdentifImgClassTest()

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

30岁老阿姨

支持一下哦!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值