数据分集

数据采集自有声书网站,首先对每个句子做一遍语音识别,识别模型使用WSJ示例中的声学模型,语言模型使用二元文法,语言模型数据为语音数据对应的电子书文本。根据识别结果,统计每个说话人的WER,从低到高排序,前一半标记为clean,表示这些说话人语音比较清晰,其余标记为other。

从clean数据中,随机抽取20名男性和20名女性作为开发集(dev-clean),剩余说话人抽取相同规模的测试集(test-clean),其余作为训练集。训练集随机分为100小时和360小时的子集(train-clean-100和train-clean-360)。

在other数据中,WER从低到高排序,在第三个四分位点附近随机选择开发集(dev-other)合测试集(test-other),剩余作为训练集(train-other-500)。

分集结果为:

子集 每人时长(分钟) 时长(小时) 女性数目 男性数目 说话人数目
dev-clean 8 5.4 20 20 40
test-clean 8 5.4 20 20 40
dev-other 5.3 10 16 17 33
test-other 5.1 10 17 16 33
train-clean-100 100.6 25 125 126 251
train-clean-360 363.6 25 439 482 921
train-other-500 496.7 30 564 602 1166

对应的数据目录为:

BOOKS.TXT
CHAPTERS.TXT
dev-clean
dev-other
LICENSE.TXT
README.TXT
SPEAKERS.TXT
test-clean
test-other
train-clean-100
train-clean-360
train-other-500

除了7个分集目录外,其余文件内容分别书籍信息(编号|书名)、章节信息(编号|阅读者编号|时长|所属子集)、说话人信息(ID|READER|MINUTES|SUBSET|PROJ.|BOOK ID|CH. TITLE|PROJECT TITLE)。

每个分集中目录结构为说话人编号/章节编号/数据,数据结构如下:

LibriSpeech/train-clean-100/103/1240
├── 103-1240.trans.txt
├── 103-1240-0001.flac
├── 103-1240-0002.flac
├── 103-1240-0003.flac
├── 103-1240-0004.flac
├── 103-1240-0005.flac
├── 103-1240-0006.flac
├── 103-1240-0007.flac
├── 103-1240-0008.flac
├── 103-1240-0009.flac
├── 103-1240-0010.flac
├── 103-1240-0011.flac
...

*.flac为音频文件,*.trans.txt记录每个音频文件对应的文本内容。

数据预处理

因为不同数据库原始格式不同,所以要给每个数据库单独写预处理脚本,以便Kaldi处理。

将原始数据转换为Kaldi数据文件夹

运行local/data_prep.sh

data
├── dev_clean
│   ├── spk2gender
│   ├── spk2utt
│   ├── text
│   ├── utt2spk
│   └── wav.scp
├── dev_other
│   ├── spk2gender
│   ├── spk2utt
│   ├── text
│   ├── utt2spk
│   └── wav.scp
├── test_clean
│   ├── spk2gender
│   ├── spk2utt
│   ├── text
│   ├── utt2spk
│   └── wav.scp
├── test_other
│   ├── spk2gender
│   ├── spk2utt
│   ├── text
│   ├── utt2spk
│   └── wav.scp
├── train_clean_100
│   ├── spk2gender
│   ├── spk2utt
│   ├── text
│   ├── utt2spk
│   └── wav.scp
└── local└── lm├── 3-gram.arpa.gz├── 3-gram.pruned.1e-7.arpa.gz├── 3-gram.pruned.3e-7.arpa.gz├── 4-gram.arpa.gz├── g2p-model-5├── librispeech-lexicon.txt├── librispeech-lm-corpus.tgz├── librispeech-vocab.txt├── lm_fglarge.arpa.gz -> 4-gram.arpa.gz├── lm_tglarge.arpa.gz -> 3-gram.arpa.gz├── lm_tgmed.arpa.gz -> 3-gram.pruned.1e-7.arpa.gz└── lm_tgsmall.arpa.gz -> 3-gram.pruned.3e-7.arpa.gz7 directories, 37 files

