机器学习算法--(一)kNN--实战改进约会网站配对效果

kNN算法项目实战———改进约会网站的配对效果

目录

kNN算法项目实战———改进约会网站的配对效果

1.项目背景

2.项目数据

3.K-邻近算法的一般流程

4.项目步骤及代码实现

1.k--邻近算法

2.Python 分析处理文本数据

3.数据可视化

4.归一化

5.测试算法

6.预测

7.完整代码


1.项目背景

海伦女士一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的不选,但她并不是喜欢每一个人。经过一番总结,她发现自己交往过的人可以进行如下分类:

  • 不喜欢的人
  • 魅力一般的人
  • 极具魅力的人

2.项目数据

海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,每个样本占据一行,总共有1000行。

https://github.com/Asia-Lee/KNN/blob/master/datingTestSet.txt   --数据集下载

海伦收集的样本数据主要包含以下3种特征

  • 每年获得的飞行常客里程数
  • 玩游戏所消耗时间百分比
  • 每周消费的冰淇淋公升数

数据格式如下:

 

3.K-邻近算法的一般流程

(1)收集数据:提供文本文件

(2)准备数据:使用Python解析文本文件

(3)分析数据:使用Matplotlib画二维扩散图

(4)测试算法:使用文本文件的部分数据作为测试样本,计算错误率

(5)使用算法:错误率再可接受范围内,就可以使用k-邻近算法进行分类

4.项目步骤及代码实现

1.k--邻近算法

# -*- coding:utf-8 -*-
import numpy as np
import operator


"""
k-邻近算法:
    inX 是待分类点, dataSet是训练集, labels是标签向量, k是选取的最近的样本点的个数
"""
def Classify0(inX, dataSet, labels, k):
    # 得到训练集的行数
    dataSetSize = dataSet.shape[0]

    # 计算待分类点与训练集中每个样本的距离并排序
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    sqdiffMat = diffMat ** 2
    sqDistance = sqdiffMat.sum(axis=1)
    distance = sqDistance ** 0.5
    sortedDistIndicies = distance.argsort()

    classCount = {} # 存放选取的样本所出现分类的频率

    for i in range(k):
        voteIlabels = labels[sortedDistIndicies[i]]
        # 计算筛选样本点标签的频率
        classCount[voteIlabels] = classCount.get(voteIlabels, 0) + 1
        # 频率排序并返回最大频率的标签作为预测标签
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

2.Python 分析处理文本数据

 

"""
对文本进行分析处理
"""
def file2matrix(filename):
    fr = open(filename)
    # 按行获取文本信息
    arrayOfLines = fr.readlines()
    # 获取行数
    numberOfLines = len(arrayOfLines)

    # 创建返回矩阵(1000 * 3) 以及 标签列表 (1000 * 1)
    returnMat = np.zeros((numberOfLines, 3))
    classLabelVector = []
    index = 0

    for line in arrayOfLines:
        line = line.strip()  # 删除空白符,如 '\t','\r','\n'
        listFromLines = line.split('\t')  # 按制表符对文本进行分割(1000 * 4)

        # 将样本特征存放至返回矩阵,将文本标签处理成数字标签后放入标签列表
        returnMat[index, :] = listFromLines[0:3]
        index += 1
        if listFromLines[-1] == 'didntLike':
            classLabelVector.append(1)
        if listFromLines[-1] == 'smallDoses':
            classLabelVector.append(2)
        if listFromLines[-1] == 'largeDoses':
            classLabelVector.append(3)
    return returnMat, classLabelVector


# 测试文本读取情况,输出前20行
datingDataMat, datingLabels = file2matrix('datingTestSet1.txt')
for i in range(20):
    print(datingDataMat[i], datingLabels[i])

3.数据可视化

"""
数据可视化处理
"""
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import matplotlib as mpl


