【问题标题】:Is there a simpler method to get slice of a tensors as shown in the following example?是否有更简单的方法来获取张量的切片,如下例所示?
【发布时间】:2019-10-05 20:33:58
【问题描述】:

我想对张量进行切片,如下面的 numpy 切片。我该怎么做?

# numpy array
a = np.reshape(np.arange(60), (3,2,2,5))
idx = np.array([0, 1, 0])
N = np.shape(a)[0]
mask = a[np.arange(N),:,:,idx]


# I have tried several solutions, but only the following success.
# tensors
import tensorflow as tf
import numpy as np


a = tf.cast(tf.constant(np.reshape(np.arange(60), (3,2,2,5))), tf.int32)
idx2 = tf.constant([0, 1, 0])

fn = lambda i: a[i][:,:,idx2[i]]
idx = tf.range(tf.shape(a)[0])
masks = tf.map_fn(fn, idx)
with tf.Session() as sess:
    print(sess.run(a))
    print(sess.run(tf.shape(masks)))
    print(sess.run(masks))

有没有更简单的方法来实现这一点?

我可以使用函数tf.gathertf.gather_nd 来实现吗? 非常感谢!

【问题讨论】:

    标签: python tensorflow slice


    【解决方案1】:

    1.另一种方法

    我不确定这是否是最好的方法,但它更快。您可以使用tf.boolean_mask 代替tf.map_fn

    import tensorflow as tf
    import numpy as np
    
    a = tf.cast(tf.constant(np.reshape(np.arange(60), (3,2,2,5))), tf.int32)
    idx2 = tf.constant([0, 1, 0])
    
    fn = lambda i: a[i,:,:][:,:,idx2[i]]
    idx = tf.range(tf.shape(a)[0])
    masks = tf.map_fn(fn, idx)
    
    # new method
    idx = tf.one_hot(idx2,depth=a.shape[-1])
    masks2 = tf.boolean_mask(tf.transpose(a,[0,3,1,2]), idx)
    
    with tf.Session() as sess:
        print('tf.map_fn version:\n',sess.run(masks))
        print('tf.boolean_mask version:\n',sess.run(masks2))
    
    # print
    tf.map_fn version:
     [[[ 0  5]
      [10 15]]
    
     [[21 26]
      [31 36]]
    
     [[40 45]
      [50 55]]]
    tf.boolean_mask version:
     [[[ 0  5]
      [10 15]]
    
     [[21 26]
      [31 36]]
    
     [[40 45]
      [50 55]]]
    

    2.性能对比

    在我的 8GB GPU 内存上,向量化方法 1000 次迭代需要 0.07stf.map_fn 方法 1000 次迭代需要 0.85s。向量化方法将明显快于tf.map_fn()

    import datetime
    ...
    with tf.Session() as sess:
        start = datetime.datetime.now()
        for _ in range(1000):
            sess.run(masks)
        end = datetime.datetime.now()
        print('tf.map_fn version cost time(seconds) : %.2f' % ((end - start).total_seconds()))
    
        start = datetime.datetime.now()
        for _ in range(1000):
            sess.run(masks2)
        end = datetime.datetime.now()
        print('tf.boolean_mask version cost time(seconds) : %.2f' % ((end - start).total_seconds()))
    
    # print
    tf.map_fn version cost time(seconds) : 0.85
    tf.boolean_mask version cost time(seconds) : 0.07
    

    我相信随着a的形状增加,性能差异会变得更加明显。

    【讨论】:

      【解决方案2】:

      另一种方法使用tf.gather_nd:

      import tensorflow as tf
      import numpy as np
      
      
      a = tf.cast(tf.constant(np.reshape(np.arange(60), (3,2,2,5))), tf.int32)
      idx = tf.range(tf.shape(a)[0])
      idx2 = tf.constant([0,1,0])
      indices = tf.stack([idx, idx2], axis=1)
      a = tf.transpose(a, [0,3,1,2])
      masks = tf.gather_nd(a, indices)
      
      with tf.Session() as sess:
          print(sess.run(a))
          print(sess.run(tf.shape(masks)))
          print(sess.run(masks))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        • 1970-01-01
        • 2017-02-19
        • 1970-01-01
        • 2018-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多