如何在 Tensorflow 中重新批处理张量?

How do I re-batch a tensor in Tensorflow?

我有一个通过 CNN 将数据传递到 LSTM 的模型。但是在LSTM阶段之前我不得不重新组织CNN的输出,如下:

输入:(600, 512, 1) --(CNN)--> (600, 32)

这个 (600, 32) 张量由两个参数 k(window 大小)和 s(步长)修改,这两个参数都是整数,它们决定了以下张量的形状(我将调用进程 're-batching'):

重新批次:(600, 32) --> (146, 20, 32)

这些维度是使用感受野方程从 k 和 s 获得的:

此处n_in=600,n_out求值为146,k=20,p=0,s=4。

然后可以将这个新张量输入到 LSTM 中,因为形状是(batch_size、时间步长、特征),所以模型从那里继续...


我的问题是我不知道如何 're-batch' 这个张量而不破坏我的模型的向后传递。我尝试创建一个空数组 - np.empty(shape_of_lstm_input) - 并用所需数据迭代填充批处理轴的每个元素,但转换为 numpy 数组会导致在尝试最小化时丢失信息丢失,如以下警告消息所示:

WARNING:tensorflow:Gradients do not exist for variables ['list of all parameters in my CNN'] when minimizing the loss.

所以我尝试遵循相同的过程,但我认为使用 tf.zeros(shape_of_lstm_input) 可以解决缺少梯度的问题,但我却收到此错误消息:

TypeError: 'tensorflow.python.framework.ops.EagerTensor' object does not support item assignment


有谁知道这个问题是否存在解决方案?我不确定后向传递将如何处理前向传递中的这个 're-batching' 张量。

您似乎在尝试从数据中创建滑动 window。这是一种简单的方法:

import tensorflow as tf

def sliding_window(x, window_size, stride, axis=0):
    n_in = tf.shape(x)[axis]
    n_out = (n_in - window_size) // stride + 1
    # Just in case n_in < window_size
    n_out = tf.math.maximum(n_out, 0)
    r = tf.expand_dims(tf.range(n_out), 1)
    idx = r * stride + tf.range(window_size)
    return tf.gather(x, idx, axis=axis)

# Test
x = tf.reshape(tf.range(30), [10, 3])
print(x.numpy())
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 6  7  8]
#  [ 9 10 11]
#  [12 13 14]
#  [15 16 17]
#  [18 19 20]
#  [21 22 23]
#  [24 25 26]
#  [27 28 29]]
y = sliding_window(x, 4, 2)
print(y.numpy())
# [[[ 0  1  2]
#   [ 3  4  5]
#   [ 6  7  8]
#   [ 9 10 11]]
# 
#  [[ 6  7  8]
#   [ 9 10 11]
#   [12 13 14]
#   [15 16 17]]
# 
#  [[12 13 14]
#   [15 16 17]
#   [18 19 20]
#   [21 22 23]]
# 
#  [[18 19 20]
#   [21 22 23]
#   [24 25 26]
#   [27 28 29]]]