• 2020-12-09 22:23:21

#-*- coding: utf-8 -*-

importjiebaimportjieba.analyseimportmathdefsentence_resemble():'''计算两个句子的相似度：

1，将输入的两个句子分词

2，求分词后两句子的并集(去重)

3，计算两句子各自词频

4，求词频向量

5，套用余弦定理公式求出相似度

余弦值越接近1，就表明夹角越接近0度，也就是两个向量越相似，这就叫"余弦相似性"

:return:'''str1="我喜欢看电视，不喜欢看电影"str2="我不喜欢看电视，也不喜欢看电影"

#结巴分词，得到去掉逗号的数组

str1 =jieba.cut(str1)

str1= ",".join(str1)

str1_array= str1.split(",")

str1_array.remove(u"，")

str2=jieba.cut(str2)

str2= ",".join(str2)

str2_array= str2.split(",")

str2_array.remove(u"，")#求分词后两句子的并集(去重)

all_array = list(set(str1_array+str2_array))

all=sorted(all_array)#计算两句子各自词频

str1_num_dic =num_count(str1_array)

str2_num_dic=num_count(str2_array)#套用余弦定理公式求出相似度

cos =resemble_cal(all,str1_num_dic,str2_num_dic)printcosdefnum_count(a):

d= {k: a.count(k) for k inset(a)}returnddefarticle_resemble():

all_key=set()

with open("article_1.txt","r") as f:

lines= "".join(lines)

article1_dic=analyse_word(lines)for k,v inarticle1_dic.items():

with open("article_2.txt","r") as f:

article2_lines= "".join(article2_lines)

article2_dic=analyse_word(article2_lines)for k,v inarticle2_dic.items():

cos=resemble_cal(all_key,article1_dic,article2_dic)printcosdefresemble_cal(all_key,article1_dic,article2_dic):

str1_vector=[]

str2_vector=[]#计算词频向量

for i inall_key:

str1_count=article1_dic.get(i,0)

str1_vector.append(str1_count)

str2_count=article2_dic.get(i,0)

str2_vector.append(str2_count)#计算各自平方和

str1_map = map(lambda x: x*x,str1_vector)

str2_map= map(lambda x: x*x,str2_vector)

str1_mod= reduce(lambda x, y: x+y, str1_map)

str2_mod= reduce(lambda x, y: x+y, str2_map)#计算平方根

str1_mod =math.sqrt(str1_mod)

str2_mod=math.sqrt(str2_mod)#计算向量积

vector_multi = reduce(lambda x, y: x + y, map(lambda x, y: x *y, str1_vector, str2_vector))#计算余弦值

cos = float(vector_multi)/(str1_mod*str2_mod)returncos'''文章关键词提取'''

defanalyse_word(content):

zidian={}

return_dic={}#内容分词

fenci =jieba.cut_for_search(content)for fc infenci:if fc inzidian:

zidian[fc]+= 1

else:

zidian[fc]= 1topK=30

#关键词 比率

tfidf = jieba.analyse.extract_tags(content, topK=topK,withWeight=True)

return_dic[word_weight[0]]=frequencereturnreturn_dicif __name__=="__main__":#比较两句子相似度

sentence_resemble()#比较两篇文章相似度

article_resemble()

文章样例详情查看 http://pan.baidu.com/s/1qXRIGUS

