Kaldi学习之数据准备详细解释说明

语音识别工具kaldi简介 阅读详情
AI摘要

本文详细介绍了Kaldi语音识别系统中数据准备流程及语言模型构建方法,涵盖数据文件组织、特征提取、语言模型训练等方面,是理解Kaldi工作原理的重要资料。

文章对Kaldi数据准备做更详细的解释,如有错误,还请指正。
数据基本源自Kaldi官网:http://www.kaldi-asr.org/doc/data_prep.html

数据准备详细介绍
在run.sh中有数据准备各个阶段的脚本。
例子中的local/文件夹下是数据准备专用的一些东西。
比如RM下的脚本run.sh部分内容:

local/rm_data_prep.sh /export/corpora5/LDC/LDC93S3A/rm_comp || exit 1;

utils/prepare_lang.sh data/local/dict '!SIL' data/local/lang data/lang || exit 1;

local/rm_prepare_grammar.sh || exit 1;

又比如WSJ下的脚本run.sh的部分内容:

wsj0=/export/corpora5/LDC/LDC93S6B
wsj1=/export/corpora5/LDC/LDC94S13B

local/wsj_data_prep.sh $wsj0/??-{?,??}.? $wsj1/??-{?,??}.?  || exit 1;

local/wsj_prepare_dict.sh || exit 1;

utils/prepare_lang.sh data/local/dict "<SPOKEN_NOISE>" data/local/lang_tmp data/lang || exit 1;

local/wsj_format_data.sh || exit 1;

WSJ涉及到准备本地语言模型脚本的脚本之后还有更多的命令,但是之前三条是更加重要的命令。
数据准备阶段的输出包括了两样东西集合。一个是“数据”(像/data/train这种目录),一个是“语言”(像/data/lang目录)。数据部分就是相关的语音数据,语言部分包含更多的是语言本身,比如字典,音素集合和一些其他的信息比如Kaldi需要的音素集。如果想准备数据,用当前系统现有的解码器和现存的语言模型,那么只需要接触“数据”部分。

数据准备之“数据”部分
看一个Switchboard的train部分例子(train和test本质上结构是一样的,只是用途不一样)。
例子目录egs/swbd/s5。里面拥有的文件如下:

s5# ls data/train
cmvn.scp  feats.scp  reco2file_and_channel  segments  spk2utt  text  utt2spk  wav.scp

不是所有的文件都是同等重要。简单数据集是没有分割的信息的。自己必须创建的文件是
Utt2spk text wav.scp ,有时候需要创建 segments 和 reco2file_and_channel ,剩下的可由标准脚本创建。

需要自己创建的文件
text 文件样例:

s5# head -3 data/train/text
sw02001-A_000098-001156 HI UM YEAH I'D LIKE TO TALK ABOUT HOW YOU DRESS FOR WORK AND
sw02001-A_001980-002131 UM-HUM
sw02001-A_002736-002893 AND IS

格式:


语音-id 标注

语音-id可以是任意字符串,如果有说话人信息,则说话人-id是语音-id的前缀。无需保证文件内的所有词都在词汇表中,词的输出会映射到专门的一个词文件中,data/lang/oov.txt。

要注意utt2spk和spk2utt这两个文件的排序顺序的一致性。比如,从utt2spk(语音-id所对应的说话人-id)文件提取的说话人-id列表和字符串的排序顺序一样。最简单的做法就是说话人-id作为语音-id的前缀,一般用”-“分隔。如果说话人-id长度不一致,在某些情况下,用标准的C字符串排序时,说话人-id和其对应的语音-id可能以不同的顺序进行排序/分类,这可能导致崩溃的情况。

另外一个重要文件就是 wav.scp
swbd例子:

s5# head -3 data/train/wav.scp
sw02001-A /home/dpovey/kaldi-trunk/tools/sph2pipe_v2.5/sph2pipe -f wav -p -c 1 /export/corpora3/LDC/LDC97S62/swb1/sw02001.sph |
sw02001-B /home/dpovey/kaldi-trunk/tools/sph2pipe_v2.5/sph2pipe -f wav -p -c 2 /export/corpora3/LDC/LDC97S62/swb1/sw02001.sph |

文件格式是:

<recording-id> <extended-filename>

extended-filename 可能是确切的文件名,或者是提取wav格式文件的命令。extended-filename 最后的管道符号意味着它将被解读成管道。如果分割文件不存在,那么wav.scp每行的第一个字符就是语音-id。wav.scp必须是单声道的,如果底层语音文件有多个声道,就必须有一个短命令在wav.scp中要用到来提取一个特殊的通道。

比如在swbd中有“segments”文件,如下:

s5# head -3 data/train/segments
sw02001-A_000098-001156 sw02001-A 0.98 11.56
sw02001-A_001980-002131 sw02001-A 19.8 21.31
sw02001-A_002736-002893 sw02001-A 27.36 28.93

格式是:

<utterance-id> <recording-id> <segment-begin> <segment-end>

即 语音-id 记录-id 分割开始时间 分割结束时间
分割的开始和结束单位是 秒。
记录-id是wav.scp中使用的相同的标识,也是可以自己选择的任意的标识。文件”reco2file_and_channel”只在打分(测量错误率)的时候用到,用NIST的”sclite”工具。

s5# head -3 data/train/reco2file_and_channel
sw02001-A sw02001 A
sw02001-B sw02001 B
sw02005-A sw02005 A

格式为

<recording-id> <filename> <recording-side (A or B)>

filename是.sph文件的名字,没有后缀,但是一般来说它是stm文件中的任何标识符。recording-side是一个电话对话中两个声道的概念,如果不是的话,用A更安全。如果没有stm文件或者不知道干啥的,record2file_and_channel文件就没必要创建。

最后一个需要自己创建的文件是”utt2spk”文件。

s5# head -3 data/train/utt2spk
sw02001-A_000098-001156 2001-A
sw02001-A_001980-002131 2001-A
sw02001-A_002736-002893 2001-A

格式:

<utterance-id> <speaker-id>

