拆分具有多个输入的LSTM的tensorflow BatchDataset

huangapple go评论135阅读模式
英文:

Split tensorflow BatchDataset for LSTM with multiple inputs

问题

I construct a LSTM model with two inputs: one for categorical variables, one for numerical variables:

model = Model(inputs=[cat_input, num_input], outputs=x, name="LSTM")

The input data for the LSTM is generated by means of tensorflow.keras.utils.timeseries_dataset_from_array():

input_dataset = timeseries_dataset_from_array(
    df[["cat", "num1", "num2"]], df["target"], sequence_length=n_timesteps, sequence_stride=1, batch_size=20
)

When I directly feed input_dataset into the model, I get the following error: "ValueError: Layer "LSTM" expects 2 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, None, 3) dtype=int64>]", because the model expects two inputs and not one.

I can achieve this (a bit ugly) like so:

input_dataset2 = input_dataset.map(lambda x, y: ((x[:,:,0:1], x[:,:,1:3]), y))
model.fit(
    input_dataset2, steps_per_epoch=20, epochs=50, verbose=0, shuffle=True
) # this now works

My question: The solution I found is not very elegant. Is this kind of split also possible with tf.split() or another function?

EDIT: When I try the following:

input_dataset.map(lambda x, y: ((split(value=x, num_or_size_splits=[1, 2], axis=-1), y))

I get this error: "ValueError: Value [<tf.Tensor 'split:0' shape=(None, None, 1) dtype=int64>, <tf.Tensor 'split:1' shape=(None, None, 2) dtype=int64>] is not convertible to a tensor with dtype <dtype: 'int64'> and shape (2, None, None, None)."

(Note: I've retained the code and only translated the comments and error messages as requested.)

英文:

I construct a LSTM model with two inputs: one for categorical variables, one for numerical variables:

model = Model(inputs = [cat_input, num_input], outputs = x, name = &quot;LSTM&quot;)

The input data for the LSTM is generated by means of tensorflow.keras.utils.timeseries_dataset_from_array():

input_dataset = timeseries_dataset_from_array(
    df[[&quot;cat&quot;, &quot;num1&quot;, &quot;num2&quot;]], df[&quot;target&quot;], sequence_length=n_timesteps, sequence_stride=1, batch_size=20
)

When I directly feed input_dataset into the model, I get the following error: "ValueError: Layer "LSTM" expects 2 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, None, 3) dtype=int64>]", because the model expects two inputs and not one.

I can achieve this (a bit ugly) like so:

input_dataset2 = input_dataset.map(lambda x, y: ((x[:,:,0:1], x[:,:,1:3]), y))
model.fit(
    input_dataset2, steps_per_epoch=20, epochs=50, verbose=0, shuffle=True
) # this now works

My question: The solution I found is not very elegant. Is this kind of split also possible with tf.split() or another function?

EDIT: When I try the following:

input_dataset.map(lambda x, y: ((split(value=x, num_or_size_splits=[1, 2], axis = -1)), y))

I get this error: "ValueError: Value [<tf.Tensor 'split:0' shape=(None, None, 1) dtype=int64>, <tf.Tensor 'split:1' shape=(None, None, 2) dtype=int64>] is not convertible to a tensor with dtype <dtype: 'int64'> and shape (2, None, None, None)."

答案1

得分: 0

你可以使用tf.split()函数沿着最后一个轴分割输入张量,然后将分割后的张量作为单独的输入传递给你的模型。为了解决你遇到的"ValueError"错误,你需要将tf.split()的输出转换为tf.int64或其他兼容的数据类型,以用作模型的输入:

input_dataset = timeseries_dataset_from_array(
    df[["cat", "num1", "num2"]], df["target"], sequence_length=n_timesteps, sequence_stride=1, batch_size=20
)

input_dataset2 = input_dataset.map(lambda x, y: (tf.split(x, [1, 2], axis=-1), y))
input_dataset2 = input_dataset2.map(lambda x, y: (list(map(lambda x: tf.cast(x, tf.int64), x)), y))

model.fit(
    input_dataset2, steps_per_epoch=20, epochs=50, verbose=0, shuffle=True
)

希望这对你有所帮助。

英文:

You can use the tf.split() function to split the input tensor along the last axis, then you can pass the split tensors as separate inputs to your model. To fix the "ValueError" you encountered, you need to cast the outputs of tf.split() to tf.int64 or another compatible data type for the input of your model:

input_dataset = timeseries_dataset_from_array(
    df[[&quot;cat&quot;, &quot;num1&quot;, &quot;num2&quot;]], df[&quot;target&quot;], sequence_length=n_timesteps, sequence_stride=1, batch_size=20
)

input_dataset2 = input_dataset.map(lambda x, y: (tf.split(x, [1, 2], axis=-1), y))
input_dataset2 = input_dataset2.map(lambda x, y: (list(map(lambda x: tf.cast(x, tf.int64), x)), y))

model.fit(
    input_dataset2, steps_per_epoch=20, epochs=50, verbose=0, shuffle=True
)

答案2

得分: 0

我通过明确添加 tuple() 解决了这个问题 - 否则括号不会被识别为元组:

input_dataset = input_dataset.map(lambda x, y: 
    (
        tuple(
            tf.split(x, [1,2], -1)
        ),
        y
    )
)
英文:

I solved it by explicitly adding tuple() - the brackets are otherwise not recognized as tuple:

input_dataset = input_dataset.map(lambda x, y: 
    (
        tuple(
            tf.split(x, [1,2], -1)
        ),
        y
    )
)

huangapple
  • 本文由 发表于 2023年2月8日 23:32:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75388099.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定