除了spk2gender记录说话人性别外,其他和例子yesno结果类似。这些Kaldi脚本可接受的标准形式文件我们称为表单文件。生成表单的关键语句如下,具体形成表单文件步骤见脚本。

# wav.scp
find -L $chapter_dir/ -iname "*.flac" | sort | xargs -I% basename % .flac | awk -v "dir=$chapter_dir" '{printf "lbi-%s flac -c -d -s %s/%s.flac |\n", $0, dir, $0}' >>$wav_scp || exit 1;
# text
sed -e 's/^/lbi\-/' $chapter_trans >> $trans
# utt2spk
awk -v "reader=$reader" -v "chapter=$chapter" '{printf "lbi-%s lbi-%s-%s\n", $1, reader, chapter}' <$chapter_trans >>$utt2spk || exit 1
# spk2gender
reader_gender=$(egrep "^$reader[ ]+\|" $spk_file | awk -F'|' '{gsub(/[ ]+/, ""); print tolower($2)}')
echo "lbi-${reader}-${chapter} $reader_gender" >>$spk2gender
# spk2utt
utils/utt2spk_to_spk2utt.pl <$utt2spk >$spk2utt || exit 1

需要注意一点,utt2spk中,说话人是由说话人编号加上章节编号标注的,因为Kaldi对说话人的定义并不局限于自然人,而是一种一致的发音状态。

生成好表单后,需要进行检查:

# 检查行数是否对应
if $prepare_text; thenntrans=$(wc -l <$trans)nutt2spk=$(wc -l <$utt2spk)! [ "$ntrans" -eq "$nutt2spk" ] && \echo "Inconsistent #transcripts($ntrans) and #utt2spk($nutt2spk)" && exit 1;
fi
# 检查文件内容 --no-feats表示跳过feats检查,utils/validate_data_dir.sh在每次生成新的表单时都要调用
utils/validate_data_dir.sh --no-feats $($prepare_text || echo "--no-text") $dst || exit 1;

Kaldi输入输出机制

在Kaldi中,所有数据文件都是以表单形式储存的。Kaldi定义了两种表单,分别是列表(Script-file)表单和存档(Archive)表单,在此基础上建立其特有的输入输出机制。

列表表单

默认但不限制扩展名为.scp,格式如下:

file1_index /path/to/file1
file2_index /path/to/file2

空格前的字符串是表单索引,之后的内容是文件定位符,用于定位文件。文件定位符可以是磁盘中的物理地址,也可以是以管道形式表示的内存地址,如:

# 物理地址
103-1240-0000 /path/to/103-1240-0000.wav
# 管道内存
103-1240-0000 flac -c -d -s /path/to/103-1240-0000.flac|
# 存档文件
103-1240-0000 /path/to/raw_mfcc_train_clean_100.ark:17
103-1240-0000 /path/to/raw_mfcc_train_clean_100.ark:17[:,0:9] # 获取前10维

存档表单

存档表单用于存储数据,可以使文本数据,也可以是二进制数据,一般扩展名为.ark。存档表单没有行的概念。

对于文本类型的存档文件,每个元素以换行符结尾,虽然展现形式很像列表表单,但是本质不同。

file1_index first text\nfile2_index second text\n

在二进制存档表单中,索引以每个字符对应的ASCII值存储,然后是一个空格加“\0B”,"\0B"是区分文本存档表单和二进制存档表单的标识。索引之后是二进制的表单元素内容,直到下一个索引。在读取二进制存档表单时可以通过内容本身判断元素占空间大小,这些信息保存在文件头中,格式如下:

binary_index1 \0B<header><content>binary_index2 \0B<header><content>

读写声明符

除了生成以上文件外,还可以使用一下命令,提取音频的时长信息:

$cmd JOB=1:$nj $data/log/get_durations.JOB.log wav-to-duration --read-entire-file=$read_entire_file scp:$sdata/JOB/wav.scp ark,t:$sdata/JOB/utt2dur