更多相关内容
• 利用C语言，实现余弦定理的运算，省去了计算时间，方便了数学、物理等习题的运算。适用于学生党。 键盘输入两边及其夹角（弧度制），即可快速求出第三边的长度。
• 余弦定理计算文章相似度
• 正弦定理、余弦定理PPT课件.ppt
• 本文实例讲述了.NET下文本相似度算法余弦定理和SimHash浅析及应用。分享给大家供大家参考。具体分析如下： 余弦相似性 原理：首先我们先把两段文本分词，列出来所有单词，其次我们计算每个词语的词频，最后把词语...
• 正弦定理和余弦定理复习(公开课课件)ppt课件.ppt
• 余弦定理的证明方法.doc
• 4正余弦定理的综合应用.ppt
• 新教材2020-2021学年北师大版高中数学第二册学案：第2章 6.1　第2课时　用余弦定理、正弦定理解三角形 含解析.doc
• 高一数学正弦定理和余弦定理PPT课件.pptx
• 高中数学-余弦定理PPT课件.pptx
• 2018版高考数学考点18正弦定理与余弦定理试题解读与变式
• 数学余弦定理新人教B必修PPT学习教案.pptx
• 2018年高考数学黄金100题系列第36题正弦定理和余弦定理的综合运用理
• (完整版)正弦定理和余弦定理知识点总结(学案)附答案.pdf
• 2018年高考数学黄金100题系列第36题正弦定理和余弦定理的综合运用文
• 2018年高考数学专题17正弦定理和余弦定理及解三角形热点题型和提分秘籍理
• 2022届一轮复习北师大版 正弦定理余弦定理 课件（44张）.ppt
• 2017_2018学年高中数学第二章解三角形2.1正弦定理与余弦定理2.1.1习题精选北师大版必修5
• 2022届一轮复习北师大版 正弦定理和余弦定理的应用 课件（42张）.ppt
• 数学新教材高一下人教A版（2019）必修第二册6.4.3　余弦定理正弦定理第二课时　正弦定理 pdf文档整理.zip
• （新课标）2015年高考数学 题型全归纳 正、余弦定理在实际生活中的应用典型例题
• 余弦定理对我们每个人都不陌生，它描述了三角形中任何一个夹角和三个边的关系，换句话说，给定三角形的三条边，我们可以用余弦定理求出三角形各个角的角度。假定三角形的三条边为 a, b 和 c，对应的三个角为...

什么是余弦定理

学过向量代数的人都知道，向量实际上是多维空间中有方向的线段。如果两个向量的方向一致，即夹角接近零，那么这两个向量就相近。而要确定两个向量方向是否一致，这就要用到余弦定理计算向量的夹角了。

余弦定理对我们每个人都不陌生，它描述了三角形中任何一个夹角和三个边的关系，换句话说，给定三角形的三条边，我们可以用余弦定理求出三角形各个角的角度。假定三角形的三条边为 a, b 和 c，对应的三个角为 A, B 和 C，那么角 A 的余弦：

$$\cos {A} =\frac{b^2+c^2-a^2}{2bc}$$

如果我们将三角形的两边 b 和 c 看成是两个向量，那么上述公式等价于：

$$\cos {A} = \frac{}{|b||c|}$$

其中分母表示两个向量 b 和 c 的长度，分子表示两个向量的内积。举一个具体的例子，假如文本X 和文本 Y 对应向量分别是：

x_1,x_2,…,x_64000

y_1,y_2,…,y_64000

那么它们夹角的余弦等于：

$$\cos {\theta } = \frac{x_1y_1+x_2y_2+…+x_{64000}y_{64000}}{\sqrt{x_1^2+x_2^2+…+x_{64000}^2}\cdot \sqrt{y_1^2+y_2^2+…+y_{64000}^2}}$$

当两个文本向量夹角的余弦等于1时，这两个文本完全重复；当夹角的余弦接近于一时，两条新闻相似；夹角的余弦越小，两条文本越不相关。

计算文本相似度的大致流程

假设有下面两个句子：

A：我喜欢看电视，不喜欢看电影。

B：我不喜欢看电视，也不喜欢看电影。

第一步：分词

A：我/喜欢/看/电视，不/喜欢/看/电影。

B：我/不/喜欢/看/电视，也/不/喜欢/看/电影。

第二步：列出所有的词、字

我，喜欢，看，电视，电影，不，也

第三步：计算词频

A：我 1，喜欢 2，看 2，电视 1，电影 1，不 1，也 0。

B：我 1，喜欢 2，看 2，电视 1，电影 1，不 2，也 1。

第四步：描述词频向量

A：[1, 2, 2, 1, 1, 1, 0]

B：[1, 2, 2, 1, 1, 2, 1]

第五步：计算夹角余弦

使用这个公式，我们就可以得到，句子A与句子B的夹角的余弦。

余弦值越接近1，就表明夹角越接近0度，也就是两个向量越相似，这就叫”余弦相似性”。所以，上面的句子A和句子B是很相似。

实际使用过程需要注意的事项

实际使用中文本长度可能过长，如果采用分词，复杂度较高，可以采用TF-IDF的方式找出文章若干个关键词(比如20个)，再进行比较。