说话人-id不需要精确地对应每一个说话人,有个大概的猜测就好。可能会出现这样的情况:打电话的一方说了几句话之后可能会拿电话给另外一个人。如果没有说话人标识的相关信息,可以使说话人-id和语音-id相同。因为有人创建了”global”说话人-id(所有语音只对应一个说话人)。这样不好的原因:它使得cmn在训练的时候无效(因为被全局应用,一般CMN都是在句子内或者说一条语音内减去特征的均值),而且在使用utils/split_data_dir.sh分割数据的时候会引起问题。

在一些数据集中还存在其它的文件,偶尔出现。比如性别相关的:

s5# head -3 ../../rm/s5/data/train/spk2gender
adg0 f
ahh0 m
ajp0 m

所有的文件都要排序。未排序会有错误。排序的最终原因就是使一些不支持fseek()函数的数据流也能够达到随机访问的效果。许多Kaldi程序从其它Kaldi命令中读取很多管道,读不同类型的对象,并且和合并排序的不同的输入做一些大致的比较。

export LC_ALL=C

如果做了这个命令,就和C++排序不一样,Kaldi会崩溃。

如果数据有NIST来的测试集组成,有”stm”和”glm”文件,使用local/score.sh脚本文件可以测试WER。swbd集有用到这样的打分文件,比如
egs/swbd/s5/local/score_sclite.sh就被egs/swbd/s5/local/score.sh调用。

无需自己创建的文件
除了上述的其它文件都可由kaldi提供的命令生成。

比如utt2spk转换成spk2utt

utils/utt2spk_to_spk2utt.pl data/train/utt2spk > data/train/spk2utt

因为utt2spk和spk2utt具有相同的信息
utt2spk 格式 :

<utterance-id><speaker-id>

spk2utt 格式 :

<spaker-id><utterance-id>…

看feats.scp文件格式

s5# head -3 data/train/feats.scp
sw02001-A_000098-001156 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:24
sw02001-A_001980-002131 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:54975
sw02001-A_002736-002893 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:62762

这个文件指向提取的特征——swbd例子中是MFCC特征,因为用了make_mfcc.sh脚本。

feats.scp格式如下:

<utterance-id> <extended-filename-of-features>

在Kaldi中每个特征文件都包含一个矩阵。swbd例中矩阵的维度将会是13维(文件以10s作为间隔的长度)。
扩展文件名/home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:24 意思是,打开ark文件,通过fseek()文件找到第24个位置,从这开始读数据。

feat.scp通过以下命令创建:

steps/make_mfcc.sh --nj 20 --cmd "$train_cmd" data/train exp/make_mfcc/train $mfccdir

这个脚本被顶层的run.sh脚本调用。Shell变量的定义可查看脚本说明。$mfccdir是用户指定的目录,.ark文件会写入到这个目录中。

dnn/train目录的最后一个文件是”cmvn.scp”文件。这个文件包含倒谱均值和方差规整的数据,通过说话人-id进行索引。每组统计量都是一个矩阵,swbd例中是维数2*14?
swbd例中,看cmvn.scp中部分内容:

s5# head -3 data/train/cmvn.scp
2001-A /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/cmvn_train.ark:7
2001-B /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/cmvn_train.ark:253
2005-A /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/cmvn_train.ark:499

和feats.scp不同的是,这个文件是通过说话人-id进行索引的,本文件通过以下命令创建:

steps/compute_cmvn_stats.sh data/train exp/make_mfcc/train $mfccdir

本例来源:egs/swbd/s5/run.sh

为了防止数据准备(不符合条件)引发后续的问题,有工具检查脚本是否符合格式规范:

utils/validate_data_dir.sh data/train

尤其是以下命令,可以修正排序错误,还会移除一些所需数据(比如特征数据或者脚本)丢失时候的语音。

utils/fix_data_dir.sh data/train

语言模型准备部分
首先需要准备dict字典,包括
lexicon.txt:包括语料中涉及的词汇与发音,与单字及其发音
lexicon_nosil.txt:同上,去掉静音部分
phones.txt:音素发音标识

然后需要使用srilm的ngram-count命令生成词汇的arpa格式文件

ngram-count -order 1 -text words.txt -lm word.arpa

ngram-count部分参数解释如下:
-order 指定n-gram的n是多少(n代表n元语言模型),默认是3
-text 提供输入的语料文件,统计该语料中的n-gram
-lm 指定输出的lm文件
-vocab 用来指定对哪些词进行n-gram统计
-wbdiscount1 表示1gram Witten-Bell discounting
注意:参数顺序无所谓

arpa文件的使用:
使用arpa2fst命令进行转换,转换成符合FST规范的文件。;
如若不然,prepare_lang.sh会使用一些自带的fst开头的程序生成.fst文件。

语言模型准备部分详述
转到”lang”目录,看目录下面的文件

s5# ls data/lang
L.fst  L_disambig.fst  oov.int  oov.txt  phones  phones.txt  topo  words.txt

还有很多相似的格式,比如在data/lang_test就包含了相同的内容,还多了一个G.fst(Grammer)语言模型的有限状态转换器格式。

s5# ls data/lang_test
G.fst  L.fst  L_disambig.fst  oov.int  oov.txt  phones  phones.txt  topo  words.txt

lang_test是通过复制lang/下面的内容,并且增加G.fst生成的。这些目录包含几个文件之外还包含几个文件夹。比如phones就是一个文件夹:

s5# ls data/lang/phones
context_indep.csl  disambig.txt         nonsilence.txt        roots.txt    silence.txt
context_indep.int  extra_questions.int  optional_silence.csl  sets.int     word_boundary.int
context_indep.txt  extra_questions.txt  optional_silence.int  sets.txt     word_boundary.txt
disambig.csl       nonsilence.csl       optional_silence.txt  silence.csl

音素目录包含很多音素集合的不同信息;有三个不同文件版本,扩展名包括.csl,.int和.txt,三种格式包含了相同信息,不需要全部创建它。因为通过一个简单的输入,脚本utils/prepare_lang.sh就会输出这些文件。接下来解释lang目录。不想了解Kaldi到底怎么工作的原理可以直接跳到Creating the “lang” directory部分