其中,scp:ark,t:称为读写声明符,分别表示列表表单和文本存档表单,此外,还可同时存储一个存档表单和一个列表表单,声明符为ark,scp:。冒号后的是表单文件名,文件名可以是:

  • 磁盘路径。
  • 标准输入(用-表示)。
  • 管道符号。
  • 磁盘路径加偏移定位符。

写法和列表表单的元素内容相似。

# 管道输入,标准输出
wav-to-duration 'scp:echo "utt1 data/103-1240-0000.wav" |' ark,t:-
# 管道输入,文件输出
wav-to-duration 'scp:echo "utt1 data/103-1240-0000.wav" |' ark,t:data/utt2dur
# 管道输入,输出到压缩文件
wav-to-duration 'scp:echo "utt1 data/103-1240-0000.wav" |' 'ark,t:| gzip -c > data/utt2dur.gz'

表单属性

读写声明符另一个重要部分是表单属性,如ark,t:中的t就表示使用文本模式的存档表单。相应的,表单属性也分为读属性和写属性。

写属性包括:

  • 表单类型:scparkark,scp

  • 二进制模式:b

  • 文本模式:t

  • 刷新模式:fnf,声明是否在每次写操作后刷新数据流,默认刷新

  • 宽容模式:p,如果表单某个元素对应存档内容无法获取,跳过该元素而不提示错误。

读属性包括:

  • 表单类型:scpark

  • 单次访问:ono,告知程序表单中每个索引只出现一次

  • 宽容模式:p,如果表单某个元素对应存档内容无法获取,跳过该元素而不提示错误

  • 有序表单:sns,表示表单是有序的

  • 有序访问:csncs,表单元素将被顺序访问

常用数据表单和处理脚本

Kaldi数据预处理的表单文件都保存在数据文件夹中,在通用脚本文件夹utils中有个叫data的文件夹,其中大部分脚本都是用于处理数据文件夹的,输入和输出都是文件夹路径。

在Kaldi脚本定义中,一个数据文件夹是其包含的若干数据形成的一个数据集,文件夹中的表单文件定义了关于这个数据集的所有信息,如音频文件路径、标注内容、特征文件路径、说话人信息等。其中表单文件的文件名都是在通用脚本中定义好的,具体如下。

列表表单

句子音频表单

文件名:wav.scp

例子:speaker_chapter_utterance /path/to/audio/speaker/filename.wav

声学特征表单

文件名:feats.scp

例子:speaker_chapter_utterance /path/to/s5/mfcc/raw_mfcc_filename.ark:17

谱特征归一化表单

文件名:cmvn.scp

例子:speaker_chapter_utterance /path/to/s5/mfcc/cmvn_train_filename.ark:9

VAD信息表单

文件名:vad.scp

例子:speaker_chapter_utterance /path/to/s5/mfcc/vad_train_filename.ark:9

存档表单

说话人映射表单

文件名:utt2spk

例子:speaker_chapter_utterance speaker_chapter

文件名:spk2utt

例子:speaker_chapter speaker_chapter_utterance1 speaker_chapter_utterance2 speaker_chapter_utterance3 ...

标注文本文件

文件名:text

例子:103-1240-0000 CHAPTER ONE MISSUS RACHEL ...

切分信息表单

文件名:segments

例子:103-1240-0000 103-1240 2.81 6.41

VTLN相关系数表单

  • 说话人性别映射:spk2gender
  • 说话人卷曲因子映射:spk2warp
  • 句子卷曲因子映射:utt2warp

句子时长表单

文件名:utt2dur

例子:103-1240-0000 14.085

数据文件夹处理脚本

