如何为回归神经网络输入特征定义系数调整其在损失函数中的权重
实现带输入特征权重的自定义MSE损失函数
要给每个输入特征分配特定权重来调整MSE损失的贡献,你需要解决两个核心问题:一是让损失函数能够访问输入特征X(默认损失函数仅接收y_true和y_pred),二是将预定义的权重数组传入损失计算逻辑。以下是完整的实现方案:
1. 定义权重化损失生成函数
通过闭包函数封装权重参数,返回可在模型中使用的损失计算逻辑:
import tensorflow as tf def get_weighted_mse_loss(coeff): # 将权重数组转为TensorFlow张量,确保数据类型匹配 coeff_tensor = tf.convert_to_tensor(coeff, dtype=tf.float32) # 扩展维度以适配3个输出维度的广播计算 coeff_tensor = tf.expand_dims(coeff_tensor, axis=-1) def loss(y_true, y_pred, X): # 计算预测值与真实值的平方误差 squared_error = tf.square(y_pred - y_true) # 将平方误差与对应输入特征的权重相乘 weighted_squared_error = squared_error * coeff_tensor # 计算全局平均损失 return tf.reduce_mean(weighted_squared_error) return loss
2. 用函数式API构建模型
使用Keras函数式API可以直接获取输入层,通过add_loss方法将自定义损失注入模型:
def get_model(n_inputs, n_outputs, coeff): # 定义输入层 input_layer = tf.keras.layers.Input(shape=(n_inputs,)) # 隐藏层 hidden = tf.keras.layers.Dense(20, kernel_initializer='he_uniform', activation='relu')(input_layer) # 输出层 output_layer = tf.keras.layers.Dense(n_outputs)(hidden) # 创建模型实例 model = tf.keras.Model(inputs=input_layer, outputs=output_layer) # 加载自定义损失函数 weighted_mse_loss = get_weighted_mse_loss(coeff) # 添加自定义损失,传入输入、真实标签和预测值 model.add_loss(weighted_mse_loss(model.output, model.targets[0], model.input)) # 编译模型,无需指定loss参数 model.compile(optimizer='adam') return model
3. 调整模型评估逻辑
修改评估函数,将权重数组传入模型构建过程:
def evaluate_model(X, y, coeff): results = [] n_inputs, n_outputs = X.shape[1], y.shape[1] # 定义交叉验证策略 cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1) for train_ix, test_ix in cv.split(X): X_train, X_test = X[train_ix], X[test_ix] y_train, y_test = y[train_ix], y[test_ix] # 传入权重构建模型 model = get_model(n_inputs, n_outputs, coeff) # 训练模型 model.fit(X_train, y_train, verbose=0, epochs=100) # 评估模型,获取自定义损失值 loss = model.evaluate(X_test, y_test, verbose=0) print('>%.3f' % loss) results.append(loss) return results
4. 主程序调用
from numpy import mean, std from sklearn.datasets import make_regression from sklearn.model_selection import RepeatedKFold # 定义输入特征的权重数组 coeff = [5,20,2,1,4,5,6,2,9,15] # 生成数据集 X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, n_targets=3, random_state=2) # 评估模型性能 results = evaluate_model(X, y, coeff) # 输出结果 print('加权MSE: %.3f (%.3f)' % (mean(results), std(results)))
关键细节说明
- 权重张量的维度扩展:通过
tf.expand_dims将(10,)的权重数组转为(10,1),这样可以自动广播到(样本数, 10, 3)的平方误差张量,实现每个输入特征的权重对所有输出维度的误差进行加权。 - 输入特征的访问:使用函数式API和
add_loss方法,让损失函数能够直接获取输入层数据,解决了默认损失函数无法访问输入的问题。 - 模型编译:因为已经通过
add_loss定义了损失,编译时无需再指定loss参数。
内容的提问来源于stack exchange,提问作者Aref Hemati
相关产品推荐
相关产品推荐