lang目录的内容
首先是phones.txt和words.txt的内容,这两个都是字符表文件,用OpenFst格式,每行都是文本形式 int形式组合。

s5# head -3 data/lang/phones.txt
<eps> 0
SIL 1
SIL_B 2
s5# head -3 data/lang/words.txt
<eps> 0
!SIL 1
-'S 2

这些文件被Kaldi用来在这些符号的整数和文本形式之间来回映射。 它们大多只能通过脚本utils / int2sym.pl和utils / sym2int.pl以及OpenFst程序fstcompile和fstprint访问。

文件L.fst是字典的有限状态转换器形式(L,参见Mohri,Pereira和Riley的论文:
“Speech Recognition with Weighted Finite-State Transducers” ,
Springer Handbook on SpeechProcessing and Speech Communication,2008)。 输入是音素符号和输出是字词符号。 文件L_disambig.fst是词典,但是和上面说的词典比多了消歧符号#1,#2等,以及带有#0的自循环,以从语法中“消除”歧义符号。 参阅Disambiguation symbols获得消歧符号更多的解释。这个文件不需要自己处理。

文件data/lang/oov.txt只包含一行内容

s5# cat data/lang/oov.txt
<UNK>

在训练的时候会映射所有词汇中的词到这个词中。<UNK>在这里没有什么特别,它不是这个文件的特定词;重要的是这个词要有一个发音,这个发音只包含一个我们指定为“垃圾音素”的音素;这个音素将与各种说话的噪音对齐。 在Kaldi设置中,这个音素被称为“SPN”(“spoken noise”)),比如在lexicon.txt文件中:

s5# grep -w UNK data/local/dict/lexicon.txt
<UNK> SPN

文件oov.int包括上述内容的int形式(从words.txt中提取),在此设置中恰好为221。 可能会注意到,在资源管理设置中,oov.txt包含静音词,该设置恰好称为“!SIL”。 在这种情况下(SIL),Kaldi只是从词汇表中选择一个任意的单词——训练集中没有这样的词,所以Kaldi选择什么词都没有影响。

文件data/lang/topo中包含以下数据:

s5# cat data/lang/topo
<Topology>
<TopologyEntry>
<ForPhones>
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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
</ForPhones>
<State> 0 <PdfClass> 0 <Transition> 0 0.75 <Transition> 1 0.25 </State>
<State> 1 <PdfClass> 1 <Transition> 1 0.75 <Transition> 2 0.25 </State>
<State> 2 <PdfClass> 2 <Transition> 2 0.75 <Transition> 3 0.25 </State>
<State> 3 </State>
</TopologyEntry>
<TopologyEntry>
<ForPhones>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
</ForPhones>
<State> 0 <PdfClass> 0 <Transition> 0 0.25 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 </State>
<State> 1 <PdfClass> 1 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 <Transition> 4 0.25 </State>
<State> 2 <PdfClass> 2 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 <Transition> 4 0.25 </State>
<State> 3 <PdfClass> 3 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 <Transition> 4 0.25 </State>
<State> 4 <PdfClass> 4 <Transition> 4 0.75 <Transition> 5 0.25 </State>
<State> 5 </State>
</TopologyEntry>
</Topology>

这是Kaldi使用的HMM拓扑。在这种情况下,“真实”音素包含三种标准的从左到右3状态的拓扑结构的发射状态——叫“Bakis模型” (发射状态是“发射”特征向量的状态,与仅用于将其他状态连接在一起的“假的”非发射状态不同)。 音素1到20是各种静音和噪音; 有很多静音和噪音是因为字位依赖,事实上大多数的静音和噪声永远都用不上; 不包括字位依赖的状态数是5个左右。 “静音音素”具有更复杂的拓扑结构,具有初始发射状态和结束发射状态,但在中间是三个发射状态。 不需要手动创建此文件。

data/lang/phones文件夹中有几个存放关于音素集的不同信息的文件。这些文件大多数都有三个不同的版本,分别是.txt .int 和 .csl版本,内容分别如下
.txt

s5# head -3 data/lang/phones/context_indep.txt
SIL
SIL_B
SIL_E

.int

s5# head -3 data/lang/phones/context_indep.int
1
2
3

.csl,是一个冒号分隔的列表

s5# cat data/lang/phones/context_indep.csl
1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20

这些文件总是包含相同的信息,所以集中看可读性最强的.txt格式内容。文件”context_indep.txt”包含我们要建立上下文模型的音素列表:对于这些音素,不需要建立一个决策树来提出音素左右上下文的问题。实际上,关于中心音素和HMM状态的问题Kaldi建立了一个小得多的树来实现它;这取决于下面要说的root.txt文件。关于树的问题,想要更深入了解的可以查看 How decision trees are used in Kaldi 。

context_indep.txt包含了非“真实音素”的所有音素,比如静音(SIL),说话人噪声(SPN),非说话人噪声(NSN),和笑声(LAU):

# cat data/lang/phones/context_indep.txt
SIL
SIL_B
SIL_E
SIL_I
SIL_S
SPN
SPN_B
SPN_E
SPN_I
SPN_S
NSN
NSN_B
NSN_E
NSN_I
NSN_S
LAU
LAU_B
LAU_E
LAU_I
LAU_S

由于字位依赖(字所在的位置有多种组合),这些音素有很多变体;不是所有的这些变种都不会被使用。在这里,SIL被选择性地插入字典(不是单词的一部分),SIL_B是一个单词开头的静音音素(不应该存在),SIL_I字内的静音(不太可能存在) ),SIL_E是结尾的静音(永远不会存在),SIL_S将作为一个“单个”的静音,即只有一个字的音素—— 如果词典中有“静音词”,则可能会在转录文件中出现明显的静音。

文件silence.txt和nonsilence.txt分别包含静音/噪声音素和非静音/噪声音素的列表。这些应该互斥,应该包含所有的音素。在这个特定的设置中,silence.txt与context_indep.txt相同。 “nonsilence”音素的意思是,Kaldi打算预测这些音素上的各种线性变换:即LDA和MLLT等全局变换,以及诸如fMLLR之类的说话人自适应变换。Kaldi基于以往经验的信念是,在预测这种变换中不包括任何silence音素。Kaldi的做法是将所有静音,噪音和发声的噪声音素指定为“silence”音素,所有代表传统音素的音素都是“nonsilence”音素。

