因为损失函数是一个凸函数,当损失函数取极小值,表示损失函数最小,损失函数最小就是表示模型对参数w是最优的
由于是一个凸函数,所以可以用梯度下降求解,
梯度下降关键在与求解偏导/梯度
而这个过程就叫bp
通过查看源码发现,其实该优化算法,
train_op = opt.minimize(loss)
包含一次,前向过程
fp_op = opt.compute_gradients(loss)
和反向过程
bp_op = opt.apply_gradients(fp_op)
def f1():
w = tf.Variable(initial_value=[[1], [1], [1]], dtype=tf.float32)
b = tf.Variable(initial_value=[0], dtype=tf.float32)
x = tf.constant(value=[
[1, 3, 5]
], dtype=tf.float32)
y = tf.constant(value=[
[5]
], dtype=tf.float32)
y_ = tf.matmul(x, w) + b
loss = tf.reduce_mean(tf.square(y - y_))
opt = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# 实际上train_op的执行的时候就是执行一次正向传播,再执行一次反向传播。
train_op = opt.minimize(loss)
# 正向过程
# [(<tf.Tensor 'gradients/MatMul_grad/tuple/control_dependency_1:0' shape=(3, 1) dtype=float32>, <tf.Variable 'Variable:0' shape=(3, 1) dtype=float32_ref>), (<tf.Tensor 'gradients/add_grad/tuple/control_dependency_1:0' shape=(1,) dtype=float32>, <tf.Variable 'Variable_1:0' shape=(1,) dtype=float32_ref>)]
fp_op = opt.compute_gradients(loss)
print(fp_op)
# 反向过程
bp_op = opt.apply_gradients(fp_op)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print("初始情况下的预测值:{}".format(sess.run(y_)))
print("初始情况下的损失函数的梯度值:{}".format(sess.run(fp_op)))
sess.run(bp_op)
print("更新之后的模型参数值:{}".format(sess.run([w, b])))
# sess.run(train_op)
# print("更新一次后:{}".format(sess.run(y_)))
# sess.run(train_op)
# print("更新一次后:{}".format(sess.run(y_)))
y=w1*1+w2*3+w3*5+b=9
初始情况下的预测值:[[9.]]
loss=1/1(w1*1+w2*3+w3*5+b-5)²
loss/θw1=2*(1+3+5-5) 带入进去得到8
loss/θw2=2*(1+3+5-5)*3 24
loss/θw3=2*(1+3+5-5)*5 40
loss/b=2*(1+3+5-5)*1 8
初始情况下的损失函数的梯度值:[(array([[ 8.],
[24.],
[40.]], dtype=float32), array([[1.],
[1.],
[1.]], dtype=float32)), (array([8.], dtype=float32), array([0.], dtype=float32))]
反向传播更新后
w1=1-8*0.01=0.92
w2=1-24*0.01=0.76
更新之后的模型参数值:[array([[0.92],
[0.76],
[0.6 ]], dtype=float32), array([-0.08], dtype=float32)]
每个神经元可以提取局部特征信息,理论上讲,神经元数目越多提取的局部特征信息就越多,那么网路的效果就会越好。但是要注意的就是太多可能会过拟合,单层的话一般不超过4096