【问题标题】:Manipulating each batch individually in a tensorflow dataset在张量流数据集中单独操作每个批次
【发布时间】:2021-12-25 05:07:57
【问题描述】:

考虑下面的代码:

import tensorflow as tf
import numpy as np
 
simple_data_samples = np.array([
         [1, 1, 1, 7, -1],
         [2, -2, 2, -2, -2],
         [3, 3, 3, -3, -3],
         [-4, 4, 4, -4, -4],
         [5, 5, 5, -5, -5],
         [6, 6, 6, -4, -1],
         [7, 7, 8, -7, -70],
         [8, 8, 8, -8, -8],
         [9, 4, 9, -9, -9],
         [10, 10, 10, -10, -10],
         [11, 5, 11, -11, -11],
         [12, 12, 12, -12, -12],
])


        
def single (ds):
    for x in ds:
        print(x)
    
def timeseries_dataset_multistep_combined(features, label_slice, input_sequence_length, output_sequence_length, sequence_stride, batch_size):
    feature_ds = tf.keras.preprocessing.timeseries_dataset_from_array(features, None, sequence_length=input_sequence_length + output_sequence_length, sequence_stride=sequence_stride ,batch_size=batch_size, shuffle=False)


    return feature_ds

ds = timeseries_dataset_multistep_combined(simple_data_samples, slice(None, None, None), input_sequence_length=4, output_sequence_length=2, sequence_stride=2, batch_size=2)

single(ds)

此代码创建以下批次输出:

tf.Tensor(
[[[  1   1   1   7  -1]
  [  2  -2   2  -2  -2]
  [  3   3   3  -3  -3]
  [ -4   4   4  -4  -4]
  [  5   5   5  -5  -5]
  [  6   6   6  -4  -1]]

 [[  3   3   3  -3  -3]
  [ -4   4   4  -4  -4]
  [  5   5   5  -5  -5]
  [  6   6   6  -4  -1]
  [  7   7   8  -7 -70]
  [  8   8   8  -8  -8]]], shape=(2, 6, 5), dtype=int64)
tf.Tensor(
[[[  5   5   5  -5  -5]
  [  6   6   6  -4  -1]
  [  7   7   8  -7 -70]
  [  8   8   8  -8  -8]
  [  9   4   9  -9  -9]
  [ 10  10  10 -10 -10]]

 [[  7   7   8  -7 -70]
  [  8   8   8  -8  -8]
  [  9   4   9  -9  -9]
  [ 10  10  10 -10 -10]
  [ 11   5  11 -11 -11]
  [ 12  12  12 -12 -12]]], shape=(2, 6, 5), dtype=int64)

我想单独操作每个批次。为此,我想分别从每个批次中提取最大值。这可以通过以下代码完成:

def timeseries_dataset_multistep_combined(features, label_slice, input_sequence_length, output_sequence_length, sequence_stride, batch_size):
    feature_ds = tf.keras.preprocessing.timeseries_dataset_from_array(features, None, sequence_length=input_sequence_length + output_sequence_length, sequence_stride=sequence_stride ,batch_size=batch_size, shuffle=False)
     
    def extract_max(x):
        return tf.reduce_max(x[:,:,-1],axis=1,keepdims=True)

    
    feature_ds = feature_ds.map(extract_max)


    return feature_ds

ds = timeseries_dataset_multistep_combined(simple_data_samples, slice(None, None, None), input_sequence_length=4, output_sequence_length=2, sequence_stride=2, batch_size=2)

single(ds)

由于我创建了四个批次,我希望有四个最大值,如下所示:

tf.Tensor(
[[-1]
 [-1]], shape=(2, 1), dtype=int64)
tf.Tensor(
[[-1]
 [-8]], shape=(2, 1), dtype=int64)

现在我想将每个最大值添加到其对应的批次中。例如,对于第一批输出,我将添加第一个最大值 (-1) 并期望以下输出:

