我已经用微调的预训练模型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
与resp相同。右侧的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'
图形看起来像这样:
现在,如果我们构造same图,但是这次在xz
之前创建xy
,我们得到以下图:
所以图形并没有真正改变-只有名称改变了。这可能是您遇到的情况:创建了相同的操作,但顺序不同。
对于诸如concat
之类的无状态节点更改名称的事实并不重要,因为例如在加载保存的模型时不会发生权重分配错误的情况。但是,如果命名稳定性对您很重要,则可以为操作指定明确的名称,也可以将它们放在不同的范围内:
xy = tf.concat([x, y], axis=0, name='xy')
xz = tf.concat([x, z], axis=0, name='xz')
如果variables开关名称,则问题更大。这就是tf.get_variable
的原因之一-在TF2之前的时代中,这种方法会优先处理变量。