机器学习实战Task01 K近邻算法

约会网站配对效果完整代码

import numpy as np 
import operator as op

import matplotlib
import matplotlib.pyplot as plt

#classify0的作用:
#给定一个输入List inX,可以是n维,这个inX一般存放待分类的条目的属性值,然后和已知数据集(因为是已知的,所以标签类别也是已知的)相比(通过两点差的平方和再开根号),和哪几个近就属于哪类。
#输出即是该条目的类别。

#这个分类函数是支持多维的,而该函数里的注释是基于2维写的。
#2维情况的输入值:
#inX=[0, 0]
#dataSet=
# [[ 1.   1.1]
#  [ 1.   1. ]
#  [ 0.   0. ]
#  [ 0.   0.1]]
#labels=['A', 'A', 'B', 'B']
#k=3 表示只取最近的3个做比较,
#输出A或B。
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0] #计算dataSet有多少行,这里的0维指x行
    diffMat = np.tile(inX, (dataSetSize,1)) - dataSet#生成和dataSet一样大小的数组,其每行的成员(x,y)都是inX的x,y减dataSet对应行的x,y。
    sqDiffMat = diffMat**2 #对每个成员做平方操作。
    sqDistances = sqDiffMat.sum(axis=1) #把每行的两个值相加
    distances = sqDistances**0.5 #再把相加的值开方,就算出了距离
    sortedDistIndicies = distances.argsort() #然后再从小到大排序,并记下相应的下标。
    classCount={}
    for i in range(k):#这里是字典相关的操作,即统计'A','B'的次数(前3名中),其中'A','B’为key,次数为value。
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #这种都是字典操作,先从字典中取出'A'的次数,然后加1,再赋值给'A'对应的值。
    #上述代码结束后,classCount字典的值为:{'B': 2, 'A': 1}
    sortedClassCount = sorted(iter(classCount.items()), key=op.itemgetter(1), reverse=True)
    #sorted可对迭代类型排序
    #operator是python的一个模块,其中itemgetter函数可以获得对象不同维度的数据,参数为维度的索引值
    #比如[('B', 2), ('A', 1)],那么op.itemgetter(1)就是以第2维来排序,即以后面的数字来排序。
    #reverse是否反转,默认排序结果是从小到大,这里想要的是从大到小。
    return sortedClassCount[0][0]#这里取第0行第0列。

def createDataSet():
    group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    # print(group)
    lables = ['A', 'A', 'B', 'B']

    return group, lables

def createDataSet_test():
    group, labels = createDataSet()#2.1.1导入数据到ndarray中。
    result = classify0([0,0], group, labels, 3)#2.1.2 实现分类算法,并给定一个条目,判断此条目属于哪类。

    print(result)

#为了理解以上内容,做的单独测试,和正式代码没有任何关系。
def createDataSet_temp_test():
     inX = [0,0]
     k=3
     group, labels = createDataSet()
     print(group)
     dataSetSize = group.shape[0]#group 0维方向大小,group因为是4行3列,0维的值即为4.
     print(group.shape[0]) #4

     dataSet = group
     print(np.tile(inX, (4,1))) #tile表示在给定的数组,在行方向重复4次,列方向重复1次。
     diffMat = np.tile(inX, (dataSetSize,1)) - dataSet
     print(diffMat)

     sqDiffMat = diffMat**2
     print(sqDiffMat)

     sqDistances=sqDiffMat.sum(axis=1)

     print(sqDistances)

     distances = sqDistances**0.5
     print(distances)

     sortedDistIndicies = distances.argsort()
     print(sortedDistIndicies)

     classCount={}
     # aa = 'B'
     # print(classCount.get('B',0))
     for i in range(k):#
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1

     print(classCount)#classCount字典的值为:{'B': 2, 'A': 1}

     print(iter(classCount.items()))
     for item in iter(classCount.items()):
         print(item)

     sortedClassCount = sorted(iter(classCount.items()), key=op.itemgetter(1), reverse=True)
     #sorted可对迭代类型排序
     #operator是python的一个模块,其中itemgetter函数可以获得对象不同维度的数据,参数为维度的索引值
     #比如[('B', 2), ('A', 1)],那么op.itemgetter(1)就是以第2维来排序,即以后面的数字来排序。
     #reverse是否反转,默认排序结果是从小到大,这里想要的是从大到小。
     print(sortedClassCount)