def showdata(datingDataMat, datingLabels):
    # 设置字体格式,处理图中文字符显示问题
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    # 把画布分割成 2行2列,不共享x 轴, y 轴, 画布大小为(13,9)
    # 当nrows=2, ncols=2, 代表fig画布分为4个区域,axs[0][0]代表第一个区域
    fig, axs = plt.subplots(nrows=2, ncols=2, sharex=False, sharey=False, figsize=(13, 9))
    LabelColors = []
    for i in datingLabels:
        if i == 1:
            LabelColors.append('black')
        if i == 2:
            LabelColors.append('orange')
        if i == 3:
            LabelColors.append('red')

    # 画出散点图1,第一列,第二列作为x, y 轴
    axs[0][0].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelColors, s=15, alpha=0.5)
    axs0_title_text = axs[0][0].set_title('每年获得的飞行常客里程数与玩视频游戏所消耗时间占比')
    axs0_xlabel_text = axs[0][0].set_xlabel('每年获得的飞行常客里程数')
    axs0_ylabel_text = axs[0][0].set_ylabel('每年玩视频游戏所消耗时间占比')
    plt.setp(axs0_title_text, size=12, weight='bold', color='red')
    plt.setp(axs0_xlabel_text, size=10, weight='bold', color='black')
    plt.setp(axs0_ylabel_text, size=10, weight='bold', color='black')
    
    # 画出散点图2,第一列, 第三列作为x, y 轴
    axs[0][1].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 2], color=LabelColors, s=15, alpha=0.5)
    axs1_title_text = axs[0][1].set_title('每年获得的飞行常客里程数与每周消费冰激凌公升数')
    axs1_xlabel_text = axs[0][1].set_xlabel('每年获得的飞行常客数')
    axs1_ylabel_text = axs[0][1].set_ylabel('每周消费冰激凌公升数')
    plt.setp(axs1_title_text, size=12, weight='bold', color='red')
    plt.setp(axs1_xlabel_text, size=10, weight='bold', color='black')
    plt.setp(axs1_ylabel_text, size=10, weight='bold', color='black')

    # 画出散点图3, 第二列, 第三列作为x, y 轴
    axs[1][0].scatter(x=datingDataMat[:, 1], y=datingDataMat[:, 2], color=LabelColors, s=15, alpha=0.5)
    axs2_title_text = axs[1][0].set_title('每年玩视频游戏所消耗时间占比与每周消费的冰激凌公升数')
    axs2_xlabel_text = axs[1][0].set_xlabel('每年玩视频游戏所消耗时间占比')
    axs2_ylabel_text = axs[1][0].set_ylabel('每周消费的冰激凌公升数')
    plt.setp(axs2_xlabel_text, size=12, weight='bold', color='red')
    plt.setp(axs2_xlabel_text, size=10, weight='bold', color='black')
    plt.setp(axs2_ylabel_text, size=10, weight='bold', color='black')

    # 设置图例
    didntLike = mlines.Line2D([], [], color='black', marker='.', markersize=6, label='不喜欢')
    smallDoses = mlines.Line2D([], [], color='orange', marker='.', markersize=6, label='魅力一般')
    largeDoses = mlines.Line2D([], [], color='orange', marker='.', markersize=6, label='极具魅力')

    # 添加图例
    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.show()


# 测试可视化结果

datingDataMat, datingLabels = file2matrix('datingTestSet1.txt')
showdata(datingDataMat, datingLabels)

 

4.归一化

"""
归一化处理
"""
def autoNorm(dataSet):
    # 获取每列中的最小,最大值 共(1 * 3)个
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)

    ranges = maxVals - minVals
    # 创建和dataSet相同的0矩阵
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]  # 查看第一维长度
    # dataSet 中每个样本 - 最小值
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    # 每个样本 / 范围
    normDataSet = normDataSet/np.tile(ranges, (m, 1))
    # 返回归一化后的数据,范围,每列最小值
    return normDataSet, ranges, minVals

# 测试归一化结果
datingDataSet, datingLabels = file2matrix('datingTestSet1.txt')
for i in range(10):
    print(datingDataSet[i], datingLabels[i])

normDataSet, ranges, minVals = autoNorm(datingDataSet)
for i in range(10):
    print(normDataSet[i], datingLabels[i])

5.测试算法

