在tensorflow中使用tf.train.Saver()对卷积层进行保存

4
我正在尝试使用tf.train.Saver()在tensorflow中的两个卷积神经网络图之间应用迁移学习,并且我想验证我的方法是否按预期工作。有没有一种方法可以检查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")

的翻译是:“使用restore_saver从'./my_model_final.ckpt'路径中恢复会话(sess)。”

5. {训练和评估新图}

我的问题:

1) 我的代码正常运行且没有错误,但我不确定它是否按照我想象的那样工作。有没有一种方法可以打印一个层的可训练特征,以确保我正确地加载和保存了权重?是否有更好的使用tf.layers API保存/加载参数的方法?我在GitHub上注意到了一个相关的request。理想情况下,我想在第一个图形上检查这些值:a)初始化后 b)训练后;在新图形上 i)加载权重后 ii)训练/评估后。

1个回答

1
  • 有没有一种方法可以打印出一个层的可训练特征,以确保我正确加载和保存权重?

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

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

请注意,这里的作用域被视为正则表达式,因此您可以编写类似于conv[123]的内容,如果您想要从作用域conv1conv2conv3获取所有变量。
如果您只想要可训练的变量,则可以将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

希望这可以帮助您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接