如何在Keras层中设置部分稀疏分布的固定不可训练权重
Keras实现部分权重固定的自定义层方案
该需求完全可实现,核心逻辑是通过掩码矩阵区分固定/可训练权重位置,自定义层在前向传播时保证固定位置值不变,仅更新可训练位置参数。
实现步骤
1. 提前准备基础参数
先拿到预训练层的权重,再定义掩码矩阵和固定值矩阵:
import tensorflow as tf from tensorflow.keras import layers, Sequential # 读取预训练层的原始权重 original_kernel = model.layers[0].get_weights()[0] original_bias = model.layers[0].get_weights()[1] n_nodes = original_kernel.shape[0] # 和实际网络维度对齐 activation = model.layers[0].activation # 掩码矩阵:0代表固定不可训练位置,1代表可训练位置 # 以下为示例配置,对应你举例的固定(0,0)、(1,2)、(2,1)、(2,2)位置 mask = tf.constant([ [0, 1, 1], [1, 1, 0], [1, 0, 0] ], dtype=tf.float32) # 固定值矩阵:存储你手动修改后的A*、F*、H*、I*等固定权重,可训练位置可随意填充 fixed_kernel_values = tf.constant([ [A_star, 0, 0], [0, 0, F_star], [0, H_star, I_star] ], dtype=tf.float32)
2. 自定义部分权重固定的Dense层
class PartiallyFixedDense(layers.Layer): def __init__(self, units, activation, mask, fixed_kernel_values, original_bias, **kwargs): super().__init__(**kwargs) self.units = units self.activation = tf.keras.activations.get(activation) self.mask = tf.constant(mask, dtype=tf.float32) self.fixed_kernel = tf.constant(fixed_kernel_values, dtype=tf.float32) # 偏置默认设为可训练,需要固定的话修改trainable为False即可 self.bias = tf.Variable(original_bias, trainable=True) def build(self, input_shape): # 可训练权重初始化:固定位置填预设值,可训练位置填原始预训练权重 init_value = self.fixed_kernel * (1 - self.mask) + original_kernel * self.mask self.trainable_kernel = self.add_weight( shape=(input_shape[-1], self.units), initializer=tf.constant_initializer(init_value), trainable=True ) super().build(input_shape) def call(self, inputs): # 前向传播时合并固定权重和可训练权重,保证固定位置值永远不变 merged_kernel = self.trainable_kernel * self.mask + self.fixed_kernel * (1 - self.mask) output = tf.matmul(inputs, merged_kernel) + self.bias return self.activation(output)
3. 重构模型并训练
new_model = Sequential() # 替换第一层为自定义的部分固定层 new_model.add(PartiallyFixedDense( units=n_nodes, activation=activation, mask=mask, fixed_kernel_values=fixed_kernel_values, original_bias=original_bias, input_shape=(n_nodes,) )) # 原样加入原模型剩余层 for layer in model.layers[1:]: new_model.add(layer) # 正常编译训练即可,固定位置权重不会更新 new_model.compile(optimizer='adam', loss='mse') new_model.fit(train_x, train_y, epochs=10)
注意事项
- 如果需要固定部分偏置参数,按照相同的掩码逻辑处理即可
- 训练完成后要获取完整权重,执行
merged_kernel = new_model.layers[0].trainable_kernel * new_model.layers[0].mask + new_model.layers[0].fixed_kernel * (1 - new_model.layers[0].mask)即可得到最终的权重矩阵
内容的提问来源于stack exchange,提问作者Artem Glukhov
相关产品推荐
相关产品推荐

