多维空间余弦公式:
举一个具体的例子,假如:句子 X 和句子 Y 对应向量分别是x1,x2,...,x64000 和y1,y2,...,y64000,
那么它们夹角的余弦等于
一二三冲鸭:使用余弦相似度算法计算文本相似度55 赞同 · 10 评论文章https://zhuanlan.zhihu.com/p/43396514
这篇文章个人觉得不太好理解,在研读之后,自己总结了一个通俗易懂的算法。
python结巴分词余弦相似度算法实现 - 圆柱模板 - 博客园 (cnblogs.com)https://www.cnblogs.com/68xi/p/11676161.html本文算法与博客园的代码思路基本相同。
Python完整实现代码
import jieba
import math
s1 = '这只皮靴号码大了。那只号码合适'
s1_cut = [i for i in jieba.cut(s1, cut_all=True) if i != '']#结巴分词,并将分词结果存入列表s1_cut当中
s2 = '这只皮靴号码不小,那只更合适'
s2_cut = [i for i in jieba.cut(s2, cut_all=True) if i != '']
word_set = set(s1_cut).union(set(s2_cut))# 求两个列表的并集,就是找出两个句子所有的切分词
print(word_set)
# 遍历基本词组
frq_s1=[]#第一个句子的词频向量
frq_s2=[]#第二个句子的词频向量
for jichuci in word_set:#由于是遍历基础词,所以两个句子的切分词的词频顺序是保持一致的,不用考虑其顺序问题。
frq=s1_cut.count(jichuci)#计算基础词在s1的分切词中的频率
frq_s1.append(frq)
frq=s2_cut.count(jichuci)#计算基础词在s2的分切词中的频率
frq_s2.append(frq)
print(frq_s1,"n",frq_s2)
# 计算余弦相似度,套用公式进行余弦相似度计算
sum = 0
sq1 = 0
sq2 = 0
for i in range(len(frq_s1)):
sum += frq_s1[i] * frq_s2[i]
sq1 += pow(frq_s1[i], 2)
sq2 += pow(frq_s2[i], 2)
try:
result = round(float(sum) / (math.sqrt(sq1) * math.sqrt(sq2)), 2)
except ZeroDivisionError:
result = 0.0
print(result)
c#实现完整代码
using JiebaNet.Segmenter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 基于结巴分词的余弦相似度
{
internal class Program
{
static void Main(string[] args)
{
var segmenter = new Jiebasegmenter();
segmenter.LoadUserDict("userdict.txt");//引用字典
var segments = segmenter.Cut("这只皮靴号码大了。那只号码合适"); // 默认为精确模式
List s1_cut = new List();
foreach (var item in segments)//将分词后的字符串存入s1_cut当中
{
s1_cut.Add(item);
}
segments = segmenter.Cut("这只皮靴号码不小,那只更合适"); // 默认为精确模式
List s2_cut = new List();//将分词后的字符串存入s2_cut当中
foreach (var item in segments)
{
s2_cut.Add(item);
}
List word_set=s1_cut.Union(s2_cut).ToList();//将两个list合并,并且没有重复项
//遍历word_set,分别计算基础词在s1和s2中出现的频率
List frq_s1 = new List();//用于存储频率
List frq_s2 = new List();//用于存储频率
foreach (string item in word_set)
{
int count = s1_cut.Count(s => s == item);
frq_s1.Add(count);
count = s2_cut.Count(s => s == item);
frq_s2.Add(count);
}
//计算余弦相似度
double sum = 0;//分子
double sq1=0;//分母之一
double sq2=0;//分母之二
//frq_s1,frq_s2,word_set长度相同
double result = 0.0;
for (int i = 0; i < word_set.Count; i++)
{
sum += frq_s1[i] * frq_s2[i];
sq1 += Math.Pow(frq_s1[i], 2);
sq2+=Math.Pow(frq_s2[i], 2);
}
if ((Math.Sqrt(sq1) * Math.Sqrt(sq2))==0.0)//如果分母为0
{
result = 0.0;
}
else
{
result = Math.Round(sum / (Math.Sqrt(sq1) * Math.Sqrt(sq2)), 2);//结果就是余弦值
}
Console.ReadKey();
}
}
}



