近来在了解卷积神经网络(CNN),后来查到CNN是受语音信号处理中时延神经网络(TDNN)影响而发明的。本篇的大部分内容都来自关于TDNN原始文献【1】的理解和整理。该文写与1989年,在识别"B", "D", "G"三个浊音中得到98.5%的准确率,高于HMM的93.7%。是CNN的先驱。
普通神经网络识别音素
在讲TDNN之前先说说一般的神经网络的是怎样识别音素的吧。假设要识别三个辅音"B", "D", "G",那么我们可以设计这样的神经网络:
图1
其中输入0-12代表每一帧的特征向量(如13维MFCC特征)。那么有人可能会问了,即使在同一个因素"B"中,比如"B"包含20帧,那么第1帧与第15帧的MFCC特征也可能不一样。这个模型合理吗?事实上,"B"包含的20帧MFCC特征虽然有可能不一样,但变化不会太大,对于因素还是有一定区分度的,也就是说这个模型凑合凑合还能用,但效果不会非常好。GMM模型可以用这种模型来解释。
时延神经网络(TDNN)
考虑到上述模型只用了一帧特征,那么如果我们考虑更多帧,那么效果会不会好呢?
好,那么我们设计一个包含多帧的神经网络,如图2我们考虑延时为2,则连续的3帧都会被考虑。其中隐含层起到特征抽取的作用,输入层每一个矩形内共有13个小黑点,代表该帧的13维MFCC特征。假设有10个隐含层,那么连接的权重数目为3*13*10=390。
图2
为了结构紧凑显示,我们将其重绘为图3
图3
图3与图2是等价的。其中每条彩色线代表13*10=130个权重值。三条彩色线为390个权重。也有资料称之为滤波器。
好,如果时间滚滚向前,我们不断地对语音帧使用滤波器,我们可以得到图4
图4
这就是延时神经网络的精髓了!其中绿色的线权值相同,红色的线权值相同,蓝色的线权值相同。相当于把滤波器延时。输入与隐层共390个权值变量待确定。
每个隐层矩形内包含10个节点,那么每条棕色的线包含10个权值,假设输出层与隐层的延时为4,则接收5个隐层矩形内的数据,那么隐层与输出层合计权值为10*5*3=150。权值非常少!所以便于训练。
下面就不难理解文献【1】上的图了。思想与上文一样,不过文章多用了一层隐层(多隐层有更强的特征提取和抽象能力)
图5
介绍一下他的做法。Input Layer为语谱图,黑块为大值,灰块为小值。输入层纵向为经过mel滤波器的16个特征(没用MFCC),横向为帧。Input Layer 的延时为2,映射到Hidden Layer 1的关系为16*3 -> 8,权值个数为384。Hidden Layer 1 的延时为4,映射到Hidden Layer 2的关系为8*5 -> 3,权值个数为120。Hidden Layer 2 的延时为8,映射到输出层的关系为3*9 -> 3,权值个数为81。合计权值为384+120+81=585。输出的三个单元分别代表"B", "D", "G"的得分。
训练方法
(1)和传统的反向传播算法一样。
(2)TDNN有快速算法,有兴趣的读者可以搜索。
小结
总结TDNN的优点有以下:
(1)网络是多层的,每层对特征有较强的抽象能力。
(2)有能力表达语音特征在时间上的关系。
(3)具有时间不变性。
(4)学习过程中不要求对所学的标记进行精确的时间定为。
(5)通过共享权值,方便学习。
参考资料
【1】Waibel A, Hanazawa T, Hinton G, et al. Phoneme recognition using time-delay neural networks[J] (TDNN的原始论文,想了解的同学请细看)
【2】赵力 《语音信号处理》 chap 6.3. 6 (也是对上文的一些解释和补充说明)
【3】https://blog.csdn.net/richard2357/article/details/16896837
接下来读者可以看卷积神经网络了(CNN),相信对CNN的理解会有所帮助。
tensorflow的实现
import tensorflow as tf import numpy as np tf.set_random_seed( 922) np.random.seed( 0) def tdnn(inp, n_class): h1_kernel_size = 3 h1_filters = 8 h1 = tf.layers.conv1d(inp, h1_filters, h1_kernel_size)# 1,15(nframes),16(features) #核的大小,其实就是上下文的总长度; #因为valid,所以输入时15,核大小为3,所以丢失2个,因此为13 #又因为有8个核,所以输出的第三个参数为8 #核的大小为3,实际上权重参数大小为(3,16) #1个上下文的输人为(3,16) #做一次卷积,输出为1;随着滑动窗口处理13次,所以第二个参数为13,最后核的个数有8个,所以第三个参数为8
#一次的输入大小的1,3,16 #输出的节点数等于核个数8; 所以总的权重连接数为16*8*3
权值共享体现在哪里?在滑动窗口的时候,16*3*8的权重矩阵参数是相同的
print(h1.shape)#1, 13(因为核为3,valid), 8(filter number) h2_kernel_size = 5 h2_filters = n_class h2 = tf.layers.conv1d(h1, h2_filters, h2_kernel_size) print(h2.shape) h2 = tf.transpose(h2, [ 0, 2, 1]) print(h2.shape) output = tf.squeeze(tf.layers.dense(h2, 1, tf.sigmoid))#3个节点 sigmoid激活函数,输出类似概率值 return output if __name__ == '__main__': bs = 1 n_frame = 15 n_feature = 16 n_class = 3 inp=tf.placeholder(tf.float32, shape=[bs, n_frame, n_feature])#1*15*16 output = tdnn(inp, n_class)#输入, 3个类别 with tf.Session() as sess: i = np.random.normal(size=(bs, n_frame, n_feature))#1 15 16 sess.run(tf.global_variables_initializer()) o = sess.run(output, feed_dict={inp: i}) print('input:', i.shape) print('o:',o)#3个不同类别的概率值 print(np.array(o).shape) # (3,)printnp.array(o) # [ 0.64834243 0.91836888 0.50499392]