文章的长度可能不一致，所以关键词词频率可以使用相对词频率。

由于计算中打乱了关键词出现的顺序，所以即使夹角余弦的值为1，也有可能文本并不重复。比如：

A：我喜欢看电视，不喜欢看电影。

B：我不喜欢看电视，喜欢看电影。

使用Python进行文本相似度计算

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from __future__ import division

import jieba.analyse

from math import sqrt

class Similarity():

def __init__(self, target1, target2, topK=10):

self.target1 = target1

self.target2 = target2

self.topK = topK

def vector(self):

self.vdict1 = {}

self.vdict2 = {}

top_keywords1 = jieba.analyse.extract_tags(self.target1, topK=self.topK, withWeight=True)

top_keywords2 = jieba.analyse.extract_tags(self.target2, topK=self.topK, withWeight=True)

for k, v in top_keywords1:

self.vdict1[k] = v

for k, v in top_keywords2:

self.vdict2[k] = v

def mix(self):

for key in self.vdict1:

self.vdict2[key] = self.vdict2.get(key, 0)

for key in self.vdict2:

self.vdict1[key] = self.vdict1.get(key, 0)

def mapminmax(vdict):

"""计算相对词频"""

_min = min(vdict.values())

_max = max(vdict.values())

_mid = _max - _min

#print _min, _max, _mid

for key in vdict:

vdict[key] = (vdict[key] - _min)/_mid

return vdict

self.vdict1 = mapminmax(self.vdict1)

self.vdict2 = mapminmax(self.vdict2)

def similar(self):

self.vector()

self.mix()

sum = 0

for key in self.vdict1:

sum += self.vdict1[key] * self.vdict2[key]

A = sqrt(reduce(lambda x,y: x+y, map(lambda x: x*x, self.vdict1.values())))

B = sqrt(reduce(lambda x,y: x+y, map(lambda x: x*x, self.vdict2.values())))

return sum/(A*B)

if __name__ == '__main__':

t1 = '''余弦定理和新闻的分类似乎是两件八杆子打不着的事，但是它们确有紧密的联系。具体说，新闻的分类很大程度上依靠余弦定理。Google 的新闻是自动分类和整理的。所谓新闻的分类无非是要把相似的新闻放到一类中。计算机其实读不懂新闻，它只能快速计算。这就要求我们设计一个算法来算出任意两篇新闻的相似性。为了做到这一点，我们需要想办法用一组数字来描述一篇新闻。我们来看看怎样找一组数字，或者说一个向量来描述一篇新闻。回忆一下我们在“如何度量网页相关性”一文中介绍的TF/IDF 的概念。对于一篇新闻中的所有实词，我们可以计算出它们的单文本词汇频率/逆文本频率值(TF/IDF)。不难想象，和新闻主题有关的那些实词频率高，TF/IDF 值很大。我们按照这些实词在词汇表的位置对它们的 TF/IDF 值排序。比如，词汇表有六万四千个词，分别为'''

t2 = '''新闻分类——“计算机的本质上只能做快速运算，为了让计算机能够“算”新闻”(而不是读新闻)，就要求我们先把文字的新闻变成一组可计算的数字，然后再设计一个算法来算出任何两篇新闻的相似性。“——具体做法就是算出新闻中每个词的TF-IDF值，然后按照词汇表排成一个向量，我们就可以对这个向量进行运算了，那么如何度量两个向量？——向量的夹角越小，那么我们就认为它们更相似，而长度因为字数的不同并没有太大的意义。——如何计算夹角，那就用到了余弦定理(公式略)。——如何建立新闻类别的特征向量，有两种方法，手工和自动生成。至于自动分类的方法，书本上有介绍，我这里就略过了。很巧妙，但是我的篇幅肯定是放不下的。除余弦定理之外，还可以用矩阵的方法对文本进行分类，但这种方法需要迭代很多次，对每个新闻都要两两计算，但是在数学上有一个十分巧妙的方法——奇异值分解(SVD)。奇异值分解，就是把上面这样的大矩阵，分解为三个小矩阵的相乘。这三个小矩阵都有其物理含义。这种方法能够快速处理超大规模的文本分类，但是结果略显粗陋，如果两种方法一前一后结合使用，既能节省时间，又提高了精确性。'''

