深层神经网络的定义:一类通过多层非线性变换对高度复杂性数据建模算法的集合
监督学习最重要的思想就是,在已知答案的标注数据集上,模型给出的预测结果要尽量接近真实的答案。通过调整神经网络中的参数对训练数据进行拟合,可以使得模型对未知的样本提供预测的能力。----反向传播算法
前面的博客TensorFlow实现神经网络之前向传播讲述的是一个线性模型。被称为线性模型是因为当模型的输入只有一个的时候,x,y形成二维空间的一条直线。当模型有n个输入时,x,y形成了n+1空间的额一个平面。
线性模型能够解决线性可分问题,复杂问题,无法通过直线或者高维空间的平面划分。这时就要使用激活函数去线性化。关于常见的激活函数介绍可查看以前的博客TensorFlow中的激活函数,下图为加上偏置和激活函数之后的神经元结构。
如下所示为在TensorFlow实现神经网络之前向传播基础上加上激活函数和偏置项后的全连接前向传播网络结构
以下为新的神经网络模型前向传播算法,隐藏层神经元的输出计算方法
前向传播算法隐藏层输出的数学定义
a= tf.nn.leaky_relu(tf.matmual(x,w1)+bias1)
a= tf.nn.leaky_relu(tf.matmual(x,w2)+bias2)
在得到前向传播结果之后,需要定义一个损失函数来刻画当前预测值和真实值之间的误差,然后通过反向传播算法来调节神经网络的参数,使得差距被减小。
其中,回归问题的神经网络一般只有一个输出节点,这个节点输出的就是预测值,最常用的损失函数是均方误差(MSE,mean squared error);数学公式如下:
yi代表第i个数据的真确答案,yi’为预测值
代码
loss = tf.reduce_mean(tf.pow((y_model_1 - y_data_), 2)) # 损失函数
神经网络的算法优化,这里介绍梯度下降算法
神经网络的优化过程可以分为两个阶段,第一个阶段先通过前向传播算法计算得到预测值,并将预测值与真实值做对比得到两者之间的差距。然后在第二阶段通过反向传播算法计算损失函数对没一个参数的梯度,再根据梯度和学习率使用梯度下降算法(或者其他优化算法)更新每一个参数,梯度下降算法不能保证被优的函数达到全局最优。
反向传播算法给出了一个高效的方式在所有参数上使用梯度下降算法,从而使神经网络模型在训练数据上的损失函数尽可能小。反向传播算法是训练神经网络的核心算法,他可以根据定义好的损失函数优化神经网络中参数的取值,从而使神经网络模型在训练数据集上的损失函数达到一个较小值。
train_op = tf.compat.v1.train.AdamOptimizer(learning_rate).minimize(loss, global_step)
# learning_rate表示学习率,来定义每次参加参数更新的幅度。
train_op定义了反向传播的优化方法,目前TensorFlow支持10种不同的优化器。常用的有 tf.compat.v1.train.AdamOptimizer、tf.train.GradientDescentOptimizer
综合前面几篇博客的介绍,一个完整的神经网络训练过程可以分为以下三步
1 定义神经网络的结构和前向传播的输出结果
2 定义损失函数以及选择反向传播优化的算法
3 生成会话(tf,Session)并且在训练数据上反复运行反向传播优化算法
案例:大家可以学习起来
import tensorflow as tf
from numpy.random import RandomState
# 定义神经网络batch的大小
batch_size = 8
# 定义神经网络的参数
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
# 在shape的维度上使用None,可以方便使用不同的batch大小。在训练时需要吧数据分成比较小的batch,但是在测试时,可以一次性使用全部的数据。
# 在数据集比较大时,将大量数据放入一个batch可能会导致内存溢出
x = tf.placeholder(tf.float32,shape=(None, 2), name='x-input')
y_ = tf.placeholder(tf.float32,shape=(None, 1), name='y-input')
# 定义神经网络前向传播的过程
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
# 定义损失函数和反向传播的算法
y = tf.sigmoid(y)
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) + (1-y_) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(cross_entropy) # AdamOptimizer
# 通过随机数生成一个模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
Y = [[int(x1+x2<1)] for (x1, x2) in X]
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
# 初始化变量
sess.run(init_op)
print(sess.run(w1))
print(sess.run(w2))
STEPS = 50000
for i in range(STEPS):
start = (i*batch_size) % dataset_size # 每次选取batch_size个样本进行训练
end = min(start+batch_size, dataset_size)
sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
if i % 1000 == 0:
total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})
print("After %d training step(s),cross entrop on all data is %g" % (i, total_cross_entropy))
print(sess.run(w1))
print(sess.run(w2))
想要了解神经网络参数的更新原理可以看博客《深层神经网络中反向传播采用梯度下降法更新神经网络参数的原理解释》