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

首先,下载kaldi,kaldi会包含很多语言模型与声学模型,(关于kaldi下载,可以参考我的另一篇文章:https://blog.csdn.net/qq_57461500/article/details/139840841?spm=1001.2014.3001.5502)本次基于Aishell1数据集的实战也会在kaldi上进行。在本文进行流程的推进时,会尽可能搞懂重要的几个脚本,让我们一起学习吧。

1 简要介绍

在这里插入图片描述

总共178小时,400个人讲,其中训练集340个人,测试解20个人,验证集40个人,每个人大概讲三百多句话,每个人讲的话都放在一个文件夹里面。

PS:文件压缩包就有将近17个g,所以我们在设置虚拟机容量时最好设置的大一点,我一般直接设80g,kaldi加数据集就将近45g,还要解压。

2 语音识别模型

在这里简单地介绍一下Aishell1训练时会用到的几个声学模型和语言模型,想要对语音模型进行一个详细的了解,敬请关注我其他的几篇文章,我会对语言模型进行一个梳理。
言归正传,在进行Aishell的训练时

我们会用到的声学模型

  • 3-gram Language Model:3-gram模型是n-gram模型的一种,其中n代表考虑的词的数量。

我们会用到的语言模型

  • Monophone Model (单音素模型)
  • Tristone Model (三音素模型)
  • LDA+MLLT Model:引入线性判别分析(LDA)和最大似然线性变换(MLLT)来改进特征表示。
  • nnet3 TDNN
  • Chain Model

3 语音识别原理

4 run.sh

此脚本位于/path/to/kaldi/egs/aishel/s5中,是Aishell 1训练中的主脚本,其实我们只需要无脑run就好了,但是对于处于学习中的人们来说,这跟没做也没区别,所以作者在此拆开脚本,尽可能地搞清楚,当然,作者也是处于学习阶段,记录下来也是为了更好地掌握,所以有错误的话欢迎大家指出,也欢迎大佬指出更好的学习方法。
话不多说,我们先看run.sh这个脚本的内容
首先是数据准备阶段
run.sh中,这部分的代码是这样的

# Lexicon Preparation,
local/aishell_prepare_dict.sh $data/resource_aishell || exit 1;

# Data Preparation,
local/aishell_data_prep.sh $data/data_aishell/wav $data/data_aishell/transcript || exit 1;

其中包含两个脚本aishell_prepare_dict.shaishell_data_prep.sh,分别
用于准备字典(将单词映射到音素)和处理音频文件、转录文本,生成所需的数据文件。其中

aishell_prepare_dict.sh的代码为

#!/usr/bin/env bash  shebang行,告诉系统此脚本应用Bash进行
# Copyright 2017 Xingyu Na
# Apache 2.0

. ./path.sh           #环境变量脚本 export ...

[ $# != 1 ] && echo "Usage: $0 <resource-path>" && exit 1;  #检查命令行参数的数量是否不等于1。如果不是,打印使用方法并退出。
res_dir=$1   #将第一个命令行参数(资源路径)赋值给变量res_dir
dict_dir=data/local/dict
mkdir -p $dict_dir
cp $res_dir/lexicon.txt $dict_dir  #将资源目录下的lexicon.txt文件复制到字典目录。

cat $dict_dir/lexicon.txt | awk '{ for(n=2;n<=NF;n++){ phones[$n] = 1; }} END{for (p in phones) print p;}' | \
  perl -e 'while(<>){ chomp($_); $phone = $_; next if ($phone eq "sil"); m:^([^\d]+)(\d*)$: || die "Bad phone $_"; $q{$1} .= "$phone "; } } foreach $l (values %q) {print "$l\n";}'
#cat输出lexicon.txt的内容。
#awk读取每一行,将除了第一个字段外的所有字段(假设是音素)存储到一个数组phones中。
#perl脚本读取awk的输出,去除静音音素sil,然后根据音素的数字后缀(如果有的话)进行分组,最后输出每个组的音素列表。

sort -k1 > $dict_dir/nonsilence_phones.txt  #对Perl脚本的输出进行排序,并重定向到nonsilence_phones.txt
echo sil > $dict_dir/silence_phones.txt  #创建一个包含sil的文件silence_phones.txt,表示静音音素。
echo sil > $dict_dir/optional_silence.txt #可选静音因素

cat $dict_dir/silence_phones.txt | awk '{printf("%s ", $1);} END{printf "\n";}' > $dict_dir/extra_questions.txt
cat $dict_dir/nonsilence_phones.txt | perl -e 'while(<>){ foreach $p (split(" ", $_)) { $p =~ m:^([^\d]+)(\d*)$: || die "Bad phone $_"; $q{$2} .= "$p "; } } foreach $l (values %q) {print "$l\n";}' >> $dict_dir/extra_questions.txt
#结合了静音和非静音音素,可能用于构建语音识别系统中的状态聚类或决策树,帮助区分不同的发音状态

echo "$0: AISHELL dict preparation succeeded"
exit 0

对字典准备脚本aishell_prepare_dict.sh进行了逐行的解析,发现此脚本对aishell 1数据集中的lexicon.txt进行了拆分和分类,生成了非静音音素列表 (nonsilence_phones.txt)、静音音素列表 (silence_phones.txt)、可选静音列表 (optional_silence.txt)、额外问题列表 (extra_questions.txt)四个文本文件,组成了字典。

aishell_data_prep.sh脚本的代码为

#!/usr/bin/env bash
# Copyright 2017 Xingyu Na
# Apache 2.0

. ./path.sh || exit 1;

if [ $# != 2 ]; then
	echo "Usage: $0 <audio-path> <text-path>"  #打印脚本的使用方法,即需要两个参数<audio-path> <text-path>
	echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript"  
	exit 1;
fi

aishell_audio_dir=$1
aishell_text=$2/aishell_transcript_v0.8.txt  #加上文件名赋值给aishell_text
train_dir=data/local/train
dev_dir=data/local/dev
test_dir=data/local/test
tmp_dir=data/local/tmp
#定义了训练集、验证集、测试集和临时目录的变量。
mkdir -p $train_dir
mkdir -p $dev_dir
mkdir -p $test_dir
mkdir -p $tmp_dir

if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then  #检查音频目录和文本文件是否存在,如果任一不存在,则进入if块。
	echo "Error: $0 requires two directory arguments"
  	exit 1;
fi

find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist  #在音频目录下查找所有以.wav结尾的文件,并将结果重定向到临时文件wav.flist(存储路径)
n=`cat $tmp_dir/wav.flist | wc -l`
[ $n -ne 141925 ] && \
  echo Warning: expected 141925 data data files, found $n  #计算找到的WAV文件数量,并与预期数量比较,如果不相等则打印警告。
grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1;
grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1;
grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1;
rm -r $tmp_dir

# Transcriptions preparation
for dir in $train_dir $dev_dir $test_dir; do  #开始准备转录文本,对每个数据集目录执行循环。
	echo Preparing $dir transcriptions
	sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list  #使用sed和awk从WAV文件列表中提取文件名(不含扩展名),并将结果写入utt.list(音频编号)
	sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{i=NF-1;printf("%s %s\n",$NF,$i)}' > $dir/utt2spk_all(音频编号和对应的说话人)
	paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all  #将将utt.list和wav.flist合并,生成wav.scp_all(音频编号和对应的路径)
	utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt   #使用filter_scp.pl脚本过滤出对应的转录文本
	awk '{print $1}' $dir/transcripts.txt > $dir/utt.list  #从转录文本中提取第一列,更新utt.list
	utils/filter_scp.pl -f 1 $dir/utt.list $dir/utt2spk_all | sort -u > $dir/utt2spk
	utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp
	sort -u $dir/transcripts.txt > $dir/text  #对转录文本进行排序,生成text文件。
	utils/utt2spk_to_spk2utt.pl $dir/utt2spk > $dir/spk2utt  #使用utt2spk_to_spk2utt.pl脚本从utt2spk生成spk2utt文件。
done

mkdir -p data/train data/dev data/test
for f in spk2utt utt2spk wav.scp text; do
  cp $train_dir/$f data/train/$f || exit 1;
  cp $dev_dir/$f data/dev/$f || exit 1;
  cp $test_dir/$f data/test/$f || exit 1;
done

echo "$0: AISHELL data preparation succeeded"
exit 0;

此脚本的主要目的是准备和处理AISHELL数据集,生成语音识别系统所需的一系列数据文件目录结构。生成了六个文件:

  • WAV文件列表 (wav.flist):在临时目录中生成一个包含所有WAV文件路径的列表。
  • 文件名列表 (utt.list):为每个数据集生成一个文件名列表,文件名不包含.wav扩展名
  • 说话人-录音对应文件 (utt2spk 或 utt2spk_all):生成一个将每个录音文件映射到其对应的说话人的文件。
  • 录音文件路径映射 (wav.scp 或 wav.scp_all):为每个数据集生成一个文件,列出所有录音文件的路径。
  • 转录文本 (text):从原始的转录文件中提取与WAV文件对应的转录文本,并进行排序,生成干净的文本文件。
  • 说话人列表 (spk2utt):从utt2spk文件生成一个反向映射,列出每个说话人的所有录音文件。
  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值