本文环境:
● 硬件:
2018版 MacBook Pro
▶ CPU:2.3 GHz Intel Core i5
▶ 内存:8 GB 2133 MHz LPDDR3
▶ 无独立显卡
● Kaldi:
commit id:66f5434d29e2a528b9363e0fa25f2793069602a3
● 参考文献:
https://www.bilibili.com/video/BV19a4y1h7cB
https://www.bilibili.com/video/BV1Ch411p7fJ
https://www.bilibili.com/video/BV1KU4y1K7gz
https://blog.csdn.net/weixin_42217661/article/details/117715318
《Kaldi语音识别实战》陈果果、都家宇、那兴宇、张俊博 / 著
● www.gaohaiyan.com
1.编译kaldi
Mac上使用brew安装较慢或不能下载墙外程序时,可为 brew 配置国内镜像。终端执行以下命令:
阿里镜像:
1 2 3 |
git -C "$(brew --repo)" remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git git -C "$(brew --repo)/Library/Taps/homebrew/homebrew-core" remote set-url origin https://mirrors.aliyun.com/homebrew/homebrew-core.git brew update |
中科大镜像:
1 2 3 |
git -C "$(brew --repo)" remote set-url origin https://mirrors.ustc.edu.cn/brew.git git -C "$(brew --repo)/Library/Taps/homebrew/homebrew-core" remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git brew update |
重置
1 2 3 4 5 6 7 8 |
# 替换brew.git: git -C "$(brew --repo)" remote set-url origin https://github.com/Homebrew/brew.git # 替换homebrew-core.git: git -C "$(brew --repo)/Library/Taps/homebrew/homebrew-core" remote set-url origin https://github.com/Homebrew/homebrew-core.git # 替换homebrew-cask.git: git -C "$(brew --repo)/Library/Taps/homebrew/homebrew-cask" remote set-url origin https://github.com/Homebrew/homebrew-cask.git # 应用生效 brew update |
1.1.检查依赖
进入 %kaldi%/tools/ 目录。
检查依赖是否安装完备。缺啥安装啥
1 2 |
./extras/check_dependencies.sh |
./check_dependencies.sh: automake is not installed.
./check_dependencies.sh: autoconf is not installed.
./check_dependencies.sh: wget is not installed.
./check_dependencies.sh: sox is not installed.
./check_dependencies.sh: gfortran is not installed
./check_dependencies.sh: neither libtoolize nor glibtoolize is installed
./check_dependencies.sh: Intel MKL does not seem to be installed.
... Download the installer package for your system from:
... https://software.intel.com/mkl/choose-download
... You can also use other matrix algebra libraries. For information, see:
... http://kaldi-asr.org/doc/matrixwrap.html
./check_dependencies.sh: The following prerequisites are missing; install them first:
automake autoconf wget sox gfortran libtool
1 2 |
brew install automake autoconf wget sox gfortran libtool |
gfortran可以从 https://github.com/fxcoudert/gfortran-for-macOS/releases 下载。
1.2.编译tools
进入 %kaldi%/tools/ 目录。
1 |
make -j8 |
if [ -d "" ]; then \
cp -p "/cub-1.8.0.tar.gz" .; \
else \
wget -nv -T 10 -t 3 -O cub-1.8.0.tar.gz \
https://github.com/NVlabs/cub/archive/1.8.0.tar.gz; \
fi
if [ -d "" ]; then \
cp -p "/sph2pipe-v2.5.tar.gz" \
sph2pipe-2.5.tar.gz; \
else \
wget -nv -T 10 -t 3 -O sph2pipe-2.5.tar.gz \
https://github.com/burrmill/sph2pipe/archive/2.5.tar.gz; \
fi
extras/check_dependencies.sh: python2.7 is installed, but the python2 binary does not exist. Creating a symlink and adding this to tools/env.sh
x SCTK-20159b580249f1598caa35ab469bd1acdb3dd86c/CHANGELOG
---
很多很多...
---
libtool: install: chmod 644 %kaldi%/tools/openfst-1.7.2/lib/fst/olabel_lookahead-fst.a
make[3]: Nothing to be done for `install-exec-am'.
make[3]: Nothing to be done for `install-data-am'.
rm -f openfst
ln -s openfst-1.7.2 openfst
-e
Warning: IRSTLM is not installed by default anymore. If you need IRSTLM
Warning: use the script extras/install_irstlm.sh
All done OK.
1.2.1安装irstlm
这是kaldi自带的训练工具。
1 |
extras/install_irstlm.sh |
****() Installing IRSTLM
Cloning into 'irstlm'...
remote: Enumerating objects: 1781, done.
remote: Total 1781 (delta 0), reused 0 (delta 0), pack-reused 1781
Receiving objects: 100% (1781/1781), 3.54 MiB | 641.00 KiB/s, done.
Resolving deltas: 100% (1187/1187), done.
patching file configure.ac
patching file src/Makefile.am
---
很多...
---
make[2]: Nothing to be done for `all'.
Making install in src
.././install-sh -c -d '%kaldi%/tools/irstlm/lib'
/bin/sh ../libtool --mode=install /usr/bin/install -c libirstlm.la '%kaldi%/tools/irstlm/lib'
libtool: install: /usr/bin/install -c .libs/libirstlm.lai %kaldi%/tools/irstlm/lib/libirstlm.la
Making install in scripts
make[2]: Nothing to be done for `install-exec-am'.
.././install-sh -c -d '%kaldi%/tools/irstlm/bin'
/usr/bin/install -c add-start-end.sh build-lm-qsub.sh build-lm.sh rm-start-end.sh split-ngt.sh mdtsel.sh build-sublm.pl goograms2ngrams.pl lm-stat.pl merge-sublm.pl ngram-split.pl sort-lm.pl split-dict.pl plsa.sh '%kaldi%/tools/irstlm/bin'
Making install in doc
make[2]: Nothing to be done for `install-exec-am'.
/Library/Developer/CommandLineTools/usr/bin/make install-exec-hook
cd %kaldi%/tools/irstlm/ && \
ln -s -n -f lib lib64
make[2]: Nothing to be done for `install-data-am'.
***() Installation of IRSTLM finished successfully
***() Please source the tools/env.sh in your path.sh to enable it
1 2 |
source env.sh |
新生成的env.sh里设置了3个环境变量,以利于之后直接执行
%kaldi%/egs/aishell/s5/path.sh 或
%kaldi%/egs/aishell/s5/run.sh 或
%kaldi%/egs/yesno/s5/run.sh
等示例项目指令。
export PATH=%kaldi%/tools/python:${PATH}
export IRSTLM=%kaldi%/tools/irstlm
export PATH=${PATH}:${IRSTLM}/bin
1.2.2安装srilm
这是早于kaldi诞生的工具。指令如“ngram-xxx”。
使用脚本安装srilm须要注册账号(收费),所以手动下载安装。
1)先装好gawk。
Macos brew install gawk
Linux sudo apt install gawk
2)然后从这里下载 https://github.com/BitSpeech/SRILM/tags ,本例1.7.2,
解压 SRILM-1.7.2.zip 到 %kaldi%/tools/srilm ,
3)extras/install_srilm.sh文件修改如下:
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 |
#!/usr/bin/env bash current_path=`pwd` current_dir=`basename "$current_path"` if [ "tools" != "$current_dir" ]; then echo "You should run this script in tools/ directory!!" exit 1 fi if [ ! -d liblbfgs-1.10 ]; then echo Installing libLBFGS library to support MaxEnt LMs bash extras/install_liblbfgs.sh || exit 1 fi ! command -v gawk > /dev/null && \ echo "GNU awk is not installed so SRILM will probably not work correctly: refusing to install" && exit 1; # 这里删除下载的代码 cd srilm # 这里删除解压tgz的代码 major=`gawk -F. '{ print $1 }' RELEASE` minor=`gawk -F. '{ print $2 }' RELEASE` micro=`gawk -F. '{ print $3 }' RELEASE` if [ $major -le 1 ] && [ $minor -le 7 ] && [ $micro -le 1 ]; then echo "Detected version 1.7.1 or earlier. Applying patch." patch -p0 < ../extras/srilm.patch fi # set the SRILM variable in the top-level Makefile to this directory. cp Makefile tmpf cat tmpf | gawk -v pwd=`pwd` '/SRILM =/{printf("SRILM = %s\n", pwd); next;} {print;}' \ > Makefile || exit 1 rm tmpf mtype=`sbin/machine-type` echo HAVE_LIBLBFGS=1 >> common/Makefile.machine.$mtype grep ADDITIONAL_INCLUDES common/Makefile.machine.$mtype | \ sed 's|$| -I$(SRILM)/../liblbfgs-1.10/include|' \ >> common/Makefile.machine.$mtype grep ADDITIONAL_LDFLAGS common/Makefile.machine.$mtype | \ sed 's|$| -L$(SRILM)/../liblbfgs-1.10/lib/ -Wl,-rpath -Wl,$(SRILM)/../liblbfgs-1.10/lib/|' \ >> common/Makefile.machine.$mtype make || exit cd .. ( [ ! -z "${SRILM}" ] && \ echo >&2 "SRILM variable is aleady defined. Undefining..." && \ unset SRILM [ -f ./env.sh ] && . ./env.sh [ ! -z "${SRILM}" ] && \ echo >&2 "SRILM config is already in env.sh" && exit wd=`pwd` wd=`readlink -f $wd || pwd` echo "export SRILM=$wd/srilm" dirs="\${PATH}" for directory in $(cd srilm && find bin -type d ) ; do dirs="$dirs:\${SRILM}/$directory" done echo "export PATH=$dirs" ) >> env.sh echo >&2 "Installation of SRILM finished successfully" echo >&2 "Please source the tools/env.sh in your path.sh to enable it" |
4)执行:
1 |
extras/install_srilm.sh |
SRILM download requires some information about you
Usage: extras/install_srilm.sh <name> <organization> <email>
Moonmen:tools moonmen$ extras/install_srilm.sh
mkdir -p include lib bin
/Library/Developer/CommandLineTools/usr/bin/make init
for subdir in misc dstruct lm flm lattice utils zlib; do \
(cd $subdir/src; /Library/Developer/CommandLineTools/usr/bin/make SRILM=%kaldi%/tools/srilm MACHINE_TYPE=macosx OPTION= MAKE_PIC= init) || exit 1; \
done
cd ..; %kaldi%/tools/srilm/sbin/make-standard-directories
/Library/Developer/CommandLineTools/usr/bin/make ../obj/macosx/STAMP ../bin/macosx/STAMP
mkdir ../bin/macosx/
touch ../bin/macosx/STAMP
/Library/Developer/CommandLineTools/usr/bin/make release-headers
for subdir in misc dstruct lm flm lattice utils zlib; do \
(cd $subdir/src; /Library/Developer/CommandLineTools/usr/bin/make SRILM=%kaldi%/tools/srilm MACHINE_TYPE=macosx OPTION= MAKE_PIC= release-headers) || exit 1; \
done
%kaldi%/tools/srilm/sbin/decipher-install -p 0444 cfuncproto.h ../../include
%kaldi%/tools/srilm/sbin/decipher-install -p 0444 zconf.h ../../include
/Library/Developer/CommandLineTools/usr/bin/make depend
for subdir in misc dstruct lm flm lattice utils zlib; do \
(cd $subdir/src; /Library/Developer/CommandLineTools/usr/bin/make SRILM=%kaldi%/tools/srilm MACHINE_TYPE=macosx OPTION= MAKE_PIC= depend) || exit 1; \
done
rm -f Dependencies.macosx
cc -Wall -Wno-unused-variable -Wno-uninitialized -Wno-overloaded-virtual -DHAVE_LIBLBFGS -I%kaldi%/tools/srilm/../liblbfgs-1.10/include -I/usr/include -I. -I../../include -DHAVE_ZOPEN -MM ./option.c ./zio.c ./fcheck.c ./rand48.c ./version.c ./ztest.c | sed -e "s&^\([^ ]\)&../obj/macosx"'$(OBJ_OPTION)'"/\1&g" -e "s&\.o&.o&g" >> Dependencies.macosx
c++ -Wall -Wno-unused-variable -Wno-uninitialized -Wno-overloaded-virtual -DINSTANTIATE_TEMPLATES -DHAVE_LIBLBFGS -I%kaldi%/tools/srilm/../liblbfgs-1.10/include -I/usr/include -I. -I../../include -DHAVE_ZOPEN -MM ./Debug.cc ./File.cc ./MStringTokUtil.cc ./tls.cc ./tserror.cc ./tclmain.cc ./testFile.cc ./testRand.cc | sed -e "s&^\([^ ]\)&../obj/macosx"'$(OBJ_OPTION)'"/\1&g" -e "s&\.o&.o&g" >> Dependencies.macosx
%kaldi%/tools/srilm/sbin/generate-program-dependencies ../bin/macosx ../obj/macosx "" ztest testFile testRand | sed -e "s&\.o&.o&g" >> Dependencies.macosx
make[2]: Nothing to be done for `release-programs'.
/Library/Developer/CommandLineTools/usr/bin/make release-scripts
for subdir in misc dstruct lm flm lattice utils zlib; do \
(cd $subdir/src; /Library/Developer/CommandLineTools/usr/bin/make SRILM=%kaldi%/tools/srilm MACHINE_TYPE=macosx OPTION= MAKE_PIC= release-scripts) || exit 1; \
done
make[2]: Nothing to be done for `release-scripts'.
make[2]: Nothing to be done for `release-scripts'.
%kaldi%/tools/srilm/sbin/decipher-install 0555 compare-sclite ../../bin
%kaldi%/tools/srilm/sbin/decipher-install 0555 cumbin ../../bin
make[2]: Nothing to be done for `release-scripts'.
readlink: illegal option -- f
usage: readlink [-n] [file ...]
Installation of SRILM finished successfully
Please source the tools/env.sh in your path.sh to enable it
1 2 |
source env.sh |
evn.sh文件又多了4行:
export PATH=%kaldi%/tools/python:${PATH}
export IRSTLM=%kaldi%/tools/irstlm
export PATH=${PATH}:${IRSTLM}/bin
export LIBLBFGS=%kaldi%/tools/liblbfgs-1.10
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:${LIBLBFGS}/lib/.libs
export SRILM=%kaldi%/tools/srilm
export PATH=${PATH}:${SRILM}/bin:${SRILM}/bin/macosx
根据需要每次在终端手动设置,或者直接加入环境变量。
之后在终端输入指令的前一两个字母,然后按 Tab 键就能出现相关提示。
1.2.3安装openblas
本步骤,在Linux替代MKL。
查看%kaldi%/tools/extras/install_openblas.sh中OPENBLAS_VERSION对版本的要求,也可修改为新版,
从github.com/xianyi/OpenBLAS/releases下载tar.gz到~/Download中,
执行:
1 |
extras/install_openblas.sh |
安装成功提示
Install OK!
OpenBLAS is installed successfully.
1.3.编译源码
进入 %kaldi%/src 目录。
替换MKL ./configure −−mathlib=OPENBLAS
或使用默认MKL ./configure
Configuring KALDI to use MKL.
Checking compiler g++ ...
Checking OpenFst library in %kaldi%/tools/openfst-1.7.2 ...
Checking cub library in %kaldi%/tools/cub-1.8.0 ...
Performing OS specific configuration ...
On Darwin: Checking for Accelerate framework ...
Configuring for OS X version 10.14 ...
Successfully configured for Darwin with Accelerate framework.
WARNING: CUDA will not be used! If you have already installed cuda drivers
and CUDA toolkit, try using the --cudatk-dir= option. A GPU and CUDA
are required to run neural net experiments in a realistic time.
Kaldi has been successfully configured. To compile:
make -j clean depend; make -j <NCPU>
where
use the smaller of the number of CPUs or the amount of RAM in GB divided by 2,
to stay within safe limits. 'make -j' without the numeric value may not limit
the number of parallel jobs at all, and overwhelm even a powerful workstation,
since Kaldi build is highly parallelized.
1 2 |
make -j8 |
test -d || mkdir
/Library/Developer/CommandLineTools/usr/bin/make depend
The version of configure script matches kaldi.mk version. Good.
****() Installing portaudio
Could not find portaudio tarball pa_stable_v19_20111121.tgz locally, downloading it...
/Library/Developer/CommandLineTools/usr/bin/make -C base/ depend
/Library/Developer/CommandLineTools/usr/bin/make -C bin/ depend
/Library/Developer/CommandLineTools/usr/bin/make -C chain/ depend
rm -f .depend.mk
g++ -M -std=c++14 -I.. -I%kaldi%/tools/openfst-1.7.2/include -O1 -Wall -Wno-sign-compare -Wno-unused-local-typedefs -Wno-deprecated-declarations -Winit-self -DKALDI_DOUBLEPRECISION=0 -DHAVE_EXECINFO_H=1 -DHAVE_CXXABI_H -DHAVE_CLAPACK -msse -msse2 -pthread -g -Wno-mismatched-tags chain-den-graph.cc chain-denominator.cc chain-generic-numerator.cc chain-numerator.cc chain-supervision-test.cc chain-supervision.cc chain-training.cc language-model-test.cc language-model.cc >> .depend.mk
configure.in:55: warning: back quotes and double quotes must not be escaped in: unknown Windows API \"$api\" (do you need --help?)
configure.in:104: warning: The macro `AC_LIBTOOL_WIN32_DLL' is obsolete.
/Library/Developer/CommandLineTools/usr/bin/make -C sgmm2
g++ -std=c++14 -I.. -I%kaldi%/tools/openfst-1.7.2/include -O1 -Wall -Wno-sign-compare -Wno-unused-local-typedefs -Wno-deprecated-declarations -Winit-self -DKALDI_DOUBLEPRECISION=0 -DHAVE_EXECINFO_H=1 -DHAVE_CXXABI_H -DHAVE_CLAPACK -msse -msse2 -pthread -g -Wno-mismatched-tags -I/usr/local/opt/openssl/include -c -o nnet-nnet.o nnet-nnet.cc
---
相当多...
---
g++ -Wl,-rpath -Wl,%kaldi%/tools/openfst-1.7.2/lib -g -L/usr/local/opt/openssl/lib lattice-add-nnlmscore.o ../rnnlm/kaldi-rnnlm.a ../nnet3/kaldi-nnet3.a ../cudamatrix/kaldi-cudamatrix.a ../lat/kaldi-lat.a ../lm/kaldi-lm.a ../fstext/kaldi-fstext.a ../hmm/kaldi-hmm.a ../tree/kaldi-tree.a ../util/kaldi-util.a ../matrix/kaldi-matrix.a ../base/kaldi-base.a %kaldi%/tools/openfst-1.7.2/lib/libfst.dylib -framework Accelerate -lm -lpthread -ldl -o lattice-add-nnlmscore
echo Done
Done
1.4.kaldi内部环境变量
进入 %kaldi%/egs/aishell/s5/ 目录,或者 %kaldi%/egs/wsj/s5 。
查看 path.sh 文件,
第一行 “export KALDI_ROOT=” 对应的是 %kaldi% 根目录。
第二行 [ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ROOT/tools/env.sh 注意env.sh路径正确
第三行 “export PATH=$PWD/utils/:$KALDI_ROOT/tools/openfst/bin:$PWD:$PATH” 注意openfst路径正确。
执行 ./path.sh
使编译kaldi后生成的新指令在当前终端生效。
也可以加入到环境变量。
先添加权限
chmod 777 %kaldi%/tools/env.sh
chmod 777 %kaldi%/tools/config/common_path.sh
chmod 777 %kaldi%/egs/wsj/s5/cmd.sh
chmod 777 %kaldi%/egs/wsj/s5/path.sh
然后把文件全路径加入.bash_profile 或Linux的.bashrc文件:
source %kaldi%/egs/wsj/s5/path.sh
再然后,source一下.bash_profile 或.bashrc,就可以在终端敲入指令的前两三个字母,按tab键出现提示了。
注意如果像本例一样单机学习测试,要修改同目录下的(即path.sh中调用的)cmd.sh,把 queue.pl 修改为 run.pl 。
1 2 3 4 5 6 7 8 9 10 |
export train_cmd=run.pl export decode_cmd="run.pl --mem 2G" export cuda_cmd="run.pl --gpu 1" if [ "$(hostname -d)" == "fit.vutbr.cz" ]; then queue_conf=$HOME/queue_conf/default.conf export train_cmd="run.pl --config $queue_conf --mem 2G --matylda 0.2" export decode_cmd="run.pl --config $queue_conf --mem 3G --matylda 0.1" export cuda_cmd="run.pl --config $queue_conf --gpu 1 --mem 10G --tmp 40G" fi |
2.材料准备
语料:
http://www.openslr.org/18/
http://www.aishelltech.com/kysjcp
本例:https://aishell-1-sample.oss-cn-beijing.aliyuncs.com/AISHELL-1_sample.zip
通常原始语料包括的信息有:录音员的id和性别、录音内容文稿的文本文件、录制的音频文件。
录音员称呼(id):recorder_01。
文稿文件名通常即录音员id,如 recorder_01.txt 。每行一个句子:
● 今天是星期一
● 我有1个梦想
录音文件则放在通常以录音员id为名称的文件夹中,
每个句子对应一个音频文件:
● ~/wavs/recorder_01/today_is_sunday.wav
● ~/wavs/recorder_01/i_hava_a_dream.wav
把音频文件整理在1个目录,如 %kaldi%/egs/xiaogao/wav/ 。
3.材料整理
选择某种方式(python/shell),整理出如下几个生成模型所需的“档案文件”。
3.1.声学模型材料
下面4个文件放在同一个目录,如 %kaldi%/egs/xiaogao/data/ 。
3.1.1.音频id列表文件 wav.scp
wav.scp是一个文本文件,每行内容为:[音频id] [音频路径] ,如:
● recorder_01_wav_01 %kaldi%/egs/xiaogao/wav/recorder_01/today_is_sunday.wav
● recorder_01_wav_02 %kaldi%/egs/xiaogao/wav/recorder_01/i_have_a_dream.wav
此时的音频id通常是录音员id+音频文件名 。
3.1.2.音频与录音员对照文件utt2spk
utt2spk是一个文本文件,每行内容为:[音频id] [录音员] ,如:
● recorder_01_wav_01 recorder_01
● recorder_01_wav_02 recorder_01
即将音频文件和录音员对应起来。
3.1.3.录音员与音频对照文件spk2utt
内容为:[录音员] [音频id 音频id 音频id ...] ,如:
● recorder_01 recorder_01_wav_01 recorder_01_wav_02 recorder_01_wav_03 ...
● recorder_02 recorder_02_wav_01 recorder_02_wav_02 ...
即将录音员和他录制的全部音频对应起来。每个录音员对应1行。
使用 %kaldi%/egs/wsj/s5/utils/spk2utt_to_utt2spk.pl 可以自动将utt2spk转为spk2utt:
utt2spk_to_spk2utt.pl ./utt2spk > ./spk2utt
3.1.4.音频与文稿分词对照文件 text
内容为:[文本id] [录音语句的文本] ,如:
● recorder_01_wav_01 今天是星期一
● recorder_01_wav_02 我有1个梦想
文本id和音频id相同,对应同一个音频文件。
同时,文本须要做分词,词语之间用空格分开。最终格式如:
● recorder_01_wav_01 今天 是 星期一
● recorder_01_wav_03 我 有 一个 梦想
分词规则:
♦ 标点符号(非汉字和英文大小写字母和数字的)都去除,如:+—*/ ; / ( } 换行符 制表符 表情 数学序号 注音符号 拉丁符号等。
♦ 通常汉语数字不分词,如:一百、五十、三千、十万、一个。
♦ 纯汉语数字语句进行分词,如电话号码:幺、八、六、五、五、六、六、幺、幺、零。
♦ 英文单词之间已有空格的,不需再加更多空格。
♦ 分词时/分词前根据音频对文本进行转换,如‘85cm’转为“八十五厘米”、‘3%’转为“百分之三”、‘3.5℃’转为“三点五度”。
中文分词库 :
https://github.com/fxsjy/jieba
3.1.5.语料检验
使用 %kaldi%/egs/wsj/s5/utils/fix_data_dir.sh 验证 wav.scp、utt2spk、spk2utt、text 四个文件是否备齐。
./fix_data_dir.sh %kaldi%/egs/xiaogao/data
3.2.语言模型材料
下面6个文件放到同一个目录,如 %kaldi%/egs/xiaogao/data/dict/ 。
参考 %kaldi%/egs/hkust/s5/local/hkust_prepare_dict.sh
3.2.1.词语清单文件words.list
上一步分词的同时,生成一个保存全部出现过的词语的文件 words.list。
每行内容为1个词(字):[词语] ,如:
● 是
● 今天
● 我
● 有
● 个
● 梦想
● 星期
● 一
words.list主要用来创建针对自己的项目可用的精简版lexicon.txt。临时使用,这一步是可选的。很多博客或视频里讲到,生产中通常使用尽可能大的lexicon.txt。
3.2.2.发音词典文件 lexicon.txt
内容为:[字/词] [发音音素] 。
首先要有一个类似《新华字典》的大的标准字典。
这里使用kaldi内置的中文发音词典。查看%kaldi%/egs/hkust/s5/local/hkust_prepare_dict.sh文件,约144行:http://www.mdbg.net/chindict/export/cedict/cedict_1_0_ts_utf-8_mdbg.txt.gz 。
下载查看,内容如下:
1 2 3 4 5 6 |
上瞼 上睑 [shang4 jian3] /upper eyelid/ 上確界 上确界 [shang4 que4 jie4] /supremum (math.)/least upper bound/ 上空 上空 [shang4 kong1] /overhead/in the sky/ 上空洗車 上空洗车 [shang4 kong1 xi3 che1] /topless car wash/ 上第 上第 [shang4 di4] /top notch/highest quality/ 上等 上等 [shang4 deng3] /highest quality/top-notch/ |
第一列为繁体,第二列为简体。
第三列是中括号包裹的发音,并非标准的汉语拼音。数字1-4对应拼音声调的阴平、阳平、晌声、去声。
第四列为斜杠开头的用英文对词语的翻译和说明。
cedict_1_0_ts_utf-8_mdbg.txt词汇量还是较小的(9.4M,约120293行),最好使用更全(词语量更多)的发音词典。
aishelltech的http://www.aishelltech.com/kysjcp页面底端“Netdisk”链接页面里,有个resource_aishell.tgz解压后得到1个lexicon文件(3.5M,约139874行)也是发音词典,只有汉语对应发音。
1 2 3 4 5 6 7 |
上空 sh ang4 k ong1 上来 sh ang4 l ai2 上来 sh ang4 l ai5 上了 sh ang4 l e5 上楼 sh ang4 l ou2 上落 sh ang4 l uo4 上坡 sh ang4 p o1 |
它和kaldi的发音词典不同之处是 “声母” “韵母” 分开了,用此字典生成phones.txt时,声母韵母也是各自独立的。
然后,从标准字典里查出用到的词,提取出我们自己的小字典。
挨个取words.list中的词语,在cedict_1_0_ts_utf-8_mdbg.txt中查找,提取匹配的发音,不得重复,不能有标点,生成lexicon.txt。
最终内容如:
1 2 3 4 5 6 7 8 9 |
上空 sh ang4 k ong1 上睑 sh ang4 j ian3 <FIL/> FIL <NON/> NON <NPS/> NPS <SPK/> SPK <UNK/> SPN <STA/> STA !SIL SIL |
其中:
“!SIL SIL”,是OOA标识词语,即说两个字之间的停顿/静音,或长时间静默。文件最后一行添加。
“
有些博客及视频中讲解,生产环境通常使用超集的字典(如上面说的2个的合体),即不根据语料创建小字典。
3.2.3.音素集合文件 phones.txt
也有人讲,此文件命名为phone.txt。就是把lexicon.txt中的发音提取出来。内容:[音素] ,如:
● shang4
● hai3
● yan3
● jing1
使用lexicon.txt将发音拿出来即可,要去重,去标点,有效音素包括杂音符号。如:
● s
● hang4
● h
● ai3
● y
● an3
● j
● ing1
3.2.4.静音音素清单silence_phones.txt
内容如下:
● FIL
● NON
● NPS
● SPK
● STA
● SPN
● SIL
这些是phones.txt文件中出现的,无意义的杂音符号。
3.2.5.非静音音素清单nonsilence_phones.txt
内容即phones.txt中去除静音音素,就是把silence_phones.txt出现的去除剩下的。
3.2.6.填充音素extra_questions.txt
或者叫 optional_silence.txt,可选的静音音素,音调和重音之类的信息,可使用silence_phones.txt中的内容。
内容如下:
● SIL
3.3.其它
回到%kaldi%/egs/xiaogao/
创建2个软连接
ln -s %kaldi%/egs/wsj/steps/ . 把steps链接到当前目录,
ln -s %kaldi%/egs/wsj/utils/ . 把utils链接到当前目录。
ln -s %kaldi/egs/wsj/s5/conf/ . 把conf链接到当前目录。
现在 %kaldi%/egs/xiaogao/ 目录结构:
steps/
utils/
conf/
wav/
*.wav
data/
wav.scp
utt2spk
spk2utt
text
dict/
lexicon.txt
phones.txt
silence_phones.txt
nonsilence_phones.txt
optional_silence.txt
模型训练方式:
1)笼统的不区分性别、地域、人员
2)按性别区分,或地域区分
3)按录音人员区分
关于数据拆分:
比如有10个录音员,每人一千条录音,共一万条录音(及对应的文本)。一般的会拿出九千条作训练集,一千条作测试集。
window中的文件转Linux下文件:
方法1:cat dos.txt | tr -d '\r' > lix.txt
方法2:使用dos2unix程序
4.发音词典L.fst
H.fst:HMM模型、C.fst:Context上下文关系、L.fst:Lexicon发音词典、G.fst:Grammar语法模型-语法规则接收器。
4.1.训练
%kaldi%/egs/wsj/s5/utils/prepare_lang.sh参数:
prepare_lang.sh <dict-src-dir> <oov-dict-entry> <tmp-dir> <lang-dir>
● options:
--num-sil-states <number of states> 默认5。静音音素状态划分数量。用1(单态)会缩小模型体积。
--num-nonsil-states <number of states> 默认3, 非静音音素状态划分数量。
--position-dependent-phones (true|false) 默认 true,使用_B、_E、_S、_I划分音素的起始结束状态。
--share-silence-phones (true|false) 默认 false; if true, share pdfs
--sil-prob (probability of silence) 默认0.5,必须大于等于0且小于1
--phone-symbol-table <filename> 默认""。如果非空则使用指定的phones.txt
--unk-fst <text-fst> 默认none
--extra-word-disambig-syms <filename> 默认"";
● dict-src-dir 此语言模型材料的目录里 %kaldi%/egs/xiaogao/data/dict ,
此目录必须包含如下文件:
extra_questions.txt
lexicon.txt
nonsilence_phones.txt
optional_silence.txt
silence_phones.txt
参阅 http://kaldi-asr.org/doc/data_prep.html#data_prep_lang_creating for more info.
● oov-dict-entry OOA标识词,如果出现了不在词典里的字词,用这个替代。
● tmp-dir 临时目录,如 %kaldi%/egs/xiaogao/lang_tmp
● lang-dir 输出目录,如 %kaldi%/egs/xiaogao/lang_out
进入 %kaldi%/egs/xiaogao 目录,执行语句:
utils/prepare_lang.sh --num-sil-states 1 --num-nonsil-states 1 --position-dependent-phones false ./dict '<SIL>' ./lang_tmp ./lang_out
或者进入 %kaldi%/egs/wsj/s5/utils/目录,使用数据的完整路径作为prepare_lang.sh的参数进行训练。
如果出现错误:
sh: ./path.sh: No such file or directory
--> ERROR: L/lang_out//L.fst is not olable sorted
sh: ./path.sh: No such file or directory
--> ERROR: L/lang_out//L_disambig.fst is not olable sorted
--> ERROR (see error messages above)
prepare_lang.sh: error validating output
回退到 %kaldi%/egs/wsj/s5/ 执行 utils/prepare_lang.sh ...
成功结束后,在 lang_out 下生成 L.fst 语音模型文件。
4.2.查看L.fst
使用 %kaldi%/tools/openfst-1.7.2/bin/fstprint 查看L.fst文件内容。
fstprint %kaldi%/egs/xiaogao/lang_out/L.fst
内容如下,有5列数字,以表的形式演示图结构:
0 1 0 0 0.3453523
第1列,输入状态-起点 ①;
第2列,输出状态-终点 ②;
第3列,输入音素,对应了L.fst同目录的phones.txt ♥;
第4列,输出单词,对应了L.fst同目录的words.txt ♣;
第5列,概率 ♦。
有向图的一条边:① -- ♥ ; ♣/♦ --> ②
可以指定关联的文件进行查看:
fstprint --isymbols=phones.txt --osymbols=words.txt L.fst
使用 %kaldi%/tools/openfst-1.7.2/bin/fstdraw 查看L.fst文件内容。
brew install ghostscript graphviz chkuni-ukai-fonts
fstdraw --isymbols=phones.txt --osymbols=words.txt L.fst > L.dot
dot -Tjpg L.dot > L.jpg
dot生成jpg这一步是非常慢的,因为图的数据结构非常复杂,图片会相当大,即便生成也很难查看。
4.3.tmp-dir下的临时文件
● align_lexicon.txt 词典。词语+发音音素对应的Begin、Internal、End、Singleton状态
● lex_ndisambig 词典。最大同音词字数量+1
● lexiconp.txt 词典。添加词频
● lexiconp_disambig.txt 词典。同音词消除歧义,同音字词添加#标注。#1 - #同音词字数量
● phone_map.txt 音素集合。添加音素的Begin、Internal、End、Singleton状态
4.4.lang-dir下的文件
● L.fst 字典的加权有限状态转换器
● L_disambig.fst 去岐后的
● oov.int 词典之外的词添加id
● oov.txt 词典之外的词。识别结果为
● phones [文件夹]
▶ align_lexicon.ini 字词+BIES音素转id
▶ align_lexicon.txt 字词+字词+BIES
▶ context_indep.ini
▶ context_indep.txt 静音音素列出BIES状态
▶ disambig.csl
▶ disambig.ini
▶ disambig.txt 同音词歧义编号#
▶ extra_questions.ini
▶ extra_questions.txt 按BIES状态整理音素
▶ nonsilence.csl
▶ nonsilence.ini
▶ nonsilence.txt 去除静音的+BIES
▶ optional_silence.csl
▶ optional_silence.ini
▶ optional_silence.txt 静音音素
▶ roots.ini
▶ roots.txt 音素的树
▶ sets.ini
▶ sets.txt 发音音素列出BIES状态
▶ silence.csl
▶ silence.ini
▶ silence.txt 静音音素列出BIES状态。似乎和context_indep.txt相同
▶ wdisambig.txt
▶ wdisambig_phones.ini
▶ wdisambig_words.ini
▶ word_boundary.ini
▶ word_boundary.txt 明文显示音素的Begin、Internal、End、Singleton状态
● phones.txt 添加BIES状态的音素集合
● topo 表述拓扑的文本文件
● words.txt 添加id的词
5.Grammar模型G.fst
使用《3.1.4.音频与文稿分词对照文件 text》创建的text文件,生成一个去除了第一列音频id的 text.txt 文件。放到一个目录,如 %kaldi%/egs/xiaogao/gram 。
text.txt内容如:
● 今天 是 星期一
● 我 有 一个 梦想
5.1.统计文件
上文《1.2.2》及《1.4》后可以直接在终端调用ngram-count指令了。
%kaldi%/tools/srilm/bin/macosx/ngram-count 的参数:
● -text 指定分词文件。%%kaldi%/egs/xiaogao/gram/text.txt
● -order 指定生成几元的n-gram。计数时每行“短句”最大分词数量。
● -write 指定计数统计文件生成路径。
进入 %kaldi%/egs/xiaogao/gram 目录
ngram-count -text ./text.txt -order 3 -write ./text.count
得到text.count文件。
5.2.统计模型
继续使用ngram-count指令。
● -read 上一步生成的text.count文件
● -order 上一步指定的数值
● -lm 模型生成路径
● -interpolate 开启差值平滑
● -kndiscount 折扣/回退算法,有如下几种:
▶ -addsmooth。 “加-k”折扣算法
▶ -cdiscount。 使用Ney的绝对折扣算法,使用参数discount作为折扣常数,discount必须要介于0和1之间。
▶ -wbdiscount。 使用Witten-Bell折扣算法。
▶ -ndiscount。 使用Ristad自然折扣算法。
▶ -ukndiscount。 使用“原始Kneser-Ney”的折扣算法。
▶ -kndiscount。 经过插值的Kneser-Ney折扣算法,输出的是经过Kneser-Ney算法修正之后的计数。
▶ 如果不设定,默认为Good-Turing折扣算法。
ngram-count -read ./text.count -order 3 -lm ./text.lm -interpolate -kndiscount
得到text.lm文件。
关于剪枝,可以压缩模型大小。
https://www.bilibili.com/video/BV19a4y1h7cB?p=4 1:48:00
https://blog.csdn.net/xmdxcsj/article/details/50321613
5.3.G.fst
方法1:
还在 %kaldi%/egs/xiaogao/gram 目录下,
使用 %kaldi%/egs/wsj/s5/utils/format_lm_sri.sh 脚本,参数:
● <lang-dir> 《4.1.训练》章节指定的输出目录:如 %kaldi%/egs/xiaogao/lang_out 。
● <arpa-LM> 上一步生成的text.lm
● <lexicon> 可选。《3.2.2.发音词典文件 lexicon.txt》
● <out-dir> 模型生成的目录,不包括文件名。
format_lm_sri.sh ../lang_out ./text.lm ../data/dict/lexicon.txt ./
指令成功后,./ 目录下得到G.fst文件。
方法2:
还在 %kaldi%/egs/xiaogao/gram 目录下,
使用 %kaldi%/src/lmbin/arpa2fst 工具,参数:
● options:
--disambig-symbol 消岐符号。使用#0,则会进行以下处理:
▶ 删除空边。如果一个状态上只发出空边(即回退边),则删除该边并状态合并。从语义上讲是删除了不存在的二元词历史所映射的状态,达到减小状态数的目的。
▶ 用特殊符号#0替换回退边上的输入空符号。
▶ 将开始结束标签<s> </s>替换为空。
--read-symbol-table 《4.1.训练》章节指定的输出目录里的words.txt文件:%kaldi%/egs/xiaogao/lang_out/words.txt
● <arpa-LM> 上一步生成的text.lm
● <out-dir> 模型生成的目录包括文件名。
arpa2fst --disambig-symbol=#0 --read-symbol-table=../lang_out/words.txt ./text.lm ./G.fst
5.4.查看G.fst
结合上文《4.2.查看L.fst》使用 %kaldi%/tools/openfst-1.7.2/bin/fstprint 查看L.fst文件内容的操作。
还在 %kaldi%/egs/xiaogao/gram 目录下,
fstprint --isymbols=../lang_out/phones.txt --osymbols=../lang_out/words.txt ./G.fst > G.txt
或 %kaldi%/tools/openfst-1.7.2/bin/fstdraw
fstdraw --isymbols=../lang_out/phones.txt --osymbols=../lang_out/words.txt ./G.fst > G.dot
dot -Tjpg ./G.dot > G.jpg
6.声学模型final.mdl
6.1.H.fst
梅尔倒谱系数,一种语音特征。
%kaldi%/egs/wsj/s5/steps/make_mfcc.sh
make_mfcc.sh [options] <data-dir> [<log-dir> [<mfcc-dir>]
● Options:
--mfcc-config <config-file> 设置了compute-mfcc-feats参数的文件。
--nj <nj> 拆分成并行任务数量。
--cmd <run.pl|queue.pl <queue opts>> 如何执行任务,单机就用run.pl。
--write-utt2num-frames <true|false> true会生成一个utt2num_frames文件,记录每个音频有多少帧
--write-utt2dur <true|false> true会生成一个utt2dur file文件
● data-dir: 《3.1.4.音频与文稿分词对照文件 text》的路径 %kaldi%/egs/xiaogao/data
● log-dir: 已存在日志目录,默认同data-dir。如 %kaldi%/egs/xiaogao/log
● mfcc-dir: 已存在输出目录,默认同data-dir。如 %kaldi%/egs/xiaogao/mfcc
进入 %kaldi%/egs/xiaogao/ 目录,
steps/make_mfcc.sh --nj 1 ./data ./log ./mfcc
有多少音频文件,就在 %kaldi%/egs/xiaogao/mfcc 下生成多少scp文件和ark文件
6.2.提取特征均值
%kaldi%/egs/wsj/s5/steps/steps/compute_cmvn_stats.sh 参数:
compute_cmvn_stats.sh [options] <data-dir> [<log-dir> [<cmvn-dir>] ]
● Options:
--fake
--two-channel
--fake-dims <n1:n2>
● data-dir %kaldi%/egs/xiaogao/data/
● log-dir 不设置,则默认同data-dir
● cmvn-dir 不设置,则默认同data-dir
进入 %kaldi%/egs/xiaogao/ 目录,
steps/compute_cmvn_stats.sh ./data ./cmvn_log ./cmvn_out
6.3.训练final.mdl
%kaldi%/egs/wsj/s5/steps/train_mono.sh 参数:
train_mono.sh [options] <data-dir> <lang-dir> <exp-dir>
● options:
--config <config-file> 配置文件
--nj <nj> 线程数
--cmd (utils/run.pl|utils/queue.pl <queue opts>) 如何执行
● data-dir %kaldi%/egs/xiaogao/data/
● lang-dir %kaldi%/egs/xiaogao/lang_out/
● exp-dir %kaldi%/egs/xiaogao/mono/
进入 %kaldi%/egs/xiaogao/ 目录,
steps/train_mono.sh --nj 1 ./data ./lang_out ./mono
./mono 下生成final.mdl声学模型文件。
7.解码网络模型HCLG.fst
%kaldi%/egs/wsj/s5/utils/mkgraph.sh 参数:
mkgraph.sh [options] <lang-dir> <model-dir> <graphdir>
● options:
--remove-oov true时,任何包含OOV的将从G.fst编译.
--transition-scale
--self-loop-scale 参阅 http://kaldi-asr.org/doc/hmm.html#hmm_scale.
● lang-dir
● model-dir
● graphdir
进入 %kaldi%/egs/xiaogao/ 目录,
utils/mkgraph.sh ./lang_out ./mono ./graph
./graph 下生成HCLG.fst 。
可以使用 fstprint,或 fstdraw+dot 查看。
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/3633.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设