是否有更简单的方法来获取张量的切片,如下例所示?
Posted
技术标签:
【中文标题】是否有更简单的方法来获取张量的切片,如下例所示?【英文标题】: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.gather
或tf.gather_nd
来实现吗?
非常感谢!
【问题讨论】:
【参考方案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.07s
,tf.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))
【讨论】:
以上是关于是否有更简单的方法来获取张量的切片,如下例所示?的主要内容,如果未能解决你的问题,请参考以下文章
在 Tensorflow 2.0 中是不是有更简单的方法来执行模型层?
是否有更简洁的方法来获取错误和 Promise 的结果 [重复]