基于YAMNet预训练模型的昆虫音频分类低准确率问题求助
昆虫音频迁移学习分类异常修复方案
核心问题成因
当前训练准确率40%、验证准确率10%、测试准确率80%的异常结果,由以下几类代码逻辑错误直接导致:
- 数据集划分逻辑错误:先对单条音频切分生成多段embedding、执行
unbatch操作后才做训练/验证/测试集划分,会导致同一条音频的不同片段同时出现在三个数据集中,产生严重数据泄露。测试集准确率虚高是因为模型在训练阶段已经见过同音频的其他片段,验证集准确率极低是因为划分逻辑混乱导致样本分布完全失衡。 - 模型结构与损失函数不匹配:隐藏层
Dense(256)错误使用softmax激活(隐藏层应使用ReLU等激活函数,softmax仅适合输出层做概率归一化),且最后输出层未添加softmax激活的情况下,损失函数sparse_categorical_crossentropy默认from_logits=False,损失计算完全错误。 - 划分样本单位错误:设置的
train_size=130、val_size=18、test_size=10是对unbatch后的embedding片段计数,不是对原始158条独立音频计数,完全不符合数据集划分的基本原则。
代码修复要点
1. 调整数据处理流程,先划分原始音频再提取特征
优先对原始158条音频做分层划分(按类别比例分配到训练/验证/测试集),再分别对三个集的音频做embedding提取、unbatch操作,从根源避免数据泄露:
from sklearn.model_selection import train_test_split # 分层拆分原始音频,保证每个类别在三个集内都有合理分布 train_files, temp_files, train_labels, temp_labels = train_test_split( filenames, targets, test_size=0.2, stratify=targets, random_state=42 ) val_files, test_files, val_labels, test_labels = train_test_split( temp_files, temp_labels, test_size=0.33, stratify=temp_labels, random_state=42 ) # 分别构建三个数据集,各自执行音频加载、embedding提取操作 def build_ds(files, labels): ds = tf.data.Dataset.from_tensor_slices((files, labels)) ds = ds.map(load_wav_for_map).map(extract_embedding).unbatch() return ds.cache().shuffle(1000).batch(5).prefetch(tf.data.AUTOTUNE) train_ds = build_ds(train_files, train_labels) val_ds = build_ds(val_files, val_labels) test_ds = build_ds(test_files, test_labels)
2. 修正模型结构与损失函数
my_model = tf.keras.Sequential([ tf.keras.layers.Input(shape=(1024), dtype=tf.float32, name='input_embedding'), tf.keras.layers.Dense(256, activation='relu'), # 隐藏层替换为ReLU激活 tf.keras.layers.Dropout(0.3), # 小数据集添加dropout层防止过拟合 tf.keras.layers.Dense(9, activation='softmax') # 输出层添加softmax激活适配损失函数 ], name='my_model') my_model.compile( optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"] )
3. 优化训练配置
- 训练轮数调整为20-30轮,搭配早停回调
tf.keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True)防止过拟合 - 可适当调低学习率提升训练稳定性
内容的提问来源于stack exchange,提问作者Dario Gandini
相关产品推荐
相关产品推荐

