如何使用Keras仅归一化指定列且保留其余列数据不变
问题解答
不需要逐列拆分做独立预处理,你可以通过两种方式在Keras层逻辑内实现「仅对指定列做归一化、其余列保留原值」的需求,逻辑可以完全整合进模型端到端流程,不需要额外写脱离模型的前置预处理代码。
方案1:修改Normalization层的统计参数(最简便)
tf.keras.layers.Normalization的核心计算逻辑为:output = (input - mean) / sqrt(variance)
对于不需要归一化的列,只要手动将其对应的均值设为0、方差设为1,这部分列经过层计算后会完全等于输入值,不会产生任何改动。
示例代码(假设3列数据中第0列保留原值,第1、2列执行归一化):
import numpy as np import tensorflow as tf adapt_data = np.array([[0., 7., 4.], [2., 9., 6.], [0., 7., 4.], [2., 9., 6.]], dtype='float32') input_data = np.array([[0., 7., 4.]], dtype='float32') # 定义需要保留原值的列索引、需要归一化的列索引 keep_raw_cols = [0] # 初始化归一化层并适配数据 layer = tf.keras.layers.Normalization(axis=-1) layer.adapt(adapt_data) # 修改不需要归一化的列对应的统计参数 mean = layer.mean.numpy() var = layer.variance.numpy() for col in keep_raw_cols: mean[0, col] = 0.0 var[0, col] = 1.0 layer.mean.assign(mean) layer.variance.assign(var) output = layer(input_data)
运行后可以看到,输出中第0列的值和输入完全一致,第1、2列为归一化后的结果,符合预期。
方案2:拆分张量分别处理后拼接(扩展性更强)
如果你的不同列后续还要做其他差异化预处理(比如部分列离散化、部分列独热编码),可以先把输入张量按列拆分,需要归一化的部分传入Normalization层,不需要改动的部分直接透传,最后用Concatenate层按原列顺序拼回即可。
示例代码:
# 定义列索引 keep_raw_cols = [0] norm_cols = [1,2] # 仅用需要归一化的列适配归一化层 norm_layer = tf.keras.layers.Normalization(axis=-1) norm_layer.adapt(adapt_data[:, norm_cols]) # 构建端到端预处理逻辑 inputs = tf.keras.Input(shape=(3,)) raw_part = tf.gather(inputs, indices=keep_raw_cols, axis=-1) norm_part = tf.gather(inputs, indices=norm_cols, axis=-1) normed_part = norm_layer(norm_part) # 注意拼接顺序要和原数据列顺序一致 outputs = tf.keras.layers.Concatenate(axis=-1)([raw_part, normed_part]) preprocess_model = tf.keras.Model(inputs=inputs, outputs=outputs) output = preprocess_model(input_data)
方案选择建议
- 仅需要跳过少量列的归一化、其余处理逻辑统一时,选方案1,代码最简洁,运行开销最小
- 不同列需要做完全不同的预处理操作时,选方案2,后续扩展调整更灵活
内容的提问来源于stack exchange,提问作者g.pickardou
相关产品推荐
相关产品推荐

