人工智能小白日记 语音情感分析探索之2 CNN相关及实验

前言

上一篇在用mfcc特征进行DNN训练后,准确率太低,接下来根据前人经验,由于CNN卷积神经网络在图片识别领域大放异彩,而由音频得到的mel声谱图作为图片,也可以用这种组合来训练。

例如,202.wav的梅尔谱绘制出来

import librosa
import librosa.display
import numpy as np
import pylab as plt

y, sr = librosa.load(path,sr=None)
S = librosa.feature.melspectrogram(y=y, sr=sr, n_fft=1024,hop_length=512, n_mels=40)
plt.figure(figsize=(10, 4))
librosa.display.specshow(librosa.power_to_db(S,ref=np.max),
                             y_axis='mel', fmax=8000,
                             x_axis='time')
plt.colorbar(format='%+2.0f dB')
plt.title('Mel spectrogram')
plt.tight_layout()

横坐标表示时域,纵坐标表示梅尔频域,颜色表示能量,这里单位是dB分贝,这不就是一张图么。

在这里插入图片描述

正文内容

1 关于CNN

由于没有相关知识,我在网络上收集了一堆资料,看起来相当难。就在犯难的时候,老天给了个好东东。又是一个教程,tensorflow中文教程作为入门相当好,而这一篇教程作为后续进阶特别合适。地址如下,拿去不谢?:
https://www.zybuluo.com/hanbingtao/note/485480

我敢说只有大神,才能做出这样的教程。

2 在tensorflow上搭建CNN

对于我等小白来说,现在做不到人家大牛那样的,直接手写cnn这种程度,但是利用现成的api还是可以的。这里官方也有个demo,参考https://tensorflow.google.cn/tutorials/estimators/cnn

在这里插入图片描述
从目录上可以看到该卷积网络模型的结构。当然这里的结构是可以自行配置的,需要多少个怎样的卷积层,多少个怎样的池化层,都是可以自己定义的。为了方便起见,直接使用它写好的模型来测试一下,看看效果

2-1 CNN MNIST分类器

2-1-1 输入层
input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])

很简洁,就一句话。文中解释也很清楚,features[“x”]很明显是28x28的图片像素集,后面
-1 动态计算样本批量的大小
28,28 将一维的像素特征转换为28x28的二维特征。由于需要卷积,转换为长宽合适的二维数组特别重要。
1 由于是黑白图片,单色图像只有 1 个通道(黑色)。

打印一下,结果是个张量:
在这里插入图片描述

2-1-2 卷积层 1

第一个卷积层中,我们需要将 32 个 5x5 过滤器应用到输入层,并应用 ReLU 激活函数。我们可以使用 layers 模块中的 conv2d() 方法创建该层,如下所示:

conv1 = tf.layers.conv2d(
    inputs=input_layer,
    filters=32,
    kernel_size=[5, 5],
    padding="same",
    activation=tf.nn.relu)

32个filter意味着有32个输出,每个输出是由原输入28x28的图像,与卷积核5x5的卷积计算出来。根据卷积原理,步幅为1的时候,如果输入是6x6,与5x5卷积,将得到2x2的输出;如果输入是7x7,与5x5卷积,将得到3x3的输出;依次类推,如果输入是nxn,与mxm(m<n)卷积,将得到(n-m+1)x(n-m+1)的输出。 所以28x28的输入,经过5x5的卷积核,步幅为1时,将得到24x24的输出,32个filter,就会有32x24x24的输出

打印一下conv1
在这里插入图片描述
ps:这里是28,28,32 是因为padding=‘same’,padding 参数指定以下两个枚举值之一(不区分大小写):valid(默认值)或 same。要指定输出张量与输入张量具有相同的高度和宽度值,我们在此教程中设置 padding=same,它指示 TensorFlow 向输入张量的边缘添加 0 值,使高度和宽度均保持为 28(没有填充的话,在 28x28 张量上进行 5x5 卷积运算将生成一个 24x24 张量,因为在 28x28 网格中,可以从 24x24 个位置提取出一个 5x5 图块)。

2-1-3 池化层 1

pooling层的作用主要是下采样,最常用的是Max Pooling。Max Pooling实际上就是在n*n的样本中取最大值,作为采样后的样本值。

除了Max Pooing之外,常用的还有Mean Pooling——取各样本的平均值。

pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

这里的max_pooling2d 用的是Max Pooling。 将卷积层的输出conv1作为它的输入,pool_size指定了2x2的最大池化过滤器 ,strides指定移动步幅是2,28/2=14 最后将得到14x14的输出
在这里插入图片描述

2-1-4 卷积层2和池化层2
conv2 = tf.layers.conv2d(
    inputs=pool1,
    filters=64,
    kernel_size=[5, 5],
    padding="same",
    activation=tf.nn.relu)

pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)

一样的不说了,
在这里插入图片描述

