语音识别算法原理文档整理(十)

Kaldi单音素脚本

从脚本run.sh来看,单音素训练

#monophone

steps/train_mono.sh –boost-silence 1.25 –nj $n –cmd “$train_cmd”
data/mfcc/train data/lang exp/mono || exit 1;

#test monophone model

local/thchs-30_decode.sh –mono true –nj $n “steps/decode.sh” exp/mono
data/mfcc &

现在来看看train_mono.sh这个执行文件

# Begin configuration section.参数设定

nj=4 #并行工作数

cmd=run.pl #采用单机计算的模式

scale_opts=”–transition-scale=1.0 –acoustic-scale=0.1 –self-loop-scale=0.1”

num_iters=40 # 训练迭代次数

max_iter_inc=30 # Last iter to increase #Gauss on.

totgauss=1000 # Target
#Gaussians总高斯数(可能难理解,但可以这么解释:比如有3状态HMM,每个状态用4组均值方差描述(GMM混合数是4个意思),那总共用了12个高斯,kaldi里不用具体指定GMM个数,而指定整个系统中总共需要多少个单高斯)

careful=false

boost_silence=1.0 # Factor by which to boost silence likelihoods in alignment

realign_iters=”1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 23 26 29 32 35 38”;
#循环到这个数的时候做对齐

config= # name of config file.

stage=-4

power=0.25 # exponent to determine number of gaussians from occurrence counts

norm_vars=false # deprecated, prefer –cmvn-opts “–norm-vars=false”

cmvn_opts= # can be used to add extra options to cmvn. #Cepstral Mean and
Variance Normalization (CMVN) 倒谱均值和方差归一化

# End configuration section.

echo “$0 $\@” # Print the command line for logging

#- - name value 参数处理

if [ -f path.sh ]; then . ./path.sh; fi

. parse_options.sh || exit 1;

#- -name 以外的参数必须有3个,否则报错