脚本名 功能简介
combine_data.sh 将多个数据文件夹合并为一个,并合并对应的表单
combine_short_segments.sh 合并原文件夹中的短句,创建一个新的数据文件夹
copy_data_dir.sh 复制原文件夹,床架一个新的数据文件夹,可指定说话人说句子的前缀、后缀,复制一部分数据
extract_wav_segments_data_dir.sh 利用原文件夹中的分段信息,切分音频文件,并保存为一个新的数据文件夹
fix_data_dir.sh 为原文件夹保留一个备份,删除没有同时出现在多个表单中的句子,并修正排序
get_frame_shift.sh 获取数据文件夹的帧移信息,打印到屏幕
get_num_frames.sh 获取数据文件夹的总帧数信息,打印到屏幕
get_segments_for_data.sh 获取音频时长信息,转换为segments文件
get_utt2dur.sh 获取音频时长信息,生成utt2dur文件
limit_feature_dim.sh 根据原数据文件夹中的feats.scp,取其部分维度的声学特征,保存到新创建的数据文件夹中
modify_speaker_info.sh 修改原数据文件夹中的说话人索引,构造“伪说话人”,保存到新创建的数据文件夹中
perturb_data_dir_speed.sh 为原数据文件夹创建一个速度扰动的副本
perturb_data_dir_volume.sh 修改数据文件夹中的wav.scp文件,添加音量扰动效果
remove_dup_utts.sh 删除原数据文件夹中文本内容重复超过指定次数的句子,保存到新创建的数据文件夹中
resample_data_dir.sh 修改数据文件夹中的feats.scp进行特征偏移,保存到新创建的数据文件夹中
shift_feats.sh 根据原数据文件夹中的feats.scp进行特征偏移,
split_data.sh 将数据文件夹分成指定数目的多个子集,保存到原数据文件夹中以split开头的目录下
subsegment_data_dir.sh 根据一个额外提供的切分信息文件,将原数据文件夹重新切分,创建一个重切分的数据文件夹
subset_data_dir.sh 根据指定的方法,床架一个原数据文件夹的子集,保存为新创建的数据文件夹
validata_data_dir.sh 检查给定数据文件夹的内容,包括排序是否正确、元素索引是否对应等

语言模型

在开始训练声学模型前,需要定义发音词典、音素集和HMM的结构。在进行音素上下文聚类时,还可以通过指定聚类问题的方式融入先验知识。这些步骤均在Librispeech总脚本第三阶段完成。

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# 根据发音词典,生成语言文件夹langutils/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

发音词典与音素集

data/local/lm中,有3个关于发音词典的文件

  • librispeech-vocab.txt:包含了语言模型训练数据中词频最高的200000个词
  • librispeech-lexicon.txt:包含了这些词的发音,共206508条
  • g2p-model-5:训练好的英文发音模型

整理发音词典会生成以下四个文件:

  • nonsilence_phones.txt:所有非静音音素

    AA AA0 AA1 AA2
    AE AE0 AE1 AE2
    AH AH0 AH1 AH2
    ...
    

    例如AA AA0 AA1 AA2是同一个基本音素AA与不同中银标记组合成的带重音音素。中文中,可以将同一个基本音素与不同音调标记组合成带调音素。

  • extra_questions.txt:构建音素的声学上下文决策树时会遇到的基本问题,每行对应一个聚类问题,如这个例子中使用重音来聚类

    SIL SPN
    AA AE AH AO AW AY B CH D DH EH ER EY F G HH IH IY JH K L M N NG OW OY P R S SH T TH UH UW V W Y Z ZH
    AA2 AE2 AH2 AO2 AW2 AY2 EH2 ER2 EY2 IH2 IY2 OW2 OY2 UH2 UW2
    AA1 AE1 AH1 AO1 AW1 AY1 EH1 ER1 EY1 IH1 IY1 OW1 OY1 UH1 UW1
    AA0 AE0 AH0 AO0 AW0 AY0 EH0 ER0 EY0 IH0 IY0 OW0 OY0 UH0 UW0
    
  • optional_silence.txt:定义了用于填充词间静音的音素

  • silence_phones.txt:定义了所有用来表示无效音内容的音素,例子中SIL表示静音,SPN表示有声音但是无法识别的声音片段(如集外词)

整理发音词典最后一步是生成lexicon.txt文件,包含了前面统计的发音词典的全部内容,并汇入了关于无效语音的发音规则。

