能否在Keras中创建反缩放输出的层?输出缩放训练疑问
Keras回归网络的输入输出缩放方案问题解答
将缩放逻辑内置到模型的实现方案
完全可以把输入缩放和输出反缩放的逻辑做成自定义层嵌入模型中,这样保存模型时会自动携带均值、最大值这些参数,预测阶段无需额外加载。自定义输入缩放层
继承keras.layers.Layer实现自定义层,训练时计算并存储每个特征的均值和绝对值最大值,推理阶段直接用这些参数完成缩放:import tensorflow as tf from tensorflow import keras class InputScaler(keras.layers.Layer): def __init__(self, num_features): super().__init__() self.num_features = num_features # 定义可保存的非训练参数:均值、绝对值最大值 self.mean = self.add_weight(shape=(num_features,), initializer="zeros", trainable=False) self.max_abs = self.add_weight(shape=(num_features,), initializer="ones", trainable=False) def adapt(self, data): # 用训练数据初始化参数 self.mean.assign(tf.reduce_mean(data, axis=0)) self.max_abs.assign(tf.reduce_max(tf.abs(data), axis=0)) # 避免除以0,添加极小值保护 self.max_abs.assign(tf.maximum(self.max_abs, tf.keras.backend.epsilon())) def call(self, inputs): # 执行缩放计算 return (inputs - self.mean) / self.max_abs使用时先调用
adapt方法传入训练输入数据,再将该层作为模型的第一层。自定义输出反缩放层
同样实现反缩放层,把模型输出的缩放后结果还原为原始尺度,训练时用缩放后的目标计算损失,最终输出原始尺度的预测值:class OutputInverseScaler(keras.layers.Layer): def __init__(self, num_outputs): super().__init__() self.num_outputs = num_outputs self.mean = self.add_weight(shape=(num_outputs,), initializer="zeros", trainable=False) self.max_abs = self.add_weight(shape=(num_outputs,), initializer="ones", trainable=False) def adapt(self, data): self.mean.assign(tf.reduce_mean(data, axis=0)) self.max_abs.assign(tf.reduce_max(tf.abs(data), axis=0)) self.max_abs.assign(tf.maximum(self.max_abs, tf.keras.backend.epsilon())) def call(self, inputs): # 执行反缩放计算 return inputs * self.max_abs + self.mean训练前先用训练输出数据调用该层的
adapt方法,再把它接在模型的最后一层后即可。
是否需要对输出进行缩放?
必须对输出做缩放。你的输出变量数量级差异极大(从±10到10万量级),如果直接用原始尺度训练,损失函数会被大数值变量主导,模型会优先拟合这类变量,小尺度变量的预测效果会被严重忽略,完全无法实现“同等对待所有变量”的目标。你当前采用的
(xᵢ - mean(X))/max(|X|)缩放方式很合适,能将所有输出变量统一到[-1,1]范围,保证损失函数对每个输出变量的权重一致。
内容的提问来源于stack exchange,提问作者Jenna
相关产品推荐
相关产品推荐

