我想设计一个跟随函数,用于将任何1D/2D/3D
矩阵扩展为4D
矩阵。
import tensorflow as tf
def inputs_2_4D(inputs):
_ranks = tf.rank(inputs)
return tf.case({tf.equal(_ranks, 3): lambda: tf.expand_dims(inputs, 3),
tf.equal(_ranks, 2): lambda: tf.expand_dims(tf.expand_dims(inputs, 0), 3),
tf.equal(_ranks, 1): lambda: tf.expand_dims(tf.expand_dims(tf.expand_dims(inputs, 0), 0), 3)},
default=lambda: tf.identity(inputs))
def run():
with tf.Session() as sess:
mat_1d = tf.constant([1, 1])
mat_2d = tf.constant([[1, 1]])
mat_3d = tf.constant([[[1, 1]]])
mat_4d = tf.constant([[[[1, 1]]]])
result = inputs_2_4D(mat_1d)
print(result.eval())
然而,该功能无法正常运行。只有在4-D
和mat_3d
张量传递到矩阵时,它才能执行输出mat-4d
矩阵。如果将1D
或2D
矩阵传递给函数,则会出现一些错误信息。
将mat_3d
或mat_4d
传递到inputs_2_4D()
时,可以将它们扩展为4D矩阵或原始矩阵:
mat_3d -----> [[[[1]
[1]]]]
mat_4d -----> [[[[1 1]]]]
将mat_1d
或mat_2d
矩阵传递到inputs_2_4D
时,错误信息:
ValueError: dim 3 not in the interval [-2, 1]. for 'case/cond/ExpandDims' (op: 'ExpandDims') with input shapes: [2], [] and with computed input tensors: input[1] = <3>.
之前我测试过另一个类似的功能。该功能可以正常运行。
import tensorflow as tf
def test_2_4D(inputs):
_ranks = tf.rank(inputs)
return tf.case({tf.equal(_ranks, 3): lambda: tf.constant(3),
tf.equal(_ranks, 2): lambda: tf.constant(2),
tf.equal(_ranks, 1): lambda: tf.constant(1)},
default=lambda: tf.identity(inputs))
def run():
with tf.Session() as sess:
mat_1d = tf.constant([1, 1])
mat_2d = tf.constant([[1, 1]])
mat_3d = tf.constant([[[1, 1]]])
mat_4d = tf.constant([[[[1, 1]]]])
result = test_2_4D(mat_3d)
print(result.eval())
当传递所有矩阵时,此函数可以正确输出相应的结果。
test_2_4D()
结果:
mat_1d -----> 1
mat_2d -----> 2
mat_3d -----> 3
mat_4d -----> [[[[1 1]]]]
我不知道为什么在执行每个分支的inputs_2_4D()
时找不到tf.equal()
中的正确分支。我觉得如果输入矩阵是"mat_1d"
或"mat_2d".
,函数中的第1和第2个分支似乎仍然有效。因此,程序将崩溃。请帮我分析一下这个问题!
答案 0 :(得分:0)
我想我解决了问题所在。结果是评估所有条件/函数对。这可以通过赋予操作不同的名称来揭示。问题是,如果你的输入是排名2,Tensorflow似乎仍在评估tf.equal(_ranks, 3): lambda: tf.expand_dims(inputs, 3)
。这会导致崩溃,因为它无法扩展dim 3以获得rank-2张量(允许的最大值为2)。
这实际上是有道理的,因为tf.case
你基本上都在说&#34;我不知道哪些情况在运行时会是真的,所以检查哪一个是合适的并执行相应的功能&#34;。但是,这意味着Tensorflow需要为所有可能的情况准备执行路径,在这种情况下会导致无效的计算(尝试扩展无效的维度)。
在这一点上,了解一下你的问题会更好,也就是说你为什么需要这个功能。如果您有不同的输入并且您只想将它们全部带到4D,但每个输入始终具有相同的维度,请考虑使用Python if语句。例如:
inputs3d = tf.constant([[[1,1]]]) # this is always 3D
inputs2d = tf.constant([[1,1]]) # this is alwayas 2D
...
def inputs_2_4D(inputs):
_rank = len(inputs.shape.as_list())
if _rank == 3:
return tf.expand_dims(inputs, 3)
elif _rank == 2:
return tf.expand_dims(tf.expand_dims(inputs, 0), 3)
...
这将检查构建图形时的输入排名(不是在运行时,如tf.case
),并且实际上只准备那些适合给定的expand_dims
操作输入
但是,如果您有一个inputs
张量,并且在程序的不同时间可能会有不同的等级,则需要使用不同的解决方案。请告诉我们您要解决的问题!
答案 1 :(得分:0)
我通过2种方式实现了我想要的功能。现在,我提供我的代码分享。
基于tf.cond
的第一种方法:
def inputs_2_4D(inputs):
_rank1d = tf.rank(inputs)
def _1d_2_2d(): return tf.expand_dims(inputs, 0)
def _greater_than_1d(): return tf.identity(inputs)
_tmp_2d = tf.cond(_rank1d < 2, _1d_2_2d, _greater_than_1d)
_rank2d = tf.rank(_tmp_2d)
def _2d_2_3d(): return tf.expand_dims(_tmp_2d, 0)
def _greater_than_2d(): return tf.identity(_tmp_2d)
_tmp_3d = tf.cond(_rank2d < 3, _2d_2_3d, _greater_than_2d)
_rank3d = tf.rank(_tmp_3d)
def _3d_2_4d(): return tf.expand_dims(_tmp_3d, 3)
def _greater_than_3d(): return tf.identity(_tmp_3d)
return (tf.cond(_rank3d < 4, _3d_2_4d, _greater_than_3d))
基于tf.case
tf.cond
的第二种方法:
def inputs_2_4D_1(inputs):
_rank = tf.rank(inputs)
def _assign_original(): return tf.identity(inputs)
def _dummy(): return tf.expand_dims(inputs, 0)
_1d = tf.cond(tf.equal(_rank, 1), _assign_original, _dummy)
_2d = tf.cond(tf.equal(_rank, 2), _assign_original, _dummy)
_3d = tf.cond(tf.equal(_rank, 3), _assign_original, _dummy)
def _1d_2_4d(): return tf.expand_dims(tf.expand_dims(tf.expand_dims(_1d, 0), 0), 3)
def _2d_2_4d(): return tf.expand_dims(tf.expand_dims(_2d, 0), 3)
def _3d_2_4d(): return tf.expand_dims(_3d, 3)
return (tf.case({tf.equal(_rank, 1): _1d_2_4d,
tf.equal(_rank, 2): _2d_2_4d,
tf.equal(_rank, 3): _3d_2_4d},
default=_assign_original))
我认为第二种方法的效率应该低于第一种方法,因为在将_dummy()
分配到inputs
时,函数_1d
总是浪费2次操作,{ {1}},_2d
。