You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CNN音频频谱图分类模型准确率仅0.026,求问题排查

问题描述

我用CNN模型对不同音频文件的频谱图做分类,训练后模型最高准确率仅为0.026,效果极差。以下是我的代码和相关信息:

模型定义代码

input_shape = (128, 216, 1)
def create_model():
    model = models.Sequential()
    model.add(layers.Conv2D(32, (5, 5), strides = (1,1), name = 'conv0', input_shape = input_shape))
    
    model.add(layers.BatchNormalization(axis = 3, name = 'bn0'))
    model.add(layers.Activation('relu'))
    
    model.add(layers.MaxPooling2D((2, 2), name='max_pool'))
    model.add(layers.Conv2D(64, (3, 3), strides = (1,1), name='conv1'))
    model.add(layers.Activation('relu'))
    model.add(layers.AveragePooling2D((3, 3), name='avg_pool'))
    
    model.add(layers.GlobalAveragePooling2D())
    model.add(layers.Dense(300, activation='relu', name='rl'))
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(50, activation='softmax', name='sm'))

    
    model.compile(loss='categorical_crossentropy',
              optimizer='adam', 
              metrics='acc')
    return model

频谱图加载代码

for filename in pbar(os.listdir(save_file + r"spec-samples/")):
    image_raw = tf.io.read_file(save_file + r"spec-samples/" + filename)
    image = tf.image.decode_image(image_raw)
    X.append(image)

标签读取代码

def reload_labels():
    y = []
    for data in tqdm(df.iterrows(), desc='Progress'):
        y.append(data[1][1])
    return y

模型训练代码

cp_callback = tf.keras.callbacks.ModelCheckpoint(
    checkpoint, monitor='accuracy', verbose=1, save_best_only=True, mode='max')

es_callback = tf.keras.callbacks.EarlyStopping(
    monitor='loss', patience=3, verbose=1)

csv_callback = tf.keras.callbacks.CSVLogger(save_file + "logs.csv", separator=',', append=False)

history = model.fit(
    X_, y_,
    epochs=20,
    validation_data=(X_test, y_test),
    callbacks=[cp_callback, es_callback, csv_callback])

频谱图示例:音频频谱图示例

请问我哪里操作出错了?


问题排查与解决建议

1. 数据加载与预处理问题

  • 频谱图维度不匹配:模型输入定义是(128,216,1)单通道灰度图,但tf.image.decode_image会保留原图通道数。如果你的频谱图是RGB格式(3通道),加载后维度会和输入形状冲突,直接导致特征提取失效。解决:加一行image = tf.image.rgb_to_grayscale(image)转单通道,或者检查加载后的维度是否和input_shape一致。
  • 数据未归一化:图像像素值默认是0-255,直接输入CNN会让梯度波动过大,训练难以收敛。必须把像素值缩放到0-1区间,比如加image = image / 255.0。
  • 样本标签不对应:os.listdir的文件顺序是不确定的,但你读取标签是按DataFrame行顺序,极大概率出现样本和标签错位,模型等于在瞎学。解决:根据文件名提取对应ID,再匹配CSV里的标签,确保每个样本对应正确类别。

2. 标签处理问题

  • 标签格式不匹配损失函数:你用categorical_crossentropy,要求标签是one-hot编码,但reload_labels直接取的是原始类别ID,这会让损失计算完全错误,模型无法优化。解决:如果标签是整数ID,改用sparse_categorical_crossentropy;或者用tf.keras.utils.to_categorical(y, num_classes=50)转成one-hot格式。
  • 类别不平衡:50个类别如果样本量差距极大,模型会偏向预测样本多的类别,导致整体准确率极低。检查数据集分布,若存在不平衡,要么补充样本,要么用加权损失、过采样/欠采样来平衡。

3. 模型与训练设置问题

  • 模型容量不足:仅两层卷积对频谱图的复杂特征提取能力太弱。可以增加卷积层数(比如在conv1后加一层Conv2D(128, (3,3), activation='relu')),或者改用ResNet50这类预训练模型做迁移学习,复用已有的图像特征。
  • 池化过度压缩特征:先MaxPooling2D(2,2)再AveragePooling2D(3,3),最后加全局平均池化,会把有效特征压缩得太厉害,丢失关键信息。可以调整池化大小,或者减少一次池化操作。
  • 早停指标错误:EarlyStopping监控loss只看训练集,不代表泛化能力。应该改为监控验证集的val_loss或val_acc,避免提前停在训练集过拟合但验证集效果差的阶段。
  • 训练轮次不足:20轮对于音频分类任务可能太少,若早停触发过早,模型还没充分学习。可以先去掉早停,观察训练集和验证集的准确率变化,再调整轮次和早停参数。

4. 其他细节

  • 检查训练集和测试集划分是否合理,有没有出现测试集包含训练集没有的类别,或者划分后类别分布失衡的情况。
  • 随机选几个样本输入模型,看输出概率分布:如果概率集中在少数类别,大概率是标签或样本匹配问题;如果概率平均,说明模型没学到有效特征,是预处理或模型结构的问题。

内容的提问来源于stack exchange,提问作者Miles DeBoer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:39:18