Tensorflow 通过嵌套tf.map_fn反向传播梯度
我想在每个向量上映射一个TensorFlow函数,该向量对应于矩阵中每个像素的深度通道,维度[批次大小,H,W,n\u通道] 换句话说,对于批次中每个大小为H x W的图像:Tensorflow 通过嵌套tf.map_fn反向传播梯度,tensorflow,nested,gradient,backpropagation,map-function,Tensorflow,Nested,Gradient,Backpropagation,Map Function,我想在每个向量上映射一个TensorFlow函数,该向量对应于矩阵中每个像素的深度通道,维度[批次大小,H,W,n\u通道] 换句话说,对于批次中每个大小为H x W的图像: 我提取了一些具有相同大小hxw的特征映射F_k(其数量为n_通道)(因此,所有特征映射都是形状[H,W,n_通道]的张量) 然后,我希望对向量v_ij应用一个自定义函数,该向量与每个特征映射F_k的第I行和第j列相关联,但探索整个深度通道(例如,v具有维度[1 x 1 x n_通道])。理想情况下,所有这一切都将并行发生
tf.map\u fn()
可能是一个选项,我尝试了以下解决方案,其中我递归地使用tf.map\u fn()
来访问与每个像素相关的功能。然而,这类功能似乎是次优的,最重要的是在尝试反向传播梯度时会出错
您是否知道发生这种情况的原因,以及我应该如何构造代码以避免错误
这是我当前对该功能的实现:
import tensorflow as tf
from tensorflow import layers
def apply_function_on_pixel_features(incoming):
# at first the input is [None, W, H, n_channels]
if len(incoming.get_shape()) > 1:
return tf.map_fn(lambda x: apply_function_on_pixel_features(x), incoming)
else:
# here the input is [n_channels]
# apply some function that applies a transfomration and returns a vetor of the same size
output = my_custom_fun(incoming) # my_custom_fun() doesn't change the shape
return output
以及我的代码主体:
H = 128
W = 132
n_channels = 8
x1 = tf.placeholder(tf.float32, [None, H, W, 1])
x2 = layers.conv2d(x1, filters=n_channels, kernel_size=3, padding='same')
# now apply a function to the features vector associated to each pixel
x3 = apply_function_on_pixel_features(x2)
x4 = tf.nn.softmax(x3)
loss = cross_entropy(x4, labels)
optimizer = tf.train.AdamOptimizer(lr)
train_op = optimizer.minimize(loss) # <--- ERROR HERE!
可以找到整个错误堆栈和代码。
谢谢你的帮助
G
更新:
根据@thushv89的建议,我为这个问题添加了一个可能的解决方案。我仍然不知道我以前的代码为什么不起作用。对此的任何见解都将非常感谢。根据@thushv89的建议,我重塑了数组,应用了函数,然后又重塑了它(为了避免
tf.map\u fn
递归)。我仍然不知道以前的代码为什么不起作用,但是当前的实现允许将渐变传播回以前的层。我将在下面留下它,可能对谁感兴趣:
def apply_function_on_pixel_features(incoming, batch_size):
# get input shape:
_, W, H, C = incoming.get_shape().as_list()
incoming_flat = tf.reshape(incoming, shape=[batch_size * W * H, C])
# apply function on every vector of shape [1, C]
out_matrix = my_custom_fun(incoming_flat) # dimension remains unchanged
# go back to the input shape shape [None, W, H, C]
out_shape = tf.convert_to_tensor([batch_size, W, H, C])
out_matrix = tf.reshape(out_matrix, shape=out_shape)
return out_matrix
请注意,现在我需要给出批量大小来正确地重塑张量,因为如果我没有给出任何或-1作为维度,TensorFlow会抱怨
如果您对上述代码有任何意见和见解,我们将不胜感激。@gabriele关于必须依赖于批大小的问题,您是否尝试过以下方法?此函数不依赖于批大小。您可以用任何您喜欢的方法替换
映射fn
def apply_function_on_pixel_features(incoming):
# get input shape:
_, W, H, C = incoming.get_shape().as_list()
incoming_flat = tf.reshape(incoming, shape=[-1, C])
# apply function on every vector of shape [1, C]
out_matrix = tf.map_fn(lambda x: x+1, incoming_flat) # dimension remains unchanged
# go back to the input shape shape [None, W, H, C]
out_matrix = tf.reshape(out_matrix, shape=[-1, W, H, C])
return out_matrix
我测试的完整代码如下所示
import numpy as np
import tensorflow as tf
from tensorflow.keras.losses import categorical_crossentropy
def apply_function_on_pixel_features(incoming):
# get input shape:
_, W, H, C = incoming.get_shape().as_list()
incoming_flat = tf.reshape(incoming, shape=[-1])
# apply function on every vector of shape [1, C]
out_matrix = tf.map_fn(lambda x: x+1, incoming_flat) # dimension remains unchanged
# go back to the input shape shape [None, W, H, C]
out_matrix = tf.reshape(out_matrix, shape=[-1, W, H, C])
return out_matrix
H = 32
W = 32
x1 = tf.placeholder(tf.float32, [None, H, W, 1])
labels = tf.placeholder(tf.float32, [None, 10])
x2 = tf.layers.conv2d(x1, filters=1, kernel_size=3, padding='same')
# now apply a function to the features vector associated to each pixel
x3 = apply_function_on_pixel_features(x2)
x4 = tf.layers.flatten(x3)
x4 = tf.layers.dense(x4, units=10, activation='softmax')
loss = categorical_crossentropy(labels, x4)
optimizer = tf.train.AdamOptimizer(0.001)
train_op = optimizer.minimize(loss)
x = np.zeros(shape=(10, H, W, 1))
y = np.random.choice([0,1], size=(10, 10))
with tf.Session() as sess:
tf.global_variables_initializer().run()
sess.run(train_op, feed_dict={x1: x, labels:y})
请参阅@geometrical谢谢你的回答。我恐怕我没有很好地解释这个问题。我更新了这个问题,所以可能它更清楚。如果你仍然认为广播是最好的选择,请你更好地解释一下如何在我的情况下使用它,好吗?(我不明白)我用我当前的代码和问题更新了这个问题。我认为错误与if语句和应用函数中的递归有关。你能与你共享要应用的确切函数吗?我认为广播可以用于基础数学,其他一些tensorflow函数采用轴参数。我不确定如果可以应用任何函数。@gabriele,看这幅图像,你似乎试图在特征映射中的每个像素上应用某个自定义函数?是否正确,如果正确,为什么需要递归?只需进行一次整形,进行映射,然后再进行一次整形,恢复到原始形状?您好@thushv89,谢谢您的建议。但是,对于wh根据你的建议,我将重塑张量,使其具有形状[-1],而不是[batch_size*W*H,C](这是我需要将函数一致地应用于每个像素的所有特征)。此外,我认为重塑为[-1,C],然后[-1,W,H,C]给了我一个错误。TensorFlow似乎在抱怨,因为它无法将形状未知的对象转换为tensor。@gabriele,实际上对我来说工作得很好。你有错误吗?嗨@thushv89,很抱歉回复太晚,但我以前无法测试。我再次尝试用-1替换批次大小,现在它似乎工作了。可能是我出了问题。谢谢您的帮助!:)您应该使用
shape=[-1,C]
更新行incoming\u flat=tf.reformate(incoming,shape=[-1])
,这是我想要获得的,然后我将为您分配bounty@gabriele,很高兴听到这个消息。更新了我的答案。:)
import numpy as np
import tensorflow as tf
from tensorflow.keras.losses import categorical_crossentropy
def apply_function_on_pixel_features(incoming):
# get input shape:
_, W, H, C = incoming.get_shape().as_list()
incoming_flat = tf.reshape(incoming, shape=[-1])
# apply function on every vector of shape [1, C]
out_matrix = tf.map_fn(lambda x: x+1, incoming_flat) # dimension remains unchanged
# go back to the input shape shape [None, W, H, C]
out_matrix = tf.reshape(out_matrix, shape=[-1, W, H, C])
return out_matrix
H = 32
W = 32
x1 = tf.placeholder(tf.float32, [None, H, W, 1])
labels = tf.placeholder(tf.float32, [None, 10])
x2 = tf.layers.conv2d(x1, filters=1, kernel_size=3, padding='same')
# now apply a function to the features vector associated to each pixel
x3 = apply_function_on_pixel_features(x2)
x4 = tf.layers.flatten(x3)
x4 = tf.layers.dense(x4, units=10, activation='softmax')
loss = categorical_crossentropy(labels, x4)
optimizer = tf.train.AdamOptimizer(0.001)
train_op = optimizer.minimize(loss)
x = np.zeros(shape=(10, H, W, 1))
y = np.random.choice([0,1], size=(10, 10))
with tf.Session() as sess:
tf.global_variables_initializer().run()
sess.run(train_op, feed_dict={x1: x, labels:y})