if [ $# != 3 ]; then

echo “Usage: steps/train_mono.sh [options] \

Kaldi单音素函数

apply-cmvn

对feats.scp做归一化处理 ,输入3个文件:
–utt2spk=ark:sdata/JOB/utt2spk语料,录音人员关联文件scp:sdata/JOB/cmvn.scp
说话人相关的均值和方差 ,scp:$sdata/JOB/feats.scp 训练用特征文件 。

gmm-init-mono

参数:

–shared-phones=E:\project\kaldi\unbtu_ftp\gmm_init\sets.int
–train-feats=ark,s,cs:E:\project\kaldi\unbtu_ftp\gmm_init\hujianhua_raw_mfcc.ark
E:\project\kaldi\unbtu_ftp\gmm_init\topo 39
E:\project\kaldi\unbtu_ftp\gmm_init\1.mdl
E:\project\kaldi\unbtu_ftp\gmm_init\tree1

作用:是mm-init-mono 构造第一个模型文件和决策树,用少量的数据初始化对应的模型。

输入是mfcc特征,topo,输出mdl,tree文件。

topo放在目录s5/data/lang,根据topo初始化tree与mdl,feats.scp文件存放mfcc的数路径索引

sdata/JOB/utt2spk语料和录音人员关联文件

$sdata/JOB/text为每句话的解释。

faem0_sx222 sil y uw ao l w ix z cl k ax m ah cl p w ix th cl p ae th ax l aa
vcl jh ix cl k el ix vcl g z ae m cl p el s sil

$lang/words.txt 存音素编号,根据脚本生成\~/kaldi/egs/yesno/s5/utils/sym2int.pl
–map-oov $oov_sym -f 2- $lang/words.txt

hmm_state表示某个音素的状态,pdf表示所有音素的状态,其存储位置。

mdl文件

写topo_结构

triples_数据,表示每一个音素的的状态

音素,对应音素的状态,状态位置

kkkkkkkkkkkkkk

log_probs_ 31个值,表示所有的状态转移及其概率值。

am_gmm每个状态建立gmm,存储了mfcc特征值产生的变量,对应于每个状态,里面有每个高斯函数对应的参数,包括期望,方差等。

kkkkkkkkkkkkkk

tree文件

ContextDependency *ctx_dep中的内容写出。

ContextDependency 1 0 ToPdf SE 0 [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127 128 129 130 131 ]

{ SE 0 [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63 64 65 66 67 ]

{ SE 0 [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 ]

{ SE 0 [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ]

{ SE 0 [ 1 2 3 4 5 6 7 8 9 10 ]

{ SE 0 [ 1 2 3 4 5 ]

{ TE -1 5 ( CE 0 CE 1 CE 2 CE 3 CE 4 )

TE -1 5 ( CE 5 CE 6 CE 7 CE 8 CE 9 )

}

SE 0 [ 11 12 13 14 15 ]

{ TE -1 5 ( CE 10 CE 11 CE 12 CE 13 CE 14 )

TE -1 3 ( CE 15 CE 16 CE 17 )

}

}

SE 0 [ 20 21 22 23 24 25 26 27 ]

{ SE 0 [ 20 21 22 23 ]

{ TE -1 3 ( CE 18 CE 19 CE 20 )

TE -1 3 ( CE 21 CE 22 CE 23 )

}

有两种情况,一种是直接接叶子节点的:
phone=?
SIL SIL_B SIL_E SIL_I SIL_S (条件) NO(条件)
PdfClass=? PdfClass=?
0,1,2,3,4(条件) 0,1,2,3,4(条件)
s0 s1 s2 s3 s4 s5 s6 s7 s8 s9
对应的文件格式是:
SE 0 [ 1 2 3 4 5 ] #条件,如果phone=[SIL SIL_B SIL_E SIL_I SIL_S ]
{ TE -1 5 ( CE 0 CE 1 CE 2 CE 3 CE 4 ) #Yes
TE -1 5 ( CE 5 CE 6 CE 7 CE 8 CE 9 ) # No
}
其中SE表示条件吧,
TE表示叶子结点的条件吧, -1不知道啥意思,5表示该音素有5个状态(pdf-class)
CE表示叶子节点的值

SE 0 [ 28 29 30 31 ]

{ TE -1 3 ( CE 24 CE 25 CE 26 )

TE -1 3 ( CE 27 CE 28 CE 29 )

}

}

sets.int表示共享的音素

compile-train-graphs

参数:

–read-disambig-syms=E:\project\kaldi\unbtu_ftp\graphs\disambig.int
E:\project\kaldi\unbtu_ftp\graphs\tree
E:\project\kaldi\unbtu_ftp\graphs\1.mdl
E:\project\kaldi\unbtu_ftp\graphs\L.fst
ark:E:\project\kaldi\unbtu_ftp\graphs\train.tra
ark:E:\project\kaldi\unbtu_ftp\graphs\graphs.fsts

作用:在嵌入式训练里有说到为每个训练的句子建立一个完整的hmm结构。

输入 :决策树tree,模型1.mdl,lexsionFST, text转ID(train.tra)这些文件,输出
:构造训练用一句话对应的FST :graphs.fsts。

train.tra

transcript_reader “ark:sym2int.pl –map-oov $oov_sym -f 2- $lang/words.txt \<
$sdata/JOB/text|” \ 的作用是生成train.tra文件,其中内容:0_0_0_0_1_1_1_1 2 2
2 2 3 3 3 3 主要是把每句话用音素编号对应起来。2表示yes音素,3表示no

语音文件与音素对应

0_0_0_1_0_0_0_1 2 2 2 3 2 2 2 3

0_0_0_1_0_1_1_0 2 2 2 3 2 3 3 2

其中2 表示yes, 3表示no

$lang/words.txt表示音素编号:

\

L.fst 文件

L.fst是字典对于的fst表示,作用是将一串的音素(phones)转换成单词(words)

kkkkkkkkkkkkkk

cur_state arc.nextstate  arc.ilabel  arc.olabel

0 1 0 0

0 1 1 0

1 1 1 1

1 1 3 2

1 2 3 2

1 1 2 3

1 2 2 3

2 2 1 0

graphs.tra文件

通过 key(句子)
就能找到这个句子的fst网络,value中保存的是句子中每两个音素之间互联的边(Arc),例如句子转换成音素后,标注为:”a
b c d e f”,那么value中保存的其实是 a->b b->c c->d d->e e->f
这些连接(kaldi会为每种连接赋予一个唯一的id),后面进行 HMM
训练的时候是根据这些连接的id进行计数,就可以得到转移概率。

MakeLinearAcceptor(transcripts[i],
word_fst);主要是一句话的fst,是由每个音素组成状态组成。

根据8个单素2 2 2 2 3 3 3 3中每一个,例如2生成下面的结构。

kkkkkkkkkkkkkk

然后丢到下面的word_fst结果中,但是是丢到cur_state中。也即把一句话(8个音素)组成一个fst结构。ofst->AddArc(cur_state,
arc);

最后把共31句话放到word_fsts队列中。word_fsts[i] = word_fst;

例由8个状态(音素组成)2 2 2 2 3 3 3 3

然后加入单素状态以及ctx状态,同时记录了状态变化(音素是由状态组成)

TableCompose(*lex_fst_, *(word_fsts[i]), &phone2word_fst, \&lex_cache_);

ComposeContextFst(*cfst, phone2word_fst, \&ctx2word_fst);

每句话生成一个

Word_fst =
9 添加了状态0\~8,这样有9个状态,然后0-7放下面的值,把输入音素赋给ilabel,olabel

kkkkkkkkkkkkkk

在8状态ofst->SetFinal(cur_state, Weight::One());

生成的状态个数ctx2word_fst = 18

生成的状态个数trans2word_fst = 70 

对于state为0,有2,3,4, 26,然后跑到下状态,一共70个状态,每一个都有一个next_state

每一个state都可能有几个num_arcs,例如如下表:num_arcs = 4

size_t num_arcs = ifst.NumArcs(s)

0_0_0_0_1_1_1_1

0 70 2 0 0.693359

0 71 3 0 0.693359

0 72 4 0 0.693359

0 4 26 2 0.693359

执行完自循环后AddSelfLoops里面有一个函数MakePrecedingInputSymbolsSameClass增加了108个状态。

转移状态trans2word_fst = 178 这里面存在是TransitionId,在这里还可能转成state

Yesno包括31个文件,因此其大小为31

写出key:表示文件名

kkkkkkkkkkkkkk

得到是一句话的状态例如66个状态。这里还没有做对齐。

AddSelfLoops(trans_model_,

disambig,

opts_.self_loop_scale,

opts_.reorder,

\&trans2word_fst);

Yesno包括31个文件,每次写一个文件及对应的178个状态。每个状态都可能有几种选择,如下所示:

fst_writer.Write(keys[i], *(fsts[i]));

0_0_0_0_1_1_1_1

arc .s arc.nextstate arc.ilabel arc.olabel

0 70 2 0 0.693359

0 71 3 0 0.693359

0 72 4 0 0.693359

0 4 26 2 0.693359

S表示当前状态,nextstate表示跳转到下一状态。

这里的arc.ilabel表示转换id, arc.olabel表示音素。

align-equal-compiled

参数:

ark:E:\project\kaldi\unbtu_ftp\align-equal-compiled\graphs.fsts
ark:E:\project\kaldi\unbtu_ftp\align-equal-compiled\hujianhua_raw_mfcc.ark
ark,t:E:\project\kaldi\unbtu_ftp\align-equal-compiled\equal.ali

作用:主要是根据生成一句话的fst结构,然后根据结构与mfcc特征值做对齐。输入一句话的fst结构,输出对齐的fst结构。训练时需要将标注跟每一帧特征进行对齐。这里采用简单对齐操作。

std::string key = fst_reader.Key(); 从fst文件中获得被形文件名

kkkkkkkkkkkkkk

再根据key到mfcc 文件中hujianhua_raw_mfcc.ark读取mfcc特征,如下图

kkkkkkkkkkkkkk

因为在转移状态,有可能是循环或者转移到下一个状态两个种情况。对于静态转移可能更多转移情况。因此通过音素得到路径可能有不同的路径,那么这里随机出来一条路径。例:

原始的state = 0,然后得到当前的num_arcs =
4。然后随机一个值出来。例如arc_offset = 3

取得状态state = 0的arc_offset = 3的const Arc &arc = aiter.Value();

其对应arc.nextstate = 4,如下:

0 4 26 2 0.693359

path.push_back(arc.nextstate);

再一次再循环state = arc.nextstate,取4处的值,再随机一个值,arc_offset =
1,取得结果

4 5 28 0

直到结束。

if (arc.ilabel != 0) num_ilabels++; 这里的arc.ilabel表示转换id,
arc.olabel表示音素。这里

根据fst状态网络求得num_ilabels标签数为66,实际mfcc帧数为633帧

计算出num_self_loops也为66

需要的自循环个数num_extra= 633-66=567

min_num_loops = num_extra / num_self_loops=(633-66)/66 = 8

那么如果遇到是loops状态时,那么会插入8个状态,最终把66个状态扩展到633个状态。

生成文件equal.ali例:

0_0_0_0_1_1_1_1 26 25 25 25 25 25 25 25 25 25 28 27 27 27 27 27 27 27 27 27 30
29 29 29 29 29 29 29 29 29 3……

26表示转移状态,这里一共有31个转移状态。连续的25表示在当前状态进行自循环。

26通过pdf_id = trans_model.TransitionIdToPdf(tid); 可以查询pdf_id=8

gmm-align-compiled

参数:

E:\project\kaldi\unbtu_ftp\gmm-align-compiled\1.mdl
ark:E:\project\kaldi\unbtu_ftp\gmm-align-compiled\graphs.fsts
ark:E:\project\kaldi\unbtu_ftp\gmm-align-compiled\hujianhua_raw_mfcc.ark
ark,t:E:\project\kaldi\unbtu_ftp\gmm-align-compiled\equal.ali

作用:通过viterbit算法进行对齐。通过当前的模型的计算出最好的一条路径(每帧计算一次)。这样就得到当前的所有帧的一条对齐的路径。

gmm-acc-stats-ali

参数:

–binary=true E:\project\kaldi\unbtu_ftp\gmm-acc-stats-ali\1.mdl
ark:E:\project\kaldi\unbtu_ftp\gmm-acc-stats-ali\hujianhua_raw_mfcc.ark
ark:E:\project\kaldi\unbtu_ftp\gmm-acc-stats-ali\equal.ali
E:\project\kaldi\unbtu_ftp\gmm-acc-stats-ali\1.acc

作用:对对齐后的数据进行训练,获得中间统计量,每个任务输出到一个acc文件。

输入是当前的模型,特征值,对齐特征值的状态数据,输出HMM 和GMM 训练相关的统计量。

acc中记录输出文件由两部分组成:HMM 和GMM 训练相关的统计量:

HMM 相关的统计量:根据对齐的网络(equal.ali)进行统计输出,

transition_accs
对于转移概率的统计,每出现对应的转移状态trans_id加1,最终写31个转移概率的数目。

GMM 相关的统计量:每个pdf-id 对应的特征累计值和特征平方累计值。

对于每一帧,都会有个对齐后的标注,可以得到对应的pdf-id。

每个pdf-id
对应的GMM可能由多个单高斯Component组成,会先计算在每个单高斯Component对应的分布下这一帧特征的似然概率(log-likes),称为posterior。

对于gmm的mfcc统计是通过当前mfcc数据data(39
维),去对应的gmm查询得到log_like相似度。如果高斯函有两个AB,分别计算AB,那么出来的log_like是二维的。所有参数输入也是二维的。

kkkkkkkkkkkkkk

由tid得到pdf-id,也就是找到对应该pdf-id的DiagGmm对象,更新与该DiagGmm对象相关的AccumDiagGmm的参数,也就是计算得到三个GMM参数更新公式的分子部分(包括每一混合分量的后验(occupancy_中保存∑njγ\^jk)、每一分量的后验乘以当前帧的特征(mean_accumulator_中保存∑njγ\^jkyj
MxD维)、每一分量的后验乘以
当前帧的特征每一维的平方(variance_accumulator_中保存∑njγ\^jky2j MxD MxD维))

kkkkkkkkkkkkkk

然后:

(1)把每个单高斯Component的posterior加到每个高斯Component的occupancy(占有率)计数器上,用于表征特征对于高斯的贡献度,如果特征一直落在某个高斯的分布区间内,那对应的这个值就比较大;相反,如果一直落在区间外,则表示该高斯作用不大。

gmm-est中可以设置一个阈值,如果某个高斯的这个值低于阈值,则不更新其对应的高斯。

另外这个值(向量)其实跟后面GMM更新时候的高斯权重weight的计算相关。

(2)把这一帧数据乘以每个单高斯Component的posterior再加到每个高斯的均值累计值上;这个值(向量)跟后面GMM的均值更新相关。

(3)把这一帧数据的平方值乘以posterior再加到每个单高斯Component的平方累计值上;

这个值(向量)跟后面GMM的方差更新相关。

最后将均值累计值和平方累计值写入到文件中。输出11个状态(高斯函数)的对应的均值与方差。

kkkkkkkkkkkkkk

DiagGmm

保存一个GMM的参数,包括分量权值weights_、均值、方差、每一分量高斯分布里的常量部分取log后的数值gconsts_。注意均值和方差为了方便计算,保存的并不是原原本本的均值、方差,而是方差每一元素求倒数后的inv_vars_、均值乘以inv_vars_后的means_invvars_。

gmm-sum-accs

这个用来合并acc文件。

gmm-est

gmm-est –min-gaussian-occupancy=3 –mix-up=$numgauss –power=$power \

$dir/0.mdl “gmm-sum-accs - $dir/0.*.acc|” $dir/1.mdl 2>
$dir/log/update.0.log || exit 1;

作用:根据前面计算的数据,得到新的gmm与hmm参数。

参数:

E:\project\kaldi\unbtu_ftp\gmm_est\1.mdl
E:\project\kaldi\unbtu_ftp\gmm_est\1.acc
E:\project\kaldi\unbtu_ftp\gmm_est\2.mdl

kkkkkkkkkkkkkk

means_ 对应acc里的mean_accumulator/occ
其中occ表示帧数 这里2286,这里表示均值。

vars_ 对应acc里的variance_accumulator/occ - means_的平方即方差

一共有11个pdf状态。那每一个状态都有转移状态,转移状态有31个。

对应一个pdf转移状态每个的新的概率new_probs(tidx) = transition_accs (tidx) /
tstate_tot; 转移状态的统计数/当前状态转移到所有可能状态总数。来自于accs

gmm-latgen-faster

解码

steps/decode.sh –nj 1 –cmd “$decode_cmd” \

exp/mono0a/graph_tgpr data/test_yesno exp/mono0a/decode_test_yesno

参数:

–max-active=7000 –beam=13.0 –lattice-beam=6.0 –acoustic-scale=0.083333
–allow-partial=true
–word-symbol-table=E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\words.txt
E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\final.mdl
E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\HCLG.fst
ark,s,cs:E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\feat-cmvn_delta.ark
ark:lat.ark ark:w.ark ark:a.ark

–max-active=7000 –beam=13.0 –lattice-beam=6.0 –acoustic-scale=0.083333
–allow-partial=true
–word-symbol-table=E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\liming\words.txt
E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\liming\final.mdl
E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\liming\HCLG.fst
ark,s,cs:E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\liming\feat-cmvn_delta.ark
ark:E:\project\kaldi\unbtu_ftp\gmm-latgen-faster\liming\latgen.ark

输入:目录graph下面的words.txt标签,final.mdl模型,HCLG.fst,以及特征值。

输出结果:latgen.ark

final.mdl模型包括以下:

trans_model

kkkkkkkkkkkkkk

HCLG.fst

根据HCLG.fst 生成LatticeFasterDecoder解码器。

构图过程 G -> L -> C -> H

1.G: 作为 acceptor (输入 symbol 与输出相同),用于对grammar 或者 language
model 进行编码

  1. L:Lexicon, 其输出 symbol 是 words, 输入 symbol 是 phones

3.C:context-dependency 其输出 symbol 是 phones, 其输入 symbol
为表示context-dependency phones

如: vector\

三音素训练

steps/decode.sh

决策树

为什么需要决策树

我们进行语音识别模型训练的过程中,首先进行的是单音素、单个高斯的模型训练。抛开单个高斯不说,单音素模型本身有很大缺点:没有考虑到本音素前后音素的发音对本音素的影响。比如,同样是一个音素iy,如果它前面的音素分别是h和p,那么iy这个音素在这两种情况下的发音会有所不同,那么模型参数也就会受到其影响,此时,如果用同一个模型来描述音素iy,那么就会不合理。

为了解决这个问题,采用三音素(triphones)模型,典型的三音素模型如下
[t-iy+n],这表示iy音素前一个音素是t,后一个因素是n,模型[t-iy+n]
用来表示这种情况下的音素iy模型,那么此时,这个三音素模型和 [t-iy+ng]
不再表示同一个模型了,虽然他们都是表示音素
iy的模型,但是因为中心音素(此处为iy)的上下文音素不同了,所以此时它们其实是两个不同的模型。

如此以来,模型的数量会剧增。单因素模型时,假如我们只有40个音素需要建模,每个音素有3个HMM状态。但是在三因素模型中,最坏的情况是需要给40×40×40
个模型进行建模,当然这其中有很多是不可能或者不会在训练数据中出现的。但是相对于单音素模型来说,这个数目已经增加了很多倍,这就导致了一个问题:训练数据不足!那么如何解决因为模型数量增加而导致训练数据不足的问题呢?HTK使用了模型状态绑定的方法。所谓的模型状态绑定,就是让一些具有某些相似特征的模型的一些状态来共享一组模型参数,这样就能够有效的减少模型参数的数量从而解决训练数据不足的问题。

如何使用决策树进行模型的状态绑定

在进行状态绑定时,我们首先要做的就是使用决策树进行聚类。具有相同类别的模型,他们的某一个状态可以共享一组参数。例如:对于音素iy,如果它的前一个音素分别是m和n,由于m和n发音比较像,所以模型[m-iy+*]和[n-iy+*]的第一个状态的参数就应该比较相似,那么我们就把这两个模型的第一个状态的参数进行绑定,也就是说这两个模型的第一个状态参数是相同的。那么到底如何确定那些模型的哪些状态可以共用一组参数也就是可以进行绑定参数?这就用到了决策树进行聚类,具有相同类别的状态就可以共用一组参数。

在这里,一定要注意,我们在建立决策树时,是对每个音素的每个状态都建立一个决策树,而不是只对某一个音素来建立。这里,我们以音素ih的首状态为例,详细说明决策树的建立过程。

kkkkkkkkkkkkkk

在上图中的每一个类中,A、B……E,每一个类中的第一个状态都被绑定在一起,如此进行,把所有的音素的所有状态都进行决策树的建立,就能完成参数的绑定。

决策树中的问题集
在上图中,我们看到一些问题集,类似与“左边是清音吗?”等等,这些问题集都是根据声学和语音学特征提出来的

特征使用LDA和MLLT进行变换

steps/decode.sh

说话人自适应训练(sat)

steps/decode_fmllr.sh

语音识别深度学习

1.标注对齐:训练CNN模型需要对每一帧进行标注,由于数据中仅对某段时间内的数据内容进行标注,因此我们需要用一个前面已经通过run.sh训练过的HMM-GMM模型进行数据对齐。DNN使用gmm-hmm的结果,对DNN的影响很大。一个坏gmm-hmm会给你坏的对齐。使用差的gmm-hmm的结果,会严重影响你的训练效果。
2.
数据准备:从网络上看到的是由7帧(从中间帧到左右帧都是3帧)组成的一个帧窗。由于神经网络很难从相关输入的数据中学习,因此以
40*7 维特征作为一个不相关的固定变换形式,通过 step/nnet2/get_lda.sh
完成该工作,实际中并非使用准确的 LDA,而是用 non-dimension-reducing 形式的
LDA,然后减少输出特征方差的维度。

3.
CNN模型训练:应用kaldi提供的核心训练代码,向训练脚本中传递相关的训练参数:网络的结构,learning
rate,运行环境,任务数等。下文将会展开脚本对各个参数进行解析。

  1. CNN模型测试:对训练所得的模型进行测试,与HMM-GMM模型,DNN模型进行比较。

kkkkkkkkkkkkkk

猜你喜欢

转载自blog.csdn.net/bvngh3247/article/details/81026856