检测书面文本的语言






4.96/5 (72投票s)
一篇关于如何检测书面文本语言的文章。
引言
很久以前,我发表了一篇关于如何检测给定文本编码的文章。在这篇文章中,我将描述文本分类漫漫长路上的下一步:语言检测。
给定的解决方案基于 n-gram 和词频比较。
它适用于所有使用词语的语言(这实际上并非适用于所有语言)。
根据模型和输入文本的长度,在使用“all”模型分类挪威语、瑞典语和丹麦语短文本时,准确率介于 70%(仅限短文本)和使用“default”模型时的 99.8% 之间。
背景
书面文本的语言检测可能是自然语言处理 (NLP) 中最基本的任务之一。对于任何依赖语言处理的未知文本,首先要知道的是该文本是用哪种语言编写的。幸运的是,这是 NLP 提供的更简单的挑战之一。我选择实现的这种方法广为人知且相当简单。其思想是,任何语言都有一组独特的字符(共)出现。
第一步是收集所有应可检测语言的这些统计数据。这最初听起来可能并不容易。问题在于收集大量的测试数据(纯文本),这些数据只包含一种语言,并且不是领域特定的。(只有报纸文章可能缺乏“我”这个词的使用和直接引语。使用莎士比亚戏剧不会是检测当代文本的最佳方法。医学文章往往包含太多领域特定术语,这些术语甚至不是语言特定的(major、minor、arteria 等……)。如果这还不够难,文本不应该受版权保护。(我不确定这是否是一个真正的要求。受版权保护文本的统计分析结果是否也受版权保护?)我选择使用维基百科作为我的主要来源。我不得不进行一些过滤,以“清理”来源中几乎所有文章中都存在的英文短语——无论它们是用哪种语言编写的(我实际上使用了 Babel 本身来检测英文短语)。清理工作绝非完美。维基百科包含许多专有名称(即乐队名称),这些名称通常包含“the”或“and”。这就是为什么这些词在许多语言中都会出现,即使它们不属于该语言。这不一定是一个缺点,因为英语化现象在许多语言中都广泛存在。我为每种语言创建了三种统计数据
- 字符集
- N-gram
- 词表
有些语言具有非常特殊的字符集(例如中文、日文和俄文);对于其他语言,某些字符可以很好地提示可能是什么语言(例如德语的变音符号)。
在将文本标记化为单词(如果适用)后,统计了每个 1-gram、2-gram 和 3-gram 的出现次数。一些 n-gram 具有很强的语言特异性(例如,英语中的“TH”)。
最后一个消除歧义的来源是实际使用的单词。有些语言(如葡萄牙语和西班牙语)在使用的字符和特定 n-gram 的出现频率上几乎相同。然而,不同的单词以不同的频率使用。
一组统计数据被称为一个模型。我创建了一些“所有”模型的子集,这些子集最能满足我的需求(见下表)。“common”模型包含世界上最常用的 10 种语言。“small”和“default”是基于我的使用场景。如果你来自世界的其他地方,你的偏好可能会有所不同。因此,请不要介意我选择哪些语言包含在哪个模型中。
所有统计数据按其出现次数排序和排名。在演示应用程序中,所有模型都可以详细研究。对未知文本的分类非常简单。文本被标记化,并生成三个统计表。结果表与模型中的所有表进行比较,并计算距离。与未知文本距离最小的模型中的比较表最可能是该文本的语言。
使用代码
关于代码的简单说明
Babel 是一个更大项目的一部分。我希望 Babel 程序集能够独立工作。由于一些使用的类最初分散在许多程序集中,我使用了定义“_DIALOGUEMASTER
”来指示是使用 DialogueMaster™ 程序集还是就地实现(可能更简单的)版本。
任何重要的 DialogueMaster™ 类都是可远程访问的。客户端只需要一个包含所有接口定义的程序集。这就是为什么 Babel 使用了如此多的接口,它们可能乍一看会使代码臃肿。此外,DialogueMaster™ 提供了大量的 PerformanceCounters。为了使程序集更易于使用(无需安装,无需管理员权限),我选择省略了它们。
我真正想说的是:代码不如它应该的那样可读和简洁。
分类文本
代码的使用非常简单。首先,您必须选择(或创建自己的)模型。ClassifyText
方法返回一个 ICategoryList
,它是一个按分数降序排列的 ICateogry
(名称-分数对)项的列表。
using System;
//
// Most simple samlple
//
class Program
{
static void Main(string[] args)
{
DialogueMaster.Babel.BabelModel model = DialogueMaster.Babel.BabelModel._AllModel;
String s = System.Console.ReadLine();
while (s.Length > 0)
{
DialogueMaster.Classification.ICategoryList result = model.ClassifyText(s, 10);
foreach (DialogueMaster.Classification.ICategory category in result)
{
System.Console.Out.WriteLine(" {0} : {1}", category.Name, category.Score);
}
s = System.Console.ReadLine();
}
}
}
定义您自己的模型
从现有集合中定义
要从现有语言集中定义您自己的模型,只需创建一个新的 BabelModel
并从 _AllModel
中添加所需的语言。
class Program2
{
static void Main(string[] args)
{
// Create a custom model
DialogueMaster.Babel.BabelModel model = new DialogueMaster.Babel.BabelModel();
model.Add("de", DialogueMaster.Babel.BabelModel._AllModel["de"]);
model.Add("en", DialogueMaster.Babel.BabelModel._AllModel["en"]);
model.Add("sv", DialogueMaster.Babel.BabelModel._AllModel["sv"]);
// ask the user for some input
String s = System.Console.ReadLine();
while (s.Length > 0)
{
// classify it
DialogueMaster.Classification.ICategoryList result = model.ClassifyText(s, 10);
// and dump the result
foreach (DialogueMaster.Classification.ICategory category in result)
{
System.Console.Out.WriteLine(" {0} : {1}", category.Name, category.Score);
}
s = System.Console.ReadLine();
}
}
}
添加新语言
添加新语言非常简单。您所需要的只是一些学习数据文本。
class Program3
{
static void Main(string[] args)
{
// Create a custom model
DialogueMaster.Babel.BabelModel model = new DialogueMaster.Babel.BabelModel();
TokenTable klingonTable = new TokenTable(new FileInfo("LearnData\\Klingon.txt"));
TokenTable vulcanTable = new TokenTable(new FileInfo("LearnData\\Vulcan.txt"));
model.Add("kling", klingonTable);
model.Add("vulcan", klingonTable);
model.Add("en", DialogueMaster.Babel.BabelModel._AllModel["en"]);
// ask the user for some input
String s = System.Console.ReadLine();
while (s.Length > 0)
{
// classify it
DialogueMaster.Classification.ICategoryList result = model.ClassifyText(s, 10);
// and dump the result
foreach (DialogueMaster.Classification.ICategory category in result)
{
System.Console.Out.WriteLine(" {0} : {1}", category.Name, category.Score);
}
s = System.Console.ReadLine();
}
}
}
关注点
支持的语言
语言代码 | 语言 | 质量 | 默认值 | Common | 大 | 小 |
---|---|---|---|---|---|---|
nl | Dutch | 13 | x | x | ||
en | English | 13 | x | x | x | x |
ca | 加泰罗尼亚语 | 13 | ||||
fr | French | 13 | x | x | x | x |
es | 西班牙语 | 13 | x | x | x | x |
否 | Norwegian | 13 | x | x | ||
da | Danish | 13 | x | x | ||
it | Italian | 13 | x | x | ||
sv | 瑞典语 | 13 | x | x | ||
de | German | 13 | x | x | x | x |
pt | 葡萄牙语 | 13 | x | x | x | |
ro | 罗马尼亚语 | 13 | ||||
vi | 越南语 | 13 | ||||
tr | 土耳其语 | 13 | x | |||
fi | Finnish | 12 | x | |||
hu | Hungarian | 12 | x | |||
cs | Czech | 12 | x | |||
pl | 波兰语 | 12 | x | |||
el | Greek | 12 | x | |||
fa | 波斯语 | 12 | ||||
he | 希伯来语 | 12 | ||||
sr | 塞尔维亚语 | 12 | ||||
sl | 斯洛文尼亚语 | 12 | ||||
ar | 阿拉伯语 | 12 | x | |||
nn | 挪威语,新挪威语 (挪威) | 12 | ||||
ru | 俄语 | 11 | x | x | ||
et | Estonian | 11 | ||||
ko | Korean | 10 | ||||
hi | 印地语 | 10 | x | |||
is | 冰岛语 | 10 | ||||
th | 泰语 | 9 | ||||
bn | 孟加拉语(孟加拉国) | 9 | x | |||
ja | Japanese | 9 | x | |||
zh | 中文 (简体) | 8 | x | |||
se | 萨米语 (北方) (瑞典) | 5 |
参考文献
历史
- 2009年10月10日:发布初始版本。