Tensorflow 图节点是交换的
Tensorflow graph nodes are exchange
我用微调预训练模型训练了一个模型ssd_mobilenet_v2_coco_2018
。在这里,我使用了完全相同的 pipeline.config 文件进行训练,该文件位于 ssd_mobilenet_v2_coco_2018
预训练文件夹中。
我只删除了 batch_norm_trainable: true
标志并更改了 类 (4) 的数量。
在使用我的自定义数据集和 4 类 训练模型后,我发现 concat
和 concat_1
节点相互交换。
预训练模型有
| concat | 1x1917x1x4 |
训练后它变成
| concat | 1x1917x5 |
我附上了两个张量板图形可视化图像。第一张图片是预训练图 ssd_mobilenet_v2_coco_2018
。
节点交换可以在图像的最右上角看到。在预训练图中,Postprocess layer
与 concat_1
连接,Squeeeze
与 concat
连接。但是在训练之后,图形显示完全相反。比如 Prosprocess layer
连接 concat
和 Squeeeze
连接 concat_1
。
此外,我还在预训练模型图中发现 Preprocessor
接受输入 ToFloat
,而训练后该图显示 Cast 作为 Preprocessor
的输入。
我已将输入作为 tfrecords
.
提供给模型
最有可能的是,区别不在于图表,而在于节点的名称,即左侧的节点 concat
和 concat_1
与相应的节点相同。 concat_1
和右边的concat
。
问题是,当您不为节点提供明确的名称时,tensorflow 需要提供一个名称,而且它的命名约定相当缺乏创造性。第一次需要命名一个节点时,它使用它的类型来命名。当它再次遇到这种情况时,它只需在名称中添加 _
+ 一个递增的数字。
举个例子:
import tensorflow as tf
x = tf.placeholder(tf.float32, (1,), name='x')
y = tf.placeholder(tf.float32, (1,), name='y')
z = tf.placeholder(tf.float32, (1,), name='z')
xy = tf.concat([x, y], axis=0) # named 'concat'
xz = tf.concat([x, z], axis=0) # named 'concat_1'
图形如下所示:
现在,如果我们构建 相同的 图,但这次在 xy
之前创建 xz
,我们将得到以下图:
所以图表并没有真正改变——只是名字变了。这可能就是您的情况:创建了相同的操作,但顺序不同。
像 concat
这样的无状态节点的名称更改这一事实并不重要,因为例如在加载已保存的模型时不会错误路由权重。尽管如此,如果命名稳定性对您很重要,您可以为您的操作指定明确的名称或将它们放在不同的范围内:
xy = tf.concat([x, y], axis=0, name='xy')
xz = tf.concat([x, z], axis=0, name='xz')
如果variables切换名称,问题就多了。这就是为什么 tf.get_variable
—— 强制变量有一个名字并在发生名称冲突时引发错误 —— 是前 TF2 时代处理变量的首选方式的原因之一。
我用微调预训练模型训练了一个模型ssd_mobilenet_v2_coco_2018
。在这里,我使用了完全相同的 pipeline.config 文件进行训练,该文件位于 ssd_mobilenet_v2_coco_2018
预训练文件夹中。
我只删除了 batch_norm_trainable: true
标志并更改了 类 (4) 的数量。
在使用我的自定义数据集和 4 类 训练模型后,我发现 concat
和 concat_1
节点相互交换。
预训练模型有
| concat | 1x1917x1x4 |
训练后它变成
| concat | 1x1917x5 |
我附上了两个张量板图形可视化图像。第一张图片是预训练图 ssd_mobilenet_v2_coco_2018
。
节点交换可以在图像的最右上角看到。在预训练图中,Postprocess layer
与 concat_1
连接,Squeeeze
与 concat
连接。但是在训练之后,图形显示完全相反。比如 Prosprocess layer
连接 concat
和 Squeeeze
连接 concat_1
。
此外,我还在预训练模型图中发现 Preprocessor
接受输入 ToFloat
,而训练后该图显示 Cast 作为 Preprocessor
的输入。
我已将输入作为 tfrecords
.
最有可能的是,区别不在于图表,而在于节点的名称,即左侧的节点 concat
和 concat_1
与相应的节点相同。 concat_1
和右边的concat
。
问题是,当您不为节点提供明确的名称时,tensorflow 需要提供一个名称,而且它的命名约定相当缺乏创造性。第一次需要命名一个节点时,它使用它的类型来命名。当它再次遇到这种情况时,它只需在名称中添加 _
+ 一个递增的数字。
举个例子:
import tensorflow as tf
x = tf.placeholder(tf.float32, (1,), name='x')
y = tf.placeholder(tf.float32, (1,), name='y')
z = tf.placeholder(tf.float32, (1,), name='z')
xy = tf.concat([x, y], axis=0) # named 'concat'
xz = tf.concat([x, z], axis=0) # named 'concat_1'
图形如下所示:
现在,如果我们构建 相同的 图,但这次在 xy
之前创建 xz
,我们将得到以下图:
所以图表并没有真正改变——只是名字变了。这可能就是您的情况:创建了相同的操作,但顺序不同。
像 concat
这样的无状态节点的名称更改这一事实并不重要,因为例如在加载已保存的模型时不会错误路由权重。尽管如此,如果命名稳定性对您很重要,您可以为您的操作指定明确的名称或将它们放在不同的范围内:
xy = tf.concat([x, y], axis=0, name='xy')
xz = tf.concat([x, z], axis=0, name='xz')
如果variables切换名称,问题就多了。这就是为什么 tf.get_variable
—— 强制变量有一个名字并在发生名称冲突时引发错误 —— 是前 TF2 时代处理变量的首选方式的原因之一。