本文是对Kaldi
中最简单例子egs/yesno/s5
的实验记录。
数据集
使用数据集waves_yesno
,该数据集只有yes
和no
两种发音。数据集没有文本文件,因为音频对应的文本都由wav
文件的文件名所表示。例如1_0_1_0_1_0_0_1.wav
中,1
表示yes
,0
表示no
。
数据准备
-
划分训练集和测试集
-
把数据规范成
Kaldi
规定的数据文件夹格式# 运行local/prepare_data.sh waves_yesno后生成的结果 # 其中local文件夹里的脚本是特别为该数据集编写的,一般很简短,可以逐行看看 # 与此对应,utils文件夹里的脚本是通用的,一般很复杂,有兴趣可以了解 data ├── local │ ├── lm_tg.arpa │ ├── test_yesno.txt │ ├── test_yesno_wav.scp │ ├── train_yesno.txt │ ├── train_yesno_wav.scp │ ├── waves_all.list │ ├── waves.test │ └── waves.train ├── test_yesno │ ├── spk2utt │ ├── text │ ├── utt2spk │ └── wav.scp └── train_yesno ├── spk2utt ├── text ├── utt2spk └── wav.scp 3 directories, 16 files
其中
-
waves_all.list
和*.test
列出了所有数据的文件名。 -
*_yesno.txt
(同*_yesno/text
)是一个字符串数组,第一列是样本编号(文件名),之后是对应的文本。 -
*_yesno_wav.scp
(同*_yesno/wav.scp
)有两列,第一列是样本编号,第二列是数据路径。 -
utt2spk
也有两列,第一列是样本编号,第二列是对应的说话人编号。 -
spk2utt
有多列,第一列是说好人编号,后面是对应的所有样本编号。 -
lm_tg.arpa
是语言模型的参数,由于本例语言模型简单,不需要训练,直接写为:\data\ ngram 1=4 \1-grams: -1 NO -1 YES -99 <s> -1 </s> \end\
-
-
准备发音词典
# 运行local/prepare_dict.sh生成的结果 data └── local └── dict ├── lexicon.txt ├── lexicon_words.txt ├── nonsilence_phones.txt ├── optional_silence.txt └── silence_phones.txt 4 directories, 21 files
lexicon.txt
和lexicon_words.txt
有多列,第一列是单词,后面是所有可能发音的音素符号。后者相比前者没有静音符号<SIL>
。nonsilence_phones
可由lexicon_words.txt
所有音素符号去重得到,silence_phones.txt
只有静音音素符号,optional_silence.txt
也是静音音素符。
-
准备语言文件
# 运行utils/prepare_lang.sh --position-dependent-phones false data/local/dict <SIL> data/local/lang data/lang生成的结果 # 用法:utils/prepare_lang.sh <dict-src-dir> <oov-dict-entry> <tmp-dir> <lang-dir> data ├── lang │ ├── L_disambig.fst │ ├── L.fst │ ├── oov.int │ ├── oov.txt │ ├── phones │ │ ├── align_lexicon.int │ │ ├── align_lexicon.txt │ │ ├── context_indep.csl │ │ ├── context_indep.int │ │ ├── context_indep.txt │ │ ├── disambig.csl │ │ ├── disambig.int │ │ ├── disambig.txt │ │ ├── extra_questions.int │ │ ├── extra_questions.txt │ │ ├── nonsilence.csl │ │ ├── nonsilence.int │ │ ├── nonsilence.txt │ │ ├── optional_silence.csl │ │ ├── optional_silence.int │ │ ├── optional_silence.txt │ │ ├── roots.int │ │ ├── roots.txt │ │ ├── sets.int │ │ ├── sets.txt │ │ ├── silence.csl │ │ ├── silence.int │ │ ├── silence.txt │ │ ├── wdisambig_phones.int │ │ ├── wdisambig.txt │ │ └── wdisambig_words.int │ ├── phones.txt │ ├── topo │ └── words.txt └── local ├── dict │ └── lexiconp.txt └── lang ├── align_lexicon.txt ├── lexiconp_disambig.txt ├── lexiconp.txt ├── lex_ndisambig ├── phone_map.txt └── phones 7 directories, 61 files
lexiconp.txt
和lexiconp.txt
相比,在第二列加入了发音概率,复杂场景下,每个单词的发音概率应该是不同的,要特别准备,但在这个简单场景下,没有准备发音概率,该脚本根据lexiconp.txt
直接在第二列插入1.0
,表示所有单词发音概率相同。- 其他暂略
-
准备语言模型
# 运行local/prepare_lm.sh data ├── lang_test_tg │ ├── G.fst │ ├── L_disambig.fst │ ├── L.fst │ ├── oov.int │ ├── oov.txt │ ├── phones │ │ ├── align_lexicon.int │ │ ├── align_lexicon.txt │ │ ├── context_indep.csl │ │ ├── context_indep.int │ │ ├── context_indep.txt │ │ ├── disambig.csl │ │ ├── disambig.int │ │ ├── disambig.txt │ │ ├── extra_questions.int │ │ ├── extra_questions.txt │ │ ├── nonsilence.csl │ │ ├── nonsilence.int │ │ ├── nonsilence.txt │ │ ├── optional_silence.csl │ │ ├── optional_silence.int │ │ ├── optional_silence.txt │ │ ├── roots.int │ │ ├── roots.txt │ │ ├── sets.int │ │ ├── sets.txt │ │ ├── silence.csl │ │ ├── silence.int │ │ ├── silence.txt │ │ ├── wdisambig_phones.int │ │ ├── wdisambig.txt │ │ └── wdisambig_words.int │ ├── phones.txt │ ├── topo │ └── words.txt 9 directories, 95 files
实验
-
提取声学特征
以测试集为例
提取MFCC特征
# 运行steps/make_mfcc.sh --nj 1 data/train_yesno exp/make_mfcc/train_yesno mfcc data └── train_yesno ├── conf │ └── mfcc.conf ├── feats.scp ├── frame_shift ├── utt2dur └── utt2num_frames 8 directories, 66 files
-
feats.scp
有两列,第一列是样本编号,第二列是声学特征储存的位置(mfcc/raw_mfcc_train_yesno.1.ark:*
)。 -
utt2dur
是样本编号对应的语音时长,utt2num_frames
是样本编号对应的帧数,frame_shift
只有一个值,表示帧长。观察到三者有以下关系:num_frames=dur/frame_shift-2
。
提取CMVN
# 运行steps/compute_cmvn_stats.sh data/train_yesno exp/make_mfcc/train_yesno mfcc data └── train_yesno └── cmvn.scp 8 directories, 67 files
cmvn.scp
对MFCC特征做z-score标准化后的特征路径。
-
-
训练
mono
模型使用
Kaldi
中最简单的单音素GMM模型训练,模型结构暂略。训练后模型储存在exp/mono0a
中,模型训练完毕,之后可以进行测试。 -
构建状态图
-
测试解码