topK = 10

s = Similarity(t1, t2, topK)

print s.similar()

参考文章：

展开全文
• 什么是余弦定理【《正弦定理余弦定理》课后反思】.rar
• 什么是余弦定理【《正弦定理余弦定理》课后反思】.pdf

世界上有些事情常常超乎人们的想象。余弦定理新闻的分类似乎是两件八杆子打不着的事，但是它们确有紧密的联系。具体地说，新闻的分类很大程度上依靠的是余弦定理。

### 1. 新闻的特征向量：

所谓新闻的分类，或者更广义地讲任何文本的分类，无非是要把相似的新闻放到同一类中。如果让编辑来对新闻分类，他—定是先把新闻读懂，然后找到它的主题，最后根据主题的不同对新闻进行分类。但是计算机根本读不懂新闻，虽然一些商业人士和爱炫耀自己才学的计算机专家宣称计算机能读懂新闻。计算机本质上只能做快速计算。为了让计算机能够"算"新闻（而不是读新闻），就要求我们首先要把文字的新闻变成可以计算的一组数字，然后再设计一个算法来算出任意两篇新闻的相似性。

首先让我们来看看怎样找一组数字（或者说一个向量）来描述一篇新闻。新闻是传递信息的，而词是信息的载体，新闻的信息和词的语义是联系在一起的。套用俄罗斯文豪托尔斯泰在《安娜·卡列尼娜》开篇的那句话工来讲，"同一类新闻用词都是相似的，不同类的新闻用词各不相同"。当然，一篇新闻有很多词，有些词表达的语义重要，有些相对次要。那么如何确定哪些重要，哪些次要呢? 首先，直觉告诉我们含义丰富的实词一定比"的、地、得"这些助词，或者"之乎者也"这样的虚词重要这点是肯定的。接下来，需要进一步对每个实词的重要性进行度量。在一篇文章中，重要的词TF- IDF值就高。不难想象，和新闻主题有关的那些实词频率高，TF-IDF值很大。

现在我们找到了一组来描述新闻主题的数字∶ 对于一篇新闻中的所有实词，计算出它们的 TF-IDF 值。把这些值按照对应的实词在词汇表的位置依次排列，就得到一个向量。比如，词汇表中有 64 000个词，其编号和词如下图所示：

在某一篇特定的新闻中，这 64000 个词的 TF-IDF 值分别如下图 所示：

如果单词表中的某个词在新闻中没有出现，对应的值为零，那么这 64000 个数，组成一个64000 维的向量。我们就用这个向量来代表这篇新闻，并成为新闻的特征向量（Feature Vector）。每一篇新闻都可以对应这样一个特征向量，向量中每一个维度的大小代表每个词对这篇新闻主题的贡献。当新闻从文字变成了数字后，计算机就有可能"算一算"新闻之间是否相似了。

一篇篇文章变成了一串串数字：

### 2. 向量距离的度量：

世界各国无论是哪门语言的"语文课"（Language Art），老师教授写作时都会强调特定的主题用特定的描述词。几千年来，人类已经形成了这样的写作习惯。因此，同一类新闻一定是某些主题词用得较多，另外一些词则用得少。比如金融类的新闻，这些词出现的频率就很高;股票，利息，债券，基金，银行，物价，上涨。而这些词出现的就少∶ 二氧化碳，宇宙，诗歌，木匠，诺贝尔，包子。反映在每一篇新闻的特征上，如果两篇新闻属于同一类，它们的特征向量在某几个维度的值都比较大，而在其他维度的值都比较小。反过来看，如果两篇新闻不属于同一类，由于用词的不同，它们的特征向量中，值较大的维度应该没有什么交集。这样就定性地认识到两篇新闻的主题是否接近，取决于它们的特征向量"长得像不像"。当然，我们还需要定量地衡量两个特征向量之间的相似性。

不同的新闻，因为文本长度的不同，它们的特征向量各个维度的数值也不同。一篇 10000 字的文本，各个维度的数值都比一篇 500 字的文本来得大，因此单纯比较各个维度的大小并没有太大意义。但是，向量的方向却有很大的意义。如果两个向量的方向一致，说明相应的新闻用词的比例基本一致。因此，可以通过计算两个向量的夹角来判断对应的新闻主题的接近程度。而要计算两个向量的夹角，就要用到余弦定理了。比如上图中，左边两个向量的夹角小，距离就较"近"，相反，右边两个向量的夹角大，距离就"远"。

