Tensorflow 关于tf.Tensor.set_shape()的澄清

Tensorflow 关于tf.Tensor.set_shape()的澄清,tensorflow,Tensorflow,我有一张478x717x3=1028178像素的图像,排名为1。我通过调用tf.shape和tf.rank来验证它 当我调用image.set_shape([478717,3])时,它抛出以下错误 "Shapes %s and %s must have the same rank" % (self, other)) ValueError: Shapes (?,) and (478, 717, 3) must have the same rank 我再次测试了第一次铸造到1028178,但错误

我有一张478x717x3=1028178像素的图像,排名为1。我通过调用tf.shape和tf.rank来验证它

当我调用image.set_shape([478717,3])时,它抛出以下错误

"Shapes %s and %s must have the same rank" % (self, other)) 
ValueError: Shapes (?,) and (478, 717, 3) must have the same rank
我再次测试了第一次铸造到1028178,但错误仍然存在

ValueError: Shapes (1028178,) and (478, 717, 3) must have the same rank
嗯,这是有道理的,因为一个级别为1,另一个级别为3。但是,为什么必须抛出错误,因为总像素数仍然匹配

我当然可以使用tf.reforme,它可以工作,但我认为这不是最佳的

如TensorFlow常见问题解答所述

x.set_shape()和x=tf.reformate(x)之间有什么区别

方法更新张量的静态形状 对象,它通常用于提供附加形状 无法直接推断时的信息。它不会改变 张量的动态形状

reformate()操作创建具有不同动态形状的新张量

创建一个新的张量涉及内存分配,当涉及更多的训练示例时,这可能会更加昂贵。这是出于设计,还是我在这里遗漏了什么?

据我所知(我编写了代码),这本书中没有bug。我认为这一误解源于该方法令人困惑的名称

详细说明,
Tensor.set_shape()
是一个纯Python函数,它改进了给定
tf.Tensor
对象的形状信息。我所说的“改进”,是指“使更具体”

因此,当你有一个具有形状
(?,)
张量
对象
t
,这是一个长度未知的一维张量。您可以调用
t.set\u shape((1028178,)
,然后
t
在调用
t.get\u shape()
时将具有shape
(1028178,)
。这不会影响底层存储,或者实际上不会影响后端上的任何内容:这仅仅意味着使用
t
的后续形状推断可以依赖于它是长度为1028178的向量的断言

如果
t
有shape
(?,)
,调用
t.set\u shape((478717,3))
将失败,因为TensorFlow已经知道
t
是一个向量,所以它不能有shape
(478717,3)
。如果要从
t
的内容中生成具有该形状的新张量,可以使用。这将在Python中创建一个新的
tf.Tensor
对象;实际使用的是张量缓冲区的浅拷贝,因此在实践中成本较低


一个类比是
Tensor.set_shape()
类似于Java等面向对象语言中的运行时转换。例如,如果您有一个指向
对象的指针
,但知道它实际上是一个
字符串
,则可以执行cast
(String)obj
,以便将
obj
传递给需要
字符串
参数的方法。但是,如果您有一个
字符串
s
,并尝试将其转换为
java.util.Vector
,编译器将给您一个错误,因为这两种类型是不相关的。

真正的问题是,重新整形的张量是否与原始张量共享数据缓冲区,或者是否复制。通过快速阅读代码,我不太清楚,但如果它确实是一个副本,那应该加以修复。莫里在下面的回答中详细说明了这是一个肤浅的副本。@merry你知道
set\u shape()
功能在
1.0+
中的位置吗?我正是在寻找这个功能,以便告诉TensorFlow
tf.py_func
结果的形状。它仍然在同一个地方:@mrry关于这个方法的文档非常棒!我只想给那一个5*。但我使用的是tf数据集,在使用.map()将一些视频填充/截断到64帧后,我得到了。我不能指定视频的长度为64帧吗?或者这对图形优化来说无关紧要?