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

如何在Keras模型中正确使用独热编码数据作为输入

解决多热编码特征与数值特征结合的Keras模型输入问题

问题根源分析

你遇到的错误核心来自两点:

  1. 输入形状与模型定义不匹配:模型中cat_input定义为shape=()的int32类型,但实际传入的是多热编码后的二维浮点数组(形状为(样本数, 类别数));同时模型期望字典输入时,你传入了列表格式,导致输入张量数量不匹配。
  2. 变长类别序列处理不当:直接将原始变长类别列表传入模型时,因每个样本的类别数量不一致,拼接时出现维度不匹配。

解决方案一:预处理多热编码后传入模型

先完成多热编码预处理,再根据编码后的特征形状定义模型输入,确保输入格式与模型要求一致。

步骤1:修正多热编码预处理

将编码结果转为numpy数组存储,避免DataFrame中存Tensor导致的格式问题:

import pandas as pd
import numpy as np
import tensorflow as tf

# 创建数据集
df = pd.DataFrame(
{
  'val': [1, 12, 123, 512, 12], 
  'cat': [["A", "B"], ["A"], ["C"], ["C", "A", "B"], ["A"]],
  'label': [0,1,1,0,0]
})

# 提取所有类别
cat_list = list(set([item.strip() for sublist in df['cat'] for item in sublist]))
# 初始化编码层
index = tf.keras.layers.StringLookup(vocabulary=cat_list)
encoder = tf.keras.layers.CategoryEncoding(num_tokens=index.vocabulary_size(), output_mode="multi_hot")

# 编码并转为numpy数组
df['cat_encoded'] = df['cat'].apply(lambda x: encoder(index(x)).numpy())
# 堆叠为二维数组(样本数 × 类别数)
cat_encoded_np = np.vstack(df['cat_encoded'])

步骤2:定义匹配的模型

根据预处理后的特征形状定义输入层,数值特征val是标量输入,多热编码特征是固定长度的向量输入:

# 数值特征输入
val_input = tf.keras.layers.Input(shape=(), name="val", dtype=tf.int32)
# 多热编码特征输入,形状为类别数
cat_input = tf.keras.layers.Input(shape=(len(cat_list),), name="cat", dtype=tf.float32)

# 拼接特征
concat_layer = tf.keras.layers.Concatenate(axis=-1)([val_input, cat_input])
# 添加分类输出层(根据任务调整)
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(concat_layer)

# 构建模型(支持列表或字典输入)
model = tf.keras.Model(inputs=[val_input, cat_input], outputs=output_layer)

步骤3:训练模型

传入与模型输入匹配的数据格式(列表或字典):

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 列表格式输入
model.fit(
    x=[df['val'].values, cat_encoded_np],
    y=df['label'].values,
    epochs=5,
    batch_size=2
)

# 或字典格式输入(对应模型inputs用字典定义的情况)
# model = tf.keras.Model(inputs={"val": val_input, "cat": cat_input}, outputs=output_layer)
# model.fit(
#     x={"val": df['val'].values, "cat": cat_encoded_np},
#     y=df['label'].values,
#     epochs=5
# )

解决方案二:将编码层嵌入模型(推荐)

把多热编码逻辑整合到模型内部,避免预处理与模型部署时的不一致问题,同时自动处理变长类别序列。

步骤1:定义包含编码逻辑的模型

利用StringLookup和CategoryEncoding层直接处理原始变长类别输入:

import pandas as pd
import tensorflow as tf

df = pd.DataFrame(
{
  'val': [1, 12, 123, 512, 12], 
  'cat': [["A", "B"], ["A"], ["C"], ["C", "A", "B"], ["A"]],
  'label': [0,1,1,0,0]
})

# 数值特征输入
val_input = tf.keras.layers.Input(shape=(), name="val", dtype=tf.int32)
# 原始类别输入:变长序列,shape=(None,)
cat_input = tf.keras.layers.Input(shape=(None,), name="cat", dtype=tf.string)

# 自动学习词汇表(替代手动提取cat_list)
index_layer = tf.keras.layers.StringLookup(output_mode='int')
index_layer.adapt(df['cat'].explode())  # 展开列表以学习所有类别

# 多热编码层
encoding_layer = tf.keras.layers.CategoryEncoding(
    num_tokens=index_layer.vocabulary_size(), 
    output_mode="multi_hot"
)

# 处理类别输入
processed_cat = encoding_layer(index_layer(cat_input))

# 拼接并构建输出
concat_layer = tf.keras.layers.Concatenate(axis=-1)([val_input, processed_cat])
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(concat_layer)

model = tf.keras.Model(inputs=[val_input, cat_input], outputs=output_layer)

步骤2:训练模型

直接传入原始数据,模型内部完成编码:

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 原始类别数据转为列表格式传入
model.fit(
    x=[df['val'].values, df['cat'].tolist()],
    y=df['label'].values,
    epochs=5,
    batch_size=2
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:03:34