天天看点

python利用余弦相似度聚类_使用python基于余弦相似度探索人员相关性

课题1

毕业设计里面涉及到人员相关度的计算,在这里我提出了一个猜想,大致如下:

现有数据:学生id、学生手机mac地址、时间戳、地点id

构想:通过学生mac地址某地点出现频次,构建频次矩阵,比如说现有六个地点,ABCDEF,某学生出现的频次分别为1、5、2、4、7、3,则[1,5,2,4,7,3]即为该学生在矩阵中的表现形式。(总的来说就是讲每个学生的出现频次规律抽象成一个向量,该向量由n个Term组成,每个Term都有一个权重,不同的频次根据学生在总矩阵中影响相关度的权重)

实现步骤:

1.数据预处理,建立空间向量模型,表现形式为:[[3,4,1,5,6,7],[6,4,5,5,2,1],......];

2.特征抽取完之后,对矩阵进行正则化处理。

3.计算余弦相似度。

python利用余弦相似度聚类_使用python基于余弦相似度探索人员相关性

image.png

分子:两个向量的点乘积

分母:两个向量的模的乘积

知识点:

1.利用python进行矩阵的正则化

正则化的过程是将每个样本缩放到单位范数(每个样本的范数为1),如果后面要使用如二次型(点积)或者其它核方法计算两个样本之间的相似性这个方法会很有用。

Normalization主要思想是对每个样本计算其p-范数,然后对该样本中每个元素除以该范数,这样处理的结果是使得每个处理后样本的p-范数(l1-norm,l2-norm)等于1。

p-范数的计算公式:||X||p=(|x1|^p+|x2|^p+...+|xn|^p)^1/p

该方法主要应用于文本分类和聚类中。例如,对于两个TF-IDF向量的l2-norm进行点积,就可以得到这两个向量的余弦相似性。

sklearn数据预处理函数:

from sklearn import preprocessing

2.python字典排序

知识点参照:python字典排序

python代码

# -*- coding: UTF-8 -*-

__author__ = 'Suzibo'

import numpy as np

import pandas as pd

from sklearn import preprocessing

from sklearn import feature_extraction

#from sklearn.feature_extraction.text import TfidfTransformer

#from sklearn.feature_extraction.text import CountVectorizer

arr = np.array([[3,5,3,0,5,5],

[3,4,3,3,5,1],

[5,7,8,12,1,0],

[5,1,3,1,1,2],

[0,7,3,1,5,1],

[7,1,2,3,6,1],

[0,9,2,1,4,1],

[3,0,3,1,0,5]])

#模拟了ABCDEF六个感知点,对应的八个人的频次矩阵。TAT,因为迟迟拿不到数据,只能靠自己模拟数据玩玩了,惨_(:з」∠)_

arr_normalized = preprocessing.normalize(arr)

#将原始矩阵正则化

result = np.zeros(((len(arr)-1),2))

n=0

#初始化结果矩阵(N行2列的0矩阵)

a=dict()

#初始化字典

for i in range(1,len(arr)):

#比较第一名同学跟其他同学的余弦相似度

num = np.sum(arr_normalized[0]*arr_normalized[i])

#向量乘积

denom = np.linalg.norm(arr_normalized[0]) * np.linalg.norm(arr_normalized[i])

#向量模的乘积

cos = num/denom

sim = 0.5 + 0.5*cos

#结果归一化

result[n][0]=i

result[n][1]=sim

n=n+1

#结果存入数组

a[i] = sim

#结果存入字典

print result

print sorted(a.iteritems(),key=lambda asd:asd[1],reverse=True)

#在这里,用了字典对象a以及初始化了数组result分别存储计算结果。其实两种方法皆可,但是字典排序写起来更加快速。

result:

[[ 1. 0.92443667]

[ 2. 0.7434795 ]

[ 3. 0.85627822]

[ 4. 0.91615085]

[ 5. 0.84737882]

[ 6. 0.88826077]

[ 7. 0.83610165]]

sorted(a.iteritems(),key=lambda asd:asd[1],reverse=True):

[(1, 0.9244366688881116), (4, 0.91615085086634984), (6, 0.88826076864678882), (3, 0.85627822353819516), (5, 0.84737881773469248), (7, 0.83610165222088828), (2, 0.74347950132065999)]