KNN算法之好感度预测

论坛 期权论坛 脚本     
匿名技术用户   2020-12-27 05:32   11   0

前篇:K-近邻算法开篇之电影
数据下载链接:https://pan.baidu.com/s/1qDPBH_E2lnq-_gWjTH4xSA
提取码:0vsp

      Hellen经常使用约会网站寻找猎物用于解决自己的终身大事。时光流逝,Hellen还是single dog。她遇见了很多人,有好有坏,Hellen将约会网站上的人分为三类:不喜欢的人,魅力一般的人和极具魅力的人。为了以后的约会能尽可能与极具魅力的人在一起,Hellen需要对约会对象进行分类。

      Hellen收集了一堆数据,每个样本包含三个特征:每年获得的飞行常客里程数,玩视频游戏所耗时间百分比和每周消费的冰淇淋公升数
部分数据如下所示:
在这里插入图片描述

数据的录入

import numpy as np

def load_data(filename):
    with open(filename) as file:
        lines = file.readlines()#读取所有的数据
    dataSize = len(lines)#获取数据量大小
    #构建一个dataSize*3大小的矩阵,用于存放数据集
    dataSet = np.zeros((dataSize,3))
    labels = [] #存放每行数据对应的分类标签(1,2,3,分别代表不喜欢,魅力一般和极具魅力)
    index = 0
    #逐行解析
    for line in lines:
        line = line.strip()#去除头尾的空格和换行符
        items = line.split("\t")
        dataSet[index,:] = items[0:3]#将数据存入dataSet中
        labels.append(int(items[-1]))
        index+=1
    return dataSet,labels

data,labels = load_data("datingTestSet.txt")
print(data[:5,:])
print(labels[:5])

在这里插入图片描述

数据的展示

      数据中总共有三个特征值,进行两两配对画图。

import matplotlib.lines as mlines

def draw_image(data,labels):
    fig, axs = plt.subplots(nrows=2, ncols=2, sharex=False, sharey=False, figsize=(13, 8))
    LabelsColors = []
    #为每个分类设置颜色
    for i in labels:
        if i == 1:
            LabelsColors.append('black')
        if i == 2:
            LabelsColors.append('green')
        if i == 3:
            LabelsColors.append('red')
    # 飞行常客里程与玩游戏所占时间
    axs[0][0].scatter(x=data[:, 0], y=data[:, 1], color=LabelsColors, s=15, alpha=.5)
    # 飞行常客里程与冰激凌公升数
    axs[0][1].scatter(x=data[:, 0], y=data[:, 2], color=LabelsColors, s=15, alpha=.5)
    # 玩游戏所占时间与冰激凌公升数
    axs[1][0].scatter(x=data[:, 1], y=data[:, 2], color=LabelsColors, s=15, alpha=.5)
    # 设置图例样式
    didntLike = mlines.Line2D([], [], color='black', marker='.', markersize=6, label='didntLike')
    smallDoses = mlines.Line2D([], [], color='green', marker='.', markersize=6, label='smallDoses')
    largeDoses = mlines.Line2D([], [], color='red', marker='.', markersize=6, label='largeDoses')
    # 添加图例
    axs[0][0].legend(handles=[didntLike, smallDoses, largeDoses])
    axs[0][1].legend(handles=[didntLike, smallDoses, largeDoses])
    axs[1][0].legend(handles=[didntLike, smallDoses, largeDoses])
    # 保存图片
    plt.savefig("data.png")
    # 显示图片
    plt.show()

在这里插入图片描述

数据处理

      观察数据我们会发现飞行常客里程数远大于另外两个特征值,并且飞行常客里程数往往相差比较大,这意味着在计算距离时这一特征的差值特别大,从而会严重影响预测结果。Hellen任务这三个特征的权重是一样的,所以我们需要对数据进行归一化操作。我们可以使用公式:newValue=oldValueminmaxminnewValue=\frac {oldValue-min}{max-min} 实现归一化操作。

max:对应特征特征值的最大值;
min:对应特征特征值的最小值。

def norm(data):
    minvalues = data.min(axis=0)
    maxvalues = data.max(axis=0)
    rangevalues = maxvalues - minvalues
    #创建矩阵,用于存储归一化后的数据
    normData = np.zeros(data.shape)
    dataSize = data.shape[0]
    # 完成oldValue - min
    normData = data - np.tile(minvalues,(dataSize,1))
    # 完成(oldValue - min) /(max-min)
    normData = normData / np.tile(rangevalues,(dataSize,1))
    #返回归一化后的数据
    return normData,rangevalues,minvalues

在这里插入图片描述

初步实现,计算错误率

KNN实现的方法请查看前篇:K-近邻算法开篇之电影
      选择100条数据用于做测试集,计算KNN算法对好感度预测的错误率如何。

if __name__ == '__main__':
    k=3
    errorCount=0.0
    rate = 0.1#测试集占所有数据的比例
    data,labels = load_data("datingTestSet.txt")
    normdata = norm(data)
    allNum = normdata.shape[0]
    testNum = int(rate*allNum)#已知数据1000条,我们选择100条作为测试集
    for i in range(testNum):
        result = classify(normdata[i,:],normdata[testNum:allNum,:],labels[testNum:allNum],k)
        print('第{}条数据,预测为:{}==>实际为:{}'.format(i+1,result,labels[i]))
        if result != labels[i]:
            errorCount+=1.0
    print('错误率为:',errorCount/testNum)

在这里插入图片描述
错误率为5%,预测的效果还不错。现在我们可以手动输入测试集,使用这个算法来进行预测了。

完成,形成可用系统

def main(case):
    k = 3
    data, labels = load_data("datingTestSet.txt")
    normdata,rangevalues,minvalues = norm(data)
    result = classify((case-minvalues)/rangevalues, normdata, labels, k)
    return result

if __name__ == '__main__':
    resultLabel = ['不喜欢','魅力一般','极具魅力']
    meters = float(input("请输入飞行常客里程数:"))
    gamerate = float(input("玩游戏所占实际比:"))
    icecream = float(input("每周冰淇淋消费数:"))
    input_case = np.array([meters,gamerate,icecream])
    #输入的数据也要进行归一化
    result = main(input_case)
    print("预测结果为:",resultLabel[result-1])

在这里插入图片描述

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP