You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在tf.keras模型内对多个特征使用Normalization层

多数值特征下Keras内置预处理的实现方案

你对「模型内预处理」的理解完全准确:把特征变换逻辑嵌入模型结构的写法,能彻底避免训练、推理阶段预处理逻辑不一致的问题,部署时不需要额外维护独立的预处理脚本,是生产场景的推荐实现方式。

针对你提到的多数值特征场景,实现逻辑和单特征场景几乎一致,不需要复杂改造,核心注意点和可运行代码如下:

全数值特征场景实现(适配你现有代码)

如果你的输入全部是类似X、Y、Z的数值型特征,直接调整Normalization层的参数即可,不需要使用函数式API:

  • 初始化归一化层时,将输入维度设置为训练集的特征总数,去掉axis=None参数(默认沿特征维度独立计算每个特征的均值、标准差,正好匹配多特征独立归一化的需求)
  • 仅使用训练集特征数据调用adapt()方法,让归一化层学习统计量,禁止使用验证集、测试集数据执行该步骤,避免数据泄露
  • 将归一化层作为模型的第一层,后续直接拼接原有全连接结构即可

注意你原有代码存在笔误:验证集的X_val、y_val错误读取了训练集数据,实际需要从val_data中提取,否则验证结果完全无效。

修正后的完整可运行代码:

import pandas as pd
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Normalization
from tensorflow.keras.optimizers import Adam

# 数据读取
train_data = pd.read_csv('train.csv')
val_data = pd.read_csv('val.csv')
target_name = 'ze_target'

y_train = train_data[target_name]
X_train = train_data.drop(target_name, axis=1)
# 修正原有验证集读取错误
y_val = val_data[target_name]
X_val = val_data.drop(target_name, axis=1)

def create_model(X_train):
    # 初始化多特征归一化层
    feature_normalizer = Normalization(input_shape=[X_train.shape[1], ])
    # 用训练集适配归一化统计量
    feature_normalizer.adapt(X_train)

    model = Sequential([
        feature_normalizer,
        Dense(20, activation='relu'),
        Dense(20, activation='relu'),
        Dense(20, activation='relu'),
        Dense(1)
    ])
    model.compile(optimizer=Adam(learning_rate=0.0001), loss='mse')
    return model

model = create_model(X_train)
model.summary()
model.fit(X_train, y_train, validation_data=(X_val, y_val), batch_size=128, epochs=30)

混合特征场景扩展(函数式API实现)

如果后续你需要同时处理数值、类别等不同类型的特征,可以用Keras函数式API给不同类型特征单独配置预处理逻辑,最后拼接输入全连接层,简单示例如下:

from tensorflow.keras import Input, Model
from tensorflow.keras.layers import StringLookup, Concatenate

# 定义数值特征预处理分支
numeric_cols = ['X', 'Y', 'Z']
numeric_input = Input(shape=(len(numeric_cols),), name='numeric_feats')
numeric_norm = Normalization()
numeric_norm.adapt(X_train[numeric_cols])
numeric_processed = numeric_norm(numeric_input)

# 定义类别特征预处理分支
cat_cols = ['cat1', 'cat2']
cat_input = Input(shape=(len(cat_cols),), name='cat_feats', dtype=tf.string)
cat_encoder = StringLookup(output_mode='one_hot')
cat_encoder.adapt(X_train[cat_cols])
cat_processed = cat_encoder(cat_input)

# 拼接所有处理后的特征,接入全连接结构
all_feats = Concatenate()([numeric_processed, cat_processed])
x = Dense(20, activation='relu')(all_feats)
x = Dense(20, activation='relu')(x)
x = Dense(20, activation='relu')(x)
output = Dense(1)(x)

model = Model(inputs=[numeric_input, cat_input], outputs=output)

补充说明

  • 模型保存时会自动存储预处理层学到的所有参数(比如归一化的均值、方差,类别特征的词表等),部署时直接加载模型传入原始特征即可,不需要额外执行预处理操作
  • 原有代码中除第一层外的全连接层不需要重复指定input_dim,框架会自动推导维度,重复写不会报错但属于冗余代码

内容的提问来源于stack exchange,提问作者cs0815

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:39:14