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

如何让Keras正常追踪训练不依赖输入的待合并层子图

问题说明

请参考如下示例:

import tensorflow as tf
units=11

entrada=tf.keras.Input(name="entrada", shape=(units,))
unidad= tf.Variable([[1.0]]) # + 0.0* entrada[:,:1]
denseSoftmax=tf.keras.layers.Dense(units,name="denseSoftmax",activation="softmax")
softMaxOutput=denseSoftmax(unidad)
finalproduct=tf.keras.layers.Multiply()([entrada,softMaxOutput])
modelo=tf.keras.Model(entrada,finalproduct)
modelo.summary()

运行该示例得到的模型无可训练参数,原因是denseSoftmax层未接入模型输入的计算链路。若取消代码中+ 0.0 * entrada[:,:1]的注释,伪造一条指向输入的零值连接,就能生成符合预期的计算图,模型结构输出如下:

Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 entrada (InputLayer)           [(None, 11)]         0           []                                
 tf.__operators__.getitem (Slic  (None, 1)           0           ['entrada[0][0]']                
 ingOpLambda)                                                                                     
 tf.math.multiply (TFOpLambda)  (None, 1)            0           ['tf.__operators__.getitem[0][0]'
 tf.__operators__.add (TFOpLamb  (None, 1)           0           ['tf.math.multiply[0][0]']       
 denseSoftmax (Dense)           (None, 11)           22          ['tf.__operators__.add[0][0]']   
 multiply (Multiply)            (None, 11)           0           ['entrada[0][0]',                
                                                                  'denseSoftmax[0][0]']        

但这种伪造零值输入连接的方案存在明显缺陷,和在输入层中新增常量分支的做法一样不够合理。

规范解决方案

不需要伪造零值连接,Keras本身提供了标准实现方式:将独立于输入的可训练参数封装为tf.keras.layers.Layer子类即可,框架会自动追踪这类不依赖输入实际值、但参与输出计算的层的参数,不需要额外手动伪造输入链路。

修正后的可运行代码如下:

import tensorflow as tf
units = 11

# 自定义独立可训练常量层,不依赖输入的实际数值
class TrainableConstant(tf.keras.layers.Layer):
    def __init__(self, initial_value, **kwargs):
        super().__init__(**kwargs)
        self.initial_value = initial_value

    def build(self, input_shape=None):
        # 注册可训练权重,不需要关联输入的具体特征维度
        self.kernel = self.add_weight(
            name="kernel",
            shape=tf.shape(self.initial_value),
            initializer=tf.keras.initializers.Constant(self.initial_value),
            trainable=True
        )
        self.built = True

    def call(self, inputs):
        # 仅用输入获取batch维度做对齐,不使用输入的实际数值参与计算
        batch_size = tf.shape(inputs)[0]
        return tf.tile(self.kernel, [batch_size, 1])

entrada = tf.keras.Input(name="entrada", shape=(units,))
# 初始化独立可训练常量,初始值为[[1.0]]
unidad = TrainableConstant([[1.0]], name="trainable_const")(entrada)
denseSoftmax = tf.keras.layers.Dense(units, name="denseSoftmax", activation="softmax")
softMaxOutput = denseSoftmax(unidad)
finalproduct = tf.keras.layers.Multiply()([entrada, softMaxOutput])
modelo = tf.keras.Model(entrada, finalproduct)
modelo.summary()

运行后输出的模型结构可以看到denseSoftmax的22个参数被正常识别为可训练参数,不需要伪造零值连接:

Model: "model"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 entrada (InputLayer)           [(None, 11)]         0           []                               
                                                                                                  
 trainable_const (TrainableCons  (None, 1)           1           ['entrada[0][0]']                
 tant)                                                                                            
                                                                                                  
 denseSoftmax (Dense)           (None, 11)           22          ['trainable_const[0][0]']        
                                                                                                  
 multiply (Multiply)            (None, 11)           0           ['entrada[0][0]',                
                                                                  'denseSoftmax[0][0]']            
                                                                                                  
==================================================================================================
Total params: 23
Trainable params: 23
Non-trainable params: 0
__________________________________________________________________________________________________

这种实现是Keras自定义可训练权重的标准写法:

  • 所有可训练参数都在层的build方法中通过add_weight注册,框架会自动识别并加入训练参数列表,只要该层的输出最终流向模型输出,就会被正常追踪
  • 不需要给独立子图强行伪造和输入的计算连接,层的call方法仅用输入获取batch size做维度对齐,不会引入无意义的零值运算
  • 自定义层可以灵活设置初始值、是否可训练、权重正则化等属性,比伪造连接的方案可控性强得多

如果不想自定义层,也可以直接使用内置的tf.keras.layers.Embedding实现固定长度的可训练常量,本质逻辑和自定义层一致:将输入设为全0的固定索引,映射为可训练的向量,同样不需要伪造有实际计算意义的输入连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:27:25