You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在训练前实例化带权重的Keras模型(含预训练CV模型场景)

为什么会遇到这个问题?

Keras采用延迟初始化机制:当你用预训练CV模型叠加自定义顶层时,新增的层并不会立刻初始化权重——因为Keras还不知道输入数据的具体形状。直接调用predict()会报错,本质是模型还没“真正完成构建”。

针对你的CV模型场景的解决方案

假设你的模型是这样构建的(预训练模型+自定义顶层):

from tensorflow.keras.applications import ResNet50
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model

# 加载预训练模型(不含顶层分类器)
base_model = ResNet50(weights='imagenet', include_top=False)
# 新增自定义顶层
x = base_model.output
x = GlobalAveragePooling2D()(x)
predictions = Dense(10, activation='softmax')(x)
# 组装完整模型
model = Model(inputs=base_model.input, outputs=predictions)

你可以用以下两种方式快速完成权重实例化:

方法1:显式调用model.build()

直接告诉模型输入数据的形状,强制触发所有层的权重初始化:

# 输入形状要和预训练模型要求一致(比如ResNet是(224,224,3),batch维度用None)
model.build(input_shape=(None, 224, 224, 3))

# 现在可以正常调用predict了
import tensorflow as tf
dummy_pred = model.predict(tf.random.normal((1, 224, 224, 3)))

预训练层的权重会保留,新增的顶层会用默认的随机初始化器(比如GlorotUniform)生成权重。

方法2:用“假数据”触发初始化

给模型喂一个符合输入形状的dummy tensor,让Keras自动完成权重初始化:

# 创建一个批量大小为1的假输入
dummy_input = tf.random.normal((1, 224, 224, 3))
# 调用一次模型(不用关心输出结果)
_ = model(dummy_input)

# 现在predict可以正常运行
dummy_pred = model.predict(dummy_input)
自定义权重初始化(随机/零值/任意值)

如果需要指定初始化方式,分两种情况处理:

1. 定义层时指定初始化器

在新增顶层的时候,直接设置kernel_initializerbias_initializer

# 零值权重示例
predictions = Dense(
    10,
    activation='softmax',
    kernel_initializer='zeros',  # 权重初始化为0
    bias_initializer='zeros'     # 偏置初始化为0
)(x)

常用的初始化器还有random_normal(正态分布随机)、he_uniform(He初始化)等,也可以自定义初始化器函数。

2. 构建模型后手动修改权重

如果已经定义好了模型,也可以手动修改指定层的权重:

# 先完成模型构建(用上面的build或dummy输入方法)
model.build(input_shape=(None, 224, 224, 3))

# 找到你要修改的顶层(比如最后一层Dense)
top_layer = model.layers[-1]

# 示例1:设置为零值权重
import numpy as np
zero_weights = [np.zeros_like(w) for w in top_layer.get_weights()]
top_layer.set_weights(zero_weights)

# 示例2:设置自定义权重(比如全1)
custom_weights = [np.ones_like(w) for w in top_layer.get_weights()]
top_layer.set_weights(custom_weights)
Keras模型权重实例化的通用方法

不管你是用Functional API、Sequential还是子类化模型,以下三种方法都通用:

  • 显式build:调用model.build(input_shape)input_shape要匹配模型输入的维度(batch维度用None)。
  • dummy输入触发:用符合形状的假数据调用一次模型(model(dummy_input)model.predict(dummy_input))。
  • 定义时指定输入形状:在模型第一层(比如Sequential的第一层,或者Functional的Input层)就指定input_shape,这样模型在定义时就会完成权重初始化:
    # Sequential示例
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Conv2D, Dense
    
    model = Sequential([
        Conv2D(32, kernel_size=(3,3), input_shape=(224,224,3)),  # 直接指定输入形状
        Dense(10, activation='softmax')
    ])
    # 模型已经完成权重初始化,可以直接调用predict
    
注意事项
  • 预训练模型的权重在加载时已经存在,不需要重新初始化,只有你新增的自定义层会被初始化。
  • 手动修改权重时,要确保你的权重数组形状和层的权重形状完全一致,否则会抛出维度不匹配的错误。
  • 子类化模型(继承tf.keras.Model)需要在__init__中调用super().__init__(),并在call方法中定义前向传播,同样可以用上述方法触发权重初始化。

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

火山引擎 最新活动