zipf定律与相似性度量
Zipf定律指出,在文本中,标识符出现的频率与其在排序列表中的排名或位置成反比。这个定律描述了标识符在文本中是如何分布的,即一些标志符出现的频次很大,另一些出现的频次较低,还有一些基本不出现。它是自然语言处理中,非常重要的一个定律,它的数学语言可以这样描述:在给定的语料库里,对于任意的一个term,它的频度f与这个频度在语料库中的排名r的乘积近似一个常数。即f正比于1/r。以英语语料库为例,其他语料库一样遵循zipf定律,表明在英语单词中,只有极少数的词被经常使用,而绝大多数词很少被使用。事实上,它是一个很普遍的规律,比如网站的访问者数量、每个国家公司的数量都近似服从zipf定律。下面用nltk来获取基于zipf定律的双对数图,代码如下:
#使用nltk获取基于zipf定律的双对数图
import nltk
from nltk.corpus import brown #使用布朗语料库
from nltk.probability import FreqDist #用来记录语料库中词频的分布
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')
def zipf_log_log():
fd=FreqDist() #FreqDist()获取语料库中的词的频率分布
for text in brown.fileids(): #fileids()为语料库中的文件
for word in brown.words(text): #words()包含了语料库中所有的单词
fd[word]+=1
ranks=[]
freqs=[]
for rank,word in enumerate(fd): #把rank和word做一个枚举
ranks.append(rank+1)
freqs.append(fd[word])
plt.loglog(ranks,freqs) #做双对数图
plt.xlabel('frequency(f)',fOntsize=14,fOntweight='bold')
plt.ylabel('rank(r)',fOntsize=14,fOntweight='bold')
plt.grid(True)
plt.show()
if __name__=="__main__":
zipf_log_log()
结果如图所示:
可以看到一个词的出现越频繁,也就是词频越高,它的排名越靠后。
相似性度量
在NLP中进行距离的相似性度量很多,这里对其中的几种非常常用的作以介绍,包括编辑距离算法、Jaccard系数、Smith Waterman算法等等。
对于编辑距离算法,以两个字符串作以比较,指的是为了使两个字符串相等所插入、替换或删除的字符的数量。
下面以代码实现再加以解释,编辑距离代码如下:
#使用编辑距离进行相似性度量
import nltk
from nltk.metrics import edit_distance
e_d=edit_distance("machine_learning","deep_learning")
print("The two words edit_distance is:"+str(e_d))
输出结果:
因为要使的这两个词相等,需要做7次替换,注意这种编辑距离算法是按长的来匹配的,即把deep替换成machine,先进行4次替换再进行3次插入。
Jaccard系数相似性度量:
Jaccard系数描述的是两个集合交集的相似程度,代码实现如下:
#使用Jaccard系数度量集合X与Y的相似度
#方法一:自己造轮子实现Jaccard系数
def jaccard_similarity(query,document):
molecular=set(query).intersection(set(document)) #分子,两个集合的交集
denominator=set(query).union(set(document)) #分母,两个集合的并集
return len(molecular)/len(denominator)
#方法二:使用nltk中的Jaccard系数
def nltk_jaccard(X,Y):
import nltk
from nltk.metrics import jaccard_distance
return jaccard_distance(X,Y)
if __name__=="__main__":
X=set([10,20,30])
Y=set([20,30,40])
d_1=jaccard_similarity(X,Y) #自己的轮子实现
d_2=nltk_jaccard(X,Y) #使用nltk中的实现
print("d_1="+str(d_1))
print("d_2="+str(d_2))
执行完程序后,结果如下:
当然了,相似性度量的距离算法有很多,想经常用到的度量词义之间的相似性,比如在word2vec中的使用欧氏距离的度量方法来寻找词义相近的词,等等。