N-grams: 解释及2个应用

18

我想用n-gram实现一些应用程序(最好是在PHP中)。


哪种类型的n-gram对于大多数目的更合适?单词级别的还是字符级别的n-gram?如何在PHP中实现一个n-gram分词器?


首先,我想知道什么是N-grams。以下是我理解n-gram的方式:

句子:“我住在纽约。”

单词级别的bigram(2个为n):“# I'”,“I live”,“live in”,“in NY”,“NY #”

字符级别的bigram(2个为n):“#I”,“I#”,“#l”,“li”,“iv”,“ve”,“e#”,“#i”,“in”,“n#”,“#N”,“NY”,“Y#”

当您有这些n-gram部分的数组时,您可以删除重复项并为每个部分添加计数器以给出频率:

单词级别的bigram:“[1, 1, 1, 1, 1]”

字符级别的bigram:“[2, 1, 1, ...]”

这是正确的吗?


此外,我想了解一下使用n-grams可以做什么:

  • 如何使用n-grams识别文本的语言?
  • 即使没有双语语料库,也是否可能使用n-grams进行机器翻译?
  • 如何构建垃圾邮件过滤器(垃圾邮件、非垃圾邮件)?将n-grams与贝叶斯过滤器相结合?
  • 如何做到话题发现?例如:一篇关于篮球或狗的文章?我的方法(对于“狗”和“篮球”的维基百科文章):为两个文档构建n-gram向量,对它们进行归一化,计算曼哈顿/欧几里得距离,结果越接近1,相似度越高。

您对我的应用程序方法有什么看法,特别是最后一个?


我希望你能帮助我。预先感谢!

2个回答

26

大多数文本分析应用程序,包括语言检测在内,使用词汇n-gram通常比字符三元组更有用。您可以为每种语言创建一个n-gram向量,然后将每个语料库中的三元组频率与您正在分类的文档中的三元组进行比较。例如,在英语中,“the”这个三元组可能比在德语中更频繁出现,因此会提供某种程度的统计相关性。一旦您将文档转换成n-gram格式,就可以选择许多算法进行进一步分析,例如贝叶斯过滤器、N最近邻算法、支持向量机等。

在您提到的应用程序中,机器翻译可能是最不切实际的,因为仅靠n-gram无法使您迈向更高层次。将输入文件转换为n-gram表示仅是一种将数据放入进一步特征分析格式的方式,但由于失去了大量上下文信息,因此对于翻译可能没有用处。

需要注意的一点是,如果维度不匹配,则为一个文档创建向量[1,1,1,2,1],对于另一个文档创建向量[2,1,2,4]是不够的。也就是说,向量中的第一个条目不能在一个文档中是“the”,在另一个文档中是“is”,否则算法将无法工作。您最终会得到像[0,0,0,0,1,1,0,0,2,0,0,1]这样的向量,因为大多数文档都不包含您感兴趣的大多数n-gram。这种“特征对齐”至关重要,它要求您事先决定要包括在分析中的n-gram。通常,这是以两个步骤的算法实现的,首先决定各种n-gram的统计显着性以决定保留什么。有关更多信息,请搜索“特征选择”。

基于词的n-gram加支持向量机是一种非常优秀的主题检测方法,但需要大量已经分类为“主题相关”和“非主题相关”的文本语料库来训练分类器。在像citeseerx这样的网站上可以找到许多研究论文来解释这个问题的各种方法。我不建议使用欧氏距离法来解决这个问题,因为它没有根据统计学意义对单个n-gram进行加权,因此两个包含theaisof的文档会被认为比两个都包含Baysian的文档更匹配。从您感兴趣的n-gram中删除停用词会在一定程度上改善这种情况。


1
非常感谢您提供的详细答案!我还有一个最后的问题:与简单的单词向量相比,n-gram向量的优势是什么?我的意思是: 为什么应该将“I live in NY”拆分为“I live, live in, in NY”,而不是简单地拆分为“I, live, in, NY”? - caw
4
使用单词作为特征相当于n=1的基于单词的n-gram。增加n的优点是可以在特征中获得更多上下文信息。例如,知道两个文档都包含n-gram“ The Who”可能比知道它们分别包含“ The”和“ Who”更有用。 - bdk
2
此外,请注意,如果为n = 3(例如)构建向量n-gram,则还应将n = 2和n = 1 n-gram包括在内。我不确定这是否是规范的,但我过去参与的项目经常这样做。增加n的优点是提供了额外的上下文,但缺点是样本集更小(任何给定的三个单词短语在语料库中出现的次数不如两个单词短语)。同时包括n = 1,2,3 n-gram可以让你兼顾两者,缺点是需要更多的存储空间和计算需求。 - bdk
3
这是我在SO上看过的任何主题中最好的答案之一。 - glomad
这是另一篇可能有所帮助的文章: https://dev59.com/a3zaa4cB1Zd3GeqPN0i3#21660459 - Mark Giaconia

2

关于n-grams的定义,您是正确的。

对于搜索类型的应用程序,可以使用单词级别的n-grams。字符级别的n-grams更适合用于分析文本本身。例如,要识别文本的语言,我会使用字母的频率与该语言已知频率进行比较。也就是说,文本应该大致匹配该语言中字母出现的频率。

在PHP中,可以使用strtok来创建单词的n-gram分词器:

http://us2.php.net/manual/en/function.strtok.php

对于字符,请使用split:

http://us2.php.net/manual/en/function.str-split.php

然后,您可以根据需要将数组拆分为任意数量的n-grams。

朴素贝叶斯过滤器需要进行训练,以用作垃圾邮件过滤器,并可与n-grams结合使用。但是,您需要提供大量输入才能使其学习。

您最后的方法听起来不错,可以学习页面的上下文...但这仍然相当困难,不过n-grams听起来是一个很好的起点。


谢谢。我认为strtok对于良好的分词来说太简单了,因为你必须添加许多标记,如:空格、逗号、点、下划线、括号等等。但第一段,即用例,确实非常有帮助。谢谢! :) - caw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接