Tensorflow TF.Dataset将使用多个不同大小的“所有输入形状”的输入进行迭代,必须匹配”

发布于 2025-02-04 00:00:17 字数 2108 浏览 5 评论 0 原文

我正在尝试制作具有两个不同输入的张量流模型,一个将具有形状[9,10],另一个将具有形状[8]。

此外,我正在尝试使用tf.dataset迭代我的输入。但是,每当我尝试这样做时,都会出现以下错误失败:

tensorflow.python.framework.errors_impl.InvalidArgumentError: Shapes of all inputs must match: values[0].shape = [9,10] != values[1].shape = [8]
     [[{{node packed}}]] [Op:IteratorGetNext]

但是肯定可以将大小不同的输入到不同的分支中!在Tensorflow的功能API指南中的示例中,确实是这种情况,但是它们不使用tf.dataset,因此我不能简单地遵循他们的示例。

为了使我想解决的问题有更多的细节,以及为什么我使用tf.dataset api:

我在我的输入中有两种类型的多个网站上做一个时间序列问题:那些随时间而变化的网站,那些不但会因站点而有所不同。暂时,我只是想估计下一个时间步骤。

首先,我使用limeseries_dataset_from_array util将动态协变量和目标在滑动窗口中得到。

    train_ds = tf.keras.preprocessing.timeseries_dataset_from_array(
        input_data, targets, sequence_length=window_size, batch_size=256)

这可以很好地运行,我可以按照此数据集训练模型。

但是,我还想使用时间序列数据来自特定站点的静态协变量。该站点ID在其自己的列中包含在窗口输入数据中,尽管在训练之前将其删除。因此,我要做的是抓住网站的静态协变量,并将其作为单独的输入附加到我的数据集中。

    train_ds = train_ds.map(lambda x, y: (tf.py_function(attach_static_covariates, [x, idindex, colnames], [tf.float64, tf.float64]), y))

    train_ds = train_ds.map(lambda x, y: ({'dynamic': x[0], 'static': x[1]}, y))

附加的代码_STATIC_COVARIATES方法是:

def attach_static_covariates(x, idindex, colnames):
    id = x[0, idindex].numpy()
    static_cov = static_df.iloc[int(id)]
    #This just filters out the id column, now that it has served its purpose
    x = tf.gather(x, [i for i in range(len(colnames)) if i != idindex])

    return (x, static_cov)

我已经确认我的代码可以在上述方法提供的多个输入上运行和训练它们的大小相同(例如,如果我返回(x,x),我可以在两个上运行我的模型将动态协变量的副本输入到我的模型的两个不同分支中)。问题不是由于不匹配或不良模型定义

    for feature_batch, label_batch in train_ds.take(1):
        print(feature_batch)

引起肯定必须使用TF.Dataset具有不同形状的输入!我无法想象这样一个令人难以置信的常见用例将完全不受支持。但是,我在网上找不到任何示例,其中某人具有多个不同形状的输入并使用tf.dataset API。任何帮助或与此类示例的链接都将不胜感激。

COLAB笔记本以说明问题:

I am trying to make a tensorflow model with two different inputs, one will have shape [9,10], the other will just have shape [8].

I am furthermore trying to use tf.dataset to iterate over my inputs. However, whenever I try to do so it fails with the following error:

tensorflow.python.framework.errors_impl.InvalidArgumentError: Shapes of all inputs must match: values[0].shape = [9,10] != values[1].shape = [8]
     [[{{node packed}}]] [Op:IteratorGetNext]

But surely it is possible to have differently sized inputs into different branches! This is exactly the case in the example in tensorflow's functional API guide, however they do not use tf.dataset so I can't simply follow their example.

To give a little more specifics into the problem I am trying to solve and why I am using the tf.dataset api:

I am doing a time-series problem over multiple sites where my inputs are of two types: those that vary with time, and those that do not but do vary by site. For the time being, I'm just trying to estimate the next time step.

First, I get my dynamic covariates and targets in a sliding window using the timeseries_dataset_from_array util.

    train_ds = tf.keras.preprocessing.timeseries_dataset_from_array(
        input_data, targets, sequence_length=window_size, batch_size=256)

This works perfectly and I can train models using this dataset as is.

However, I want to also use the static covariates from the specific site that the time series data is coming from. The site id is included in the window input data in its own column, though it gets removed before training. Thus, what I am trying to do is grab the static covariates for the site and attach it as a separate input to my dataset.

    train_ds = train_ds.map(lambda x, y: (tf.py_function(attach_static_covariates, [x, idindex, colnames], [tf.float64, tf.float64]), y))

    train_ds = train_ds.map(lambda x, y: ({'dynamic': x[0], 'static': x[1]}, y))

The code for the attach_static_covariates method is:

def attach_static_covariates(x, idindex, colnames):
    id = x[0, idindex].numpy()
    static_cov = static_df.iloc[int(id)]
    #This just filters out the id column, now that it has served its purpose
    x = tf.gather(x, [i for i in range(len(colnames)) if i != idindex])

    return (x, static_cov)

I've confirmed that my code can run and train on multiple inputs provided by the above method provided they are the same size (e.g. if I return (x, x) I can run my model on two copies of the dynamic covariates inputted into two different branches of my model). The problem is not due to a mismatch or a bad model definition because I get the same error from the following code:

    for feature_batch, label_batch in train_ds.take(1):
        print(feature_batch)

I've looked everywhere on google and the tensorflow git and I can't find anyone else with this problem, and yet it surely MUST be possible to have differently shaped inputs using tf.dataset! I can't imagine that such an incredibly common use case would be completely unsupported. However, I can't find any examples online where someone has multiple inputs of different shapes and uses tf.dataset api. Any help or links to such examples would be greatly appreciated.

Colab notebook to illustrate issue:
https://colab.research.google.com/drive/1EnaJoUULl-fyAwlcG_5tcWfsRFVCOMtv#scrollTo=PHvsIOx6-Uux

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尤怨 2025-02-11 00:00:17

我发现了一个解决方法:嵌入py_function,无法返回dict,在另一个映射以返回dict的函数中,从而避免了在非double Double Doputs上迭代的数据集问题(这是错误发生的地方,因为它将它们解释为批处理,因此要求它们具有相同的昏暗)。

例如

    def dictionarize(x):

        x, static_cov = tf.py_function(attach_static_covariates, [x, idindex, colnames], [tf.float64, tf.float64])

        return {'dynamic': x, 'static': static_cov}

    train_ds = train_ds.map(lambda x, y: (dictionarize(x), y))

I have discovered a workaround: embed the py_function, which can't return a dict, inside another function that is mapped to return a dict, thereby sidestepping the issue of the dataset ever iterating over nondicted double inputs (which is where the bug happens because it interprets them as being batched together and thus demands they have the same dims).

E.g.

    def dictionarize(x):

        x, static_cov = tf.py_function(attach_static_covariates, [x, idindex, colnames], [tf.float64, tf.float64])

        return {'dynamic': x, 'static': static_cov}

    train_ds = train_ds.map(lambda x, y: (dictionarize(x), y))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文