Antkillerfarm Hacking V7.0

Kaldi(二)

2018-06-07

ARPA文件格式(续)

1-grams部分中每一条包括了3项,其中第二项显然是条目文本本身。

第一项表示ngram的条件概率,即\(P(word_N \mid word_1,word_2,\dots,word_{N-1})\)。

第三项表示回退(backoff)概率。

下面我们举例说明条件概率和回退概率的用法。

假设arpa的最高元是3元,则句子ABCDEF发生的概率为:

\[P(ABCDEF)=P(A)*P(B\mid A)*P(C\mid AB)*P(D\mid BC)*P(E\mid CD)*(F\mid DE)\]

其中,P(A)通过访问arpa中的1-grams项获得,\(P(B\mid A)\)通过访问2-grams项获得,其他的概率通过访问3-grams项获得。

P(A)的计算直接找对应A的文法项获得概率即可。如果2-grams中存在“A B”项,\(P(B\mid A)\)的概率也很容易获得,但是如果“A B”词组在2-grams中不存在,我们就需要利用回退概率计算\(P(B\mid A)\),计算公式为\(P(B\mid A)=\alpha(A)*P(B)\),其中的\(\alpha(A)\)就表示A的回退概率。

类似地,可以获得三元词组的概率计算公式:

\[P(C│AB)=\left\{\begin{matrix}P(C\mid AB) \qquad ABC存在 \\ \alpha(AB)*P(C\mid B) \qquad BC存在 \\ \alpha(AB)*\alpha(B)*P(C) \qquad 其他 \end{matrix}\right.\]

参考:

https://blog.csdn.net/lv_xinmy/article/details/8595561

ARPA的n-gram语言模型格式

https://blog.csdn.net/SAJIAHAN/article/details/52901422

语言模型-ARPA格式

https://blog.csdn.net/yutianzuijin/article/details/78756130

arpa2fst原理详解

https://www.jianshu.com/p/ab356b3c889e

Kaldi(A5)语言模型及HCLG.fst生成

https://blog.csdn.net/nihaomafb/article/details/48009695

语言模型Katz backoff以及HMM模型

WFST

生成WFST

生成L:

scripts/make_lexicon_fst.pl data/lexicon.txt 0.5 SIL | \
  fstcompile --isymbols=data/phones.txt --osymbols=data/words.txt \
  --keep_isymbols=false --keep_osymbols=false | \
   fstarcsort --sort_type=olabel > data/L.fst

生成G:

gunzip -c data_prep/lm.arpa.gz | \
  arpa2fst --disambig-symbol=#0 \
             --read-symbol-table=data/words.txt - data/G.fst

生成\(L \circ G\):

fsttablecompose data/L_disambig.fst data/G.fst | \
    fstdeterminizestar --use-log=true | \
    fstminimizeencoded | fstpushspecial | \
    fstarcsort --sort-type=ilabel > somedir/LG.fst

生成\(C \circ L \circ G\):

fstmakecontextfst --read-disambig-syms=$dir/disambig_phones.list \
--write-disambig-syms=$dir/disambig_ilabels.list data/phones.txt $subseq_sym \
  $dir/ilabels | fstarcsort --sort_type=olabel > $dir/C.fst
fstaddsubsequentialloop $subseq_sym $dir/LG.fst | \
 fsttablecompose $dir/C.fst - > $dir/CLG.fst

生成\(H \circ C \circ L \circ G\):

make-h-transducer --disambig-syms-out=$dir/disambig_tstate.list \
   --transition-scale=1.0  $dir/ilabels.remapped \
   $tree $model  > $dir/Ha.fst
fsttablecompose $dir/Ha.fst $dir/CLG2.fst | \
   fstdeterminizestar --use-log=true | \
   fstrmsymbols $dir/disambig_tstate.list | \
   fstrmepslocal  | fstminimizeencoded > $dir/HCLGa.fst
add-self-loops --self-loop-scale=0.1 \
    --reorder=true $model < $dir/HCLGa.fst > $dir/HCLG.fst

解码

https://mp.weixin.qq.com/s/2HqAQjLIQBGbuSQ9FYvTJg

Kaldi的解码搜索

对齐工具

Montreal-Forced-Aligner:

https://github.com/MontrealCorpusTools/Montreal-Forced-Aligner

Penn Forced Aligner:

https://web.sas.upenn.edu/phonetics-lab/

FAVE:

http://fave.ling.upenn.edu

nnet

2010年以后,DL算法逐渐取代传统算法,成为目前的主流。因此,传统部分的代码已经基本稳定,而DL部分还在不断更新中。

kaldi包含了三个不同的DL实现:

nnet1:最早的一个实现,由Karel Vesely维护,因此又叫做Karel’s DNN。这个版本只支持单GPU训练,因此修改起来比较简单。nnet1还使用了早期DL常用的pre-training步骤,这在目前基本已经废弃了。

nnet2:nnet1的加强版,由Daniel Povey维护,又叫做Dan’s DNN。这个版本支持多GPU、多GPU多线程,而且这些GPU可以不在一台PC上。

kaldi的nnet1和nnet2是以层设计为基础的,也即当你新增加一种神经网络层时需要自己定义它的结构,都有哪些变量,正向怎么算,反向误差怎么传播等等,并且过于复杂的连接方式很难支持。

nnet1和nnet2的模型文件的格式是不兼容的。可以使用steps/nnet2/convert_nnet1_to_nnet2.sh将nnet1的模型文件转换成nnet2的模型文件。

而kaldi的nnet3和CNTK以及TensorFlow都是以图结构为基础的,通过配置文件实现对网络连接方式的定义,数据就像流水一样在你定义的网络图中游走,并自己实现误差的反向传播。

kaldi的DL实现,不仅具有inference的能力,也具有train的能力

kaldi中cnn的例程较少,而且其最新的cnn实现单元TimeHeightConvolutionComponent与机器视觉那边的cnn实现有着很大的区别, 如果按照机器视觉中的cnn实现去做语音识别,那么训练的计算复杂度太高;kaldi最初的cnn实现单元ConvolutionComponent的设计思路和机器视觉cnn实现的思路是一致的,但是由于计算复杂度太高,现在已经打算废弃。

值得注意的是,除了TensorFlow提供的Speech Commands Datasets之外,其他的数据集基本都是以一句话作为训练数据的最小单元。由于训练数据存在着语音和文字之间的帧对齐问题,因此即便是DL方案,通常也需要利用由传统方法生成的粗糙模型,进行相关的对齐操作,以加快模型训练的收敛速度。

Chain

Chain是Kaldi的作者Daniel Povey新进引入的技术,该工作可以看做是对CTC的进一步扩展,直接使用句子级区分性准则进行模型的训练,该方法被认为是下一步提升语音识别效率与性能最有潜力的技术之一。

论文:

《Purely Sequence-Trained Neural Networks for ASR Based on Lattice-Free MMI》

参考:

http://www.cnblogs.com/JarvanWang/p/7499589.html

Kaldi中的Chain模型

online

online识别通常会通过麦克风来获取音频,这部分一般是系统函数调用获取得到音频数据,一般系统采用16k采样率,16bits,单通道的音频。当然也可能会用到高采样率等,但对于识别来说已经足够。

kaldi里的在线识别有2个版本,online跟online2。

online是很早的一些版本,通过麦克风获取数据,然后得到文本结果,但只支持gmm的模型。

online2版本没有麦克风获取数据这部分,就直接是音频文件到识别结果,这里支持nnet2跟nnet3的模型。

参考:

https://blog.csdn.net/lijin6249/article/details/51838936

基于kaldi的在线中文识别,online的操作介绍

https://mp.weixin.qq.com/s/Scq8LumtTisPAdRE4CYPdA

kaldi里的在线识别

数据增强

数据集的基础数据往往是单一的,我们怎么才能让数据变多呢?

目前在基础数据上增加数据的方法主要有:加性噪声,乘性噪声,便音量,变语速等。这四种方法kaldi里都有对应的脚本干这些事情。

1.加性噪声。比如不同风格的纯音乐和歌曲,不同场景的环境噪声。加冲击响应或者加性噪声的脚本位于egs/aspire/s5/local/multi_condition

2.乘性噪声。不同场景的信道情况,混响,衰减等因素。

3.变音量跟变语速:

音量脚本:egs/wsj/s5/utils/data/perturb_data_dir_volume.sh

语速脚本:egs/wsj/s5/utils/data/perturb_data_dir_speed_3way.sh

kaldi的变音量跟变语速都是借助sox这个工具来实现的,具体的命令大家可以参考脚本,音量的变化范围从1.0/8到2;语速的变化范围就0.9,1,1.1。

参考:

https://mp.weixin.qq.com/s/p1mAfM8LBLMQILeNOpbf6Q

改进语音识别性能的数据增强技巧

https://mp.weixin.qq.com/s/Tmq_b7uPEk4SF1AJlr_XvQ

性能超越经典ASR模型!谷歌重磅推出全新语音识别数据增强方法

使用训练好的模型

由于Kaldi的设计目标主要是方便研究人员训练模型,而不是使用模型,因此很多例子都只有训练步骤,而没有使用步骤。

但实际上,Kaldi官网已经有些训练好的模型可供下载:

http://kaldi-asr.org/models.html

这里比较重要的是CVTE开源的中文模型。

这些训练好的模型的脚本,就基本全是使用指南了。

参考:

http://www.luojie1987.com/index.php/post/140.html

Kaldi离线在线解码应用

Kaldi参考资源

https://mp.weixin.qq.com/s/xBbYHMQhxkRQ-dy-0gHvaw

如何用kaldi参加京东金融对话语音识别大赛

https://zhuanlan.zhihu.com/p/59686031

怎样从二进制数据分辨单声道与双声道音频

https://mp.weixin.qq.com/s/BDrJjrYsOJ2WP3niVG_aZA

语音识别系列之区分性训练和LF-MMI

SpeechBrain

SpeechBrain是一个基于pytorch的语音工具包,目前(2019.9)正在开发中。

它的目标是采用目前主流的DL框架,替代Kaldi。毕竟后者年头有些久远,扩展麻烦,使用也复杂,不符合目前的开发需求。

官网:

https://speechbrain.github.io/

Flume & Kafka+

https://mp.weixin.qq.com/s/UFfpPnouxXjOFAmZVdSTVg

Kafka核心源码剖析(一):Producer发送消息流程

https://mp.weixin.qq.com/s/exOs0zrZ2x8Mxi6aB1x-QQ

流数据并行处理性能比较:Kafka vs Pulsar vs Pravega

https://mp.weixin.qq.com/s/ijek6Tdb6H3hqY2CEC917Q

从面试角度来看一看Kafka

https://mp.weixin.qq.com/s/zmDTaW8c65BWZ-mhsED1jw

从演进式角度看消息队列

Fork me on GitHub