自己尝试复现了一下SSD,train一切顺利,但是在存储模型的时候遇到了这个问题。
花了整整24个小时,一度绝望,以为是自己代码的根本逻辑出了问题,记录一下解决这个问题的过程。
先说解决方法:
#-------------------
#(1)这里不应该有网络变量
#-------------------
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
...
...
saver = tf.train.Saver().
saver.save(sess, os.path.join('./save/', 'ckp'), global_step=1)
#-----------------
#saver.sava()这里应该是sess,而不是tf.Session()
#-----------------
报错截图:
尝试1.先看了stackoverflow上的问题,遇到了同样遇到这个问题的老哥,说是有local_variables没有被初始化,使用
tf.local_variables_initializer()
无效。
尝试2.然后发现我从网上复制的,储存模型的办法,是这样写的:
saver.save(tf.Session(), os.path.join('./save/', 'ckp'), global_step=1)
这在原有的项目里是不会出现问题的,因为原项目并没有用
with tf.Session() sess:
包裹训练/储存模块。但是,如果包裹了(就像最上面的代码块),就等于新开了一个回话,储存新开回话里的variables了。这显然是不对的,我们需要储存的是当前回话,也就是sess里的variables。应该把它改成sess。
这样改了。发现还是报错。
尝试3.然后我就想:在循环里的variables都是正常的,不然模型不可能正常训练。我打印了这些变量,也都是存在的。问题应该会出现在循环外的变量上。
接着就发现了,在最上方代码块中的(1)位置,我调用了自己的ssd_net网络模型。一开始是用来给绑定ground_truth的模块提供6个layer用的,得到一些tensor的形状,用于接下来的处理。
显然,调用了
tf.global_variables_initializer()
之后,一开始调用的ssd_net模型的参数就会出问题(会出什么问题还在思考中)。
然后改了代码结构,将一些处理都放在loss函数的模块里了,在循环外只有三行代码了
最后,在同时进行尝试2,尝试3之后,问题解决了。
但过程比较曲折。因为尝试2无效,我就将代码回滚了。然后发现尝试3之后还是会报一样的错误,再次将代码回滚了。就这样来回尝试/回滚了好多次。我甚至将网络变量一个个打印出来对比。最后才发现,同时错了两个地方,并且这两个错误会报同一个错。。。。。。
我对tensorflow的理解好像又变深了一点了。
为了庆祝,吃顿好的!