我刚读过这个article。文章说,tensorflow的resize算法有一些bug。现在我想使用scipy.misc.imresize
代替tf.image.resize_images
。我想知道实现scipy resize算法的最佳方法是什么。
让我们考虑以下一层:
def up_sample(input_tensor, new_height, new_width):
_up_sampled = tf.image.resize_images(input_tensor, [new_height, new_width])
_conv = tf.layers.conv2d(_up_sampled, 32, [3,3], padding="SAME")
return _conv
如何在此图层中使用scipy算法?
修改
一个例子可以是这个函数:
input_tensor = tf.placeholder("float32", [10, 200, 200, 8])
output_shape = [32, 210, 210, 8]
def up_sample(input_tensor, output_shape):
new_array = np.zeros(output_shape)
for batch in range(input_tensor.shape[0]):
for channel in range(input_tensor.shape[-1]):
new_array[batch, :, :, channel] = misc.imresize(input_tensor[batch, :, :, channel], output_shape[1:3])
但显然scipy引发了一个ValueError,即tf.Tensor对象没有正确的形状。我读到在tf.Session期间,Tensors可以作为numpy数组访问。如何仅在会话期间使用scipy函数并在创建协议缓冲区时省略执行?
有没有比循环所有批次和渠道更快的方法?
答案 0 :(得分:4)
一般来说,您需要的工具是tf.map_fn
和tf.py_func
的组合。
tf.py_func
允许您将标准python函数包装到插入到图形中的tensorflow操作中。tf.map_fn
允许您在批处理样本上重复调用函数,此时函数无法在整个批处理中运行 - 通常是图像函数的情况。在目前的情况下,我可能建议使用scipy.ndimage.zoom
,因为它可以直接在4D张量上运行,这使事情变得更简单。另一方面,它需要输入缩放因子,而不是大小,因此我们需要计算它们。
import tensorflow as tf
sess = tf.InteractiveSession()
# unimportant -- just a way to get an input tensor
batch_size = 13
im_size = 7
num_channel=5
x = tf.eye(im_size)[None,...,None] + tf.zeros((batch_size, 1, 1, num_channel))
new_size = 17
from scipy import ndimage
new_x = tf.py_func(
lambda a: ndimage.zoom(a, (1, new_size/im_size, new_size/im_size, 1)),
[x], [tf.float32], stateful=False)[0]
print(new_x.eval().shape)
# (13, 17, 17, 5)
你可以使用其他功能(例如OpenCV' cv2.resize
,Scikit-image transform.image
,Scipy' s misc.imresize
)但没有人可以直接操作在4D张量上,因此使用起来更加冗长。如果您想要除zoom
基于样条曲线的插值之外的插值,您可能仍希望使用它们。
但请注意以下事项:
Python函数在主机上执行。因此,如果您在图形卡等设备上执行图形,则需要停止,将张量复制到主机内存,调用函数,然后将结果复制回设备。如果内存传输很重要,这可能会完全破坏您的计算时间。
渐变不会传递python函数。如果您的节点在网络的升级部分中使用,则上游层将不会接收任何梯度(或者只有部分梯度,如果您有跳过连接),这会影响您的训练。
出于这两个原因,我建议仅在CPU上预处理并且不使用渐变时,将这种重采样应用于输入。
如果您确实想要使用这个高档节点进行设备培训,那么我认为无论是坚持使用有问题的tf.image.resize_image
,还是自己编写。