Tensorflow分布式训练过程中所遇到的问题
之前发过一篇文章也是关于在tensorflow上进行分布式训练的,当时只是初步的实现了这个方案,但是后来发现这个方案有问题,并且直到现在我也没有解决,不知道有没有大佬遇到过类似的问题。
因为研究方向的问题,在深度学习的过程中,需要做到对训练过程中的梯度做一些变换,我们知道在tensorflowd在参数更新的时候其实是分为两步的,一步是tf.gradients(), 通过给定的损失函数以及训练参数计算得到与之对应的梯度,该op返回的是一个list,其中包含着每一层参数的tensor对象,比如针对MNIST的一个网络 tf.gradient()返回的就如图所示
而第二步就是optimizer.apply_gradients() 也就是将计算好的梯度提交给optimizer,然后它再进行参数的更新操作。
举一个具体的例子就是,梯度消失或者梯度爆炸是我们在深度学习过程当中经常会遇到的问题,所以我们可以想到的办法就是针对计算得到的梯度进行一些裁剪,尽量让训练的过程中不会出现此类问题,而且tensorflow这个框架它也给出了相应的内部方法,废话不多说,上代码
grad_op = tf.train.AdamOptimizer(learning_rate) #选择优化器为Adam
params=tf.trainable_variables() #对所有的训练参数进行优化
grads=tf.gradients(cross_entropy,params) #计算出梯度
clippled_grads,_=tf.clip_by_global_norm(grads,2) #对梯度进行clip操作,tensorflow提供了几个clip操作可以自行选择
train_op=grad_op.apply_gradients(zip(clippled_grads,params)) #将clip后的梯度用于更新
我所作的工作也是基于此,我想对计算得到的梯度添加一些噪音啥的,因为“Deep Leakage from Gradients”这篇文章中提到在ps_worker这种分布式的工作模式下,梯度是有可能会泄露原始数据的隐私的,所以在分布式的深度学习过程中,对梯度进行一些保护也是必要的,那么显然大家都可以想象得到的就是在训练过程中对梯度添加噪音,对梯度进行扰乱(比如差分隐私) ,但是自己在实现的过程中却是碰了壁。
因为tensorflow是静态图,也就是说,所有的op应该是提前定义好的?然后后期在训练的时候直接给网络喂数据就行了,就像上面的那段代码一样,它都是在session会话开始之前定义好的,clip操作也是返回裁剪后的梯度的tensor对象。 但是由于自己编码能力有限,我在实现自己的想法过程中实际是这样的:
with tf.name_scope('train'):
#grad_op = tf.train.GradientDescentOptimizer(learning_rate)
grad_op = tf.train.AdamOptimizer(learning_rate)
train_op = grad_op.minimize(cross_entropy, global_step=global_step)
params = tf.trainable_variables()
gradients = tf.gradients(cross_entropy, params)
这一段代码是在session会话开始之前定义的,因为我要对梯度进行扰乱,需要用到它真实的值,所以智能在训练过程中 让sess来run一下gradients这个操作得到它真实的值,然后执行我接下来的操作:
with sv.prepare_or_wait_for_session(server.target) as sess:
sess.graph._unsafe_unfinalize()
start_time = time.time()
for epoch in range(training_epochs):
for i in range(100):
grads=sess.run(gradients,feed_dict={x: batch_x, y_: batch_y})
new_grads=update(grads) #update()就是对梯度的扰乱操作 并且返回的是新的梯度的tensor对象
train_step = grad_op.apply_gradients(zip(new_grads, params))
_,=sess.run( [train_step],feed_dict={x: batch_x, y_: batch_y})
但是后来发现一个问题就是说,它这些个操作是在sess会话中运行的,但是程序会报错说 “Graph is finalized and cannot be modified”,后来想一想也是的,因为tensorflow图结构是静态的,但是我在执行过程中生成的新的tensor对象,所以它会报这个错,并且clip()也会生成新的tensor对象呀? 但是我在不是分布式的情况下运行没有报这个错呀,也不知道具体是什么原因,只能加上sess.graph._unsafe_unfinalize()这个操作,但是加上这个后面也会出现问题就是一旦网络结果复杂一点,梯度多一点,我最后保存的文件里 图片里的这个META文件就会特别大,而且运行过程的内存还会溢出,train_step = grad_op.apply_gradients(zip(new_grads, params)),这个op所耗费的时间也会随着迭代次数的增加而增加
我现在觉得是不是我从头到尾的实现问题,看了很多文章,感觉是不是要推到重来? 我是不是应该写一个一定义的op来实现我对梯度进行的这些操作呢 ,害。