美文网首页
使用k-邻近算法改进约会网站的配对效果

使用k-邻近算法改进约会网站的配对效果

作者: 梦vctor | 来源:发表于2018-10-17 15:53 被阅读0次

使用k-邻近算法改进约会网站的配对效果

首先要找数据出处,海伦约会数据放在文本文件datingTestSet.txt中,每个数据样本数据占据一行,总共有1000行。
下载网址:[http:/www.manning.com/MachineLearninginAction]
点击左侧Source Code
或者:http://www.ituring.com.cn/book/1021 点击右侧“随书下载”

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

#将文本记录到转换NumPy的解析程序
def file2matrix(filename):
    fr=open(filename)
    # 得到文本行数
    arrayOLines=fr.readlines()
    numberOfLines=len(arrayOLines)
    returnMat=zeros((numberOfLines,3))
    classLabelVector=[]     #创建返回的Numpy库
    index=0
    for line in arrayOLines:
        # 截取掉所有的回车字符
        line = line.strip()
        # 将上一行得到的整行数据分割成一个元素列表
        listFromLine=line.split('\t')       #解析文本数据到列表
        # 取前3个数据
        returnMat[index,:]=listFromLine[0:3]
        # 将列表最后一列存储到向量classLabelVector中
        classLabelVector.append(int(listFromLine[-1]))
        index+=1
    return returnMat,classLabelVector

Debug:
ValueError: invalid literal for int() with base 10: 'largeDoses'
书上示例datingTestSet.txt应改为datingTestSet2.txt
datingDataMat,datingLabels=KNN.file2matrix('datingTestSet.txt')改为datingDataMat,datingLabels=KNN.file2matrix('datingTestSet2.txt')

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

>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig=plt.figure()
>>> ax=fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
<matplotlib.collections.PathCollection object at 0x0000029E3B9C57F0>
>>> plt.show()

输出:


image.png
#coding: utf-8
from numpy import *                     #导入numpy包,这里要用到numpy中的array
from KNN import *                 #导入产生数据的包
import matplotlib                       #导入绘图的库
import matplotlib.pyplot as plt         #将绘图的函数重命名
from mpl_toolkits.mplot3d import Axes3D  #导入3维图像的包
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定字体为仿宋
plt.rcParams['axes.unicode_minus'] = False # 解决图像显示为方块的问题


datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
fig1=plt.figure()   #创建图形

#-------------------二维-----------
#第一个子图,是第2个特征和第3个特征的散点图  但是没有颜色标识
ax=fig1.add_subplot(2,2,1)  #代表创建2行2列从上到下的第一块的子图
ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
plt.xlabel(u'x 玩视频游戏所消耗时间半分比')
plt.ylabel(u'y 每周消费的冰淇淋公升数')
plt.title(u'图一(2&&3)')

#定义三个类别的空列表
type1_x=[]
type1_y=[]
type2_x=[]
type2_y=[]
type3_x=[]
type3_y=[]


#第二个子图 是第2个特征和第3个特征的散点图
ax=fig1.add_subplot(2,2,2)  #代表创建2行2列从上到下的第二块的子图

#循环获得每个列表中的值
for i in range(len(datingLabels)):
    if datingLabels[i]==1:  #不喜欢
        type1_x.append(datingDataMat[i][1])
        type1_y.append(datingDataMat[i][2])

    if datingLabels[i]==2:  #魅力一般
        type2_x.append(datingDataMat[i][1])
        type2_y.append(datingDataMat[i][2])

    if datingLabels[i]==3:  #极具魅力
        type3_x.append(datingDataMat[i][1])
        type3_y.append(datingDataMat[i][2])

type1=ax.scatter(type1_x,type1_y,s=20,c='red')
type2=ax.scatter(type2_x,type2_y,s=40,c='green')
type3=ax.scatter(type3_x,type3_y,s=50,c='blue')
ax.legend((type1,type2,type3),(u'不喜欢',u'魅力一般',u'极具魅力'),loc=2)   #显示图例 1 右上 2 左上 3 左下 4 右下 逆时针
#ax.scatter(datingDataMat[:,0],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
plt.xlabel(u'x 玩视频游戏所消耗时间半分比')
plt.ylabel(u'y 每周消费的冰淇淋公升数')
plt.title(u'图二(2&&3)')

#第三个子图 是第1个特征和第2个特征的散点图
ax=fig1.add_subplot(2,2,3)  #代表创建2行2列从上到下的第三块的子图
#循环获得每个列表中的值
for i in range(len(datingLabels)):
    if datingLabels[i]==1:  #不喜欢
        type1_x.append(datingDataMat[i][0])
        type1_y.append(datingDataMat[i][1])

    if datingLabels[i]==2:  #魅力一般
        type2_x.append(datingDataMat[i][0])
        type2_y.append(datingDataMat[i][1])

    if datingLabels[i]==3:  #极具魅力
        type3_x.append(datingDataMat[i][0])
        type3_y.append(datingDataMat[i][1])

