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

TensorFlow:如何正确合并多个已拼接的数据集以适配多输入Keras模型?

解决多输入Keras模型中tf.data.Dataset合并的TypeError问题

首先,咱们来定位你遇到的错误根源:TypeError: Inputs to a layer should be tensors. Got: <tensorflow.python.data.ops.dataset_ops._NestedVariant object>。这个问题出在window函数的处理上——window返回的是一个「数据集的数据集」(Dataset of Datasets),你虽然用了interleave,但每个元素依然是未展开的Dataset对象,而不是Keras需要的张量。另外,你分开处理三种类型的数据集再zip的方式,也容易出现样本不匹配的问题。

下面是修正后的完整方案,我会标注关键修改点:

步骤1:修正windowed数据集的处理逻辑

我们需要把每个window转换成一个张量,用flat_map配合batch来实现——因为你的window size是5,drop_remainder=True,所以每个window刚好有5个元素,batch后会变成形状为(5, 2)的张量(对应2个特征)。

步骤2:调整数据集合并顺序

先为每个DataFrame单独生成(输入组,目标)的数据集,确保单个DataFrame的windowed、static、target样本一一对应,再把这些数据集合并在一起,这样能避免样本错位。

修正后的完整代码

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

# Create dataframes with 4 features and target
dataframe1 = pd.DataFrame(np.random.randn(1000, 5), columns=["feature1", "feature2", "feature3", "feature4", "target"])
dataframe2 = pd.DataFrame(np.random.randn(800, 5), columns=["feature1", "feature2", "feature3", "feature4", "target"])

# 修正:处理windowed数据集时,将每个window转为张量
def get_dataset_windowed(df: pd.DataFrame, features):
    dataset = tf.data.Dataset.from_tensor_slices(df.loc[:, features].to_numpy())
    # window返回Dataset of Datasets,用flat_map+batch把每个window转成(5, 2)的张量
    dataset = dataset.window(5, shift=1, stride=1, drop_remainder=True).flat_map(lambda window: window.batch(5))
    return dataset

def get_dataset(df: pd.DataFrame, features):
    # 注意:window处理后,有效样本数是len(df)-4,所以这里要和windowed数据集对齐
    dataset = tf.data.Dataset.from_tensor_slices(df.loc[:, features].iloc[4:].to_numpy())
    return dataset

# 修正:先为每个DataFrame生成完整的(输入,目标)数据集,再合并
def create_full_dataset_for_df(df):
    windowed_ds = get_dataset_windowed(df, ["feature3", "feature4"])
    static_ds = get_dataset(df, ["feature1", "feature2"])
    target_ds = get_dataset(df, ["target"])
    
    # 为单个DataFrame zip输入和目标
    return tf.data.Dataset.zip(
        (
            {
                "short_term_ts_input": windowed_ds,
                "static_input": static_ds,
            },
            {
                "output": target_ds,
            }
        )
    )

# 合并两个DataFrame对应的数据集
full_dataset = create_full_dataset_for_df(dataframe1).concatenate(create_full_dataset_for_df(dataframe2))

# 打乱+分批
full_dataset = full_dataset.shuffle(buffer_size=1024).batch(128)

# 模型部分保持不变(你的原代码是对的,补充了损失函数)
short_term_ts_input = tf.keras.Input(shape=(5, 2), name="short_term_ts_input")
static_input = tf.keras.Input(shape=(2,), name="static_input")

short_term_ts_features = tf.keras.layers.LSTM(32, return_sequences=False)(short_term_ts_input)
short_term_ts_features = tf.keras.layers.Dense(8)(short_term_ts_features)

static_features = tf.keras.layers.Dense(16)(static_input)

x_concat = tf.keras.layers.concatenate([short_term_ts_features, static_features])
x_concat = tf.keras.layers.Dense(32)(x_concat)

output = tf.keras.layers.Dense(1)(x_concat)

model = tf.keras.Model(inputs=[short_term_ts_input, static_input], outputs=[output])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss="mse") # 补充损失函数,适配回归任务
model.fit(full_dataset, epochs=5)

关键修改点解释

  1. windowed数据集的展开:
    原代码中get_dataset_windowed返回的是Dataset of Datasets,我们添加了.flat_map(lambda window: window.batch(5)),把每个window里的5个元素拼成一个形状为(5, 2)的张量,这样每个元素就变成了Keras可以接收的张量。

  2. 数据集合并顺序:
    先为每个DataFrame单独生成对应的(输入组,目标)数据集,确保windowed、static、target的样本完全对齐,再用concatenate合并两个数据集。这种方式比分开处理三类数据集再zip更可靠,避免了不同DataFrame样本数差异导致的错位问题。

  3. 补充损失函数:原代码model.compile没指定损失函数,训练时会报错,所以我加了loss="mse"(你可以根据任务类型调整为分类损失等)。

这样修改后,full_dataset中的每个元素都是(字典形式的输入张量,字典形式的目标张量),完全符合Keras模型的输入要求,就不会再出现NestedVariant的错误了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:28:11