"""
测试算法
"""
def datingClassTest():
    hoRatio = 0.10  # 测试集所占比例
    datingDataSet, datingLabels = file2matrix('datingTestSet1.txt')
    # 归一化
    normDataSet, ranges, minVals = autoNorm(datingDataSet)
    m = normDataSet.shape[0]
    # 测试集数量
    numTestVecs = int(m*hoRatio)
    errorCount = 0
    for i in range(numTestVecs):
        # 利用训练数据训练分类器,再用分类器预测测试集结果
        classifierResult = Classify0(normDataSet[i, :],
                                     normDataSet[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("The classifier came back with %d, the real answer is: %d"
              % (classifierResult, datingLabels[i]))
        if(classifierResult != datingLabels[i]):
            errorCount += 1
    print("The total error rate is : %f" % (errorCount/float(numTestVecs)))
    

6.预测

"""
预测
"""
def classifyPerson():
    resultList = ['不喜欢', '有点好感', '非常喜欢']
    percentTats = float(input("Percentage of time spent playing video game?"))
    ffMiles = float(input("Frequent flier miles earned per year?"))
    iceCream = float(input("liters of ice cream consumed per week?"))
    datingDataSet, datingLabels = file2matrix('datingTestSet1.txt')
    normDataSet, ranges, minVals = autoNorm(datingDataSet)

    inArr = np.array([ffMiles, percentTats, iceCream])  # 待分类特征向量
    # 输入数据归一化
    classifierResult = Classify0((inArr-minVals)/ranges, normDataSet, datingLabels, 3)

    print("You will probably like this person: ", resultList[classifierResult-1])

7.完整代码

# -*- coding:utf-8 -*-
import numpy as np
import operator


"""
k-邻近算法:
    inX 是待分类点, dataSet是训练集, labels是标签向量, k是选取的最近的样本点的个数
"""
def Classify0(inX, dataSet, labels, k):
    # 得到训练集的行数
    dataSetSize = dataSet.shape[0]

    # 计算待分类点与训练集中每个样本的距离并排序
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    sqdiffMat = diffMat ** 2
    sqDistance = sqdiffMat.sum(axis=1)
    distance = sqDistance ** 0.5
    sortedDistIndicies = distance.argsort()

    classCount = {} # 存放选取的样本所出现分类的频率

    for i in range(k):
        voteIlabels = labels[sortedDistIndicies[i]]
        # 计算筛选样本点标签的频率
        classCount[voteIlabels] = classCount.get(voteIlabels, 0) + 1
        # 频率排序并返回最大频率的标签作为预测标签
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]


"""
对文本进行分析处理
"""
def file2matrix(filename):
    fr = open(filename)
    # 按行获取文本信息
    arrayOfLines = fr.readlines()
    # 获取行数
    numberOfLines = len(arrayOfLines)

    # 创建返回矩阵(1000 * 3) 以及 标签列表 (1000 * 1)
    returnMat = np.zeros((numberOfLines, 3))
    classLabelVector = []
    index = 0

    for line in arrayOfLines:
        line = line.strip()  # 删除空白符,如 '\t','\r','\n'
        listFromLines = line.split('\t')  # 按制表符对文本进行分割(1000 * 4)

        # 将样本特征存放至返回矩阵,将文本标签处理成数字标签后放入标签列表
        returnMat[index, :] = listFromLines[0:3]
        index += 1
        if listFromLines[-1] == 'didntLike':
            classLabelVector.append(1)
        if listFromLines[-1] == 'smallDoses':
            classLabelVector.append(2)
        if listFromLines[-1] == 'largeDoses':
            classLabelVector.append(3)
    return returnMat, classLabelVector


# # 测试文本读取情况,输出前20行
# datingDataMat, datingLabels = file2matrix('datingTestSet1.txt')
# for i in range(20):
#     print(datingDataMat[i], datingLabels[i])





"""
数据可视化处理
"""
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import matplotlib as mpl


def showdata(datingDataMat, datingLabels):
    # 设置字体格式,处理图中文字符显示问题
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    # 把画布分割成 2行2列,不共享x 轴, y 轴, 画布大小为(13,9)
    # 当nrows=2, ncols=2, 代表fig画布分为4个区域,axs[0][0]代表第一个区域
    fig, axs = plt.subplots(nrows=2, ncols=2, sharex=False, sharey=False, figsize=(13, 9))
    LabelColors = []
    for i in datingLabels:
        if i == 1:
            LabelColors.append('black')
        if i == 2:
            LabelColors.append('orange')
        if i == 3:
            LabelColors.append('red')

    # 画出散点图1,第一列,第二列作为x, y 轴
    axs[0][0].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelColors, s=10, alpha=0.5)
    axs0_title_text = axs[0][0].set_title('每年获得的飞行常客里程数与玩视频游戏所消耗时间占比')
    axs0_xlabel_text = axs[0][0].set_xlabel('每年获得的飞行常客里程数')
    axs0_ylabel_text = axs[0][0].set_ylabel('每年玩视频游戏所消耗时间占比')
    plt.setp(axs0_title_text, size=10, weight='bold', color='red')
    plt.setp(axs0_xlabel_text, size=8, weight='bold', color='black')
    plt.setp(axs0_ylabel_text, size=8, weight='bold', color='black')

    # 画出散点图2,第一列, 第三列作为x, y 轴
    axs[0][1].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 2], color=LabelColors, s=10, alpha=0.5)
    axs1_title_text = axs[0][1].set_title('每年获得的飞行常客里程数与每周消费冰激凌公升数')
    axs1_xlabel_text = axs[0][1].set_xlabel('每年获得的飞行常客数')
    axs1_ylabel_text = axs[0][1].set_ylabel('每周消费冰激凌公升数')
    plt.setp(axs1_title_text, size=10, weight='bold', color='red')
    plt.setp(axs1_xlabel_text, size=8, weight='bold', color='black')
    plt.setp(axs1_ylabel_text, size=8, weight='bold', color='black')

    # 画出散点图3, 第二列, 第三列作为x, y 轴
    axs[1][0].scatter(x=datingDataMat[:, 1], y=datingDataMat[:, 2], color=LabelColors, s=10, alpha=0.5)
    axs2_title_text = axs[1][0].set_title('每年玩视频游戏所消耗时间占比与每周消费的冰激凌公升数')
    axs2_xlabel_text = axs[1][0].set_xlabel('每年玩视频游戏所消耗时间占比')
    axs2_ylabel_text = axs[1][0].set_ylabel('每周消费的冰激凌公升数')
    plt.setp(axs2_title_text, size=10, weight='bold', color='red')
    plt.setp(axs2_xlabel_text, size=8, weight='bold', color='black')
    plt.setp(axs2_ylabel_text, size=8, weight='bold', color='black')

    # 设置图例
    didntLike = mlines.Line2D([], [], color='black', marker='.', markersize=6, label='不喜欢')
    smallDoses = mlines.Line2D([], [], color='orange', marker='.', markersize=6, label='魅力一般')
    largeDoses = mlines.Line2D([], [], color='orange', marker='.', markersize=6, label='极具魅力')

    # 添加图例
    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.show()