type1=ax.scatter(type1_x,type1_y,s=20,c='red')
type2=ax.scatter(type2_x,type2_y,s=40,c='green')
type3=ax.scatter(type3_x,type3_y,s=50,c='blue')
ax.legend((type1,type2,type3),(u'不喜欢',u'魅力一般',u'极具魅力'),loc=2)   #显示图例 1 右上 2 左上 3 左下 4 右下 逆时针
#ax.scatter(datingDataMat[:,0],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
plt.xlabel(u'x 每年获取的飞行常客里程数')
plt.ylabel(u'y 玩视频游戏所耗时间半分比')
plt.title(u'图三(1&&2)')

#第四个子图 是第1个特征和第3个特征的散点图
ax=fig1.add_subplot(2,2,4)  #代表创建2行2列从上到下的第四块的子图
#循环获得每个列表中的值
for i in range(len(datingLabels)):
    if datingLabels[i]==1:  #不喜欢
        type1_x.append(datingDataMat[i][0])
        type1_y.append(datingDataMat[i][2])

    if datingLabels[i]==2:  #魅力一般
        type2_x.append(datingDataMat[i][0])
        type2_y.append(datingDataMat[i][2])

    if datingLabels[i]==3:  #极具魅力
        type3_x.append(datingDataMat[i][0])
        type3_y.append(datingDataMat[i][2])

type1=ax.scatter(type1_x,type1_y,s=20,c='red')
type2=ax.scatter(type2_x,type2_y,s=40,c='green')
type3=ax.scatter(type3_x,type3_y,s=50,c='blue')
ax.legend((type1,type2,type3),(u'不喜欢',u'魅力一般',u'极具魅力'),loc=2)   #显示图例 1 右上 2 左上 3 左下 4 右下 逆时针
#ax.scatter(datingDataMat[:,0],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
plt.xlabel(u"x 每年获取的飞行常客里程数")
plt.ylabel(u'y 每周消费的冰淇淋公升数')
plt.title(u'图四(1&&3)')

#------------三维-----------
fig2=plt.figure()   #创建图形
ax=fig2.add_subplot(111)
ax=Axes3D(fig2)
ax.scatter(datingDataMat[:,0],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
ax.set_xlabel(u'x 每年获取的飞行常客里程数')
ax.set_ylabel(u'y 视频游戏所耗时间半分比')
ax.set_zlabel(u'z 每周消费的冰淇淋公升数')

plt.title(u'图四(1&&2&&3)')
plt.show()

Debug:绘图中坐标轴中文乱码问题
添加代码:
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定字体为仿宋
plt.rcParams['axes.unicode_minus'] = False # 解决图像显示为方块的问题
输出:


image.png
image.png

准备数据:归一化数值

归一化数值是为了不让某个特殊的属性对计算结果影响比较大,而应该每一个特征都是等权重的。

#归一化特征值
def autoNorm(dataSet):
    #最小值放在minVals中,从列中选取最小值,而不是选取当前行的最小值
    minVals=dataSet.min(0)
    #最大值放在maxVals中
    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))
    return normDataSet,ranges,minVals
#检测函数输出结果
normMat,ranges,minVals=KNN.autoNorm(datingDataMat)
print(normMat)
print(ranges)
print(minVals)

Debug:<class 'range'>
autoNorm函数返回range改为ranges

输出:

[[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]]
[9.1273000e+04 2.0919349e+01 1.6943610e+00]
[0.       0.       0.001156]

测试算法

#分类器针对约会网站的测试代码
def datingClassTest():
    hoRatio = 0.50      #hold out 10%
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[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.0
    print("the total error rate is: %f" % (errorCount/float(numTestVecs)))
    print(errorCount)
#代码输出:
print(KNN.datingClassTest())

输出:

the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
......
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the total error rate is: 0.066000

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

#约会网站预测函数
def classifyPerson():
    resultList=['not at all','in small doses','in large doses']
    percentTats=float(input("percentage of time spent playing video games?"))
    ffMiles=float(input("frequent flier miles earned per year?"))
    iceCream=float(input("liters of ice cream consumed per year?"))
    datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)
    inArr=array([ffMiles,percentTats,iceCream])
    classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    print("You will probably like this person: ",resultList[classifierResult -1] )
#输出结果:
print(KNN.classifyPerson())

输出:

percentage of time spent playing video games?10
frequent flier miles earned per year?10000
liters of ice cream consumed per year?0.5
You will probably like this person:  in small doses

相关文章

网友评论

      本文标题:使用k-邻近算法改进约会网站的配对效果

      本文链接:https://www.haomeiwen.com/subject/osnhzftx.html