s5# head -3 data/lang/phones/silence.txt
SIL
SIL_B
SIL_E
s5# head -3 data/lang/phones/nonsilence.txt
IY_B
IY_E
IY_I

文件disambig.txt包括“消歧符号”(看Disambiguation symbols)

s5# head -3 data/lang/phones/disambig.txt
#0
#1
#2

如果这些符号是音素,它们会在phones.txt出现

文件optional_silence.txt 包括能够有选择性地在词之间出现的单音素

s5# cat data/lang/phones/optional_silence.txt
SIL

在词之间可以选择性出现的机制是,在字典的FST中,它可以任意地在每个单词结尾(语音的开始)中出现。必须在phones/指定,而不是仅出现在L.fst中的原因Kaldi也未说明,不在这里细说。

文件sets.txt包括组合的音素集合(考虑是相同的音素),同时对音素进行聚类来创造上下文相关性问题(Kaldi中在构造决策树时使用自动生成的问题,而不是语言的有意义的问题)。这种设定下,sets.txt对每个音素的所有字位依赖版本做组合:

s5# head -3 data/lang/phones/sets.txt
SIL SIL_B SIL_E SIL_I SIL_S
SPN SPN_B SPN_E SPN_I SPN_S
NSN NSN_B NSN_E NSN_I NSN_S

文件extra_questions.txt包括一些Kaldi需要包括的其它(除了自动生成问题之外)的问题

s5# cat data/lang/phones/extra_questions.txt
IY_B B_B D_B F_B G_B K_B SH_B L_B M_B N_B OW_B AA_B TH_B P_B OY_B R_B UH_B AE_B S_B T_B AH_B V_B W_B Y_B Z_B CH_B AO_B DH_B UW_B ZH_B EH_B AW_B AX_B EL_B AY_B EN_B HH_B ER_B IH_B JH_B EY_B NG_B
IY_E B_E D_E F_E G_E K_E SH_E L_E M_E N_E OW_E AA_E TH_E P_E OY_E R_E UH_E AE_E S_E T_E AH_E V_E W_E Y_E Z_E CH_E AO_E DH_E UW_E ZH_E EH_E AW_E AX_E EL_E AY_E EN_E HH_E ER_E IH_E JH_E EY_E NG_E
IY_I B_I D_I F_I G_I K_I SH_I L_I M_I N_I OW_I AA_I TH_I P_I OY_I R_I UH_I AE_I S_I T_I AH_I V_I W_I Y_I Z_I CH_I AO_I DH_I UW_I ZH_I EH_I AW_I AX_I EL_I AY_I EN_I HH_I ER_I IH_I JH_I EY_I NG_I
IY_S B_S D_S F_S G_S K_S SH_S L_S M_S N_S OW_S AA_S TH_S P_S OY_S R_S UH_S AE_S S_S T_S AH_S V_S W_S Y_S Z_S CH_S AO_S DH_S UW_S ZH_S EH_S AW_S AX_S EL_S AY_S EN_S HH_S ER_S IH_S JH_S EY_S NG_S
SIL SPN NSN LAU
SIL_B SPN_B NSN_B LAU_B
SIL_E SPN_E NSN_E LAU_E
SIL_I SPN_I NSN_I LAU_I
SIL_S SPN_S NSN_S LAU_S

可以看到这个问题就是一个简单的音素集合。前四个问题是询问常规音素的字位; 最后五个对于“静音”操作是一样的。 “静音”音素也会出现一个不带_B字样的后缀,例如SIL。 这些可能在词典中表现为可选的静音,比如,不在实际的单词内。 在使用诸如音调依赖或重音标记的设置中,extra_questions.txt可能包含与这些功能相关的问题。

文件word_boundary.txt解释了音素如何和字位进行关联:

s5# head  data/lang/phones/word_boundary.txt
SIL nonword
SIL_B begin
SIL_E end
SIL_I internal
SIL_S singleton
SPN nonword
SPN_B begin

这是与音素后缀相同的信息(_B等等),但是我们不喜欢在音素的文本形式中对这个进行硬编码,首先,Kaldi的可执行文件永远都不会看到音素的文本形式,只能看到整数形式。 所由文件word_boundary.txt指定。 需要这个信息的主要原因是为了恢复词图内的单词边界(例如,程序lattice-align-words读取此文件的整数形式,word_boundaray.int)。 寻找单词边界非常有用,原因包括NIST sclite评分,这需要时间标记的单词和其他下游处理。

文件roots.txt包括关于如何建立音素上下文决策树的信息:

head data/lang/phones/roots.txt
shared split SIL SIL_B SIL_E SIL_I SIL_S
shared split SPN SPN_B SPN_E SPN_I SPN_S
shared split NSN NSN_B NSN_E NSN_I NSN_S
shared split LAU LAU_B LAU_E LAU_I LAU_S
...
shared split B_B B_E B_I B_S

现在可以忽略关键字”shared” and “split”——这些跟如何建立决策树的选项相关(更多信息看How decision trees are used in Kaldi )。每行有几个音素的意义,比如SIL SIL_B SIL_E SIL_I SIL_S,是因为这些音素在决策树中都有相同的“共享根节点”,所以这些音素的状态可能也是共享的。对于重音和音调相关系统,通常重音或音调相关的所有版本都会出现在同一行。另外,HMM的所有3个状态(对于静音来说是5个)都共享根,决策树的构造过程中可以询问状态。HMM状态之间决策树的根共享就是在roots文件中”shared”的意思。

创建 lang 文件夹
data/lang/ 目录包含一些不同的文件,所以提供了脚本来创建这些文件,可以用来从一些简单的输入入手:

utils/prepare_lang.sh data/local/dict "<UNK>" data/local/lang data/lang

输入是目录 data/local/dict/,标签 <UNK> 是字典里的单词,映射OOV单词到出现在副本中的单词中(data/lang/oov.txt)。目录data/local/lang/是脚本会用到的临时目录;data/lang/是输出目录。

