如何判断写入的纯文本文件是什么语言?

假设我们有一个内容文本文件:“Je suis un beau homme ……”

另一个:“我是一个勇敢的人”

第三个用德语发表文字:“Guten morgen。Wie geht’s?”

我们如何编写一个告诉我们的函数:第一个文件中的文本是英文的,第二个文件是英文等等?

欢迎链接到书籍/开箱即用的解决方案。 我用Java编写,但如果需要我可以学习Python。

我的评论

  1. 我需要添加一个小评论。 该文本可能包含不同语言的短语,作为整体的一部分或由于错误的结果。 在经典文学中,我们有很多例子,因为贵族成员是多语言的。 因此,概率更好地描述了情况,因为文本的大多数部分是用一种语言编写的,而其他部分可能用另一种语言编写。
  2. Google API – 互联网连接。 我不想使用远程function/服务,因为我需要自己做或使用可下载的库。 我想就这个话题进行研究。

有一个名为JLangDetect的包,它似乎完全符合您的要求:

langof("un texte en français") = fr : OK langof("a text in english") = en : OK langof("un texto en español") = es : OK langof("un texte un peu plus long en français") = fr : OK langof("a text a little longer in english") = en : OK langof("a little longer text in english") = en : OK langof("un texto un poco mas largo en español") = es : OK langof("J'aime les bisounours !") = fr : OK langof("Bienvenue à Montmartre !") = fr : OK langof("Welcome to London !") = en : OK // ... 

编辑:正如Kevin指出的那样, org.apache.nutch.analysis.lang包提供的Nutch项目中有类似的function。

Google的语言检测: http : //code.google.com/apis/ajaxlanguage/documentation/#Detect

对于较大的文本corpi,您通常使用字母,有向图甚至三字母的分布,并与您想要检测的语言的已知分布进行比较。

但是,一句话很可能太短,无法产生任何有用的统计措施。 然后,您可能会更幸运地将单个单词与字典匹配。

NGramJ似乎有点更新:

http://ngramj.sourceforge.net/

它还具有面向字符和面向字节的配置文件,因此它也应该能够识别字符集。

对于多种语言的文档,您需要识别字符集( ICU4J有一个可以执行此操作的CharsetDetector ),然后将文本拆分为多个换行符,如多个换行符或段落,如果文本已标记。

试试Nutch的语言标识符 。 它使用n-gram语言配置文件进行训练,可用语言的配置文件与输入文本匹配。 有趣的是,如果需要,您可以添加更多语言。

查找马尔可夫链。

基本上,您需要具有统计学意义的语言样本才能识别。 当您获得新文件时,请查看特定音节或音素的频率,并比较预先计算的样本。 选择最近的一个。

虽然比您正在寻找的解决方案更复杂,但您可以使用Vowpal Wabbit并使用不同语言的句子进行训练。

从理论上讲,您可以为文档中的每个句子找回一种语言。

http://hunch.net/~vw/

(不要被项目副标题中的“在线”所愚弄 – 这只是学习数学,而不必在记忆中有完整的学习材料)

如果您对可以执行语言检测的机制感兴趣,我将引用您使用(非常)天真的方法的以下文章 (基于python),但特别是对这个问题和机器学习 (只是一个一般而言。

对于java实现,其他海报建议的JLangDetect和Nutch非常好。 还可以看看Lingpipe , JTCL和NGramJ 。


对于同一页面中有多种语言的问题,您可以使用句子边界检测器将页面切成句子,然后尝试识别每个句子的语言。 假设一个句子只包含一种(主要)语言,那么使用上述任何实现仍然可以获得良好的结果。

注意:句子边界检测器(SBD)在理论上是语言特定的(鸡蛋问题,因为你需要一个用于另一个)。 但对于基于拉丁语脚本的语言(英语,法语,德语等),主要使用句点(除了惊叹等)进行句子分隔,即使您使用专为英语设计的SBD,您也会获得可接受的结果。 我写了一个基于规则的英语SBD,它对法语文本非常有效。 对于实现,请查看OpenNLP 。

使用SBD的另一种选择是使用10个令牌(空格分隔)的滑动窗口来创建伪句 (PS)并尝试识别语言变化的边界。 这样做的缺点是,如果您的整个文档有n个令牌,您将对每个长度为10个令牌的字符串执行大约n-10个分类操作。 在另一种方法中,如果平均句子有10个令牌,那么你将进行大约n / 10个分类操作。 如果文档中n = 1000个单词,则表示您正在比较990个操作与100个操作:一个数量级的差异。


如果您有短语(不超过20个字符),语言检测的准确性在我的经验中很差。 特别是在专有名词的情况下,以及在诸如“巧克力”之类的语言中相同的名词。 例如,如果出现在法语句子中,“纽约”是英语单词还是法语单词?

如果您有互联网连接,那么Google Language API将是您的最佳选择。

 // This example request includes an optional API key which you will need to // remove or replace with your own key. // Read more about why it's useful to have an API key. // The request also includes the userip parameter which provides the end // user's IP address. Doing so will help distinguish this legitimate // server-side traffic from traffic which doesn't come from an end-user. URL url = new URL( "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&" + "q=Paris%20Hilton&key=INSERT-YOUR-KEY&userip=USERS-IP-ADDRESS"); URLConnection connection = url.openConnection(); connection.addRequestProperty("Referer", /* Enter the URL of your site here */); String line; StringBuilder builder = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); while((line = reader.readLine()) != null) { builder.append(line); } JSONObject json = new JSONObject(builder.toString()); // now have some fun with the results... 

如果你没有,还有其他方法。

bigram模型表现良好,编写简单,训练简单,只需要少量文本进行检测。 nutch语言标识符是我们发现的一个java实现,并与一个瘦包装器一起使用。

我们遇到了混合CJK和英文文本的二元模型的问题(即推文主要是日语,但只有一个英语单词)。 从数学上看,这是显而易见的(日语中有更多的字符,因此任何给定对的概率都很低)。 我认为你可以通过一些更复杂的对数线性比较来解决这个问题,但我欺骗并使用了一个基于特定语言特有的字符集的简单filter(即如果它只包含统一的汉语,那么它是中文的,如果它包含一些日本假名和统一汉,然后它是日本人)。