Tensorflow 图节点是交换的

Tensorflow graph nodes are exchange

我用微调预训练模型训练了一个模型ssd_mobilenet_v2_coco_2018。在这里,我使用了完全相同的 pipeline.config 文件进行训练,该文件位于 ssd_mobilenet_v2_coco_2018 预训练文件夹中。 我只删除了 batch_norm_trainable: true 标志并更改了 类 (4) 的数量。 在使用我的自定义数据集和 4 类 训练模型后,我发现 concatconcat_1 节点相互交换。 预训练模型有 | concat | 1x1917x1x4 | 训练后它变成 | concat | 1x1917x5 | 我附上了两个张量板图形可视化图像。第一张图片是预训练图 ssd_mobilenet_v2_coco_2018

节点交换可以在图像的最右上角看到。在预训练图中,Postprocess layerconcat_1 连接,Squeeezeconcat 连接。但是在训练之后,图形显示完全相反。比如 Prosprocess layer 连接 concatSqueeeze 连接 concat_1。 此外,我还在预训练模型图中发现 Preprocessor 接受输入 ToFloat,而训练后该图显示 Cast 作为 Preprocessor 的输入。 我已将输入作为 tfrecords.

提供给模型

最有可能的是,区别不在于图表,而在于节点的名称,即左侧的节点 concatconcat_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 时代处理变量的首选方式的原因之一。