!SIL SIL
<SPOKEN_NOISE> SPN
<UNK> SPN
A  AH0
A  EY1
A''S  EY1 Z
A'BODY EY1 B AA2 D IY0
A'COURT    EY1 K AO2 R T
A'D    EY1 D
A'GHA  EY1 G AH0
...

Kaldi支持定义发音概率,对不同发音加以区分,这里没有定义,全部默认为1.0,保存在lexiconp.txt中。

语言文件夹

准备好发音词典文件夹后,就可以开始用Kaldi的通用脚本生成语言文件夹data/lang了。生成内容如下:

data/lang_nosp
├── L_disambig.fst # 在L.fst基础加上消歧符号
├── L.fst # 发音词典将音素和词替换为索引后生成的FST
├── oov.int # 指出词索引文件中那个词条是集外词
├── oov.txt
├── phones # 定义关于音素的各种属性
│   ├── align_lexicon.* # 将第一列内容重复了一次的发音文件,用来除了词网格文件和一些识别结果文件
│   ├── context_indep.* # 所有上下文无关的音素列表(所有静音音素)
│   ├── disambig.* # 所有消歧符号列表
│   ├── extra_questions.* # 增加音素位置标记的聚类问题
│   ├── nonsilence.* # 所有非静音、非消歧符号的音素列表
│   ├── optional_silence.* # 词间选择性填充的静音音素列表
│   ├── roots.* # 定义哪些音素共享上下文决策树的一个根节点
│   ├── sets.* # 音素组
│   ├── silence.* # 静音音素列表
│   ├── wdisambig_phones.* # 消歧音素索引
│   ├── wdisambig.* # 消歧符号文本
│   ├── wdisambig_words.* # 消歧符号词索引
│   ├── word_boundary.* # 每个音素的词位置
├── phones.txt # 定义词索引,在音素集基础上加入空音素<eps>,以#开头的消歧符号,加入位置标记
├── topo # 定义HMM的拓扑结构
└── words.txt # 定义音素索引,与vocab相比,增加了句首符<s>,句尾符</s>,空符<eps>和消歧符号#0
data/lang_nosp_test_tgmed
├── G.fst
├── L_disambig.fst
├── L.fst
├── oov.int
├── oov.txt
├── phones
│   ├── align_lexicon.int
│   ├── align_lexicon.txt
│   ├── context_indep.csl
│   ├── ...
├── phones.txt
├── topo
└── words.txt
data/lang_nosp_test_tgsmall
├── G.fst
├── L_disambig.fst
├── L.fst
├── oov.int
├── oov.txt
├── phones
│   ├── align_lexicon.int
│   ├── align_lexicon.txt
│   ├── context_indep.csl
│   ├── ...
├── phones.txt
├── topo
└── words.txt3 directories, 107 files

相比第一个文件夹,后两个文件夹多了G.fst文件。后两个文件夹是由第一个文件夹复制并进一步整理而来,分别添加了各自的G.fst文件,这个文件保存对应测试集的语言模型(第4步还会生成tglarge和fglarge测试)。

