如何在tensorflow / keras中移动像pandas.shift这样的张量? (无需将最后一行移至第一行,如 tf.roll)

问题描述 投票:0回答:5

我想在给定轴上移动张量。在 pandas 或 numpy 中很容易做到这一点。像这样:

import numpy as np
import pandas as pd

data = np.arange(0, 6).reshape(-1, 2)
pd.DataFrame(data).shift(1).fillna(0).values

输出是:

数组([[0., 0.],
[0., 1.],
[2., 3.]])

但是在张量流中,我找到的最接近的解决方案是

tf.roll
。但它会将最后一行移到第一行。 (我不想那样)。所以我必须使用类似的东西

tf.roll + tf.slice(remove the last row) + tf.concat(add tf.zeros to the first row)

.

真的是

丑陋

在tensorflow或keras中是否有更好的方法来处理

shift

谢谢。

pandas numpy tensorflow keras shift
5个回答
3
投票
我想我找到了解决这个问题的更好方法。

我们可以使用

tf.roll

,然后应用 
tf.math.multiply
 将第一行设置为零。

示例代码如下:

原始张量:

A = tf.cast(tf.reshape(tf.range(27), (-1, 3, 3)), dtype=tf.float32) A
输出:

<tf.Tensor: id=117, shape=(3, 3, 3), dtype=float32, numpy= array([[[ 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.]]], dtype=float32)>

Shift(如 pd.shift)

B = tf.concat((tf.zeros((1, 3)), tf.ones((2, 3))), axis=0) C = tf.expand_dims(B, axis=0) tf.math.multiply(tf.roll(A, 1, axis=1), C)
输出:

<tf.Tensor: id=128, shape=(3, 3, 3), dtype=float32, numpy= array([[[ 0., 0., 0.], [ 0., 1., 2.], [ 3., 4., 5.]], [[ 0., 0., 0.], [ 9., 10., 11.], [12., 13., 14.]], [[ 0., 0., 0.], [18., 19., 20.], [21., 22., 23.]]], dtype=float32)>
    

2
投票
试试这个:

import tensorflow as tf input = tf.constant([[0, 1, 3], [4, 5, 6], [7, 8, 9]]) shifted_0dim = input[1:] shifted_1dim = input[:, 1:] shifted2 = input[2:]
    

2
投票

接受的答案推广到任意张量形状、所需的移位和要移位的轴:

import tensorflow as tf def tf_shift(tensor, shift=1, axis=0): dim = len(tensor.shape) if axis > dim: raise ValueError( f'Value of axis ({axis}) must be <= number of tensor axes ({dim})' ) mask_dim = dim - axis mask_shape = tensor.shape[-mask_dim:] zero_dim = min(shift, mask_shape[0]) mask = tf.concat( [tf.zeros(tf.TensorShape(zero_dim) + mask_shape[1:]), tf.ones(tf.TensorShape(mask_shape[0] - zero_dim) + mask_shape[1:])], axis=0 ) for i in range(dim - mask_dim): mask = tf.expand_dims(mask, axis=0) return tf.multiply( tf.roll(tensor, shift, axis), mask )
编辑:
上面的代码不允许负移位值,并且速度相当慢。这是一个更有效的版本,利用 

tf.roll

tf.concat
,无需创建掩码并将感兴趣的张量乘以它。

import tensorflow as tf def tf_shift(values: tf.Tensor, shift: int = 1, axis: int = 0): pad = tf.zeros([val if i != axis else abs(shift) for i, val in enumerate(values.shape)], dtype=values.dtype) size = [-1 if i != axis else val - abs(shift) for i, val in enumerate(values.shape)] if shift > 0: shifted = tf.concat( [pad, tf.slice(values, [0] * len(values.shape), size)], axis=axis ) elif shift < 0: shifted = tf.concat( [tf.slice(values, [0 if i != axis else abs(shift) for i, _ in enumerate(values.shape)], size), pad], axis=axis ) else: shifted = values return shifted
    

1
投票
假设是一个二维张量,这个函数应该模仿数据帧移位:

def shift_tensor(tensor, periods, fill_value): num_row = len(tensor) num_col = len(tensor[0]) pad = tf.fill([periods, num_col], fill_value) if periods > 0: shifted_tensor = tf.concat((pad, tensor[:(num_row - periods), :]), axis=0) else: shifted_tensor = tf.concat((tensor[:(num_row - periods), :], pad), axis=0) return shifted_tensor
    

0
投票
我认为你可以使用底片垫。 这会向后移动 -1,并在末尾添加 0。

keras.ops.pad([1, 2, 3], (-1, 1), 'constant', 0.)


张量([2, 3, 0], device='cuda:0', dtype=torch.int32)

这将向前移动一位,并在开头添加 0

keras.ops.pad([1, 2, 3], (1, 0), 'constant', 0.)


张量([0, 1, 2, 3], device='cuda:0', dtype=torch.int32)

你明白了。

https://www.tensorflow.org/api_docs/python/tf/keras/ops/pad

© www.soinside.com 2019 - 2024. All rights reserved.