资讯详情

【语音识别】详解kaldi的数据和模型文件——librispeech

文章目录

  • 引言-语音识别ASR
  • 1. kaldi的编译流程
  • 2. librispeech示例


引言—语音识别ASR

参考博客.

在基于GMM-HMM在传统的语音识别中,比音素(phone)较小的单位是状态(state)。一般每种音素由三种状态组成,特别是静音(SIL)由五种状态组成。这里提到的状态是指状态HMM每帧数据中隐藏的状态是指HMM里面的观测值。每个状态可以使用一个GMM模型表示(这个GMM通过训练获得模型参数)。在识别时把每帧数据对应的特征值放进每个状态的GMM计算概率,概率最大的是这帧对应的状态。然后从状态得到音素(HMM负责),从音素得到单词(字典模型负责),从单词得到句子(语言模型负责),最终完成识别。

1. kaldi的编译流程

第一次编译kaldi可能缺少各种各样的东西,最好有管理员的安装权限。

## 下载 git clone https://github.com/kaldi-asr/kaldi.git kaldi --origin upstream cd kaldi  ## 编译tools cd tools extras/check_dependencies.sh ///安装缺少的东西,需要管理员的权限 make  ## 编译src cd ../src ./configure --shared make depend -j 8 make -j 8 

2. librispeech示例

kaldi内置了许多语料库本身asr示例,librispeech例子是一个共有960小时数据的英语常用语料库。此外,中文常用语料库是aishell2.需要申请。根据培训流程查看生成的文件。

打开kaldi/egs/librispeech/s5,其中cmd.sh对于集群相关配置,如果是单机训练,则改为

export train_cmd=run.pl export decode_cmd=run.pl export mkgraph_cmd=run.pl 

然后是主要的训练脚本,run.sh,第一行的 data 修改为准备存放的语料库路径。 该脚本由 20 个 stage 组成,可以一个一个 stage 把自己放在命令里跑,观察生成了什么。

第一步:下载语料库和词典,或者自己 openslr 下载,有很多开源ASR语料库。

if [ $stage -le 1 ]; then   for part in dev-clean test-clean dev-other test-other train-clean-100; do     local/download_and_untar.sh $data $data_url $part   done   local/download_lm.sh $lm_url data/local/lm fi 

步骤2重构数据kaldi所需的形式将每个集生成文件夹.

if [ $stage -le 2 ]; then   for part in dev-clean test-clean dev-other test-other train-clean-100; do     local/data_prep.sh $data/LibriSpeech/$part data/$(echo $part | sed s/-/_/g)   done fi 

在每个文件夹中,有更重要的文件 text、wav.scp、utt2spk、spk2utt、feats.scp、cmvn.scp。 前三项需要手动准备,后三项可以根据前三项自动生成。

$ls data/train_clean_100 cmvn.scp  conf  feats.scp  frame_shift  spk2gender  spk2utt  split20  text  utt2dur  utt2num_frames  utt2spk  wav.scp  # text <utterance-id> <text> # 第一个是句子id,如果有发言人的信息,发言人的编号应该是(speaker-id)作为话语编号的前缀进行排序; # 第二个是转录文本。这些词不一定在字典里,不在的词会映射到data/lang/oov.txt文件的特定词。 $head -3 train_clean_100/text 103-1240-0000 CHAPTR ONE MISSUS RACHEL LYNDE IS SURPRISED MISSUS RACHEL LYNDE LIVED 
103-1240-0001 THAT HAD ITS SOURCE AWAY BACK IN THE WOODS OF THE OLD CUTHBERT
103-1240-0002 FOR NOT EVEN A BROOK COULD RUN PAST MISSUS RACHEL LYNDE'S DOOR

# wav.scp <recording-id> <extended-filename>
# 第一个为记录的语音id,当没有segments文件时它等于utterance-id;
# 第二个为文件路径,也可以是提取路径的命令。
$head -3 train_clean_100/wav.scp
103-1240-0000 flac -c -d -s /home/fwq/Project/kaldi/kaldi/data/LibriSpeech/LibriSpeech/train-clean-100/103/1240/103-1240-0000.flac |
103-1240-0001 flac -c -d -s /home/fwq/Project/kaldi/kaldi/data/LibriSpeech/LibriSpeech/train-clean-100/103/1240/103-1240-0001.flac |
103-1240-0002 flac -c -d -s /home/fwq/Project/kaldi/kaldi/data/LibriSpeech/LibriSpeech/train-clean-100/103/1240/103-1240-0002.flac |

# utt2spk <utterance-id> <speaker-id>
# 若无说话人信息,让speaker-id=utterance-id,但不要设置一个全局的speaker-id,会导致训练时倒谱均值归一化无效。
$head -3 train_clean_100/utt2spk
103-1240-0000 103-1240
103-1240-0001 103-1240
103-1240-0002 103-1240