【Kaldi例子】Librispeech数据整理相关推荐

  1. 《数据分析实战:基于EXCEL和SPSS系列工具的实践》——3.3 耗时耗力的数据整理过程...

    本节书摘来自华章计算机<数据分析实战:基于EXCEL和SPSS系列工具的实践>一书中的第3章,第3.3节,作者 纪贺元,更多章节内容可以访问云栖社区"华章计算机"公众号 ...

  2. 机器学习项目中的数据预处理与数据整理之比较

    要点 在常见的机器学习/深度学习项目里,数据准备占去整个分析管道的60%到80%. 市场上有各种用于数据清洗和特征工程的编程语言.框架和工具.它们之间的功能有重叠,也各有权衡. 数据整理是数据预处理的 ...

  3. ajax实现下拉列表回显,layui实现下拉复选功能的例子(包括数据的回显与上传)

    一.layui下拉复选实现的背景:实现一个管理员拥有多个权限 二. 具体实现: //依赖资源 //页面显示 角色: xm-select-search xm-select-skin="defa ...

  4. sql用于字符串的聚合函数_SQL字符串函数用于数据整理(争用)

    sql用于字符串的聚合函数 In this article, you'll learn the tips for getting started using SQL string functions ...

  5. 《数据整理实践指南》一第2章 是我的问题还是数据的问题

    本节书摘来自异步社区<数据整理实践指南>一书中的第2章,第2.1节,作者[美]Q. Ethan McCallum(麦卡伦),更多章节内容可以访问云栖社区"异步社区"公众 ...

  6. 数据科学和人工智能技术笔记 十九、数据整理(上)

    十九.数据整理(上) 作者:Chris Albon 译者:飞龙 协议:CC BY-NC-SA 4.0 在 Pandas 中通过分组应用函数 import pandas as pd# 创建示例数据帧 d ...

  7. 七大数据陷阱之技术过失(上):数据整理中的问题

    引言 许多著名运动员都曾坦言:我所做的不过是令自己精力充沛,技巧娴熟.同样的,虽然之前谈论了不少与数据科学相关的理论和思想, 但实际的数据工作也不外乎基础设施的性能优化,以及到各种到位的技术性操作,如 ...

  8. PB Send()函数应用有关数据整理

    PB Send()函数应用有关数据整理 Send()函数定义:Send(handle,message#,lowword,long) 其中的message#是一个UnsignedIntege,就是WM_ ...

  9. ​数据整理——大数据治理的关键技术

    数据整理--大数据治理的关键技术 杜小勇1,2, 陈跃国1,2, 范举1,2, 卢卫1,2 1. 中国人民大学信息学院,北京 100872: 2. 数据工程与知识工程教育部重点实验室(中国人民大学), ...

  10. Keras图像分割实战:数据整理分割、自定义数据生成器、模型训练

    Keras图像分割实战:数据整理分割.自定义数据生成器.模型训练 目录 Keras图像分割实战:数据整理分割.自定义数据生成器.模型训练

最新文章

  1. VM之Linux:Linux的Ubuntu中,解决安装后屏幕太小的问题
  2. 掌握Angular2的服务(service)
  3. linux——samba共享以及基础用法
  4. RMAN SET NEWNAME
  5. Redis Master/Slave 实践
  6. 日站会——你的站会姿势正确吗?
  7. get方法请求返回一个文件_一键转换多种文件格式,完全免费,总有一个方法适合你...
  8. java mysql 配置_Java连接MySQL数据库详细分析
  9. 纯CSS的方法解决文字溢出与截断的问题
  10. 深入理解 Javascript 面向对象编程
  11. Android App 免杀教程
  12. XCode怎么搜索图片文件
  13. 毕业进行时:人生的二次选择
  14. 计算机的网线连接路由器的什么接口,tp-link路由器网线插哪个口 tplink路由器网线连接图解...
  15. 实现基于小米的电子商务平台架构
  16. 汇编语言||存储单元,存储字长,存储字,存储容量的理解
  17. Sql 从一个表往另一个表里插数据
  18. 对话英特尔副总裁Erez Dagan:自动驾驶引擎盖下的秘密!|《新程序员》
  19. CVPR 2020 | 旷视研究院探究优化场景文字识别的「词汇依赖」问题
  20. 读ICCV Best Student Paper有感

热门文章

  1. SEO页面优化以及如何对单页面应用进行SEO优化
  2. UserBehavior 阿里巴巴淘宝用户行为数据字段分析
  3. 使用RMAN备份时应如何处置归档日志文件
  4. Asp.net Web Api开发Help Page配置和扩展
  5. OpenCV图像轮廓提取
  6. 年薪50万PM总结的20个成功项目管理经验
  7. 性能优化-service进程防杀
  8. Win7系统ip地址配置错误网络无法连接的解决办法
  9. 手机插了sd卡显示无服务器,手机sd卡无法读取之sd卡无文件系统或文件系统不受支持怎么办...
  10. php点击按钮保存图片到相册,手机端点击下载按钮将页面保存成图片到本地