Я хотел бы иметь возможность повернуть тензор в моде, похожее на collections.deque.rotate. Возможность транслировать этот пакетный мудрый будет идеальным. Например, учитывая массив вращений foo, я хотел бы повернуть каждую строку bar соответствующей записью в foo.

Например

def tf_rotate(to_rotate, rotate_by):
    pass #How to do this?

with tf.Session('') as sesh:
    foo = tf.constant([1,2,3])
    bar = tf.constant(
        [[1,  2,  3],
         [4,  5,  6],
         [7,  8,  9]])
    print(
        sesh.run(
            tf_rotate(bar, foo)
    ))

Должен дать:

[[3  1  2]
 [5  6  4]
 [7  8  9]]

Эта операция довольно тривиальная, как и для цикла, но такие вещи становятся сложными при реализации алгоритма в Tensorflow. Как мы можем выполнить Круговая перестановка к массиву / тензоре в Tensorflow?

0
Him 30 Сен 2019 в 21:35

1 ответ

Лучший ответ

Может быть, как это так:

def rotate(matrix, shifts):
    """"requested rotate function - assumes matrix shape is mxn and shifts shape is m"""

    # get shape of the input matrix
    shape = tf.shape(matrix)

    # compute and stack the meshgrid to get the index matrix of shape (2,m,n)
    ind = tf.stack(tf.meshgrid(tf.range(shape[0]), tf.range(shape[1]), indexing='ij'))

    # reshape it to (m,n,2)
    ind = tf.transpose(ind, [1,2,0])

    # add the value from shifts to the corresponding row and devide modulo shape[1]
    # this will effectively introduce the desired shift, but at the level of indices
    shifted_ind = tf.mod(tf.transpose(tf.transpose(ind[:,:,1]) + shifts), shape[1])

    # convert the shifted indices to the right shape
    new_ind = tf.transpose(tf.stack([ind[:,:,0], shifted_ind]) , [1,2,0]) 

    # return the resliced tensor
    return tf.gather_nd(matrix, new_ind)

Примере:

In [36]: matrix = np.tile(10*np.arange(10), [7,1])                                                                                        

In [37]: matrix                                                                                                                           
Out[37]: 
array([[ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
       [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90]])

In [38]: shifts = np.random.randint(low=0, high=matrix.shape[1], size=matrix.shape[0], dtype=int32)                                       

In [39]: shifts                                                                                                                           
Out[39]: array([5, 7, 6, 4, 5, 6, 6], dtype=int32)

In [40]: res = rotate(tf.constant(matrix), tf.constant(shifts))                                                                           

In [41]: sess.run(res)                                                                                                                    
Out[41]: 
array([[50, 60, 70, 80, 90,  0, 10, 20, 30, 40],
       [70, 80, 90,  0, 10, 20, 30, 40, 50, 60],
       [60, 70, 80, 90,  0, 10, 20, 30, 40, 50],
       [40, 50, 60, 70, 80, 90,  0, 10, 20, 30],
       [50, 60, 70, 80, 90,  0, 10, 20, 30, 40],
       [60, 70, 80, 90,  0, 10, 20, 30, 40, 50],
       [60, 70, 80, 90,  0, 10, 20, 30, 40, 50]])

Не уверен, что это лучше, чем петля, хотя.

1
Alexandr Dibrov 1 Окт 2019 в 00:01