Keras中TimeDistributed封装Dense层使用l1_l2正则化报错如何解决
报错原因分析
该报错是旧版本TensorFlow(2.0~2.3版本区间)的已知Keras层正则化计算bug导致:TimeDistributed会将封装的Dense层在时间步维度做广播计算,当你给内部Dense层添加kernel正则化规则后,框架没有自动把正则化损失正确降维为标量(0维),反而输出了和模型输出维度一致的3维张量[1,1000,1],后续总损失计算阶段需要把这个3维损失和其他0维标量损失相加,就触发了维度不匹配的报错。
解决方法
- 方案1:升级TensorFlow版本
该bug在TensorFlow 2.4及以上稳定版本已经被官方修复,直接升级框架版本即可正常运行原有代码。 - 方案2:手动计算并添加正则损失(适配无法升级版本的场景)
不在Dense层参数中声明正则规则,模型定义完成后手动提取Dense层核参数计算正则损失,再添加到模型总损失中,示例代码如下:
model = Sequential() model.add(Bidirectional( LSTM(self.n_neurons, return_sequences=True, use_bias=False, unit_forget_bias=False, kernel_initializer=tf.keras.initializers.RandomNormal(mean=0., stddev=0.01), recurrent_initializer=tf.keras.initializers.RandomNormal(mean=0., stddev=0.01), ), input_shape=(self.time_steps, self.input_features), )) model.add(Dropout(rate=self.dropout_rate)) model.add(TimeDistributed( Dense(self.output_features, activation='linear', use_bias=False, kernel_initializer=tf.keras.initializers.RandomNormal(mean=0., stddev=0.01), ) )) # 手动添加L1L2正则损失 l1_coef = 1e-5 l2_coef = 1e-4 dense_kernel = model.layers[-1].layer.kernel reg_loss = l1_coef * tf.reduce_sum(tf.abs(dense_kernel)) + l2_coef * tf.reduce_sum(tf.square(dense_kernel)) model.add_loss(reg_loss)
- 方案3:移除冗余的TimeDistributed封装
Dense层本身默认仅对输入张量的最后一维做计算,前面的时间步维度会自动广播处理,你的场景完全不需要用TimeDistributed封装,直接使用普通Dense层即可规避该维度问题,修改后的层代码如下:
model.add(Dense(self.output_features, activation='linear', use_bias=False, kernel_initializer=tf.keras.initializers.RandomNormal(mean=0., stddev=0.01), kernel_regularizer=tf.keras.regularizers.l1_l2(l1=1e-5, l2=1e-4), ))
内容的提问来源于stack exchange,提问作者JM Zhou
相关产品推荐
相关产品推荐

