如何在Keras中从零训练EfficientNet、ResNet等模型及加载架构后训练
嘿,这个问题问到点子上了!在Keras里训练EfficientNet、ResNet这类经典CNN模型,主要有两种靠谱的思路——要么完全从零手动搭建模型结构,要么直接调用官方预定义的网络架构(不带预训练权重)来从头训练。下面我给你一步步拆解清楚:
一、从零手动搭建模型(以ResNet为例)
如果你想彻底搞懂模型的底层逻辑,手动搭建是个绝佳的练习方式。拿ResNet来说,核心是残差块的设计,我们先定义残差单元,再堆叠起来构建完整模型:
import tensorflow as tf from tensorflow.keras import layers, Model # 定义ResNet的残差块 def residual_block(x, filters, stride=1): shortcut = x # 第一个卷积层 x = layers.Conv2D(filters, (3,3), strides=stride, padding='same')(x) x = layers.BatchNormalization()(x) x = layers.ReLU()(x) # 第二个卷积层 x = layers.Conv2D(filters, (3,3), strides=1, padding='same')(x) x = layers.BatchNormalization()(x) # 如果步长不为1或者通道数不匹配,调整shortcut if stride != 1 or shortcut.shape[-1] != filters: shortcut = layers.Conv2D(filters, (1,1), strides=stride, padding='same')(shortcut) shortcut = layers.BatchNormalization()(shortcut) # 残差连接 x = layers.Add()([x, shortcut]) x = layers.ReLU()(x) return x # 构建ResNet50模型 def build_resnet50(input_shape=(224,224,3), num_classes=10): inputs = layers.Input(shape=input_shape) # 初始卷积层 x = layers.Conv2D(64, (7,7), strides=2, padding='same')(inputs) x = layers.BatchNormalization()(x) x = layers.ReLU()(x) x = layers.MaxPooling2D((3,3), strides=2, padding='same')(x) # 堆叠残差块 x = residual_block(x, 64, stride=1) x = residual_block(x, 64, stride=1) x = residual_block(x, 64, stride=1) x = residual_block(x, 128, stride=2) x = residual_block(x, 128, stride=1) x = residual_block(x, 128, stride=1) x = residual_block(x, 128, stride=1) x = residual_block(x, 256, stride=2) x = residual_block(x, 256, stride=1) x = residual_block(x, 256, stride=1) x = residual_block(x, 256, stride=1) x = residual_block(x, 256, stride=1) x = residual_block(x, 256, stride=1) x = residual_block(x, 512, stride=2) x = residual_block(x, 512, stride=1) x = residual_block(x, 512, stride=1) # 全局平均池化+全连接层 x = layers.GlobalAveragePooling2D()(x) outputs = layers.Dense(num_classes, activation='softmax')(x) model = Model(inputs=inputs, outputs=outputs) return model # 初始化模型并查看结构 model = build_resnet50() model.summary()
搭好结构后,就可以按照常规流程编译、训练了——这个后面统一说。
二、加载官方架构(不带预训练权重)从头训练
这种方法更省心,因为官方已经把模型的拓扑结构优化到最优,还避免了手动搭建可能出现的错误。Keras的keras.applications模块里内置了几乎所有主流CNN模型,只需要设置weights=None就可以加载纯净的架构,然后从头训练:
1. 加载ResNet架构
from tensorflow.keras.applications import ResNet50 # 加载不带预训练权重的ResNet50,自定义输入形状和类别数 resnet_model = ResNet50( weights=None, # 关键:不加载预训练权重 input_shape=(224,224,3), classes=10 # 根据你的任务调整类别数 )
2. 加载EfficientNet架构
EfficientNet有多个版本(B0到B7),用法和ResNet类似:
from tensorflow.keras.applications import EfficientNetB0 efficientnet_model = EfficientNetB0( weights=None, input_shape=(224,224,3), classes=10 )
三、通用训练流程(两种方式通用)
不管是手动搭建的模型,还是加载的官方架构,训练流程都是一致的:
1. 准备训练数据
可以用ImageDataGenerator做数据增强,或者用tf.data.Dataset加载数据:
# 示例:用ImageDataGenerator加载文件夹中的图片 from tensorflow.keras.preprocessing.image import ImageDataGenerator train_datagen = ImageDataGenerator( rescale=1./255, rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True ) train_generator = train_datagen.flow_from_directory( 'path/to/train_data', target_size=(224,224), batch_size=32, class_mode='categorical' )
2. 编译模型
选择合适的优化器、损失函数和评估指标:
model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4), loss='categorical_crossentropy', # 分类任务用这个,回归任务换MSE等 metrics=['accuracy'] )
3. 开始训练
调用fit方法启动训练:
history = model.fit( train_generator, epochs=50, validation_data=val_generator # 如果有验证集的话 )
4. 评估与保存模型
训练完成后可以评估模型性能,然后保存:
# 评估 test_loss, test_acc = model.evaluate(test_generator) print(f"测试准确率:{test_acc:.4f}") # 保存模型 model.save('my_trained_model.h5')
一些实用小贴士
- 如果你的数据集很小,即使是从头训练,也可以考虑先用公开数据集(比如ImageNet)的预训练权重做微调,但如果严格要求从零开始,就坚持用
weights=None。 - 不同模型的默认输入形状可能不同,比如EfficientNetB0默认是224x224,ResNet50也是,但你可以根据自己的数据调整
input_shape。 - 学习率是关键超参数,建议用学习率调度器(比如
ReduceLROnPlateau)来动态调整,避免模型过早收敛。
内容的提问来源于stack exchange,提问作者Aditya Jain
相关产品推荐
相关产品推荐

