如何在Keras后端的TensorFlow图中添加可训练标量参数用于函数逼近
解决方案核心思路
不随输入x变化的可训练标量a_i属于模型的独立可训练参数,不需要作为输入或输出定义,直接声明为tf.Variable并加入模型的可训练变量列表即可,TF2的优化器会自动对其求导更新。
具体实现方案
核心逻辑说明
- 基函数生成网络仅负责接收输入x,输出N个基函数的计算结果
[f_1(x), f_2(x), ..., f_N(x)] a_i作为独立的可训练权重,和网络参数一起参与梯度更新- 前向传播时直接计算线性组合结果
h(x) = sum(a_i * f_i(x)),再和目标g(x)=exp(x)计算MSE损失
最简实现示例(自定义训练循环)
import tensorflow as tf # 超参数:基函数数量 N_BASE_FUNC = 10 # 1. 定义生成f_i(x)的基础网络 base_net = tf.keras.Sequential([ tf.keras.layers.Dense(32, activation='relu', input_shape=(1,)), tf.keras.layers.Dense(32, activation='relu'), tf.keras.layers.Dense(N_BASE_FUNC) # 输出N个基函数的计算值 ]) # 2. 定义独立可训练的a_i向量 a = tf.Variable(tf.random.normal(shape=(N_BASE_FUNC,)), trainable=True) # 3. 训练配置 optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3) loss_fn = tf.keras.losses.MeanSquaredError() @tf.function def train_step(x): with tf.GradientTape() as tape: f_i = base_net(x) h_x = tf.reduce_sum(a * f_i, axis=-1) g_x = tf.exp(x) loss = loss_fn(g_x, h_x) # 同时对网络参数和a_i求导更新 trainable_params = base_net.trainable_variables + [a] grads = tape.gradient(loss, trainable_params) optimizer.apply_gradients(zip(grads, trainable_params)) return loss # 示例训练:在[0,1]区间采样训练数据 x_train = tf.random.uniform(shape=(1000, 1), minval=0, maxval=1) for epoch in range(200): loss = train_step(x_train) if epoch % 20 == 0: print(f"Epoch {epoch:3d} | Loss: {loss.numpy():.6f}")
更规范的Keras子类实现
如果想用Keras原生的compile/fit接口,直接把a定义为模型类的属性即可,Keras会自动识别为可训练参数:
class ExpApproxModel(tf.keras.Model): def __init__(self, n_base=10): super().__init__() self.base_net = tf.keras.Sequential([ tf.keras.layers.Dense(32, activation='relu', input_shape=(1,)), tf.keras.layers.Dense(32, activation='relu'), tf.keras.layers.Dense(n_base) ]) # 定义为模型属性会自动加入可训练参数列表 self.a = tf.Variable(tf.random.normal(shape=(n_base,)), trainable=True) def call(self, x): f_i = self.base_net(x) return tf.reduce_sum(self.a * f_i, axis=-1) # 直接用Keras接口编译训练 model = ExpApproxModel() model.compile(optimizer='adam', loss='mse') x_train = tf.random.uniform((1000, 1), 0, 1) y_train = tf.exp(x_train) model.fit(x_train, y_train, epochs=150, batch_size=32, verbose=1)
内容的提问来源于stack exchange,提问作者Benny K
相关产品推荐
相关产品推荐

