在张量流中的卷积层上使用tf.train.Saver()

时间:2017-09-30 20:26:19

标签: tensorflow

我尝试使用tf.train.Saver()在张量流中的两个卷积神经网络图之间应用转移学习,并且我想验证我的方法是否按预期工作。有没有办法检查tf.layers.conv2d()图层中的可训练功能?

我的方法

1。初始化图层

conv1 = tf.layers.conv2d(inputs=X_reshaped, filters=conv1_fmaps, kernel_size=conv1_ksize,
                             strides=conv1_stride, padding=conv1_pad, 
                             activation=tf.nn.relu, 
                             kernel_initializer=tf.contrib.layers.xavier_initializer(), 
                             bias_initializer=tf.zeros_initializer(), trainable=True, 
                             name="conv1")

2。 {训练网络}

3。保存当前图表

tf.train.Saver().save(sess, "./my_model_final.ckpt")

4。构建包含相同图层的新图形,使用Saver()

加载指定的权重
reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
                               scope="conv[1]") 
reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars])
restore_saver = tf.train.Saver(reuse_vars_dict)

...

restore_saver.restore(sess, "./my_model_final.ckpt")

5。 {训练并评估新图}

我的问题:

1)我的代码按预期工作'并且没有错误,但我并不是100%自信它的工作就像我认为的那样。有没有办法从图层打印可训练的功能,以确保我正确加载和保存重量?是否有更好的"使用tf.layers API保存/加载参数的方法?我注意到GitHub上的request与此相关。理想情况下,我想在第一张图上检查这些值a)在初始化之后b)在训练之后和新图上i)在加载权重之后ii)在训练/评估之后。

1 个答案:

答案 0 :(得分:1)

  • 有没有办法从图层打印可训练的功能,以确保我正确加载和保存重量?<​​/ li>

是的,您首先需要处理图层的变量。有几种方法可以做到这一点,但可以说最简单的方法是使用get_collection()函数:

conv1_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
                               scope="conv1")

请注意,此处的范围被视为正则表达式,因此如果您想要范围conv[123]conv1conv2中的所有变量,则可以编写conv3之类的内容

如果您只想要可训练的变量,可以将GLOBAL_VARIABLES替换为TRAINABLE_VARIABLES

如果您只想检查单个变量,例如图层的内核,那么您可以像这样使用get_tensor_by_name()

graph = tf.get_default_graph()
kernel_var = graph.get_tensor_by_name("conv1/kernel:0")

另一种选择是迭代所有变量并根据其名称进行过滤:

conv1_vars = [var for var in tf.global_variables()
              if var.op.name.startswith("conv1/")]  

一旦掌握了这些变量,您就可以在不同的点上对它们进行评估,例如:刚刚初始化之后,刚恢复图形后,刚刚训练后,依此类推,并比较这些值。例如,这是在初始化之后获取值的方法:

with tf.Session() as sess:
    init.run()
    conv1_var_values_after_init = sess.run(conv1_vars)

然后,一旦你在你感兴趣的各个点捕获了变量值,就可以检查它们是否相等(或者足够接近,考虑到微小的浮点不精确),如下所示:

same = np.allclose(conv1_var_values_after_training,
                   conv1_var_values_after_restore)
  • 使用tf.layers API保存/加载参数是否有“更好”的方法?

不是我知道的。您指向的功能请求实际上并不是将参数保存/加载到磁盘,而是能够轻松获取图层变量的句柄,并轻松创建分配节点以设置其值。

例如,可以(在TF 1.4中)获取图层内核的句柄并非常简单地获取其值,如下所示:

conv1_kernel_value = conv1.kernel.eval()

当然,您可以使用它来获取/设置变量的值并将其加载/保存到磁盘,如下所示:

conv1 = tf.layers.conv2d(...)
new_kernel = tf.placeholder(...)
assign_kernel = conv1.kernel.assign(new_kernel)
init = tf.global_variables_initializer()

with tf.Session() as sess:
    init.run()
    loaded_kernel = my_function_to_load_kernel_value_from_disk(...)
    assign_kernel.run(feed_dict={new_kernel: loaded_kernel})
    ...

这不漂亮。如果要加载/保存到数据库(而不是平面文件)可能很有用,但一般情况下我建议使用Saver

我希望这会有所帮助。