作为数据准备者需要创建的是目录data/local/dict/。此目录包含以下内容:

s5# ls data/local/dict
extra_questions.txt  lexicon.txt nonsilence_phones.txt  optional_silence.txt  silence_phones.txt

(实际上还有几个没有列出来的文件,但是它们只是创建目录放进去的临时文件,可以忽略它们)。下面的命令对这些文件内容有些了解:

s5# head -3 data/local/dict/nonsilence_phones.txt
IY
B
D
s5# cat data/local/dict/silence_phones.txt
SIL
SPN
NSN
LAU
s5# cat data/local/dict/extra_questions.txt
s5# head -5 data/local/dict/lexicon.txt
!SIL SIL
-'S S
-'S Z
-'T K UH D EN T
-1K W AH N K EY

可以看到,目录的内容在这个例子(Switchboard)的设置中很简单。只有分开的“真实”音素和“静音”音素的列表,还有个空文件extra_questions.txt,另外还有个叫lexicon.txt 的字典文件,文件有以下形式:

<word> <phone1> <phone2> ...

注意:lexicon.txt中同一个词如果有不同发音的话,可能会包含多个重复的条目,分布在不同的行。如果想使用发音概率,创建lexiconp.txt(第二个字段是概率)代替原来的lexicon.txt。注意一般都要对发音概率做规范化,而不是对一个词求和,每个单词最有可能的发音都是一个。这样会得到更好的结果。对于以发音概率跑实验的顶层脚本,在egs/wsj/s5/run.sh中找关键字”pp”。

请注意,在该输入中,没有字位置依赖性的概念,即没有后缀如_B和_E。 这是因为添加这些后缀是脚本prepare_lang.sh才做的。

可以从空文件extra_questions.txt中看到,这里还有一些没有被充分挖掘的东西。 这涉及重音标记或音调标记的一些东西。 用户可能会需要具有不同重音或音调的特定音素的不同版本。 为了演示这样的内容,查看与上述相同的文件,但在egs / wsj / s5 / setup中。 结果如下:

s5# cat data/local/dict/silence_phones.txt
SIL
SPN
NSN
s5# head data/local/dict/nonsilence_phones.txt
S
UW UW0 UW1 UW2
T
N
K
Y
Z
AO AO0 AO1 AO2
AY AY0 AY1 AY2
SH
s5# head -6 data/local/dict/lexicon.txt
!SIL SIL
<SPOKEN_NOISE> SPN
<UNK> SPN
<NOISE> NSN
!EXCLAMATION-POINT  EH2 K S K L AH0 M EY1 SH AH0 N P OY2 N T
"CLOSE-QUOTE  K L OW1 Z K W OW1 T
s5# cat data/local/dict/extra_questions.txt
SIL SPN NSN
S UW T N K Y Z AO AY SH W NG EY B CH OY JH D ZH G UH F V ER AA IH M DH L AH P OW AW HH AE R TH IY EH
UW1 AO1 AY1 EY1 OY1 UH1 ER1 AA1 IH1 AH1 OW1 AW1 AE1 IY1 EH1
UW0 AO0 AY0 EY0 OY0 UH0 ER0 AA0 IH0 AH0 OW0 AW0 AE0 IY0 EH0
UW2 AO2 AY2 EY2 OY2 UH2 ER2 AA2 IH2 AH2 OW2 AW2 AE2 IY2 EH2

可以看到nonsilence_phones.txt里面在单行中包括了多个音素的行有很多。这些是元音的不同重音相关版本。注意,CMU字典中每个音素都出现了四个不同版本:例如,UW UW0 UW1 UW2;由于某些原因,其中一个版本没有数字后缀。音素在一行的顺序并不重要,但分组到不同行的时候就很重要了;一般来说,Kaldi建议用户“真实音素”分组的不同形式在不同行。Kaldi使用CMU字典中存在的重音标记。文件extra_questions.txt包括一个包含所有“silence”音素的问题(实际上这是不必要的,因为脚本prepare_lang.sh会添加这样的问题),还有一个与每个不同的重音标记相对应的问题。为了从重音标记得到更好的结果,这些问题是必要的,因为实际上每个音素的不同重音相关版本都统一放在nonsilence_phones.txt文件行中,确保他们都在文件data/lang/phones/roots.txt 和data/lang/phones/sets.txt中,这反过来又确保它们共享相同的树根结点,并且永远不能被一个问题所区分。因此,我们必须提供一个特殊的问题,使决策树建立过程能够区分音素。注意:我们将音素放在sets.txt和roots.txt中的原因是,一些重音相关版本的音素可能没有足够的数据可靠地估计单独的决策树或生成问题时用到的音素聚类信息。通过将它们分组在一起,我们确保在没有足够的数据的情况下分别预测它们,这些不同版本的音素在整个决策树构建过程中都“保持在一起”。

还有一个要提出的点事是脚本utils/prepare_lang.sh支持几个选项。以下是脚本的使用信息,可以看看这些选项到底是什么:

usage: utils/prepare_lang.sh <dict-src-dir> <oov-dict-entry> <tmp-dir> <lang-dir>
e.g.: utils/prepare_lang.sh data/local/dict <SPOKEN_NOISE> data/local/lang data/lang
options:
     --num-sil-states <number of states>             # default: 5, #states in silence models.
     --num-nonsil-states <number of states>          # default: 3, #states in non-silence models.
     --position-dependent-phones (true|false)        # default: true; if true, use _B, _E, _S & _I
                                                     # markers on phones to indicate word-internal positions.
     --share-silence-phones (true|false)             # default: false; if true, share pdfs of
                                                     # all non-silence phones.
     --sil-prob <probability of silence>             # default: 0.5 [must have 0 < silprob < 1]

一个很重要的选项是–share-silence-phones选项。默认是false。如果选项是true,所有“silence”音素(比如静音,发声噪声和笑声)的高斯混合模型的概率密度函数都是共享的,只有这些模型之间的转移概率不同。不清楚为什么有帮助,但是发现这对IARPA的BABEL项目的粤语数据确实是非常有帮助的。这些数据非常混乱,并且有很长一部分没有转录,Kaldi试图为此目的与指定的特殊音素对齐。Dan怀疑训练数据不知道什么原因无法正确对齐,但是将此选项设置为true可以改变这种情况。

