TensorFlow中reshape操作后张量值异常改变的问题咨询
问题原因分析与解决办法
你遇到的这个“reshape改变张量值”的问题其实是个TensorFlow静态计算图执行机制的误区——根本不是reshape操作修改了数值,而是你两次调用.eval()时,TensorFlow重新执行了tf.random_normal生成了新的随机数!
具体原因拆解
在TensorFlow的静态计算图模式下:
- 当你定义
a_S = tf.random_normal([1,1,1,3], ...)时,只是在计算图中添加了一个“生成随机数”的节点,并没有立刻生成具体数值。 - 第一次调用
a_S.eval()时,TensorFlow会遍历计算图,执行这个随机数生成节点,得到第一组值:[[-[[-1.68344498 1.89428568 4.18909216]]]] - 当你执行
a_S = tf.reshape(a_S, [n_C, n_H*n_W])后,再次调用a_S.eval(),TensorFlow会重新遍历整个计算图:先执行原来的tf.random_normal节点(生成了全新的随机数),再对新生成的数值执行reshape操作,所以你看到的是新随机数reshape后的结果,而非原数值的reshape结果。
解决办法
你需要把随机生成的数值固定下来,避免每次eval都重新生成,这里有几种可行方案:
方案1:提前计算并固定随机值
在会话中先把a_S和a_G的数值计算出来,再传入reshape操作:
def compute_layer_style_cost(a_S, a_G): m, n_H, n_W, n_C = a_S.get_shape().as_list() print("m=>", m, "n_H=>", n_H, "n_W=>", n_W, "n_C=>", n_C) print("a_S.shape=>", a_S.shape) # 先计算并固定随机值 a_S_val = a_S.eval() a_G_val = a_G.eval() print("a_S=>", a_S_val) # 对固定的数值执行reshape a_S_reshaped = tf.reshape(a_S_val, [n_C, n_H*n_W]) a_G_reshaped = tf.reshape(a_G_val, [n_C, n_H*n_W]) print("a_S.shape=>", a_S_reshaped.shape) print("a_S=>", a_S_reshaped.eval())
方案2:用同一个eval调用获取所有结果
把需要打印的张量打包成一个列表,一次eval就能获取所有结果,这样tf.random_normal只会执行一次:
def compute_layer_style_cost(a_S, a_G): m, n_H, n_W, n_C = a_S.get_shape().as_list() print("m=>", m, "n_H=>", n_H, "n_W=>", n_W, "n_C=>", n_C) print("a_S.shape=>", a_S.shape) # 定义reshape后的张量 a_S_reshaped = tf.reshape(a_S, [n_C, n_H*n_W]) a_G_reshaped = tf.reshape(a_G, [n_C, n_H*n_W]) # 一次eval获取原始值和reshape后的值 original_S, reshaped_S = test.run([a_S, a_S_reshaped]) print("a_S=>", original_S) print("a_S.shape=>", a_S_reshaped.shape) print("a_S=>", reshaped_S)
方案3:用Variable固定随机值
把随机张量转换成Variable,初始化后数值就固定了:
tf.reset_default_graph() with tf.Session() as test: tf.set_random_seed(1) # 定义为Variable并初始化 a_S = tf.Variable(tf.random_normal([1, 1,1,3], mean=1, stddev=4)) a_G = tf.Variable(tf.random_normal([1, 1,1,3], mean=1, stddev=4)) test.run(tf.global_variables_initializer()) J_style_layer = compute_layer_style_cost(a_S, a_G) print("J_style_layer = " + str(J_style_layer.eval()))
这样修改后,你就能看到reshape操作只是改变了张量的形状,数值完全和原始值对应了。
内容的提问来源于stack exchange,提问作者Jiancong
相关产品推荐
相关产品推荐