### 3. 余弦定理：

我们对余弦定理都不陌生，它描述了三角形中任何一个夹角和三个边的关系，换句话说，给定三角形的三条边，可以用余弦定理求出三角形各个角的角度。假定三角形的三条边为a，b和c，对应的三个角为A，B和C。

那么$\angle A$的余弦是：$cos(A)=\frac{b^{2}+c^{2}-a^{2}}{2bc}$ 。

如果将三角形的两边b和c看成是两个以A为起点的向量，那么上述公式等价于 $cos(A) =\frac{< b,c> }{\left | b \right |\cdot \left | c \right |}$ 。

其中，分母表示两个向量b和c的长度，分子表示两个向量的内积。举一个具体的例子，假如新闻X和新闻Y对应的向量分别是：$x_{1},x_{2},...,x_{64000}$ 和 $y_{1},y_{2},...,y_{64000}$

那么它们夹角的余弦等于：

由于向量中的每一个变量都是正数，因此余弦的取值在 0和1 之间，也就是说夹角在 0 度到 90 度之间。当两条新闻向量夹角的余弦等于1时，这两个向量的夹角为零，两条新闻完全相同;当夹角的余弦接近于1时，两条新闻相似，从而可以归成一类;夹角的余弦越小，夹角越大，两条新闻越不相关。当两个向量正交时（90 度），夹角的余弦为零，说明两篇新闻根本没有相同的主题词，它们毫不相关。

现在把一篇篇文字的新闻变成了按词典顺序组织起来的数字（ 特征向量），又有了计算相似性的公式，就可以在此基础上讨论新闻分类的算法了。余弦定理就这样通过新闻的特征向量和新闻分类联系在一起。我们在中学学习余弦定理时，恐怕很难想象它可以用来对新闻进行分类。

### 补充：什么是TF-IDF:

TF-IDF(Term Frequency - Inverse Document Frequency, 单文本词频-逆文本频率指数)，一种用于信息检索和信息探勘的常用加权技术，被公认为信息检索中最重要的发明。

TF-IDF是一种统计方法，用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加，但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜寻引擎应用，作为文件与用户查询之间相关程度的度量或评级。

词频(Term Frequency)：某一给定词语在该文本中出现次数。该数字通常会被归一化（分子一般小于分母），以防止它偏向长的文件，因为不管该词语重要与否，它在长文件中出现的次数很可能比在段文件中出现的次数更大。需要注意的是有一些通用词对文章主题没有太大作用，如“的”、“是”等，而有一些频率出现少的词如一些专业词更能表现文章主题，所以为词语设置权重，权重的设计满足：一个词预测主题的能力越强，权重越大，反之，权重越小。也就是说，一些词只在很少几篇文章中出现，那么这样的词对文章主题的判断能力很大，这些词的权重应该设计的较大。IDF完成这样的工作。

逆向文件频率IDF（Inverse Document Frequency）：一个词语普遍重要性的度量。主要思想是：如果包含一个词条的文档越少, IDF越大，则说明词条具有很好的类别区分能力。

可以简单的理解成：一个词语在一篇文章中出现的次数越多，同时在其他的所有文档中出现的次数越少，越能够代表该文章。

读者可以自行去查阅资料，了解TF-IDF的具体计算方法和基于信息论的基本原理。

### 结语：

本文旨在简单的介绍余弦定理与新闻分类的联系，也就是数学和计算机科学的交叉。在我们看来复杂的计算机处理工程中，其中蕴含的原理可能就是一个简单的数学公式，数学有着简单美的特性，计算机科学也有，文章主要参考了吴军博士的《数学之美》，吴军博士遵循着简单的哲学，倡导要努力去寻找简单有效的方法，不是靠直觉，更不是撞大运，而是要靠自己的经验，不怕失败，大胆尝试，总会有所收获的。

### Everything is difficult until you know how to do it.😀

展开全文
• 余弦定理公式大全高中余弦定理公式大全.doc
• 部编版第11讲：余弦定理余弦定理应用.doc

...