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

CNN模型训练准确率高但验证表现差的原因及优化咨询

巴迪克图案分类CNN模型过拟合优化方案

针对训练集准确率高、验证集表现差的过拟合问题,结合你的数据规模(256个训练样本、65个验证样本)和现有尝试,给出以下具体优化建议:

1. 修正数据生成器的迭代步数设置

你当前设置stepsPerEpochVal=200,但实际训练样本仅256个、batch size为2,每个epoch只需迭代256//2=128次即可遍历完训练数据。设置200步会导致每个epoch重复使用训练数据,大幅加剧过拟合。
修改代码:

stepsPerEpochVal = len(X_train) // batchSizeVal

2. 调整图像预处理策略,保留关键特征

巴迪克图案的色彩信息是核心分类特征,你当前将彩色图转为灰度图的操作会丢失大量区分度信息。建议修改预处理流程:

def PreProcessing(img):
    # 保留RGB通道,仅做归一化
    img = img / 255.0
    return img

同时调整模型输入维度:

# 匹配RGB输入,修改Conv2D的input_shape
model.add((Conv2D(NumberOfFilters1, sizeOfFilter1, input_shape=(32,32,3), activation='relu')))

另外,equalizeHist可能过度破坏图案纹理,保留RGB时建议移除该操作。

3. 缩小模型容量,匹配小数据集规模

你当前使用128、256个卷积核的模型,对仅256个样本的数据集来说容量过大,极易过拟合。建议大幅缩减模型参数:

def myModel():
    NumberOfFilters1 = 32  # 从128降至32
    NumberOfFilters2 = 64  # 从256降至64
    sizeOfFilter1=(3,3)    # 缩小卷积核尺寸
    sizeOfFilter2=(3,3)
    sizeOfPool=(2,2)
    
    NumberOfNode=64        # 全连接层从128降至64
    
    model = Sequential()
    model.add((Conv2D(NumberOfFilters1, sizeOfFilter1, input_shape=(32,32,3), activation='relu')))
    model.add(MaxPooling2D(pool_size=sizeOfPool))
    model.add(Dropout(0.3))  # 降低Dropout比例,避免欠拟合
    
    model.add((Conv2D(NumberOfFilters2, sizeOfFilter2, activation='relu')))
    model.add(MaxPooling2D(pool_size=sizeOfPool))
    model.add(Dropout(0.3))
    
    model.add(Flatten())
    model.add(Dense(NumberOfNode, activation='relu'))
    model.add(Dropout(0.3))
    model.add(Dense(NumberOfClasses, activation='softmax'))
    model.compile(Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
    return model

更高效的方案是使用迁移学习,基于预训练模型(如MobileNetV2)微调,利用预训练的图像特征适配小数据集:

from tensorflow.keras.applications import MobileNetV2

base_model = MobileNetV2(input_shape=(32,32,3), include_top=False, weights='imagenet')
base_model.trainable = False  # 冻结预训练层

model = Sequential([
    base_model,
    tf.keras.layers.GlobalAveragePooling2D(),
    Dense(64, activation='relu'),
    Dropout(0.3),
    Dense(NumberOfClasses, activation='softmax')
])
model.compile(Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])

4. 强化数据增强,扩充有效样本多样性

当前数据增强参数保守,可进一步增加变换强度,生成更多差异化样本:

dataGen = ImageDataGenerator(
    width_shift_range=0.2,
    height_shift_range=0.2,
    zoom_range=0.3,
    shear_range=0.2,
    rotation_range=30,
    horizontal_flip=True,  # 加入水平翻转
    brightness_range=[0.8, 1.2]  # 亮度调整
)

注意:验证集和测试集绝对不能使用数据增强,你当前的处理是正确的,需保持。

5. 加入正则化与早停机制

  • L2正则化:在卷积层和全连接层加入权重约束,限制参数规模:
from tensorflow.keras.regularizers import l2

model.add((Conv2D(NumberOfFilters1, sizeOfFilter1, 
                  input_shape=(32,32,3), 
                  activation='relu',
                  kernel_regularizer=l2(0.001))))
  • 早停(Early Stopping):当验证集损失连续多轮不下降时停止训练,避免过度拟合,同时保留最优模型:
from tensorflow.keras.callbacks import EarlyStopping

early_stop = EarlyStopping(patience=10, restore_best_weights=True)
# 修改训练代码,加入回调
history = model.fit_generator(
    dataGen.flow(X_train,Y_train,batch_size=batchSizeVal),
    steps_per_epoch=stepsPerEpochVal,
    epochs=epochsVal,
    validation_data=(X_validation,Y_validation),
    shuffle=1,
    callbacks=[early_stop]
)

6. 优化数据集划分与类别平衡

  • 分层抽样:使用train_test_split的stratify参数,保证训练、验证、测试集的类别分布与原始数据一致:
X_train,X_test,Y_train,Y_test = train_test_split(images,classNumber,test_size=testRatio, stratify=classNumber)
X_train,X_validation,Y_train,Y_validation= train_test_split(X_train,Y_train,test_size=validationRatio, stratify=Y_train)
  • 类别平衡:如果某类样本数量过少(从你输出的NumberOfSamples可查看),可针对性对少样本类别做数据增强,或使用加权交叉熵损失:
# 计算类别权重
class_weight = {}
total_samples = len(Y_train)
for i in range(NumberOfClasses):
    count = len(np.where(Y_train == i)[0])
    class_weight[i] = total_samples / (NumberOfClasses * count)

# 训练时传入class_weight
history = model.fit_generator(..., class_weight=class_weight)

7. 学习率动态调整

使用学习率衰减策略,当验证集性能停滞时降低学习率,帮助模型跳出局部最优:

from tensorflow.keras.callbacks import ReduceLROnPlateau

lr_scheduler = ReduceLROnPlateau(factor=0.5, patience=5, min_lr=1e-6)
# 加入训练回调
history = model.fit_generator(..., callbacks=[early_stop, lr_scheduler])

内容的提问来源于stack exchange,提问作者Bhetrand Dwilangga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:01:19