另外一个很重要的选项是”–sil-prob“选项。总的来说,Dan没有对这些选项进行实验,所以不能给出非常详细的建议。

创建语法的语言模型
上面说的如何创建lang/目录没有说如何创建G.fst文件,这个文件是需要解码的语言模型或者语法的有限状态转移机形式。实际上,在一些设置中可能会针对不同的测试目的有多个不同的”lang”目录,那里面有不同的语言模型和字典文件。华尔街日报(WSJ)是一个例子:

s5# echo data/lang*
data/lang data/lang_test_bd_fg data/lang_test_bd_tg data/lang_test_bd_tgpr data/lang_test_bg \
 data/lang_test_bg_5k data/lang_test_tg data/lang_test_tg_5k data/lang_test_tgpr data/lang_test_tgpr_5k

创建G.fst的过程根据是否用统计量语言模型或用什么种类的语法是不同的。在RM设置中有一个bigram语法,它只允许某些单词对。 在每个语法状态下,通过分配概率1在这些输出弧上,把这些单词对总计到一个?。

local/ rm_data_prep.sh中有一条语句:

local/make_rm_lm.pl $RMROOT/rm1_audio1/rm1/doc/wp_gram.txt  > $tmpdir/G.txt || exit 1;

脚本local/make_rm_lm.pl创建了一个FST格式(文本格式)的语法。它包含了以下形式的行

s5# head data/local/tmp/G.txt
0    1    ADD    ADD    5.19849703126583
0    2    AJAX+S    AJAX+S    5.19849703126583
0    3    APALACHICOLA+S    APALACHICOLA+S    5.19849703126583

OpenFst的更多信息查看www.openfst.org。

脚本local/rm_prepare_grammar.sh会把这个文件的文本形式转换成二进制形式G.fst。命令如下:

fstcompile --isymbols=data/lang/words.txt --osymbols=data/lang/words.txt --keep_isymbols=false \
    --keep_osymbols=false $tmpdir/G.txt > data/lang/G.fst

如果想创建自己的语法,或者会想做一些类似的事情。要注意:这个程序只适用一个固定类的语法:不允许编译完全上下文自由的语法,因为这不能以OpenFst形式表示。可以通过WFST框架做到这件事(可以看看Mike Riley 下推转移机的近期工作),但是Kaldi中还没有实现这些想法。

在关于语言模型或制作语法FST的列表上有任何问题,请阅读Joshua Goodman的“A Bit of Progress in Language Modeling” 并访问www.openfst.org并执行FST教程,以便了解有限状态转移机的基础知识。 (请注意,语言模型将被表示为有限状态接收器或FSA,可被视为有限状态转换机的特殊情况)。

脚本utils/format_lm.sh解决把ARPA格式的语言模型转换成OpenFST格式类型。脚本用法如下:

Usage: utils/format_lm.sh <lang_dir> <arpa-LM> <lexicon> <out_dir>
E.g.: utils/format_lm.sh data/lang data/local/lm/foo.kn.gz data/local/dict/lexicon.txt data/lang_test
Convert ARPA-format language models to FSTs.

这个脚本的一些关键命令如下:

gunzip -c $lm \
  | arpa2fst --disambig-symbol=#0 \
             --read-symbol-table=$out_dir/words.txt - $out_dir/G.fst

Kaldi程序arpa2fst将ARPA格式的语言模型转换成一个加权有限状态转移机(实际上是接收机)。

构建语言模型的常用工具时SRILM。不同的语言模型工具都在Kaldi的样例脚本中用到了。SRILM有最好的文档和最全面的功能,通常推荐它(唯一的缺点是它没有最免费的许可证)。 以下是utils / format_lm_sri.sh的使用信息:

Usage: utils/format_lm_sri.sh [options] <lang-dir> <arpa-LM> <out-dir>
E.g.: utils/format_lm_sri.sh data/lang data/local/lm/foo.kn.gz data/lang_test
Converts ARPA-format language models to FSTs. Change the LM vocabulary using SRILM.
kaldi做语音识别 kaldi是一个开源的语音识别工具箱,是基于c++、perl、shell编写的,可以在windows和unix 平台上编译。教程网页:http://www.kaldi-asr.org/doc/ 里面可以查阅语音/说话人识别实现过程、kaldi的数据结构、命令的使用说明等。还有网上的dan的ppt。kaldi下载:https:// 阅读详情

相关推荐

kaldi数据准备部分,文件解释

若想用已识别的系统对你的数据解码,要重写 “数据部分”. 直接以thchs30项目为例里面或许会有cmvn.scp feats.scp reco2file_and_channel segments spk2utt text utt2spk wav.scp 文件”text” :包含每段语音的文字意思 每行的第一项是录音编号(utterance-id),发音编号后面跟着的 是每段录音的

dzp443366的专栏 4326

Kaldi的简单介绍和基本使用说明

Kaldi作为目前最流行的ASR开源项目之一,已被广泛研究和使用。 自从2019年Daniel Povey加入小米,小米和Kaldi相互成就,大大推动了Kaldi的发展,使Kaldi保持了持续、强劲的生命力。 Kaldi使用了最自由的授权协议,任何人都可以自由修改和使用(包括商用),大家不妨也来用用。 本文大概讲了语音识别的原理和过程,对kaldi的安装、训练和部署在线语音识别服务的一整套使用过程作了大概说明, 可以作为初学者的入门资料来参考。非常欢迎大家来共同交流,不足之处还望批评指正。

DL_62532的专栏 3万+

Kaldi脚本分析(1)——数据准备

1 数据准备 数据准备阶段的输出包含两个部分:一部分与“数据”相关,保存在data/train、data/dev、data/test之类的目录下,“数据”部分与特定的录音数据有关,包括训练测试集划分、音频分段、文本标注、发音标注、说话人信息等;另一部分与“语言”相关,保存在data/local、data/dict、data/lang、data/graph目录下,“语言”部分与当前使用的语言本身相

baidu_36137891的博客 6822

