import tensorflow as tf
import random
#训练函数y=2x-1,a/b分别要训练为2,-1
x=tf.placeholder(tf.float32,[1])
a=tf.Variable(tf.constant([1],dtype=tf.float32))
#b=tf.Variable(tf.constant([1],dtype=tf.float32))
y=a*x#+b
#
_y=tf.placeholder(tf.float32,[1])
loss=tf.square(y-_y)
train=tf.train.GradientDescentOptimizer(1e-4).minimize(loss)
sess=tf.Session()
sess.run(tf.global_variables_initializer())
while True:
input=[random.randint(0,100)] #不乘以0.0001,则网络无法收敛
label=[input[0]*2]
print(input)
print(label)
_,av,bv,lossv=sess.run([train,a,a,loss],feed_dict={x:input,_y:label})
if (lossv<1e-6):
break
print("a=%s b=%s loss=%s" %(av,bv,lossv))
以上网络训练参数a,使其满足y=a*x=2*x。
以下两个条件成立时,网络会无法收敛,且参数迅速扩大直至变成NaN:
input/label值过大:如0~100
学习率较大,如0.1。
分析如下:
loss对a的函数为二次函数,Loss对a的导数为一次函数,导数大小取决输入数据x/y的大小,
当学习率太高/输入数据太大,会导致导数非常大,直接跳到二次函数对称轴另一边,如下图:
如何解决这个问题:
BN应该可以很大程度上解决这个问题;
其他的就是改小学习率。。。凭经验。。
learning rate 减小10倍有时候意味网络训练非常慢。