# spk2utt <speaker-id> <utterance-id1> <utterance-id2> ....
# 可通过如下命令提取,行数一般比utt2spk少,为说话人个数。
# $utils/utt2spk_to_spk2utt.pl data/train_clean_100/utt2spk > data/train_clean_100/spk2utt
$head -3 train_clean_100/spk2utt
103-1240 103-1240-0000 103-1240-0001 103-1240-0002 103-1240-0003 ....
103-1241 103-1241-0000 103-1241-0001 103-1241-0002 103-1241-0003 ....
1034-121119 1034-121119-0000 1034-121119-0001 1034-121119-0002 1034-121119-0003 ....

# feats.scp <utterance-id> <extended-filename-of-features>
# 提取的mfcc路径,第一行的14表示从14个位置读起
# $steps/make_mfcc.sh --nj 20 --cmd "$train_cmd" data/train_clean_100 exp/make_mfcc/train_clean_100 $mfccdir
$head -3 train_clean_100/feats.scp
103-1240-0000 /home/fwq/Project/kaldi/kaldi/egs/librispeech/s5/mfcc/raw_mfcc_train_clean_100.1.ark:14
103-1240-0001 /home/fwq/Project/kaldi/kaldi/egs/librispeech/s5/mfcc/raw_mfcc_train_clean_100.1.ark:18444
103-1240-0002 /home/fwq/Project/kaldi/kaldi/egs/librispeech/s5/mfcc/raw_mfcc_train_clean_100.1.ark:39292

# cmvn.scp <speaker-id> <extended-filename-of-cmvn>
# 说话人的倒谱归一化均值和方差的统计信息
# $steps/compute_cmvn_stats.sh data/train_clean_100 exp/make_mfcc/train_clean_100 $mfccdir
$head -3 train_clean_100/cmvn.scp
103-1240 /home/fwq/Project/kaldi/kaldi/egs/librispeech/s5/mfcc/cmvn_train_clean_100.ark:9
103-1241 /home/fwq/Project/kaldi/kaldi/egs/librispeech/s5/mfcc/cmvn_train_clean_100.ark:257
1034-121119 /home/fwq/Project/kaldi/kaldi/egs/librispeech/s5/mfcc/cmvn_train_clean_100.ark:508
步骤3,准备词典,并生成语言模型保存于 data/lang_nosp。

if [ $stage -le 3 ]; then
  local/prepare_dict.sh --stage 3 --nj 30 --cmd "$train_cmd" \
   data/local/lm data/local/lm data/local/dict_nosp

  utils/prepare_lang.sh data/local/dict_nosp \
   "<UNK>" data/local/lang_tmp_nosp data/lang_nosp

  local/format_lms.sh --src-dir data/lang_nosp data/local/lm
fi

着重看语言模型文件夹。

$ls lang_nosp
L.fst  L_disambig.fst  oov.int  oov.txt  phones  phones.txt  topo  words.txt

# 包含音素集的信息,用 utils/prepare_lang.sh 生成。
$ls lang_nosp/phones
align_lexicon.int  context_indep.txt  extra_questions.int  nonsilence.txt        roots.int  silence.csl    wdisambig_phones.int
align_lexicon.txt  disambig.csl       extra_questions.txt  optional_silence.csl  roots.txt  silence.int    wdisambig_words.int
context_indep.csl  disambig.int       nonsilence.csl       optional_silence.int  sets.int   silence.txt    word_boundary.int
context_indep.int  disambig.txt       nonsilence.int       optional_silence.txt  sets.txt   wdisambig.txt  word_boundary.txt

# 音素和单词,在整数和文本形式之间来回映射。
$head -3 lang_nosp/phones.txt
<eps> 0
SIL 1
SIL_B 2
$head -5 lang_nosp/words.txt
<eps> 0
!SIL 1
<SPOKEN_NOISE> 2
<UNK> 3
A 4

# L.fst 是有限状态机形式的词典,输入音素符号,输出词符号。
# L_disambig.fst 是包含了歧义符号`#1, #2`等的词典。

# 仅一行,超出词典范围的符号及其对应的整数形式
$cat lang_nosp/oov.txt
<UNK>
$cat lang_nosp/oov.int
3

# 定义了HMM的拓扑。
$cat lang_nosp/topo
....
<TopologyEntry>
<ForPhones>
1 2 3 4 5 6 7 8 9 10
</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>
....

步骤4,扩展成三元和四元的语言模型,生成两个新的语言模型文件夹。

if [ $stage -le 4 ]; then
  # Create ConstArpaLm format language model for full 3-gram and 4-gram LMs
  utils/build_const_arpa_lm.sh data/local/lm/lm_tglarge.arpa.gz \
    data/lang_nosp data/lang_nosp_test_tglarge
  utils/build_const_arpa_lm.sh data/local/lm/lm_fglarge.arpa.gz \
    data/lang_nosp data/lang_nosp_test_fglarge
fi
$ls lang_nosp_test_tglarge/
G.carpa  L.fst  L_disambig.fst  oov.int  oov.txt  phones  phones.txt  topo  words.txt
$ls lang_nosp_test_fglarge/
G.carpa  L.fst  L_disambig.fst  oov.int  oov.txt  phones  phones.txt  topo  words.txt

