语音识别系列1--语音识别CTC之数据准备 忘是亡心i 2022-01-29 23:09 450阅读 0赞 **语音识别CTC之数据准备** **一、简介** CTC是一种端到端的神经网络训练方法,在语音识别领域应用非常广泛,和传统的语音识别HMM相比,CTC省略了数据对齐,特征选取的过程。传统的HMM在训练神经网络之前需要选择特定的语音特征,比如FBANK、MFCC。而CTC则直接将语音转到频域即可使用,传统的HMM在训练之前需要对数据进行帧对齐,对齐的过程首先要进行HMM-GMM的聚类,并且较小的建模粒度需要做状态的绑定,因为较大的建模粒度效果往往不好。最后使用GMM或者DNN对齐的标签也不是很准确。而端到端的CTC技术正好解决了这个问题,建模粒度更大,HMM-DNN模型用一个DNN模型替代,不需要对齐标签,仅需要整句话的标签即可,语料充足的情况下效果比传统的HMM方法要好。 tensorflow原生支持CTC目标函数,网络结构搭建简单,是一个不错的深度学习工具,我们通过tensorflow训练CTC模型,在3000小时语音数据的基础上,效果达到了字准95%,句准91%的效果,下面我们首先介绍训练过程的数据准备阶段。 **二、数据格式** 输入为kaldi提取的ark文件对应的scp文件,标签文件,输出为准备好的tfrecord文件。 scp文件格式如下: 0000000000000000000001 3000h.ark:43 0000000000000000000002 3000h.ark:68421 0000000000000000000003 3000h.ark:140799 0000000000000000000004 3000h.ark:213177 0000000000000000000005 3000h.ark:269235 0000000000000000000006 3000h.ark:312973 标签文件格式如下: 0000000000000000000001 125 61 146 113 146 2 216 115 124 1 0000000000000000000002 26 126 56 19 123 61 26 7 0000000000000000000003 57 163 26 62 143 95 121 98 121 59 0000000000000000000004 26 126 56 19 58 37 26 7 124 38 57 180 0000000000000000000005 192 189 58 23 121 62 124 129 0000000000000000000006 28 19 146 139 57 31 26 0 **三、代码** Python代码如下: import numpy as np from tqdm import tqdm import sys import struct #统计空标签个数 null_label=0 def int64_feature(value): return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) def bytes_feature(value): return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) def get_features(scp_file): #找到特征存储位置并读取 scp_file = scp_file.split(':') file_name = scp_file[0] position = int(scp_file[1]) + 5 with open(file_name, 'rb') as f: f.seek(position) #获取特征帧数 var_byte = struct.unpack('B', f.read(1))[0] seq_len = struct.unpack('i', f.read(var_byte))[0] #获取特征维数 var_byte = struct.unpack('B', f.read(1))[0] feat_width = struct.unpack('i', f.read(var_byte))[0] #读取特征 feats = f.read(4 * seq_len * feat_width) #返回特征及特征帧数 return feats, seq_len def get_label(raw_label): #标签转为int数组 label = np.asarray(raw_label).astype(np.int64) #标签转字符串 label = label.tostring() return label def create_tfrecord(scp_file, text_file, tfrecord_file): #声明全局变量 global null_label #特征索引全部读入内存 with open(scp_file) as f: scp_list = f.readlines() #标签全部读入内存 with open(text_file) as f: text_list = f.readlines() #检查特征文件与标签文件语音个数是否相等 if (len(scp_list) != len(text_list)): print("error, wav file and text lines num not equal") return print("Converting data into %s ..." % tfrecord_file) #创建写文件句柄 writer = tf.python_io.TFRecordWriter(tfrecord_file) #tqdm显示处理进度条 for i in tqdm(range(len(scp_list))): scp_line = scp_list[i].split() text_line = text_list[i].split() #检查特征ID和标签ID是否相同 if (scp_line[0] != text_line[0]): print("scp and label not equal") break #读取特征及特征帧数 feature, seq_len = get_features(scp_line[1]) #读取标签 label = get_label(text_line[1:]) #标签长度为0时略过此条音频 if (len(label)==0): null_label+=1 continue #TFrecord数据格式 tf_example = tf.train.Example( features = tf.train.Features( feature={ #序列化为字符型 'feature': bytes_feature(feature), 'label' : bytes_feature(label), #序列化为整形 'seq_len': int64_feature(seq_len) } ) ) #写入文件句柄 writer.write(tf_example.SerializeToString()) #关闭文件句柄 writer.close() if __name__ == "__main__": #输入使用kaldi提取特征的ark文件对应的scp索引文件,每一句话对应的标签文件,输出为tfrecord文件 if (len(sys.argv) != 4): print (sys.argv[0], ":please input scp file, label file and output file") exit(0) else: #导入tensorflow import tensorflow as tf #输入 scpfile=sys.argv[1] textfile=sys.argv[2] #输出 outputfile=sys.argv[3] #根据特征文件和标签文件生成tfrecord文件 create_tfrecord(scpfile, textfile, outputfile) #统计输出空标签的文件个数 print("null label ", null_label) **四、总结** 以上就是tensorflow的数据准备过程,多卡并行的时候数据读取还是比较慢,如何快速有效读写文件也是需要解决的一个问题。
还没有评论,来说两句吧...