kaldi入门:搭建第一个中文ASR (AISHELL-1)

请在linux环境下开展实验,非常建议熟悉 awk, grep, sed, cut, 等shell 命令快速处理文本,以及学会使用python脚本处理数据等.这里我们根据发音词典来定义我们的声学单元,在kaidi中对声学单元的表述需要以下四个文件:其中简单介绍如下:(1)意义:非静音音素集样例:(2)意义:静音音素集样例:(3)意义:指定静音音素集样例:(3)意义:用于三音素聚类问题。

Pika 1万+

kaldi中的声纹识别

kaldi中的声纹识别 文章目录kaldi中的声纹识别kaldi的安装运行aishell例程使用TIMIT数据库进行声纹识别 &amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;前段时间一直到在使用kaldi来做声纹识别,算是可以把整个i-vector

yutouwd的博客 7581

语音识别之Kaldi:学习GMM-HMM

kaldi语音识别理论与实践课程学习。前面的博客介绍了语音识别的基础知识及原理。现在开始学习实战。以Kaldi框架为基础。Kaldi是一个有全套的语音识别代码的工具,由Dan Povey博士和捷克的BUT大学联合开发,最早发布于2011年,底层代码使用C++编写,接口采用shell和python,覆盖了统计模型和深度学习方法,操作灵活,易于扩展,开发者更为活跃。语音识别流程:目前开源的语料库有: Kaldi官网:KALDI里面有详细的文档。 下载Kaldi:https://github.com/du-ud/

Barbara‘s Blog 2924

kaldi中的数据准备

数据准备 译者:V (shiwei@sz.pku.edu.cn)  水平有限,如有错误请多包涵。 介绍 在运行完示例脚本后(见Kaldi tutorial),你可能会想用自己的数据在Kaldi上跑一下。本节主要讲述如何准备相关数据。我们假设本页的读者使用的是最新版本的示例脚本(即在脚本目录下被命名为s5的那些,例如egs/rm/s5)。另外,除了阅读本页所述内容外,你还可以查看脚本目录下的那

u010384318的专栏 2万+

语音识别:安装编译Kaldi详细过程及遇到的一些问题汇总

语音识别-Kaldi的安装编译实录(Ubuntu环境) 本篇博客用于记录一次用开源语音识别(ASR)工具Kaldi来实现中文语音识别功能的经历,记录一路遇到的一些问题。希望本篇文章可以给广大有需要的人提供一些帮助,也以防之后若再做此方向的东西会重蹈覆辙。 注意:本文是在Ubuntu64位的虚拟机环境下运行的,通过阅读Kaldi官方的INSTALL文件中指出的,似乎不能在Windows下正常编译使用。 Kaldi简介:Kaldi是当前最流行的开源语音识别工具(Toolkit),它使用WFST来实现解码算法

Ryan0828的博客 1万+

aishell详细脚本解析---kaldi入门实战(1)--数据准备

总共178小时,400个人讲,其中训练集340个人,测试解20个人,验证集40个人,每个人大概讲三百多句话,每个人讲的话都放在一个文件夹里面。PS:文件压缩包就有将近17个g,所以我们在设置虚拟机容量时最好设置的大一点,我一般直接设80g,kaldi加数据集就将近45g,还要解压。

qq_57461500的博客 2074

Kaldi-yesno详解

在Kaldi的egs文件下有很多基于公共语音数据库的训练步骤及测试结果,其中也有中文的,本文就相对很简单的yesno样例结合脚本以及脚本运行结果进行详细的解析,以更好地理解语音识别的整体流程。 总括 我们先来看一下run.sh脚本 cd ./egs/yesno/s5/ vi run.sh =================================================...

nsh119的博客 6462

Kaldi简介【开源语音识别工具】

Kaldi架构如所示,最上面是外部的工具,包括用于线性代数库BLAS/LAPACK和我们前面介绍过的OpenFst。中间是Kaldi的库,包括HMM和GMM等代码,下面是编译出来的可执行程序,最下面则是一下脚本,用于实现语音识别的不同步骤(比如特征提取,比如训练单因子模型等等)。Kaldi是当前最流行的开源语音识别工具(Toolkit),它使用WFST来实现解码算法。Kaldi的主要代码是C++编写,在此之上使用bash和 python 脚本做了一些工具。...

u013250861的博客 4364

kaldi数据准备,Subtools数据准备,详细分享Asv-Subtools数据准备,小白必看!

有没有刚开始接触kaldi的小伙伴们,也像我一样,感觉理论很多,但是上手就崩。俗话说:“万事开头难”,数据准备就是kaldi实验的开始。因为我上手直接学习,我绕过kaldi,直接学习使用asv-subtools。但是subtools里面没有关于数据准备的代码。网上关于asv-subtools的内容也少之又少。然而kaidl和subtools的数据准备一样。所以我就把目光投向了kaldi的数据处理。我想通过kaldi学习有关数据的处理。kaldi数据准备,asv-subtools数据准备,小白必看!~

JYT666666的博客 1916

狗都能看懂的Proximal Policy Optimization(PPO)PPO算法详解

李宏毅老师的PPO算法讲解笔记

个人学习笔记 2万+

Kaldi如何准备自己的数据

Introduction 跑完kaldi的一些脚本例子,你可能想要自己用Kaldi跑自己的数据集。这里将会阐述如何准备好数据。 run.sh较上的部分是有关数据准备的,通常local与数据集相关。 例如:RM数据集 local/rm_data_prep.sh /export/corpora5/LDC/LDC93S3A/rm_comp || exit 1; utils/pre...

aig8440的博客 708

Visual Studio 2013 + Intel(R) Visual Fortran 安装教程

安装了好几遍,ivf都不能加载到vs中,中途放弃了vs,又改用codeblocks编译器,依然在写fortran的时候出现了各种问题,于是又放弃了codeblocks改回vs,总之是折腾了好久,终于装明白了ivf并且将fortran模板成功加载到vs中。 PS:一定要安装Intel Visual Fortran.Composer XE.2013-SP1,不要用Intel Visual Fortr...

Coco_wjy的博客 12万+

【暂时完结】Prescan学习笔记

