一、NLP文本相似度
内容:
1.NLP(自然语言处理入门)
TF-IDF、 关键词提取、LCS最长公共子序列
2.中文分词
jiaba、HMM
3.实践
MR TF-IDF
MR 根据LCS计算文本相似度
MR 结巴分词
共同好友:
A:B,C,D,F,E,O A的好友有——》B,C,D,F,E,O
B:A,C,E,K B的好友有——》A,C,E,K
C:F,A,D,I C的好友有——》:F,A,D,I
D:C D的好友有——》C
返回结果:
A,B的共同好友有:C和E
A,C用户的共同好友有:D和F
...
两轮MR
1. map输入
map输出 C \t A ; 一个好友及拥有这个好友对应的人
C \t B
C \t D
reduce输入
reduce输出 C \t A, B, D; 一个好友及拥有这个好友的所有人
2. map 输入
map 输出 A_B \t C ;A_B的共同好友里有的一个是C
A_D \t C
reduce 输入
reduce 输出 A_B \t C,E A_B的共同好友里面所有的共同好友
问题1:只有1轮MR,其中代码map里面用了一个字典,在不同map里面字典是不能共享的。
本地执行是可以的,分布式的结果不对。
本地测试:根据map分而治之的思想
head -7 file |python map.py >f1
tail -7 file |python map.py >f2
cat f1 f2>f12
cat f12 |sort |python red.py >res
wc -l res
问题2:A_B \t C 本地
B_A \t C 集群
排序导致的,没有问题, C \t A, B, D
1、文本相似度
1)字面相似,但是语义不相似
我吃饱饭了
我吃不饱饭
方案:(1)中文分词,看多少词是相同的 (2)分词之后LCS最长公共子序列
2)语义相似,但是字面不相似
老铁的个人简历
铁匠人物介绍
方案:基于人的行为(1)基于共同的行为(CF)(2)word embedding ,映射到向量空间
相似度的度量
1)余弦相似度 cos
A (1,2,3)
B (2,3,4)
cos(A,B)
分子:A*B = 1*2+2*3+3*4=20
分母:|A| *|B| = sqrt(1*1 + 2*2 +3*3) * sqrt(2*2 + 3*3 +4*4) = 3.74*5.38
cos(A,B) = 20 / 3.74*5.38
优化的思路:把词频换成词在文章中的重要性
词在文章中的重要性:
1.词频,去掉停用词,在本篇文章出现次数多 :tf
2.词在其他文章出现的少 :idf
聚类算法
1、密度——在指定半径内出现的邻居数量
2、与其他比自己密度值大的点的距离的最小值(例如:两个类:A、B,A的聚类的第二大的值比B的聚类的第一大的值还要大,但是A的这个值离B远,所以选B的聚类的第一大的值为聚类中心。)
聚类中心两个值(上边1和2两点)都要大。
1)TF:词频
2)IDF:反文档频率
取值范围(0,log(语料库中文档总数))
自动摘要
1)确定一批关键词(TF-IDF)
2)包含关键词的句子找出来
3)对句子做些处理,排序(关键词越多,权重大)
4)把句子汇总,就是摘要
LCS 最大公共子序列(业务紧密相连)
A:我很喜欢看电影,最喜欢看《我不是药神》
B:我很喜欢看电影,最喜欢看《我不是潘金莲》
LCS(A,B)我很喜欢看电影,最喜欢看《我不是》
文本相似度 = 2*LCS(A,B) / [ len(A) + len(B)]
目的:从字面衡量文本相似度的方法之一,动态规划的思路与中文分词里面有一个viterbi算法也用到DP。
推荐:LCS(A,B)>0.9 AB非常相似,过滤掉(近似等价于已经看过的),多样化。
TF-IDF 以及LCS 都是已经做了中文分词的基础上。
中文分词:
结婚的和尚未结婚的
结婚的 \ 和 \ 尚未 \ 结婚的
结婚的 \ 和尚 \ 未 \ 结婚的
广州本田雅阁汽车
广州 \ 本田 \ 雅阁 \ 汽车
广州本田 \ 雅阁 \ 汽车
广州 \ 本田雅阁 \ 汽车
分词的粒度:
粗粒度: 比如:成语;推荐场景:拿字去索引库召回效果不好。
细粒度:搜索场景,搜索引擎不会把所有小粒度的词都建索引,而是选择更有可能展现相关结果的小粒度词——所以前几页效果好,后边效果不好,因为召回变多。
例:车 —— 》 汽车坐垫,自行车,越野车
DAG图有向无环图:切开哪一个位置好?
C = 本田雅阁
S1 = 本田 \ 雅阁
S2 = 本 \ 田 \ 雅阁
P(S1 | C) P(S2 | C) 比较大小
朴素贝叶斯公式:(分类:邮件:S是:类别是否是垃圾 ,C是:样本) 独立性假设,每个词的出现都跟其他词没有关系。
P(S | C) = P(S,C) / P(C) = P(C | S)* P(S)/ P(C)
P(S,C) =P(C | S)* P(S)
P(C | S)=P(本田雅阁 | 本田 \ 雅阁) =1
P(S)
P(C) = P(本田雅阁) =常数(比较两个概率的大小,共同除以P(C),所以省去)
P(S1 | C)= P(S1)=P(本田 \ 雅阁) = P(本田) * P(雅阁)=logP(本田 \ 雅阁) =log( P(本田) * P(雅阁)) = log(P(本田)) +log(P(雅阁))
P(S2 | C)= P(S2)=P(本 \ 田 \ 雅阁)= P(本) * P(田) * P(雅阁)
P(本田) = 分子/分母
分子:本田在语料库中出现的次数
分母:语料库总词数,可能会很大
P会特别小,P连乘(尤其在句子长时)会计算结果非常小 = 0
所以我们对P,取log再比较
为什么能取log:log是增函数,可以保证大小顺序一致,实际当中不关系概率值是多少,只是比较大小。
log(a*b) = log(a) + log(b)
取log的好处
1.防止数据向下溢出
2.加法运算速度快于乘法
独立性假设有些不合理 ——》概率语言模型(本田后面跟雅阁的概率 > 本田后面跟奔驰的概率)
语言模型:
P(w1,w2,w3) = p(w1)*p(w2 | w1) * p(w3 | w1,w2)
一元模型(Unigram)
P(w1,w2,w3) =p(w1) * p(w2) * p(w3)
二元模型(Bigram)
P(w1,w2,w3) = p(w1)*p(w2 | w1) * p(w3 | w2)
三元模型(trigram)
P(w1,w2,w3) = p(w1)*p(w2 | w1) * p(w3 | w1,w2)
什么是模型:
p(w1) = 0.1
p(w2) = 0.2
p(w2 | w1) =0.3
模型有了也就是概率计算好了,使用的时候直接用值即可。
p(w1) =p(本田)=w1的次数 / 语料库总次数
p(w2 | w1) = p(w2,w1) / p(w1) = w1,w2共同出现的次数 / w1 出现的次数
结巴分词背后实现的原理:
结巴分为两个阶段:
(1)基于本地词库,前向遍历方式,构造DAG图出来,进行最优路径的选择(求概率)
(2)如果词库不够大, HMM隐马模型
HMM
状态序列:希望得到的,比如中文输入法的汉字,翻译的结果,分词(每个字要不要停顿),词性标注(词性,n,v)
观测序列:可以观察到的,中文输入法的拼音,翻译前的语言,每个字,每个字
分词:
观察到的是字
状态:
B ——begin
M —— middle
E —— end
S —— single
我 / 喜欢/ 广州本田
S B E B M M E
参数:
1、初始概率 :数量4(分词:BMME),状态的个数M
2、转移概率:M*M
3、发射概率:观察值数量是N,M*N
把所有参数计算出来就得到了模型:上面1、2、3点。
三个基本问题(概率语言模型)
1.模型参数估计 M个初始概率+M*M个状态转移概率+M*N个发射概率
2.给定模型,计算一个观测序列出现的概率, 广州本田雅阁汽车这句话出现的概率是多少
3.给定模型和观测序列,找到最优的隐藏状态序列(词性标注,中文分词。。。)
1.状态已知 (隐藏序列),观测序列都知道,相当于已经分好词,求解模型只需要基于统计
初始概率:p(B) = B在句子开头的次数 / B总出现次数
转移概率:p(B->M) = (B后面一个是M)出现次数 / B 出现次数
发射概率: p(B->广)=(状态是B,观测是广)出现次数 / B出现次数
状态未知 ,观测序列都知道 , EM。
2.DP,前向算法和后向算法
3.分词过程(有模型):viterbi算法,动态规划。
概率最大化: π(b) * p(s|b)*p(广 |s) *p(m | s ) *p(州|m)......
实践:
tfidf : 一个词的tf在所有文章是不是一样的? 不一定
一个词的idf 在所有文章都是一样的吗? 一样
文本相似度=2*LCS(A,B)/[len(A)+len(B)]
网友评论