2-1-5 密集层
# Dense Layer
  #扁平化降维,将7,7,64的张量,降成7x7x64的一维向量,即3136
  pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
  #密集层,指定1024个神经元
  dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
  #丢弃正则化,随机丢弃40%的样本
  dropout = tf.layers.dropout(
      inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)

在这里插入图片描述

2-1-6 对数层

该层返回预测的原始值。创建一个具有 10 个神经元(介于 0 到 9 之间的每个目标类别对应一个神经元)的密集层,并应用线性激活函数(默认函数):

logits = tf.layers.dense(inputs=dropout, units=10)

在这里插入图片描述
以上就是模型部分,训练部分暂且不论,模仿这个写一个咱需要的CNN模型

2-2 CNN 音频情感分类器

在开始之前,还要看看它的输入特征和标签
在这里插入图片描述

输入特征是 55000张图的28x28像素值
标签就是55000条标注

因此,音频的特征和标签也是这样。log_mel声谱图作为特征40x40的方便处理,标签也需要转换成数字0-5

在这里插入图片描述

2-2-1 数据集

这里顺便介绍下数据集,上节中忘了介绍了。本次实验分别使用CASIA数据集和iemocap数据集进行了实验。主要CASIA数据集免费下载到的只有1200条,规模较小。

1)CASIA数据集
在这里插入图片描述
casia数据集结构如上,每个演员中都已经划分好6类情绪,每个情绪中都会有对应的多条语音文件。所以写个程序去获取音频和对应情绪不成问题,然后获取对应音频的特征,就可以得到想要的特征-情绪集合。然后进行训练。经过提取,里面的情感规模如下:
在这里插入图片描述

2)iemocap数据集
这个数据集较大,共分为5个Session,一起十几个G,包含了视频,音频,面部特征等诸多文件,不过一次下载受益无穷?。

每个Session的结构如下:
在这里插入图片描述
在这里插入图片描述
能看得懂可以用的,我用红框框标出来了。dialog中的wav文件,是长音频,每个音频里是两人对话,各种情绪都有。而sentenses中把这些语句做了分离,一小段一小段。比如女人的第一句话,女人的第二句话,男人的第一句话,…这样拆开。然后每段的情绪在EmoEvaluation中的文件中进行了标注。

这时候只要把这些语音和标注提取出来,就可以进行训练了。经过提取,里面的情感规模如下:
在这里插入图片描述
可以看出,有些情感的样本过少,有些样本情感有争议,这些都可以忽略。可以选取fru,neu,ang,sad,exc等进行实验

2-2-2 cnn模型规划

40x40 第一层卷积 32x5x5, 池化 32x2x2 ,最后应该输出 32x20x20
第二层卷积 64x5x5, 池化 64x2x2 ,最后应该输出 64x10x10
密集层一致
对数层units改为6

在这里插入图片描述

2-2-3 模型训练相关

模型训练这里有几个参数说明一下,跟教程里面略有不一样:

# Train the model
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": training_examples},
    y=training_targets,
    batch_size=20,
    num_epochs=10,
    shuffle=True)
mnist_classifier.train(
    input_fn=train_input_fn,
    steps=None,
    hooks=[logging_hook])

epoch:将所有训练样本完整训练一次,叫做一个epoch。这里num_epochs指的是重复完整训练的次数,当然要配上shuffle=True,让每次训练都随机打乱样本。

batch_size:单次训练(一个step)的样本数

steps:一次完整训练需要的步数。 要求 总样本数量=batch_size*steps
比如CASIA中规划了1000个样本做训练,那么这里的batch_size是20,自然steps应该是50,当然设为None也行,它训练50个steps就会完成一个epoch。

2-2-4 实验结果

1)CASIA数据集:随机1000做训集,200做测试集。batch_size=10
10个epoch后:
在这里插入图片描述
20个epoch后:有提升
在这里插入图片描述
30个epoch后:测试集loss变大,后面慢慢开始过拟合了
在这里插入图片描述

110个epoch后:测试集loss持续变大
在这里插入图片描述
得到了0.65左右的识别率。

2)iemocap数据集:选取了ang,sad,neu,exc四类情绪的样本进行实验,共5000条左右,随机4200条做训练集,剩余的做测试集。为了和上面对齐,这里batch_size=42

10个epoch后:
在这里插入图片描述
训练集loss持续下降
在这里插入图片描述

20个epoch后:
在这里插入图片描述
训练集loss上下震荡
在这里插入图片描述
验证集loss略有降低

30个epoch后:
在这里插入图片描述
训练集loss继续下降
在这里插入图片描述
测试集loss略有下降

40个epoch后:
在这里插入图片描述
训练集loss震荡
在这里插入图片描述
测试集loss变大了,注意后面可能过拟合了

50个epoch后:
在这里插入图片描述
测试集loss继续下降了,难道还有空间?


在这里插入图片描述
好吧确实没空间了

得到了0.55左右的识别率。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值