Вообще говоря, инструменты, которые вам нужны, представляют собой комбинацию tf.map_fn
и tf.py_func
.
tf.py_func
позволяет вам обернуть стандартную функцию python в оператор тензорного потока, который вставляется в ваш график. tf.map_fn
позволяет вам повторно вызывать функцию в пакетных выборках, когда функция не может работать для всей партии - как это часто бывает в случае функций изображения.
В данном случае я бывероятно, советуем использовать scipy.ndimage.zoom
на том основании, что он может работать непосредственно с 4-мерным тензором, что упрощает задачу.С другой стороны, он принимает в качестве входных коэффициентов масштабирования, а не размеров, поэтому нам нужно их вычислить.
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.Если ваш узел используется, скажем, в масштабируемой части сети, слои в восходящем направлении не получат никакого градиента (или только его часть, если у вас пропущены соединения), что может поставить под угрозу ваше обучение.
По этим двум причинам я бы посоветовал применять этот вид повторной выборки только к входам, когда предварительная обработка на ЦП и градиенты не используются.
Если вы хотите использовать этот высококлассный узел для обученияна устройстве, тогда я не вижу альтернативы, чтобы либо придерживаться глючной tf.image.resize_image
, либо написать свою собственную.