tensorflow reproducible(再现性)
平时做实验一般需要保证每次实验结果一致(同样的设置下),这样才能知道哪些改进是真正有用的,最近在做实验的时候遇到一些问题,代码结果每次都不一样(小数点后面三位开始不相同,而且随着epoch的增加,结果慢慢就越来越不一样),下面是我我看见的一些保证reproducible的方法(tensorflow下):
1:tensorflow.set_random_seed()
因为tensorflow的参数初始化一般是随机的,除了你设置为常数,但是这样往往会造成学习到的网络不好,甚至梯度消失等问题,所以设置tensorflow.set_random_seed(seed)可以保证每次产生的初始化的参数一致。
import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np
temp=[range(30)] *5
graph=tf.Graph()
with graph.as_default():
tf.set_random_seed(1)
X=tf.placeholder(dtype=tf.float32,shape=[5,30])
fc1=slim.fully_connected(X,10)
with tf.Session(graph=graph) as sess:
sess.run(tf.global_variables_initializer())
print(fc1.eval(feed_dict={X:temp})[0])
这里的主要问题就是tensorflow.set_random_seed(seed)放置到哪里,经过试验,在graph里面才有用,下面的方法都不行(放在session后面,放在开头等等):
#beigining
import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np
tf.set_random_seed(1)
temp=[range(30)] *5
graph=tf.Graph()
with graph.as_default():
X=tf.placeholder(dtype=tf.float32,shape=[5,30])
fc1=slim.fully_connected(X,10)
with tf.Session(graph=graph) as sess:
sess.run(tf.global_variables_initializer())
print(fc1.eval(feed_dict={X:temp})[0])
#after sess
import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np
temp=[range(30)] *5
graph=tf.Graph()
with graph.as_default():
X=tf.placeholder(dtype=tf.float32,shape=[5,30])
fc1=slim.fully_connected(X,10)
with tf.Session(graph=graph) as sess:
tf.set_random_seed(1)
sess.run(tf.global_variables_initializer())
print(fc1.eval(feed_dict={X:temp})[0])
#middle
import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np
temp=[range(30)] *5
graph=tf.Graph()
tf.set_random_seed(1)
with graph.as_default():
X=tf.placeholder(dtype=tf.float32,shape=[5,30])
fc1=slim.fully_connected(X,10)
with tf.Session(graph=graph) as sess:
sess.run(tf.global_variables_initializer())
print(fc1.eval(feed_dict={X:temp})[0])
2:numpy & python
设置np.random.seed(seed)保证np的一些函数产生的结果reproducible,比如说np.random.shuffle().
对于python来说,random.seed(seed).
3:不确定因素
把上面的所有都设置了也不一定能够每次产生一样的值,我试过一些例子,如果保证前三个添加了的话,每次的结果大概是能保持一致的(交叉熵,adamoptimizer,三层全连接层的分类器),但是对于一个比较复杂的网络,每次的结果差异很小,但是多迭代训练几次差距就慢慢变大了(前几次仅仅小数点后面四位开始不一样),有的博客说是cuDNN的计算是不确定的(见参考文献),有的说GPU并行计算的时候可能会产生一些细小的差异。
但是,一般只要遵循前两个方法,把seed固定,那么每次产生的结果一般都一样。
参考:
https://stackoverflow.com/questions/38469632/tensorflow-non-repeatable-results
https://www.tensorflow.org/api_docs/python/tf/random/set_random_seed
https://groups.google.com/forum/#!topic/theano-users/QtaUzZ4iMlM
https://github.com/nagadomi/waifu2x/issues/132