(二)k-邻近算法(约会网站配对效果)

2018-01-09  本文已影响0人  张潇_64df
机器学习实战.jpg

机器学习之k-邻近算法

本文主要根据2013年6月出版的《机器学习实战》中所讲述内容,使用python3.6实现了书中所写代码。


github地址:https://github.com/IBITM/Machine-Learning-in-Action


代码实现如下
# 手动实现knn算法
__author__="ZhangXiao"
# group -- array
# labels -- list类型


from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt


# 创造数据集
def createDataSet():  # labels
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 1.0]])
    labels = ['A', 'B', 'C', 'D']
    return group, labels


# x是用于分类的输入向量
def classify(x, dataSet, labels, k):
    # shape[0] 是返回第一维,也就是行数
    dataSetSize = dataSet.shape[0]  # shape方法:一个整型数字的元组,元组中的每个元素表示相应的数组每一维的长度
    diffMat = tile(x, (dataSetSize, 1)) - dataSet  # 见我简书博客的专门讲解
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)  # 每一行,把所有的列的数加起来
    distances = sqDistances ** 0.5
    sortedDistances = distances.argsort()  # argsort函数返回的是数组值从小到大的索引值,并不是对数组进行排序
    classCount = {}
    # 选择距离最小的k个点
    for i in range(k):
        voteIabel = labels[sortedDistances[i]]
        classCount[voteIabel] = classCount.get(voteIabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    # 书本中所写的是classCOunt.iteritems() 这是python2.7的写法,我已经更换成python3.6的写法了
    return sortedClassCount[0][0]


# 从文本中读取数据
def filematrix(filename):
    fr = open(filename)
    arrayLines = fr.readlines()  # 把文件的每一行读入进来
    numberOfLines = len(arrayLines)
    returnMat = zeros((numberOfLines, 3))  # 构造一个n行3列的0数组
    classLabelVector = []
    index = 0
    for line in arrayLines:
        line = line.strip()  # 去掉所有的回车字符
        listFromLine = line.split('\t')  # 返回是一个list
        returnMat[index, :] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))  # 显示指出是int型
        index += 1
    return returnMat, classLabelVector


# 进行数据归一化
def autoNorm(dataSet):
    minValue = dataSet.min(0)  # axis=0; 每列的最小值
    maxValue = dataSet.max(0)
    ranges = maxValue - minValue
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minValue, (m, 1))
    normDataSet = normDataSet / tile(ranges, (m, 1))
    return normDataSet, ranges, minValue


def datingClassTest():
    hoRatio = 0.10
    datingDataMat, datingLabels = filematrix("datingTestSet2.txt")
    normMat, ranges, minValue = 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("分类器返回的结果为:%d, 实际的结果为:%d" \
              % (classiFierResult, datingLabels[i]))
        if (classiFierResult != datingLabels[i]):
            errorCount += 1.0
    print("错误率为:%f" % (errorCount / float(numTestVecs)))


def calssifyPerson():
    resultList = ["没兴趣", "稍微感兴趣", "非常感兴趣"]
    percentTats = float(input("玩视频游戏所占的时间比"))
    ffMiles = float(input("每年飞行时间历程数"))
    iceCream = float(input("每周消费的冰激凌公斤数"))
    datingDataMat, datingLabels = filematrix("datingTestSet2.txt")
    normMat, ranges, minValue = autoNorm(datingDataMat)
    inArr = array([ffMiles, percentTats, iceCream])
    classifierResult = classify((inArr - minValue) / ranges, normMat, datingLabels, 3)
    print("你对这个人的印象可能是:", resultList[classifierResult - 1])


if __name__ == "__main__":
    # 开始数据的读入
    datingDataMat, datingLabels = filematrix("datingTestSet2.txt")
    # 进行绘图
    # fig = plt.figure() # 新建一个绘画窗口
    # ax = fig.add_subplot(111) # 设置子图的行数、列数、子图的个数
    # ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
    # plt.show()
    # datingClassTest()
    calssifyPerson()

所用到数据和源码的下载地址:
https://www.manning.com/MachineLearninginAction

上一篇下一篇

猜你喜欢

热点阅读