kNN ( 二 )

# -*- coding: utf-8 -*-

import numpy as np
import kNN
"""






函数说明:打开并解析文件,对数据进行分类:
        1 代表不喜欢
        2 代表魅力一般
        3 代表极具魅力
Parameters:
    filename 文件名
Return:
    returnMat 特征矩阵
    classLabelVector 分类Label向量
"""

def file2matrix(filename):
    with open(filename, 'r') as fr:
        arrayOfLines = fr.readlines()
    #得到文件的行数
    numberOfLines = len(arrayOfLines)
    #返回的numpy矩阵,解析完成的数据:numberofLines行, 3列
    returnMat = np.zeros((numberOfLines, 3))
    #返回分类的标签向量
    classLabelVector = []
    #行的索引值
    index = 0
    for line in arrayOfLines:
        #删除行头尾的空白,包括 ‘\n’,‘\t’,‘\r’,‘ ’
        line = line.strip()
        #提取前三列
        listFromline = line.split('\t')
        returnMat[index,:] = listFromline[0:3]
        #根据文本中的喜欢程度进行标记:1:不喜欢,2:魅力一般, 3:极具魅力
        if 'didntLike' == listFromline[-1]:
            classLabelVector.append(1)
        elif 'smallDoses' == listFromline[-1]:
            classLabelVector.append(2)
        elif 'largeDoses' == listFromline[-1]:
            classLabelVector.append(3)
        index += 1
        
    return returnMat, classLabelVector


"""
在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化,
如将取值范围处理为0到1或者-1到1之间。
下面的公式可以将任意取值范围的特征值转化为0到1区间内的值:
newValue = (oldValue - min) / (max - min)
"""

"""
函授说明:对数据进行归一化
Parameters:
    dataSet 特征矩阵
Returns:
    normDataSet 归一化后的特征矩阵
    ranges 数据范围
    minVals 数据最小值
    
"""

def autoNorm(dataSet):
    #获得数据的最小值和最大值
    #min(0)返回该矩阵中每一列的最小值
    #min(1)返回该矩阵中每一行的最小值
    #max(0)返回该矩阵中每一列的最大值
    #max(1)返回该矩阵中每一行的最大值
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    #最大值和最小值的差值
    ranges = maxVals - minVals
    #shape(dataSet)返回dataSet的行列数(m,n)
    normDataSet = np.zeros(np.shape(dataSet))
    #返回dataSet的行数
    m = dataSet.shape[0]
    #减去最小值
    #tile(),把一个量复制,此处沿x轴复制1次,沿y轴复制m次
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet / np.tile(ranges, (m, 1))
    
    return normDataSet, ranges, minVals
    

"""
机器学习算法一个很重要的工作就是评估算法的正确率,
通常我们只提供已有数据的90%作为训练样本来训练分类器,
而使用其余的10%数据去测试分类器,
需要注意的是,10%的测试数据应该是随机选择的,
由于海伦提供的数据并没有按照特定目的来排序,
所以我们可以随意选择10%数据而不影响其随机性。
"""  
"""
函数说明:分类器测试函数

Parameters:
    无
Returns:
    无
"""
def datingCalssTest():
    filename = 'datingTestSet.txt'
    #返回特征矩阵和特征向量
    datingDataMat, datingLabels = file2matrix(filename)
    #取所有数据的10%
    hoRatio = 0.1
    #特征矩阵数据归一化
    normMat, ranges, minVals = autoNorm(datingDataMat)
    #获取特征矩阵的行数 m=1000
    m = normMat.shape[0] 
    #10%的测试数据,即测试集 numTestVecs = 100
    numTestVecs = int(m * hoRatio) 
    #分类错误计数
    errorCount = 0.0
    #range(n),从0至n-1
    for x in range(numTestVecs):
        #前numTestVecs的个数作为测试集,后m-numTestVecs的数据作为训练集
        #Numpy 中多维数组的切片操作与 Python 中 list 的切片操作一样,
        #同样由 start, stop, step 三个部分组成, 不同维度用 , 分开
        classifierResult = kNN.classify(
                normMat[x , :],
                normMat[numTestVecs : m,:], 
                datingLabels[numTestVecs:m],
                4)
        print("分类结果:%d\t真实类别:%d" % (classifierResult, datingLabels[x]))
        if classifierResult != datingLabels[x]:
            errorCount += 1.0
    print("错误率:%f%%" % ( errorCount / float(numTestVecs) * 100) )
    

"""
函数说明:通过输入一个人的特征,进行分类输出
Parameters:
    无
Returns:
    无
ranges, minVals 在这里用到了   
"""    
def classifyPerson():
    resultList = ['讨厌', '有些喜欢', '非常喜欢']
    flyMiles = float(input("每年飞行里程数:"))
    gameTime = float(input("玩游戏时间所占百分比:"))   
    iceCream = float(input("每周吃的冰激凌升数:"))
    filename = 'datingTestSet.txt'
    #处理数据
    datingDataMat, datingLabels = file2matrix(filename)
    #归一化数据
    normMat, ranges, minVals = autoNorm(datingDataMat)
    #生成测试集
    inX = np.array([flyMiles, gameTime, iceCream])
    #测试集归一化
    inX = (inX - minVals) / ranges
    classifierResult = kNN.classify(inX, normMat, datingLabels, 3)
    print("你可能%s这个人" % ( resultList[classifierResult - 1] ))
    
    
if __name__ == '__main__':
    classifyPerson()
       

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值