用于自然语言处理的词频算法
在没有获得信息检索学位的情况下,我想知道是否存在用于计算单词在给定文本主体中出现频率的算法。目的是让人们对一组文本评论中所说的内容有一种"总体感觉"。沿着Wordle。
我想要的是:
- 忽略文章,代词等(" a"," an"," the"," him"," them"等)
- 保留专有名词
- 忽略连字号,软类型除外
伸手摘星,这些将是桃红色的:
- 处理词干和复数(例如,喜欢,喜欢,喜欢,喜欢匹配相同的结果)
- 形容词(副词等)及其主题的分组("优质服务",而不是"优质","服务")
我已经尝试使用Wordnet进行一些基本的操作,但是我只是盲目地进行调整,并希望它适用于我的特定数据。更通用的东西会很棒。
解决方案
我们刚刚描述的算法。一个开箱即用的程序,带有一个大按钮,上面写着" Do it"(执行)...我不知道。
但是,让我保持建设性。我向我们推荐这本书《编程集体智慧》。第3章和第4章包含非常实用的示例(实际上,没有复杂的理论,仅是示例)。
我写了一个完整的程序来做这个。我回家后可以上传演示。
这是代码(asp.net/c#):http://naspinski.net/post/Findingcounting-Keywords-out-of-a-Text-Document.aspx
遵循以下内容,我们不需要一个,但需要几个不错的算法。
- 忽略代词是通过非连续列表完成的。
- 保留专有名词?我们是说要检测诸如胡佛水坝之类的命名实体并说"这是一个单词"或者诸如编程语言这样的复合名词?我会给我们一个提示:这很困难,但是两者都有库。寻找NER(命名实体识别)和词法分块。 OpenNLP是同时执行这两种操作的Java工具包。
- 忽略连字号?你的意思是,像在换行符吗?使用正则表达式,并通过字典查找来验证生成的单词。
- 处理复数/词干:我们可以查看Snowball词干分析器。它的技巧很好。
- 将形容词和名词进行"分组"通常是浅层分析的任务。但是,如果我们正在寻找定性形容词(好的,坏的,卑鄙的,惊人的……),我们可能会对情感分析感兴趣。 LingPipe可以做到这一点,还有更多。
对不起,我知道我们说过要KISS,但不幸的是,要求很难满足。但是,存在用于所有这些功能的工具,如果我们不想这样做,则应该能够将它们捆绑在一起,而不必自己执行任何任务。如果我们想自己执行任务,建议我们考虑一下词干,这是最简单的方法。
如果我们使用Java,请将Lucene与OpenNLP工具包结合使用。由于Lucene已经内置了词干分析器和大量教程,我们将获得非常好的结果。另一方面,OpenNLP工具包的文档很少,但是我们不需要太多。我们可能也对用Python编写的NLTK感兴趣。
我会说我们放弃了最后一个要求,因为它涉及浅层解析,并且绝对不会改善结果。
啊,顺便说一句。我们要查找的文档术语频率词的确切术语称为tf-idf。这几乎是查找术语的文档频率的最佳方法。为了正确地做到这一点,我们将无法使用多维矢量矩阵。
... 是的,我知道。在参加IR研讨会之后,我对Google的敬意更高。但是,在IR中做了一些事情之后,我对它们的敬意就下降了。
问题的第一部分听起来还不错。我们基本上要做的就是从文件(或者带w / e的流)中读取每个单词,并将其放入前缀树中,并且每次在已存在的单词上发生时,都将增加与之关联的值。当然,我们也将有一个忽略列表,其中列出了我们想要排除在计算之外的所有内容。
如果使用前缀树,请确保要找到要去O(N)的单词,其中N是数据集中单词的最大长度。在这种情况下,前缀树的优势在于,如果我们想查找复数形式和词干,则可以在O(M + 1)中检入该词是否可行,其中M是没有词干或者复数的词的长度(这是一个字吗?呵呵)。构建完前缀树后,我将对其进行重新分析以查找词干等,然后将其压缩下来,以使根词保留结果。
在搜索时,我们可能有一些简单的规则,以使匹配在出现根或者茎或者我们拥有的内容时返回正数。
第二部分似乎极具挑战性。我的幼稚倾向是为形容词-主题分组保留单独的结果。使用与上述相同的原理,但将其分开。
语义分析的另一种选择是将每个句子建模为主题,动词等关系的树(句子具有主题和动词,主题具有名词和形容词等)。一旦用这种方式将所有文本分解,似乎很容易遍历并快速了解发生的不同配对。
只是有些杂乱无章,我敢肯定有更好的主意,但我喜欢考虑这些东西。
欢迎来到NLP的世界^ _ ^
我们所需要的只是一些基本知识和一些工具。
已经有工具可以告诉我们句子中的单词是名词,形容词还是动词。它们被称为词性标记器。通常,他们以纯文本英语作为输入,然后输出单词,其基本形式和词性。这是帖子第一句中流行的UNIX词性标记器的输出:
$ echo "Without getting a degree in information retrieval, I'd like to know if there exists any algorithms for counting the frequency that words occur in a given body of text." | tree-tagger-english # Word POS surface form Without IN without getting VVG get a DT a degree NN degree in IN in information NN information retrieval NN retrieval , , , I PP I 'd MD will like VV like to TO to know VV know if IN if there EX there exists VVZ exist any DT any algorithms NNS algorithm for IN for counting VVG count the DT the frequency NN frequency that IN/that that words NNS word occur VVP occur in IN in a DT a given VVN give body NN body of IN of text NN text . SENT .
如我们所见,它将"算法"标识为"算法"的复数形式(NNS),将"存在"标识为"存在"的共轭(VBZ)。它还将" a"和" the"标识为" determiners(DT)"(决定词)。如我们所见,POS标记器还标记了标点符号。
要完成列表中最后一点以外的所有操作,我们只需要通过POS标记器运行文本,过滤掉我们不感兴趣的类别(决定因素,代词等),并计算基本形式的频率的话。
以下是一些流行的POS标记器:
TreeTagger(仅限二进制文件:Linux,Solaris,OS-X)
GENIA Tagger(C ++:编译自己)
斯坦福POS Tagger(Java)
要执行列表中的最后一项操作,我们不仅需要单词级别的信息。一个简单的开始方法是计算单词的顺序,而不只是单词本身。这些被称为n-gram。 UNIX for Poets是一个很好的起点。如果我们愿意投资一本有关NLP的书,我将推荐统计自然语言处理基础。
这是一个示例,说明如何在Python中进行操作,这些概念在任何语言中都是相似的。
>>> import urllib2, string >>> devilsdict = urllib2.urlopen('http://www.gutenberg.org/files/972/972.txt').read() >>> workinglist = devilsdict.split() >>> cleanlist = [item.strip(string.punctuation) for item in workinglist] >>> results = {} >>> skip = {'a':'', 'the':'', 'an':''} >>> for item in cleanlist: if item not in skip: try: results[item] += 1 except KeyError: results[item] = 1 >>> results {'': 17, 'writings': 3, 'foul': 1, 'Sugar': 1, 'four': 8, 'Does': 1, "friend's": 1, 'hanging': 4, 'Until': 1, 'marching': 2 ...
第一行仅获得可解决部分问题的库,如第二行中urllib2下载Ambrose Bierce的"魔鬼字典"的副本。接下来的几行列出了文本中所有单词的列表,没有标点符号。然后,我们创建一个哈希表,在这种情况下,该哈希表就像一个与数字关联的唯一单词的列表。 for循环遍历Bierce书中的每个单词,如果表中已有该单词的记录,则每个新出现的单词都会在与该单词相关的值中添加一个;如果尚未出现该单词,则将其添加到表中,并将其值添加为1(表示一次出现。)对于我们正在谈论的情况,我们需要更加关注细节,例如使用大写为了仅在句子中间等处帮助识别专有名词,这很粗糙,但表达了这一概念。
为了深入研究词干和多元性的东西,进行实验,然后研究第三方的工作,我喜欢NLTK的部分内容,这是一个学术性开源项目,也使用python。
我们可以使用worldnet词典来获取问题关键字的基本信息(例如其过去的语言),提取同义词,我们也可以对文档进行相同操作以为其创建索引。
那么我们可以轻松地将关键字与索引文件进行匹配,并对文档进行排名。然后将其夏季化。