想手动实现Adagrad,因为Adagrad有两部分需要更新,因为之前合并两个initializer用过tf.group,想当然认为tf.group可能是带顺序的,所以打算把两个update直接group起来执行,看起来省事,感觉却会出事,觉得很可能不带顺序,所以写了个小demo验证:
一个操作是a自加1,这类似adagrad的分母更新;
一个操作是给b赋值a的值,相当于使用第一步的结果。
无论跑500、3000、30000次,结果都有不确定性,经常会少1
#demo1
#when range(500)two results randomly occur:499 and 500
#when range(3000)two results randomly occur:2999 and 3000
with tf.name_scope('initial'):
a = tf.Variable(0,dtype=tf.float32)
b = tf.Variable(0,dtype=tf.float32)
#update
update1 = tf.assign_add(a,1)
update2 = tf.assign(b, a)
update = tf.group(update1,update2)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for _ in range(30000):
_ = sess.run(update)
print(sess.run(b))
虽然结果表现出一定的随机性,但是验证效果不明显,为了进一步验证,让a先自加,再自减,那么b应该永远是0才算执行顺序明确!
实际测试:30000次循环,b的数值非常不稳定,一直上下随机跳,最终结果有时候能到正4、5,有时候-4.
猜测是因为无序执行,造成了a只执行了一个自加或者自减,b就被赋值了,就是说,期待1->2->3的顺序,实际上是1->3->2(增)、2->3->1(减)这样的顺序!(A33任意顺序都可能,这两种影响结果)
#demo2
#for _ in range(30000): output is randomly in 0,-1,-2,-3,-4 and the final output is -4
#for _ in range(30000): output is randomly in 0,1,2,3,4,5 and the final output is 4
#speculate wrong sequence:
#update1,update3,update2
#update2,update3,update1
with tf.name_scope('initial'):
a = tf.Variable(0,dtype=tf.float32)
b = tf.Variable(0,dtype=tf.float32)
#update
update1 = tf.assign_add(a,1)
update2 = tf.assign_sub(a,1)
update3 = tf.assign(b, a)
update = tf.group(update1,update2,update3)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for _ in range(30000):
_ = sess.run(update)
print(sess.run(b))
tf.group的说明,没说有顺序,这就坑爹了,所以说,tf.group只适合合并不关心顺序的操作,多步更新不能乱用tf.group。
Help on function group in module tensorflow.python.ops.control_flow_ops:
group(*inputs, **kwargs)
Create an op that groups multiple operations.
When this op finishes, all ops in `inputs` have finished. This op has no
output.
See also @{tf.tuple$tuple} and
@{tf.control_dependencies$control_dependencies}.
Args:
*inputs: Zero or more tensors to group.
name: A name for this operation (optional).
Returns:
An Operation that executes all its inputs.
Raises:
ValueError: If an unknown keyword argument is provided.