【机器学习实战】KNN算法的两个经典例子(电影类型判断,约会网站的改进)

一、使用K-邻近算法来对电影的类型进行判断

1.实验思路:

通过电影场景里面的打斗镜头次数与接吻镜头次数的比较然后根据KNN算法来进行判断该电影的类型是动作片还是爱情片

2.代码实现:

(一)首先创建一个数据集,里面有两个数组,其中一个存放打斗/接吻次数,另一个存放与之相对应的电影类型标签

def createDataSet():
    # 四组二维特征
    group = np.array([[104, 3], [100, 2], [81, 1], [10, 101], [5, 99], [2, 98]])
    # 四组特征的标签
    labels = ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']
    return group, labels

(二)KNN算法的核心,用来判断测试集属于训练集中的哪一种。这里有四个参数,分别表示输入的测试集,数据集,数据集中的标签,选择距离最小的k个点以用来投票。出现次数最多的为影片的最终类型

def classify(inx, dataset, labels, k):
    # 计算距离  其实就是计算点一定之间的距离
    dist = np.sum((inx - dataset) ** 2, axis=1) ** 0.5
    # dist.argsort 将x中的元素从小到大排列,提取其对应的index(索引)
    k_labels = [labels[index] for index in dist.argsort()[0: k]]
	label = collections.Counter(k_labels).most_common(1)[0][0]
    return label

(三)输入一个自定义测试集进行测试

if __name__ == '__main__':
    # 创建数据集
    group, labels = createDataSet()
    # 测试集
    test = [100, 23]
    test_class = classify(test, group, labels, 3)
    # 打印分类结果
    print('最终判定的影片类型:',test_class)

3.运行截图:

给定的测试集[100,23],接吻镜头次数为100/打斗镜头次数为23
在这里插入图片描述

4.完整代码展示:

import collections
import numpy as np
def createDataSet():
    # 四组二维特征
    group = np.array([[104, 3], [100, 2], [81, 1], [10, 101], [5, 99], [2, 98]])
    # 四组特征的标签
    labels = ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']
    return group, labels

def classify(inx, dataset, labels, k):
    # 计算距离  其实就是计算点一定之间的距离
    dist = np.sum((inx - dataset) ** 2, axis=1) ** 0.5
    # k个最近的标签
    # dist.argsort 将x中的元素从小到大排列,提取其对应的index(索引)
    k_labels = [labels[index] for index in dist.argsort()[0: k]]
    label = collections.Counter(k_labels).most_common(1)[0][0]
    return label
    
if __name__ == '__main__':
    # 创建数据集
    group, labels = createDataSet()
    # 测试集
    test = [100, 23]
    test_class = classify(test, group, labels, 5)
    # 打印分类结果
    print('最终判定的影片类型:',test_class)

二、在约会网站上使用KNN算法

(一)准备数据:从文本文件中解析数据

通过海伦收集的一些数据存放在文本文件datingTestSet.txt中,每个样本数据占一行,总共有1000行。(数据前三列分别表示:每年获得的飞行常客里程数,玩视频游戏所消耗时间百分比和每周消耗的冰淇淋公升数目。最后一列则表示喜欢和讨厌程度),然后通过自定义的函数file2matrix将本本文件的数据处理为分类器可以接受的格式,以此来处理输入格式的问题。
datingTestSet.txt中的个别数据:

40920 8.326976 0.953952 3
14488 7.153469 1.673904 2
26052 1.441871 0.805124 1
75136 13.147394 0.428964 1
38344 1.669788 0.134296 1
72993 10.141740 1.032955 1
35948 6.830792 1.213192 3
42666 13.276369 0.543880 3
67497 8.631577 0.749278 1

file2matrix函数

def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()  #注意需要加s
    numberOfLines = len(arrayOLines)
    returnMat = zeros((numberOfLines,3))
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFormLine = line.split('\t')
        for x in range(0,3):
            returnMat[index,x] = float(listFormLine[x])
        classLabelVector.append(int(listFormLine[-1])) # -1 为最后一个元素
        index += 1
    return returnMat,classLabelVector

(二)分析数据:使用Matplotlib创建散点图

使用Matplotlib制作原始数据的散点图

datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),marker=(4,1),alpha=0.5)
plt.show()

横坐标表示“玩视频游戏所消耗时间百分比”
纵坐标表示“每周消耗冰淇凌公升数”
在这里插入图片描述

(三)准备数据:归一化数值

由于特征值的大小不同,所以就会对结果的影响程度不同。这就需要我们归一化特征值,把每个特征值的大小固定在[0,1]

def autoNorm(dataSet):
    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))   #element wise divide
    return normDataSet, ranges, minVals

(四)测试算法:作为完整程序验证分类器

用10%的数据作为输入来测试,另外90%作为已知集合

def datingClassTest():
    filename = "datingTestSet.txt"
    datingDataMat, datingLabels = file2matrix(filename)
    hoRatio = 0.10
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m * hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        # 前numTestVecs个数据作为测试集,后m-numTestVecs个数据作为训练集
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 4)
        print("分类结果:%d\t真实类别:%d" % (classifierResult, datingLabels[i]))
        if classifierResult != datingLabels[i]:
            errorCount += 1.0
        print("错误率:%f%%" % (errorCount / float(numTestVecs) * 100))

在这里插入图片描述

(五)使用算法:构建完整可用系统

根据问题提示输出相应的信息,判断出海伦是否喜欢这个人

#约会网站测试函数
def classifyperson():
    resultList=['讨厌', '喜欢', '非常喜欢']
    percentTats=float(input("玩视频游戏所占时间百分比?"))
    ffMiles=float(input("每年获得的飞行常客里程数?"))
    iceCream=float(input("每周消费的冰淇淋公升数?"))
    datingDatMat,datingLabels=file2matrix('datingTestSet.txt')
    normMat,ranges,minVals=autoNorm(datingDatMat)
    inArr=np.array([ffMiles,percentTats,iceCream])
    classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    print("你喜欢这个人的程度可能是:",resultList[classifierResult-1])

在这里插入图片描述
以上一些代码数据来源于Peter Harrington所著的《机器学习实战》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

打代码能当饭吃?

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值