如何评价多个向量之间的相似性
现有的方法多是通过余弦相似度、KL散度等方法分析两个向量之间的相似性,如何对群体相似性进行考量,仅能考虑到整体也不损失个体相似度?
基于Monster 组和GPT的调写:
问题描述:
海伦一直师兄在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人,但是并不是每一个她都喜欢。经过一番总结,她发现自己曾交往过三种类型的人:1、不喜欢的人 ; 2、魅力一般的人;3、极具魅力的人。
尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归入恰当的类别。海伦希望分类软件可以更好地帮助她将匹配对象划分到确切的分类中,此外海伦收集了一些约会网站未记录的数据信息,她认为这些数据有助于匹配对象的归类。
文本数据集:
数据集内有一千个样本,每个样本各占一行,样本中主要包括三种特征:
1、每年获得的飞行常客里程数 (第一列数据)
2、玩视频游戏所消耗的时间百分比 (第二列数据)
3、每周消费的冰淇淋公升数 (第三列数据)
最后一列为样本标签,对应三种类型的人。
数据预处理:从文件中解析数据,并绘制散点图、进行归一化
import matplotlib.pyplot as plt
###############从文本文件中解析数据#########
'''
filename:存储数据集的文件
returnMat:从文件中解析出的数据特征
label:从文件中解析出的样本标签
'''
def file2matrix(filename):
fr=open(filename) #打开文件
AllLine=fr.readlines() #读取所有行
NumLine=len(AllLine) #统计行数
label=[] #标签列表
returnMat=zeros((NumLine,3)) #创建数组存储文件中数据
index=0
for line in AllLine:
line=line.strip() #去除每一行后面的回车
listfromLine=line.split('\t') #取出的一行内容使用split函数分开,对应四个元素,存在列表listfromLine中
returnMat[index,:]=listfromLine[0:3] ##按行复制前三个元素,listfromLine[0]至listfromLine[2]
index+=1 ##行标+1
label.append(int(listfromLine[-1])) #列表listfromLine最后一个元素对应样本标签
return returnMat,label
##########散点图展示样本分布##############
'''
取前两个特征
x轴:每年飞行里程数
y轴:玩视频游戏所耗时间百分比
'''
DatasetMat,datingLabels=file2matrix('datingTestSet2.txt')
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(DatasetMat[:,0],DatasetMat[:,1],10.0*array(datingLabels),90.0*array(datingLabels))
plt.xlabel(u'flying ')
plt.ylabel(u'playing game')
plt.title(u"KNN")
plt.legend(loc="upper left")
plt.show()
###############归一化#####################
'''
datasetMat:数据特征
normMat:datasetMat归一化后的值
归一化:
newValue=(oldValue-min)/max-min
'''
def autoNorm(datasetMat):
maxnum=datasetMat.max(0) #每一列最大值
minNum=datasetMat.min(0) #每一列最小值
range=maxnum-minNum #每一个特征对应范围
normMat=zeros(shape(datasetMat))
minmat=tile(minNum,(normMat.shape[0],1))
rangemat=tile(range,(normMat.shape[0],1))
normMat=(datasetMat-minmat)/rangemat
return normMat,range,minNum
散点图绘制结果,x轴为每年飞行里程数,y轴为玩视频游戏所耗时间百分比,如图,展现的是三种类型的点在这两种特征下的分布情况。
算法测试
############算法测试#########################
'''
将normDataSet中的数据按比例划分为测试数据集和训练数据集
testData_num:测试数据集数量
normDataSet[i,:]:测试数据集样本
normDataSet[testData_num:m,:]:训练数据集样本
errorCount:分类错误数量统计
'''
def datingclasstest():
dataset,label=file2matrix('datingTestSet2.txt')
normDataSet,ranges,min=autoNorm(dataset)
testData_num=int(normDataSet.shape[0]*0.1)
m=normDataSet.shape[0]
errorCount=0
for i in range(testData_num):
classResult=knn(normDataSet[i,:],normDataSet[testData_num:m,:],label[testData_num:m],3)
if classResult!=label[i]:
errorCount+=1
print(errorCount/float(testData_num))
datingclasstest()
错误率输出结果:
0.05
构建完整应用,进行预测
###############构建完整可用系统#########################
'''
game、mile、icecream:待分类样本对应的特征
result:算法执行结果对应的文字标签
'''
def datingClassPerson():
listlabel=['不喜欢的人','魅力一般的人','极具魅力的人']
game=float(input('玩视频游戏所耗时间百分比:'))
mile=float(input('每年飞行里程数:'))
icecream=float(input("每周消费的冰淇淋公升数:"))
inx=array([mile,game,icecream])
dataset,datalabel=file2matrix('datingTestSet2.txt') #读取文件,解析数据
normMat,range,min=autoNorm(dataset) #归一化
classResult=knn(((inx-min)/range),normMat,datalabel,3) #调用算法
result=listlabel[classResult-1]
print("分类结果为:%s" %(result))
datingClassPerson()
输入
玩视频游戏所耗时间百分比:90
每年飞行里程数:400
每周消费的冰淇淋公升数:3
输出
分类结果为:不喜欢的人