利用余弦距离比较文档间的相似度

一.数据说明

在进行正式的操作之前,对后续进行处理的数据进行说明,首先,从豆瓣电影网站爬取了电影对于的影评,然后进行了中文分词(jieba)和删除停用词操作,最后处理的结果展示如下如所示:

中文处理文档注意:后续的操作都是在经过上述步骤处理的文档基础上!

二.根据文档建立词频矩阵

2.1 什么是词频?

词频(Term Frequency,tf)指某个词(term)在文章中出现次数,若某个词(不包括停用词)在文章中出现的频率很高,则说明这个词可能比较重要。

2.2 sklearn中的CountVectorizer类

对于词频矩阵的建立,这里直接调用sklearn库中的CountVectorizer类,通过该类的方法fit_transform()可以获取一个词频矩阵,其中每一行代表一个文档,每一列代表词在该文档中出现的频率,词频矩阵的结构如下图所示:


fit_transform()函数使用起来比较简便,只需传递一个"文档列表"即可,该列表中的每个元素为一个经处理后的文档字符串,例如:

doclists = [
'韩国 山寨 路线 中心思想 西巴 狠 新鲜 东西 爱情片 哭 弄巧成拙 姜 科长 无心插柳 李子 唯我独尊 李仲久 超长 待机 丁青 壮哉 天朝 黑客 实力',
...
'三星 天朝 多矿 难 类似 佩服 33 名 矿工 素养 纪律 政府 公开 透明 办事 能力 智利 南美洲 发达 国家 改编自 历史 真实 事件 2010 智利 圣何塞 铜矿 坍塌 事故',
...
]

该函数的使用示例代码如下:

vc = CountVectorizer() #构造一个CountVectorizer类对象
wfm = vc.fit_transform(doclists)    #获取对应的词频矩阵

三.根据词频矩阵求tf-idf矩阵

3.1 tf-idf简介

tf上述步骤已经介绍,这里主要介绍一下idf。idf的全称为inverse document frequency,即反向文档频率,它的含义是包含某个词的文档数,其计算公式为:

idf=log10​(N/dft​)
其中 N为文档总数,dft​为所有文档中包含词汇t的文档数,从该公式可知,一个词越常见,idf越低。tf-idf就是将二者乘起来,即 tf-idf=tf×idf。

3.2 sklearn中的TfidfTransformer类

要想求得包含文档中对应词的tf-idf值的tf-idf矩阵,可以使TfidfTransformer类,通过该类的fit_transform()方法可以获取对应的tf-idf矩阵,其结构如下图所示:

该类的fit_transform()函数只需要传入之前通过CountVectorizer类得到的矩阵即可得到一个词频矩阵,其示例代码如下:

transformer = TfidfTransformer() #构造一个TfidfTransformer实例
tmatrix = transformer.fit_transform(wfm) #获取tf-idf矩阵

四.L2归一化

4.1 计算公式

设一个向量  (x1​,x2​,x3​,...,xN​),其归一化后的向量为(y1​,y2​,y3​,...,yN​),则归一化的公式为:

4.2 示例代码

def L2Normalization(matrix):
    """
    matrix:文档的tfidf矩阵,每一行为一个文档各个term的tfidf值
    输出为进行L2正则化后的矩阵
    """
    return matrix / np.sqrt(np.sum(matrix ** 2,axis=1,keepdims=True))

需要注意的是在调用该函数之前,需要将上述求得的tfidf矩阵,转换为numpy的ndarray对象,具体做法为:

matrix = np.array(tmatrix)

五.求余弦距离

5.1计算公式

由于上述的tfidf矩阵进行了L2归一化,因此求两个文档的余弦距离的公式为:

经过计算后的余弦距离矩阵结构如下:

在该余弦距离矩阵中 arr[i][j]=cosij的含义是,文档 i和文档 j 之间的余弦距离为cosij,可知该余弦距离矩阵是一个对称方阵,即arr[i][j]=arr[j][i]。

5.2 示例代码

def cosineDistance(nmatrix):
    """
    nmatrix:L2正则化后的tfidf矩阵
    输出包含各个文档的余弦距离矩阵,例如
        1   2   3
    1   c1  c2  c3
    2   c2  c4  c5
    3   c3  c5  c6
    m[0,1]表示文档1和文档2之间的余弦距离
    """
    return np.matmul(nmatrix,nmatrix.T)

六.结果展示

在求得对应的文档间余弦距离矩阵后利用np.where()函数筛选出文档余弦距离大于0.9的文档对,示例代码为:

x,y = np.where(arr > 0.9) #arr为余弦距离矩阵
for i,j in zip(x,y):
    if     i != j:
        print("Doc {} Doc{} CosineDistance {}".format(i,j,arr[i][j]))
posted @ 2021-04-20 20:06  王陸  阅读(362)  评论(0编辑  收藏  举报