文章目录
一、简单说明
常用的N-gram训练工具有SRILM、IRSTLM、BerkeleyLM和KenLM等。这几种工具所 用的算法思想基本一致,只是在实现细节上有所不同,所以我们只需理解其中一个训 练工具即可。
本文以KenLM(号称速度最快,占用内存最少)作为训练工具,对基于N-gram的过程进行详细介绍,所用的平滑技术是Modified Kneser-ney smoothing,因为它是当 前一个标准的、广泛采用的、效果最好的平滑算法。
Modified Kneser-ney smoothing 论文,点我
二、执行过程
以2-gram为例
1.拿到文本
我
我是
他
2.分词处理 text
我
我 是
他
cd language_model/srilm
3.生成n-gram统计文件
sudo ngram-count -text 输入文本 -order 2 -write 输出的统计文本 -unk
例如
sudo ngram-count -text language_model_demo/text -order 2 -write language_model_demo/2gram.count -unk
4.生成语言模型
sudo ngram-count -read 输入统计文本 -order 2 -lm 输出语言模型文件 -interpolate -unk
例如:
sudo ngram-count -read language_model_demo/2gram.count -order 2 -lm language_model_demo/2gram.count.klm -interpolate -unk
5.转为二进制文件
进入kenLm目录:cd ../kenlm
sudo build/bin/build_binary 输入语言模型文件 输出二进制语音模型文件
例如:
sudo build/bin/build_binary language_model_demo/2gram.count.klm language_model_demo/2gram.binary
6.生成trie文件
cd mozilla_deepspeech/native_client
./generate_trie 字母表文件 二进制语言模型文件 trie文件
例如
./generate_trie ../data/alphabet_zh.txt language_model_demo/2gram.binary language_model_demo/2gram_trie
7.结果分析
vim 2gram.count
这一步分别对1-gram和2-gram做原始计数
vim 2gram.count.klm
生成两张表,1-gram表比2-gram表多一列,多出来的一列表示回退概率。
三、生成原理
1.增加<s>
和</s>
标记符,表示句子的开头和结尾。
<s> 我 </s>
<s> 我 是 </s>
<s> 他 </s>
2.映射ID
把每个词映射到唯一的数字id,为了更直观地描述下面的关键步骤,我们这里就不把单词映射为数字id。
3.Counting
(原始计数)。也就是把相同的字合并,然后排序(假设编码顺序为<s>
、我、是、他、<\s>
) 。根据步骤一的文本,我们可以得到1-gram和2-gram的原始计数:
1-gram | 原始计数 |
---|---|
<s> |
3 |
我 | 2 |
是 | 1 |
他 | 1 |
<\s> |
3 |
2-gram | 原始计数 |
---|---|
<s> 我 |
2 |
我</s> |
1 |
我 是 | 1 |
是 </s> |
1 |
<s> 他 |
1 |
他 </s> |
1 |
4.Adjusting
(调整计数)。其基本思想是对于那些lower-gram,我们不care其出现的次数,而是关心其作为novel continuation的可能性。比如“York”,其在语料中出现的次数一般会比较多,因为“New York”是很高频的词。但“York”作为continuation(中文意思:别的词把“york”作为接续词)的可能性就较低,也就是说它前面的词只有“new”等少数几类词,所以应该给它较低的计数。
1-gram | 中间计算过程 | adjust计数 |
---|---|---|
<s> |
w1=<s> ,计数保持 |
3 |
我 | “我”的前面只出现了"<s> "一种情况 |
1 |
是 | “是”的前面只出现了"我"一种情况 | 1 |
他 | “他”的前面只出现了"<s> "一种情况 |
1 |
<\s> |
“</s> ”的前面出现了"我"、“是”、“他”三种情况 |
3 |
2-gram表的计数保持不变
5.Discounting。
其基本思想是把经常出现的一些N-Gram的概率分一些出来给没有出 现的N-gram,也就等同于将经常出现的N-Gram次数减去(discount)一部分,这样做的道理就在于,对于出现次数比较多的计数我们其实已经得到了一个相对比较好的估计,那么当我们从这个计数值中减去一个较小的数值d后应该影响不大。那 到底该discount取多少呢?其中比较有代表性的有Church & Gale于1991年通过留存 法实验从而得到的Absolute Discounting;另一个是Chen and Goodman于1998年提出 的方法。
6.Normalization
(1)计算n-gram的概率,该概率称之为pseudo probability,也就是说它不是最终的概率,但对于计算最终概率是有用的
(2)计算回退权重,也称为back-off weight, 它衡量的是某个词后面能接不同词的能力。
举个例子,考虑 spite 和 constant 的 bigram,在 Europarl corpus 中,两个 bigram 都出现了 993 次,以 spite 开始的 bigram 只有 9 种,大多数情况下 spite 后面跟着 of(979 次),因为 in spite of 是常见的表达,而跟在 constant 后的单词有 415 种,所以我们更有可能见到一个跟在 constant 后面的bigram,因此back-off(constant)>back-off(spite)
对上述两个概率取以10为底的log,就能得到最终的结果
7.Interpolation
我们先看一个例子:如果c(多的)和c(多敛) 都为0,也就是说在某个语料中都没出现,那么在传统的n-gram中,p(的∣多)=p(敛∣ 多)。而这个概率我们直观上来看是错误的,p(的∣多)应该比p(敛∣多)高很多。要实 现这个,我们就希望把 bigram 和 unigram 结合起来,因为“的”比“敛”常见的多,就能保证p(的∣多)>p(敛∣多)。interpolate 就是这样一种方法。