我想用n-gram(最好用PHP)实现一些应用程序。
哪种类型的n-gram更适合大多数用途?单词级别或字符级别n-gram?你怎么能在PHP中实现一个n-gram-tokenizer?
首先,我想知道N-gram到底是什么。它是否正确?这就是我理解n-gram的方式:
句子:“我住在纽约。”
单词级别的双字母(n为2):“#I',”我活着“,”住在“,”在纽约“,”纽约#“
字符级别双字母(n为2):“#I”,“I#”,“#l”,“li”,“iv”,“ve”,“e#”,“#i”,“in “,”n#“,”#N“,”NY“,”Y#“
如果你有这个n-gram-parts数组,你可以删除重复的数组并为每个给出频率的部分添加一个计数器:
单词级别的双字母:[1,1,1,1,1]
字符级别的双字母:[2,1,1,...]
这是对的吗?
此外,我想了解更多关于你可以用n-gram做什么的事情:
您如何看待我的申请方法,特别是最后一个?
我希望你能帮助我。提前谢谢!
答案 0 :(得分:26)
对于你提到的大多数文本分析应用程序来说,Word n-gram通常会更有用,除了语言检测之外,其中像字符三元组这样的东西可能会提供更好的结果。实际上,您可以为您感兴趣的每种语言中的文本语料库创建n-gram向量,然后将每个语料库中的三元组频率与您正在分类的文档中的三元组进行比较。例如,三语the
可能在英语中比在德语中出现得更频繁,并且会提供一定程度的统计相关性。一旦您的文档采用n-gram格式,您就可以选择许多算法进行进一步分析,Baysian过滤器,N-Nearest Neighbor,支持向量机等。
在你提到的应用程序中,机器翻译可能是最牵强的,因为单独的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。这个'衬里功能是必不可少的,它需要您“提前”决定您将在分析中包含哪些ngram。通常,这是作为双通算法实现的,首先确定各种n-gram的统计显着性以决定保留什么。谷歌的“功能选择”了解更多信息。
基于Word的n-gram加上支持向量机以极好的方式执行主题定位,但是您需要一个大的文本语料库,预先分类为“on topic”和“off topic”来训练分类器。您将在citeseerx等网站上找到大量研究论文,解释解决此问题的各种方法。我不建议使用欧几里德距离来解决这个问题,因为它不会根据统计显着性对单个n-gram进行加权,因此两个文档都包含the
,a
,is
,与包含of
的两个文档相比,Baysian
被认为是更好的匹配。从你感兴趣的n-gram中删除停用词将会有所改善。
答案 1 :(得分:2)
你对n-gram的定义是正确的。
您可以将词级n-gram用于搜索类型的应用程序。字符级别n-gram可以更多地用于分析文本本身。例如,为了识别文本的语言,我将使用字母的频率与语言的既定频率进行比较。也就是说,文本应大致与该语言中字母的出现频率相匹配。
PHP中的单词的n-gram标记化器可以使用strtok完成:
http://us2.php.net/manual/en/function.strtok.php
对于字符,请使用split:
http://us2.php.net/manual/en/function.str-split.php
然后你可以根据需要将数组拆分为任意数量的n-gram。
贝叶斯过滤器需要经过培训,可用作垃圾邮件过滤器,可与n-gram结合使用。但是你需要给它足够的输入才能学习。
就学习页面的上下文而言,你的最后一种方法听起来不错......但这仍然相当困难,但n-gram听起来是一个很好的起点。