如何确定文档的(自然)语言?

时间:2009-09-05 14:50:31

标签: .net nlp text-mining

我有一套两种语言的文件:英语和德语。没有关于这些文档的可用元信息,程序只能查看内容。基于此,程序必须决定编写文档的两种语言中的哪一种。

是否有针对此问题的“标准”算法可以在几个小时内实施?或者,可以执行此操作的免费.NET库或工具包?我知道LingPipe,但它是

  1. 爪哇
  2. “半商业”用途不可免费使用
  3. 这个问题似乎非常困难。我检查了Google AJAX Language API(我通过首先搜索这个网站找到了),但这太荒谬了。对于我指出的六个德语网页,只有一个猜测是正确的。其他猜测是瑞典语,英语,丹麦语和法语......

    我想出的一个简单方法是使用停用词列表。我的应用程序已经使用德国文档的这样一个列表,以便用Lucene.Net进行分析。如果我的应用程序扫描文档中是否出现任何一种语言的停用词,那么具有更多出现次数的那些将获胜。当然,这是一种非常天真的方法,但可能足够好。不幸的是,我没有时间成为自然语言处理方面的专家,尽管这是一个有趣的话题。

11 个答案:

答案 0 :(得分:6)

尝试测量文本中每个字母的出现次数。对于英语和德语文本,计算频率,也可以计算它们的分布。获得这些数据后,您可以推断出文本频率分布所属的语言。

您应该使用贝叶斯推理来确定最接近的语言(具有一定的错误概率),或者,可能还有其他统计方法来执行此类任务。

答案 1 :(得分:6)

使用停用词列表的问题是鲁棒性。停止单词列表基本上是一组规则,每个单词一个规则。与统计方法相比,基于规则的方法对于看不见的数据往往不那么健壮。您将遇到的一些问题是每种语言包含相同数量的停用词的文档,没有停用词的文档,使用错误语言停止文字的文档等。基于规则的方法无法执行任何规则t指定。

一种不需要你自己实现Naive Bayes或任何其他复杂的数学或机器学习算法的方法是计算字符双字母和三字符(取决于你是否有很多或一些数据开始 - - bigrams将使用较少的训练数据)。对已知源语言的少数文档(越多越好)运行计数,然后按计数数量为每种语言构造有序列表。例如,英语将“th”作为最常见的二元组。使用您的有序列表,计算您希望分类的文档中的双字母并按顺序排列。然后浏览每一个并将其在已排序的未知文档列表中的位置与其在每个训练列表中的排名进行比较。为每个语言提供每种语言的分数

1 / ABS(RankInUnknown - RankInLanguage + 1)

无论哪种语言得分最高,都是赢家。它很简单,不需要大量编码,也不需要大量的训练数据。更好的是,您可以继续向其中添加数据,并且它会得到改善。另外,您不必手动创建一个停用词列表,它不会因为文档中没有停用词而失败。

仍然会被包含相等对称双字母计数的文档混淆。如果你能获得足够的训练数据,使用三元组将降低这种可能性。但是使用trigrams意味着您还需要更长的未知文档。真正短的文档可能要求您下拉到单个字符(unigram)计数。

所有这些说,你会有错误。没有银弹。结合方法并选择最能使您对每种方法充满信心的语言可能是最明智的选择。

答案 2 :(得分:4)

除ä,ö,ü和ß(eszett)外,英语和德语使用相同的字母组。您可以查找这些字母来确定语言。

您还可以从Grefenstette查看此文本(Comparing two language identification schemes)。它着眼于字母三字母和短字。德语en_,er_,_de的常见三元组。英语的常见三元组the_,he_,...

还有Bob Carpenter的How does LingPipe Perform Language ID?

答案 3 :(得分:3)

我认为标准程序是用测试数据(即用corpus)测量所提算法的质量。定义您希望算法实现的正确分析的百分比,然后在您手动分类的许多文档上运行它。

至于具体算法:使用停止词列表听起来很好。据报道,另一种方法是使用Bayesian Filter,例如SpamBayes。而不是将其训练成火腿和垃圾邮件,而是将其训练成英语和德语。使用语料库的一部分,通过spambayes运行,然后在完整数据上进行测试。

答案 4 :(得分:3)

语言检测在概念上并不是很困难。请查看我对related question的回复以及对同一问题的其他回复。

如果你想自己写一下,你应该可以在半天内写一个天真的探测器。我们在工作中使用类似于以下算法的东西,它的效果非常好。另请阅读我链接的帖子中的python实现教程。