然后看模型文件。 步骤8,训单因素模型并解码。

if [ $stage -le 8 ]; then
  # 训单音素HMM模型,保存于exp/mono
  steps/train_mono.sh --boost-silence 1.25 --nj 20 --cmd "$train_cmd" \
                      data/train_2kshort data/lang_nosp exp/mono

  # decode using the monophone model
  (
    # 构建HCLG解码图
    # data/lang_nosp_test_tgsmall/L_disambig.fst + data/lang_nosp_test_tgsmall/G.fst -> data/lang_nosp_test_tgsmall/tmp/LG.fst
    # data/lang_nosp_test_tgsmall/tmp/LG.fst + data/lang_nosp_test_tgsmall/tmp/ilabels_3_1(消歧符) -> data/lang_nosp_test_tgsmall/tmp/CLG_3_1.fst
    # data/lang_nosp_test_tgsmall/tmp/CLG_3_1.fst + exp/mono/graph_nosp_tgsmall/Ha.fst(由make-h-transducer形成) -> exp/mono/graph_nosp_tgsmall/HCLGa.fst
    # exp/mono/graph_nosp_tgsmall/HCLGa.fst + 自循环add_self_loops -> exp/mono/graph_nosp_tgsmall/HCLG.fst
    utils/mkgraph.sh data/lang_nosp_test_tgsmall \
                     exp/mono exp/mono/graph_nosp_tgsmall

    for test in test_clean test_other dev_clean dev_other; do
      steps/decode.sh --nj 20 --cmd "$decode_cmd" exp/mono/graph_nosp_tgsmall \
                      data/$test exp/mono/decode_nosp_tgsmall_$test
    done
  )&
fi

步骤9,用单音素模型对齐后,再训三音素模型。

if [ $stage -le 9 ]; then
  # 将每一个特征向量都对应到了具体的 phone 的状态上,每一段utt对应一串表示状态变化的 transition_id 
  # exp/mono -> exp/mono_ali_5k
  steps/align_si.sh --boost-silence 1.25 --nj 10 --cmd "$train_cmd" \
                    data/train_5k data/lang_nosp exp/mono exp/mono_ali_5k

  # 训三音素模型,保存于exp/tri1
  # 一个音素在不同上下文会有不同的发音,三音素模型对l_a_i和l_a_n用不同的GMM建模,并同样映射到a。
  # 2000为决策树的叶子数,10000为总高斯数。
  steps/train_deltas.sh --boost-silence 1.25 --cmd "$train_cmd" \
                        2000 10000 data/train_5k data/lang_nosp exp/mono_ali_5k exp/tri1
fi

步骤10,用三音素模型对齐后,再训LDA+MLLT模型。

if [ $stage -le 10 ]; then
  # 继续对齐
  steps/align_si.sh --nj 10 --cmd "$train_cmd" \
                    data/train_10k data/lang_nosp exp/tri1 exp/tri1_ali_10k


  # 训LDA+MLLT模型,在mfcc特征提取出来后,将相邻几个帧拼接起来,降到40维,用LDA 去评估,经过多次迭代,最后使用对角变换,用转换后的特征去训练。
  steps/train_lda_mllt.sh --cmd "$train_cmd" \
                          --splice-opts "--left-context=3 --right-context=3" 2500 15000 \
                          data/train_10k data/lang_nosp exp/tri1_ali_10k exp/tri2b
fi

步骤11,用LDA+MLLT模型对齐后,再训LDA+MLLT+SAT模型。

if [ $stage -le 11 ]; then
  ### 继续对齐
  steps/align_si.sh  --nj 10 --cmd "$train_cmd" --use-graphs true \
                     data/train_10k data/lang_nosp exp/tri2b exp/tri2b_ali_10k

  ### 训LDA+MLLT+SAT模型,是训说话人自适应(Speaker Adaptive Training)的,同样是特征转换后再训。
  steps/train_sat.sh --cmd "$train_cmd" 2500 15000 \
                     data/train_10k data/lang_nosp exp/tri2b_ali_10k exp/tri3b
fi

步骤12,在100h干净数据上,用LDA+MLLT+SAT模型对齐后,再训LDA+MLLT+SAT模型。

if [ $stage -le 12 ]; then
  # 先预对齐一次,计算 fmllr transforms, 再用预对齐和 fmllr 一起计算最终对齐。
  steps/align_fmllr.sh --nj 20 --cmd "$train_cmd" \
    data/train_clean_100 data/lang_nosp \
    exp/tri3b exp/tri3b_ali_clean_100

  # 训LDA+MLLT+SAT模型。
  steps/train_sat.sh  --cmd "$train_cmd" 4200 40000 \
                      data/train_clean_100 data/lang_nosp \
                      exp/tri3b_ali_clean_100 exp/tri4b
fi

完整流程可参照上一篇博客。

标签: 荔波智能电容器fst

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台