1.前向传播
前向传播就是搭建模型的计算过程,让模型具有推理能力,可以针对一组输入给出相应的输出,即得到一个y关于x的关系式。
以该图为例,从左到右依次是输入层,隐藏层,输出层,x1,x2为输入,图中并没有偏置项,但是为了写全就额外加了偏置项b1,这里,将b1当作是到第一层的偏置项
n
e
t
a
11
=
w
11
∗
x
1
+
w
21
∗
x
2
+
b
1
net_{a_{11}}=w_{11}*x_1+w_{21}*x_2+b_1
neta11=w11∗x1+w21∗x2+b1
n
e
t
a
12
=
w
12
∗
x
1
+
w
22
∗
x
2
+
b
2
net_{a_{12}}=w_{12}*x_1+w_{22}*x_2+b_2
neta12=w12∗x1+w22∗x2+b2
n
e
t
a
13
=
w
13
∗
x
1
+
w
23
∗
x
2
+
b
3
net_{a_{13}}=w_{13}*x_1+w_{23}*x_2+b_3
neta13=w13∗x1+w23∗x2+b3
加入激活函数g(x)后
a
11
=
g
(
n
e
t
a
11
)
a_{11}=g(net_{a_{11}})
a11=g(neta11)
a
12
=
g
(
n
e
t
a
12
)
a_{12}=g(net_{a_{12}})
a12=g(neta12)
a
13
=
g
(
n
e
t
a
13
)
a_{13}=g(net_{a_{13}})
a13=g(neta13)
从而将值从输入层传播到了隐藏层,同理,从隐藏层到输出层也是如此.
为了能够更加清晰地表达,各个量之间的关系,我们用矩阵将上述的关系式进行转换表达,在转换矩阵表达之前,我们先搞清楚各个量的属性。
第一层
- x :表示的两个不同的输入,为1×2的矩阵,表示依次输入一组特征,两个元素
- a :表示的是中间隐藏层,为1×3的矩阵,
- w1 :表示的是输入层传播到隐藏层的权重,因为前边是2个节点,后边是3个节点,因此w1是2×3的矩阵
第二层
- w2 : 表示的是隐藏层传播到输出层的权重,因为前边是3个节点,后边是1个节点,因此w1是3×1的矩阵
- y :表示输出,1×1
( x 1 x 2 ) ∗ ( w 11 w 12 w 13 w 21 w 22 w 23 ) + ( b 1 b 2 b 3 ) \left ( \begin{matrix} x_{1} &x_2 \end{matrix} \right )*\left ( \begin{matrix} w_{11} & w_{12} & w_{13}\\ w_{21} & w_{22} & w_{23} \end{matrix} \right ) + \left ( \begin{matrix} b_{1}\\ b_{2} \\ b_{3} \end{matrix} \right ) (x1x2)∗(w11w21w12w22w13w23)+⎝⎛b1b2b3⎠⎞
下面展示一些 前向传播的代码
。
#coding:utf-8
import tensorflow as tf
#定义输入和参数
x=tf.placeholder(tf.float32,shape=(1,2))
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))
#定义前向传播过程
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)
#用会话计算结果
with tf.Session() as sess:
init_op=tf.global_variables_initializer()
sess.run(init_op)
print (sess.run(y,feed_dict={x:[[0.7,0.5]]}))
2.反向传播
就是训练模型参数,在所有参数上用梯度下降,使 NN 模型在训练数据上的损失函数最小。
2.1损失函数
分类问题和回归问题是监督学习的两大种类,分类问题是希望将不同的样本分类到事先定义好的类别中。通过神经网络解决多分类问题最常用的方式是设置n个输出节点,其中n为类别的个数,对于每一个样例,神经网络可以得到的一个n维数组作为输出结果。数组中的每一个维度(也就是输出的每一个节点)对应一个类别。
解决分类问题,交叉熵是常用的评判方法之一,交叉熵刻画了两个概率分布之间的距离
从信息论的角度来看
交叉熵 | 解释 |
---|---|
tensorflow 函数表示 | Tensor=tf.nn.softmax_cross_entropy_with_logits(logits= Network.out, labels= Labels_onehot) |
解释 | 上面是softmax交叉熵loss,参数为网络最后一层的输出和onehot形式的标签。切记输入一定不要经过softmax,因为在函数中内置了softmax操作,如果再做就是重复使用了。在计算loss的时候,输出Tensor要加上tf.reduce_mean(Tensor)或者tf.reduce_sum(Tensor),作为tensorflow优化器(optimizer)的输入。 |
回归问题,计算得到的预测值 y 与已知答案 y_的差距,损失函数计算方法:有很多方法,均方误差 MSE 是比较常用的方法之一
均方误差 MSE | 解释 |
---|---|
定义 | 求前向传播计算结果与已知答案之差的平方再求平均 |
公式 | |
tensorflow 函数表示 | loss_mse = tf.reduce_mean(tf.square(y_ - y)) |
2.2反向传播算法
反向传播算法的核心是代价函数C对网络中参数(各层的权重w和偏置b)的偏导表达式∂C/∂w和∂C/∂b。这些表达式描述了代价函数值C随权重w或偏置b变化而变化的程度。这里,BP算法的思路就很容易理解了:如果当前代价函数值距离预期值较远,那么我们通过调整w和b的值使新的代价函数值更接近预期值(和预期值相差越大,则w和b调整的幅度就越大)。一直重复该过程,直到最终的代价函数值在误差范围内,则算法停止。
反向传播算法实现了一个迭代的过程,每次迭代的开始,首先需要选取一小部分训练数据,这一部分训练数据叫做batch,然后,这个batch的样例会通过前向传播的算法得到神经网络模型的预测结果,因为训练数据都是有答案标注的,因此可以计算出预测答案与正确答案的差距,最后基于差距,反向传播算法会相应的更新神经网络参数的取值,使得在这个batch上神经网络的预测结果和真实值更加接近。
参数 | 意义 |
---|---|
W a b W_{ab} Wab | 表示a节点到b节点的权重 |
y a y_a ya | 表示a结点的输出 |
z a z_a za | 表示a结点的输入, y a y_a ya与 z a z_a za的关系是: y a = f ( z a ) y_a=f(z_a) ya=f(za),其中f(x)代表激活函数 |
δ \delta δ | 表示节点的错误(用于反向传播) |
C C C | 损失函数 |
f ( x ) = 1 1 + e − x f(x)=\frac{1}{1+e^{-x}} f(x)=1+e−x1 | 激活函数 |
w 2 w2 w2 | 左边字母,右边数字代表第几层的矩阵或向 |
对应的网络如下图:
以下推导为手推过程,因为没有太多时间进行公式排版,保存只为后期复习
2.3 网络优化
本节具体地介绍如何通过反向传播算法(backpropagation)和梯度下降算法(gradientdecent)调整神经网络中参数的取值。梯度下降算法主要用于优化单个参数的取值,**而反向传播算法给出了一个高效的方式在所有参数上使用梯度下降算法,从而使神经网络模型在训练数据上的损失函数尽可能小。**反向传播算法是训练神经网络的核心算法,它可以根据定义好的损失函数优化神经网络中参数的取值,从而使神经网络模型在训练数据集上的损失函数达到一个较小值。神经网络模型中参数的优化过程直接决定了模型的质量,是使用神经网络时非常重要的一步。
网络的优化过程主要经过两个阶段
- 第一个阶段是先通过前向传播算法得到预测值,并将预测值和真实值直接对比得出二者之间的差距
- 第二个阶段是是通过反向传播算法计算损失函数对每一个参数的梯度,再依据梯度和学习率使用梯度下降法更新每一个参数。
但是因为梯度下降法得到的是局部最优解,而不是全局最优解,且计算时间太长,综合梯度下降法的优缺点,在实际应用中一般采用每此计算一小部分训练数据的损失函数的方法。
batch_size = n
#每次读取一小部分数据作为当前的训练数据来执行反向传播算法
x = tf.placeholder(tf.float32 , shape =(batch_size , 2 ),name = 'x_input')
y_ = tf.placeholder(tf.float32 , shape =(batch_size , 1 ),name = 'y_input')
#定义神经网络结构和优化算法
loss = ...
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)
#训练神经网络
with tf.Session() as sess:
#参数初始化
...
for i in range(step):
#准备batch个训练数据,一般将素有训练数据随机打乱之后再选取得到更好的优化效果
current_X, current_Y=...
sess.run(train_step , feed_dict = {x : current_X,t : ecurrent_Y})
【参考文献】
- https://blog.csdn.net/qq_40234695/article/details/87277721
- https://blog.csdn.net/bitcarmanlee/article/details/78819025
- https://blog.csdn.net/qq_16137569/article/details/81449209
- https://blog.csdn.net/guoyunfei20/article/details/78031498
- Tensorflow 损失函数(loss function)