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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:17:46