<强>步骤

  1. 为两种语言取两个语料库并提取字符级别的双字母组,三字组和空格分隔的标记(单词)。跟踪他们的频率。这一步构建了两种语言的“语言模型”。

  2. 给定一段文字,确定每个语料库中的字母双字母组,三字组和空格分隔的标记及其对应的“相对频率”。如果模型中缺少特定的“特征”(char bigram / trigram或token),则将其“原始计数”视为1并使用它来计算其“相对频率”。

  3. 特定语言的相对频率乘积给出了该语言的“得分”。这是句子属于该语言的概率的非常幼稚的近似

  4. 得分较高的语言获胜。

  5. 注1:对于我们语言模型中没有出现的功能,我们将“原始计数”视为1。这是因为,实际上,该特征的价值非常小,但由于我们有一个有限的语料库,我们可能还没有遇到它。如果你认为它是零,那么你的整个产品也将为零。为了避免这种情况,我们假设它的出现在我们的语料库中是1。这称为加一平滑。有other advance smoothing techniques

    注意2:由于您将乘以大量分数,因此您可以轻松地运行到零。为避免这种情况,您可以在对数空间中工作,并使用此公式计算您的分数。

                    a X b =  exp(log(a)+log(b))
    

    注3:我描述的算法是“Naive Bayes Algorithm”的“非常天真”版本。

答案 5 :(得分:2)

这两种语言的停用词方法很快,并且可以通过对那些在德语中没有出现“das”而在英语中用“the”出现的语言进行加权来加快。使用“专有词汇”有助于在更大的一组语言中强有力地扩展这种方法。

答案 6 :(得分:2)

如果您希望自己灵活地解决问题,我鼓励您;但是,如果您想使用它,则存在轮子。

Windows 7内置了此功能。名为“扩展语言服务”(ELS)的组件能够检测脚本和自然语言,并且可以在任何Windows 7或Windows Server 2008计算机上使用。取决于您是否有任何此类机器可用以及当您说“免费”时您的意思,它将为您完成。无论如何,这是Google或此处提到的其他供应商的替代品。

http://msdn.microsoft.com/en-us/library/dd317700(v=VS.85).aspx

如果你想从.NET访问它,那里有一些信息:

http://windowsteamblog.com/blogs/developers/archive/2009/05/18/windows-7-managed-code-apis.aspx

希望有所帮助。

答案 7 :(得分:1)

如果您只有两种语言(英语和德语)可供选择,问题不是几个数量级更容易吗?在这种情况下,你对停用词列表的处理可能已经足够了。

如果您在列表中添加了更多语言,显然您需要考虑重写。

答案 8 :(得分:1)

首先,您应该对当前解决方案进行测试,看看它是否达到了您所需的准确度。在特定领域取得成功不仅仅是遵循标准程序。

如果您的方法需要改进,请尝试用大量英语和德语中的稀有词来加权您的停用词。或者您可以使用更复杂的技术,例如培训Markov modelBayesian classifier。您可以扩展任何算法以查看高阶n-grams(例如,两个或三个单词序列)或文本中的其他功能。

答案 9 :(得分:1)

您可以使用Google语言检测API。

这是一个使用它的小程序:

baseUrl = "http://ajax.googleapis.com/ajax/services/language/detect"

def detect(text):
    import json,urllib
    """Returns the W3C language code of a natural language"""

    params = urllib.urlencode({'v': '1.0' , "q":text[0:3000]}) # only use first 3000 characters                    
    resp = json.load(urllib.urlopen(baseUrl + "?" + params))
    try:
        retText = resp['responseData']['language']
    except:
        raise
    return retText


def test():
    print "Type some text to detect its language:"
    while True:
        text = raw_input('#>  ')
        retText = detect(text)
        print retText


if __name__=='__main__':
    import sys
    try:
        test()
    except KeyboardInterrupt:
        print "\n"
        sys.exit(0)

其他有用的参考资料:

Google宣布API(和演示):        http://googleblog.blogspot.com/2008/03/new-google-ajax-language-api-tools-for.html

Python包装器:        http://code.activestate.com/recipes/576890-python-wrapper-for-google-ajax-language-api/

另一个python脚本:         http://www.halotis.com/2009/09/15/google-translate-api-python-script/

RFC 1766定义了W3C语言

从以下位置获取当前语言代码:     http://www.iana.org/assignments/language-subtag-registry

答案 10 :(得分:0)

你试过Apache Tika吗?它可以确定给定文本的语言:

http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/07/02/using-the-tika-java-library-in-your-net-application-with-ikvm

我没有.Net的经验,但该链接可能有所帮助。如果您可以在您的环境中执行jar,请尝试以下操作:

 java -jar tika-app-1.0.jar -l http://www.admin.ch/

输出:

de

希望有所帮助。