Prescan学习记录1. Prescan基础知识1.1 Conventions·坐标1.2 Road segment·道路片段1.2.1 让一个路段连接其他两个路段1.2.2 配置车道线1.2.3 Road marking·道路标志1.3 Trajectory·轨迹1.3.1 建立一个Path·路径1.3.2 配置Speedprofile1.3.3 Synchronization of Trajectories·轨迹同步1.3.4 Multiple trajectories · 多轨迹分配 1. Pres

dreautumn的博客 1万+

kaldi数据准备脚本学习(以AISHELL的数据准备为例)

aishell_data_prep.sh 代码分析学习 原始代码块如下所示: #!/bin/bash # Copyright 2017 Xingyu Na # Apache 2.0 # 导入一些执行本脚本必须的环境变量 . ./path.sh || exit 1; # 如果输入参数不是两个,那么弹出本脚本的使用方法 if [ $# != 2 ]; then echo "Usage: ...

qq_37991715的博客 1536

内存预取黑科技:__builtin_prefetch在数据库和游戏开发中的高阶用法

本文深入探讨了GCC内置函数`__builtin_prefetch`在数据库和游戏开发中的高阶应用。通过LevelDB的SSTable文件读取优化和UE5引擎场景数据流式加载的实战案例,详细解析了预取参数调优的艺术,并借助perf工具量化分析了不同策略的性能提升效果。文章还介绍了与`__builtin_expect`等内置函数的协同优化技巧,帮助开发者最大化缓存命中率。

weixin_29019241的博客 415

AIBigKaldi(三)| Kaldi的数据准备(源码解析)

本文来自公众号“AI大道理”。 正所谓巧妇难为无米之炊。 对于语音识别任务来说,对于Kaldi来说,数据就是这个米。 在进行特征提取、模型训练之前,首先要做的就是数据准备。 以最简单的YesNo为例。 1 YesNo实例结构 其中: 文件夹 脚本 2 脚本解析 cmd.sh 源码解读: 这里的queue.pl为kaldi调用的gridengine,是一种多cpu(gpu)的一种并行处理的方案。 如果是slurm其他并行任务分发软件配合,则...

aibigtruth的博客 1082

Java开发者终极抉择:IntelliJ IDEA vs VS Code —— 4大维度深度对比评测

🔥关注墨瑾轩,带你探索Java的奥秘!🚀🔥超萌技术攻略,轻松晋级编程高手!🚀🔥技术宝库已备好,就等你来挖掘!🚀🔥订阅墨瑾轩,智趣学习不孤单!🚀🔥即刻启航,编程之旅更有趣!🚀在Java开发领域,选择合适的集成开发环境(IDE)对于提高开发效率和代码质量至关重要。和(简称VS Code)是两个广受好评的开发工具,各自拥有独特的特性和庞大的用户群。本篇将从多个维度深入探讨这两款IDE对Java开发者来说的优劣,包括但不限于性能、用户体验、生态系统、调试能力、以及特定Java功能的支持等方面。

java专栏 8590

YOLO26涨点改进 | 小目标损失函数独家改进篇 | TGRS 2025 | 引入AdaFocalLoss损失函数,改进小目标检测,自适应聚焦小目标与样本分布不平衡,提升检测精度与训练稳定性

本文提出将AdaFocalLoss损失函数应用于YOLO26模型优化,有效提升小目标检测性能。AdaFocalLoss通过目标尺寸感知机制和IoU引导的动态调节,自动调整训练权重和聚焦程度,解决了样本不平衡问题。相比传统损失函数,它无需手动调参,能增强训练稳定性,在多尺度、复杂场景下表现优异。文章详细介绍了AdaFocalLoss的原理、优势及实现方法,并提供了代码集成指南。实验表明该方法能显著提升检测精度和鲁棒性,特别适用于小目标检测任务。

Ai缝合怪、助力小伙伴高效发论文 335

Ubuntu上Kaldi跑librispeech数据集步骤

Kaldi跑librispeech步骤 步骤分为数据准备跟训练模型 kaldi环境默认是安装好的,这里不详细说明kaldi的安装步骤, 这里的实验室在Ubuntu16.04上跑的。 一、数据准备 数据准备分为两种:手动下载跟脚本下载。 1.手动下载 1.1下载训练数据: 从http://www.openslr.org/12/网址下载librispeech数据 下载train-clean-100.t...

cheetah的专栏 4895

AE 与 ISP 参数联动机制解析:自动曝光系统与图像信号处理模块协同设计实践

AE(自动曝光)并不是一个独立的图像控制模块,而是与 ISP(Image Signal Processor)深度耦合运作的系统协同体。其输出的曝光参数直接决定了图像处理链路中 Gamma 曲线选择、黑电平补偿、去噪级别、边缘增强等一系列关键参数的取值。本文基于主流平台(如高通、MTK、海思)的工程实战经验,详细剖析 AE 与 ISP 在曝光驱动、调节优先级、图像还原逻辑等环节的联动机制,并结合拍照与视频等不同场景,给出可落地的联调方法。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1527

kaldi学习 - egs/yesno —— 数据准备(二)

  参考文档:http://www.cnblogs.com/welen/p/7485151.html   写在前面,本文虽然对大多数脚本进行了解释,但只是初学者的理解,如果你认为读起来不知所云,建议从 kaldi 官方文档 读起,两边配合理解,可以解决很多看起来好像很难理解的东西。(官方文档地址: http://www.kaldi-asr.org/doc/data_prep.h...

dianguan5769的博客 442

使用everything出现mem_virtual_alloc(): Fatal Error: out of memory解决方案

本文主要介绍了使用everything出现mem_virtual_alloc(): Fatal Error: out of memory解决方案,希望能对使用everything的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

kaldi源码分析(二)-数据准备

文件名称 内容格式 text < uttid > < word > wav.scp < uttid > < utter_file_path > utt2spk < uttid > < speakid > spk2utt < speakid > < uttid > segm...

会飞的鱼 1271

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

上一篇: Kaldi学习之如何运行脚本
下一篇: Kaldi配置环境变量
llearner
博客等级 码龄11年 23粉丝 14原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值