如何将Keras音频1D CNN模型最终层输出调整为(None,100)形状?
问题描述
搭建了用于处理音频数据的简易CNN模型,需要将音频特征与形状为(None,128)的文本特征做拼接,要求音频模型最终层输出尺寸为(None,100),当前实现代码如下:
from keras.layers import Reshape inputs_au = Input(shape=(637,20)) audio_model = Conv1D(100,3,activation='relu')(inputs_au) audio_model = MaxPooling1D()(audio_model) audio_model = Conv1D(100,3,activation='relu')(audio_model) audio_model = MaxPooling1D()(audio_model) audio_model = Conv1D(100,3,activation='relu')(audio_model) audio_model = MaxPooling1D()(audio_model) #audio_model = Reshape((100,))(audio_model) model_audio = Model(inputs = inputs_au, outputs = audio_model) model_audio.summary()
调用model_audio.summary()打印的模型结构如下:
当前模型输出形状为(None,77,100),直接使用Reshape((100,))无法完成维度转换,需要调整模型结构,得到目标形状为(None,100)的输出。
解决方案
当前模型输出是三维张量:(批次大小, 时间步数量77, 卷积通道数100),要转成二维的(批次大小, 100),核心是把长度为77的时间步维度压缩掉,有3种常用实现方案:
- 方案1:使用全局池化层(最推荐)
全局池化是序列CNN提取固定长度特征的标准做法,不需要手动计算维度,对不同长度的输入兼容性好,参数量为0。直接在最后一个池化层后加全局池化即可,可选两种实现:GlobalAveragePooling1D:对每个通道在所有时间步的特征取平均值,输出形状直接为(None,100)GlobalMaxPooling1D:对每个通道在所有时间步的特征取最大值,输出形状直接为(None,100)
- 方案2:调整池化参数将时间步压缩到1
手动修改最后一层MaxPooling1D的pool_size参数为77,池化后输出形状会变成(None,1,100),之后接Flatten()或者Reshape((100,))就能得到目标尺寸。这种方法硬编码了池化尺寸,一旦输入音频长度变化就会报错,灵活性差。 - 方案3:展平后接全连接层映射
先接Flatten()层把三维张量拉成一维,得到形状为(None, 77*100=7700)的特征,再接一个Dense(100)全连接层映射到100维。这种方案参数量大,容易过拟合,仅适合数据量充足的场景。
参考修改代码(全局池化版本)
from keras.layers import Input, Conv1D, MaxPooling1D, GlobalAveragePooling1D from keras.models import Model inputs_au = Input(shape=(637,20)) audio_model = Conv1D(100,3,activation='relu')(inputs_au) audio_model = MaxPooling1D()(audio_model) audio_model = Conv1D(100,3,activation='relu')(audio_model) audio_model = MaxPooling1D()(audio_model) audio_model = Conv1D(100,3,activation='relu')(audio_model) audio_model = MaxPooling1D()(audio_model) # 新增全局平均池化,直接输出(None,100)维度 audio_model = GlobalAveragePooling1D()(audio_model) model_audio = Model(inputs = inputs_au, outputs = audio_model) model_audio.summary()
内容的提问来源于stack exchange,提问作者Serena Taylor
相关产品推荐
相关产品推荐