#
# # 测试可视化结果
#
# datingDataMat, datingLabels = file2matrix('datingTestSet1.txt')
# showdata(datingDataMat, datingLabels)



"""
归一化处理
"""
def autoNorm(dataSet):
    # 获取每列中的最小,最大值 共(1 * 3)个
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)

    ranges = maxVals - minVals
    # 创建和dataSet相同的0矩阵
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]  # 查看第一维长度
    # dataSet 中每个样本 - 最小值
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    # 每个样本 / 范围
    normDataSet = normDataSet/np.tile(ranges, (m, 1))
    # 返回归一化后的数据,范围,每列最小值
    return normDataSet, ranges, minVals

# # 测试归一化结果
# datingDataSet, datingLabels = file2matrix('datingTestSet1.txt')
# for i in range(10):
#     print(datingDataSet[i], datingLabels[i])
#
# normDataSet, ranges, minVals = autoNorm(datingDataSet)
# for i in range(10):
#     print(normDataSet[i], datingLabels[i])
#

"""
测试算法
"""
def datingClassTest():
    hoRatio = 0.10  # 测试集所占比例
    datingDataSet, datingLabels = file2matrix('datingTestSet1.txt')
    # 归一化
    normDataSet, ranges, minVals = autoNorm(datingDataSet)
    m = normDataSet.shape[0]
    # 测试集数量
    numTestVecs = int(m*hoRatio)
    errorCount = 0
    for i in range(numTestVecs):
        # 利用训练数据训练分类器,再用分类器预测测试集结果
        classifierResult = Classify0(normDataSet[i, :],
                                     normDataSet[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("The classifier came back with %d, the real answer is: %d"
              % (classifierResult, datingLabels[i]))
        if(classifierResult != datingLabels[i]):
            errorCount += 1
    print("The total error rate is : %f" % (errorCount/float(numTestVecs)))


"""
预测
"""
def classifyPerson():
    resultList = ['不喜欢', '有点好感', '非常喜欢']
    percentTats = float(input("Percentage of time spent playing video game?"))
    ffMiles = float(input("Frequent flier miles earned per year?"))
    iceCream = float(input("liters of ice cream consumed per week?"))
    datingDataSet, datingLabels = file2matrix('datingTestSet1.txt')
    normDataSet, ranges, minVals = autoNorm(datingDataSet)

    inArr = np.array([ffMiles, percentTats, iceCream])  # 待分类特征向量
    # 输入数据归一化
    classifierResult = Classify0((inArr-minVals)/ranges, normDataSet, datingLabels, 3)

    print("You will probably like this person: ", resultList[classifierResult-1])


classifyPerson()

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值