如何计算人工神经网络(ANN)对单个输入变量的偏导数
问题解决实现方案
核心逻辑
- 先确认你需要计算偏导的目标输入特征的列索引:你给出的输入特征顺序如下,对应索引可以直接参考:
- 0: strike
- 1: Time to Maturity
- 2: RF Rate
- 3: Sigma 20 Days Annualized
- 4: Underlying Price
- 原代码存在错误:自定义损失函数中硬编码全量训练集计算梯度的逻辑不符合Keras的batch训练规则,会导致梯度计算完全不符合预期,改用自定义训练循环获取每一批次的输入,计算对应偏导。
- 梯度张量维度为
(batch_size, 输入特征数),直接对最后一维切片即可取出单个特征对应的偏导数。
可运行修改后代码
import pandas as pd from tensorflow import keras import tensorflow as tf from tensorflow.keras import layers, losses import numpy as np # -------------------------- 配置项 -------------------------- # 超参数 n_hidden_layers = 2 # 隐藏层数 n_units = 128 # 隐藏层神经元数 n_batch = 64 # 批次大小 n_epochs = 30 # 训练轮数 # 目标特征索引:比如要对Underlying Price求偏导,填4,换其他特征改对应索引即可 target_feature_idx = 4 # 偏导项权重,可根据实际损失量级调整,避免两项量级差距太大导致训练不稳定 lambda_reg = 1.0 # ----------------------------------------------------------- # 样本数据构造(和你原有代码一致) x_train = {'strike': [200, 2925], 'Time to Maturity': [0.312329, 0.0356164], "RF Rate": [0.08, 2.97], "Sigma 20 Days Annualized": [0.123251, 0.0837898], "Underlying Price": [1494.82, 2840.69] } call_X_train = pd.DataFrame(x_train, columns = ['strike', "Time to Maturity", "RF Rate", "Sigma 20 Days Annualized", "Underlying Price"] ).astype('float32') x_test = {'strike': [200], 'Time to Maturity': [0.0356164], "RF Rate": [2.97], "Sigma 20 Days Annualized": [0.0837898], "Underlying Price": [2840.69] } call_X_test = pd.DataFrame(x_test, columns = ['strike', "Time to Maturity", "RF Rate", "Sigma 20 Days Annualized", "Underlying Price"] ).astype('float32') y_train = np.array([1285.25, 0.8]).astype('float32') call_y_train = pd.Series(y_train) y_test = np.array([0.8]).astype('float32') call_y_test = pd.Series(y_test) # 隐藏层构造函数(和你原有代码一致) def hl(tensor, n_units): hl_output = layers.Dense(n_units, activation = layers.LeakyReLU())(tensor) return hl_output # MLP模型构造(和你原有代码一致) def mlp3_call(n_hidden_layers, n_units): inputs = keras.Input(shape = (call_X_train.shape[1],)) x = layers.LeakyReLU(alpha = 1)(inputs) for _ in range(n_hidden_layers): x = hl(x, n_units) outputs = layers.Dense(1, activation = keras.activations.softplus)(x) model = keras.Model(inputs=inputs, outputs=outputs) return model # 初始化模型、优化器、损失函数 model = mlp3_call(n_hidden_layers, n_units) optimizer = keras.optimizers.Adam() mse_loss = losses.MeanSquaredError() # 构造训练数据集 train_dataset = tf.data.Dataset.from_tensor_slices((call_X_train, call_y_train)).batch(n_batch) # 自定义训练循环 for epoch in range(n_epochs): print(f"Epoch {epoch + 1}/{n_epochs}") total_loss = 0.0 for step, (x_batch, y_batch) in enumerate(train_dataset): with tf.GradientTape() as tape: # 1. 计算模型预测值和MSE损失 y_pred = model(x_batch, training=True) mse = mse_loss(y_batch, y_pred) # 2. 计算模型输出对目标输入特征的偏导 with tf.GradientTape() as grad_tape: grad_tape.watch(x_batch) y = model(x_batch, training=True) # 取所有样本对target_feature_idx对应特征的偏导 g_all = grad_tape.gradient(y, x_batch) g_target = g_all[:, target_feature_idx] # 可以根据需求对g_target做聚合,比如取平均、求和等 g_mean = tf.reduce_mean(g_target) # 3. 总损失 = MSE + 偏导项(可加lambda调整权重) loss = mse + lambda_reg * g_mean # 反向传播更新参数 grads = tape.gradient(loss, model.trainable_weights) optimizer.apply_gradients(zip(grads, model.trainable_weights)) total_loss += loss print(f"Total loss: {total_loss.numpy():.4f}")
调整说明
如果需要更换计算偏导的目标变量,只需修改target_feature_idx为对应特征的列索引即可。如果训练时损失波动过大,可以调整lambda_reg的大小,平衡MSE项和偏导项的量级。
内容的提问来源于stack exchange,提问作者Wasonic
相关产品推荐
相关产品推荐