#从文件中获取数据,并格式化成Numpy数组。
#returnMat[]数组用于存放样本的属性。
#classLabelVector[]用于存放样本的类别
def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #1000
    returnMat = np.zeros((numberOfLines,3))        #创建numberOfLines行,3列矩阵,初始化为0.
    classLabelVector = []                       #用于存放第四列的的值。
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3] #因为index是会自增的,所以数据会往returnMat上增。
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector
# returnMat={ndarray} [[  4.09200000e+04   8.32697600e+00   9.53952000e-01]
#  [  1.44880000e+04   7.15346900e+00   1.67390400e+00]
#  [  2.60520000e+04   1.44187100e+00   8.05124000e-01]
#  ...,
#  [  2.65750000e+04   1.06501020e+01   8.66627000e-01]
#  [  4.81110000e+04   9.13452800e+00   7.28045000e-01]
#  [  4.37570000e+04   7.88260100e+00   1.33244600e+00]]
#classLabelVector={list}[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1,……]


#归一化处理公式:newValue=(oldValue-min)/(max-min)
def autoNorm(dataSet):
    #dataSet是1000行3列的数据。
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))#shape取ndarray dataSet的大小(维度),然后创建一个一样大小的ndarray,并以0初始化。
    m = dataSet.shape[0]#取0维大小,1000行。
    normDataSet = dataSet - np.tile(minVals, (m,1))#做(oldValue-min)操作
    normDataSet = normDataSet/np.tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals
# normDataSet={ndarray}[[ 0.44832535  0.39805139  0.56233353]
#  [ 0.15873259  0.34195467  0.98724416]
#  [ 0.28542943  0.06892523  0.47449629]
#  ...,
#  [ 0.29115949  0.50910294  0.51079493]
#  [ 0.52711097  0.43665451  0.4290048 ]
#  [ 0.47940793  0.3768091   0.78571804]]

# ranges={ndarray}[  9.12730000e+04   2.09193490e+01   1.69436100e+00]
# minVals={ndarray}[ 0.        0.        0.001156]

#从文本文件中解析数据,并使用Matplotlib画图展示。
def file2matrix_test():
    #2.2.1节代码,从文本文件中解析数据。
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    print(datingDataMat) #数据前三列的矩阵
    print(datingLabels) #第四列值存放在list中。

    #2.2.2使用Matplotlib创建散点图。
    fig = plt.figure()
    ax = fig.add_subplot(111)
    num_show=0#需要从矩阵的第几行数据开始展示,0为展示所有
    ax.scatter(datingDataMat[num_show:,0], datingDataMat[num_show:,1], 15.0*np.array(datingLabels[num_show:]), 15.0*np.array(datingLabels[num_show:]))
    #用datingLabels类型标注不同的颜色,scatter的具体用法再学。
    plt.show()
    #这里还有一个小问题没有解决,就是显示在图上的颜色没有标注到底是属于哪一类的,这个可在后续学Matplotlib时再完善。

#归一化处理,因为有一项属性数据太大,这样在算距离时其它属性就不起作用了,但是其它属性也是一样重要的,需要要做归一化处理。
def autoNorm_test():
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')

    normMat, ranges, minVals = autoNorm(datingDataMat)
    print(normMat,'\n', ranges,'\n',minVals,'\n')

#用来测试分类算法的正确性
def datingClassTest():
    hoRatio = 0.10      #预留的数据用来测试分类器。
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0] #算出0维大小,一共1000条
    numTestVecs = int(m*hoRatio) #预留数据的后面数据用来训练样本。预留数据用来和这些训练样本比较,计算距离。
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        #classifierResult是使用分类器测出来的结果,拿此结果和真实结果(datingLabels[i])对比,如果一样表示预测正确。
        #normMat[i,:],表示norMat的第i行,第i取所有(:冒号表示所有),具体可看my_4_1_intro.py二维数组切片。
        #normMat[numTestVecs:m,:]表示从训练数据位置numTestVecs开始到最后一条数据m为止
        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 classifyPerson():
    resultList = ['没有魅力', '魅力一般', '极具魅力']
    ffMiles = float(input("每年飞行公里数?"))
    percentTats=float(input("打游戏耗费时间的百分比?"))
    iceCream = float(input("每周消费的冰激凌?"))

    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ffMiles,percentTats,iceCream])
    classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)
    print("这个人:", resultList[classifierResult-1])


if __name__ == '__main__':
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值