[[[  1   1   1   7  -1]
  [  2  -2   2  -2  -2]
  [  3   3   3  -3  -3]
  [ -4   4   4  -4  -4]
  [  5   5   5  -5  -5]
  [  6   6   6  -4  -1]] +(-1) ###first max value =

[[[  0   0   0   6  -2]
  [  1  -3   1  -3  -3]
  [  2   2   2  -4  -4]
  [ -5   3   3  -5  -5]
  [  4   4   4  -6  -6]
  [  5   5   5  -5  -2]] 

我将如何编码?

【问题讨论】:

    标签: python tensorflow tensorflow-datasets


    【解决方案1】:

    你想要广播。广播只能从右边开始。要从左侧广播,请将您的最大张量重塑为 (2,1,1) 以填充右侧的额外暗点,然后使用 + 号天真地执行加法。广播将负责其余的工作。

    欲了解更多信息,请查看https://www.tensorflow.org/api_docs/python/tf/broadcast_to

    【讨论】:

    • 谢谢,但更简单的方法是在保持形状的同时提取最大值,然后我可以执行算术运算,如加法。使用函数tf.reduce_max 我得到了shape=(2, 1) 的形状,但预期的形状应该是shape=(2, 6, 5)
    • 是的,同意 - 你用 keep_kims=True 做对了,它应该提供一个形状 (2,1,1)。我不确定是什么命令进一步将您的暗淡减少到 (2,1)。
    【解决方案2】:

    您可以使用 tf.repeat 并尝试以下操作:

    def broad_cast_and_merge(ds1, ds2):
      ds1_shape = tf.shape(ds1)
      ds2 = tf.reshape(tf.repeat(ds2, repeats=ds1_shape[1] * ds1_shape[2]), ds1_shape)
      return ds1 + ds2
    
    final_ds = tf.data.Dataset.zip((time_series_ds, max_ds)).map(broad_cast_and_merge)
    single(final_ds)
    

    或者tf.broadcast_to:

    def broad_cast_and_merge(ds1, ds2):
      ds2 = tf.expand_dims(ds2, axis=-1)
      ds2 = tf.broadcast_to(ds2, tf.shape(ds1))
      return ds1 + ds2
    
    final_ds = tf.data.Dataset.zip((time_series_ds, max_ds)).map(broad_cast_and_merge)
    single(final_ds)
    

    两者都会给你相同的结果:

    tf.Tensor(
    [[[  0   0   0   6  -2]
      [  1  -3   1  -3  -3]
      [  2   2   2  -4  -4]
      [ -5   3   3  -5  -5]
      [  4   4   4  -6  -6]
      [  5   5   5  -5  -2]]
    
     [[  2   2   2  -4  -4]
      [ -5   3   3  -5  -5]
      [  4   4   4  -6  -6]
      [  5   5   5  -5  -2]
      [  6   6   7  -8 -71]
      [  7   7   7  -9  -9]]], shape=(2, 6, 5), dtype=int64)
    tf.Tensor(
    [[[  4   4   4  -6  -6]
      [  5   5   5  -5  -2]
      [  6   6   7  -8 -71]
      [  7   7   7  -9  -9]
      [  8   3   8 -10 -10]
      [  9   9   9 -11 -11]]
    
     [[ -1  -1   0 -15 -78]
      [  0   0   0 -16 -16]
      [  1  -4   1 -17 -17]
      [  2   2   2 -18 -18]
      [  3  -3   3 -19 -19]
      [  4   4   4 -20 -20]]], shape=(2, 6, 5), dtype=int64)
    

    如前所述,您也可以跳过广播步骤,直接使用tf.expand_dims

    【讨论】:

    • 谢谢,但我可以跳过广播步骤,直接使用tf.expand_dims(ds2, axis=-1)。它会给我同样的输出。
    • 是的,已更新答案以包含您的选项。现在还好吗?
    • 我仍然看到相同的答案,但我的意思是ds2 = tf.broadcast_to(ds2, tf.shape(ds1)) 的步骤可以省略
    猜你喜欢
    • 2021-02-10
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 2016-10-05
    • 2018-09-29
    • 2020-09-01
    • 2018-08-04
    • 1970-01-01
    相关资源
    最近更新 更多