目录
- 1 基本概念
- 2 批标准化BN
- 3 优化方法
1 基本概念
- 图(Graph):图描述了计算的过程,TensorFlow使用图来表示计 算任务。
- 张量(Tensor):TensorFlow使用tensor表示数据。每个Tensor是 一个类型化的多维数组。
- 操作(op):图中的节点被称为op(opearation的缩写),一个op 获得0个或多个Tensor,执行计算,产生0个或多个Tensor。
- 会话(Session):图必须在称之为“会话”的上下文中执行。会话 将图的op分发到诸如CPU或GPU之类的设备上执行。
- 变量(Variable):运行过程中可以被改变,用于维护状态。
1.1 图
把操作任务描述成有向无环图,按着计算顺序定义图中的节点。
matrix1 = tf.constant([[3.,3.]])
# 定义一个1*2矩阵
matrix2 = tf.constant([[2.],[2.]])
# 定义一个2*1的矩阵
product = tf.matmul(matrix1, matrix2)
# 用矩阵乘法将两个矩阵相乘
1.2 会话与设备
启动图的第一步是创建一个Session对象,会话提供在图中执行操作的一些方法。通过会话可以把定义在图中的操作执行出来:
# 创建一个会话:
with tf.Session() as sess:
# 指定在第二个CPU上执行。/gpu可以指定在GPU上执行
with tf.device('/cpu:1'):
result = sess.run([product])
print(result)
# [array([[ 12.]], dtype=float32)]
1.3 变量
变量是一种特殊的数据,它在图中有固定的位置,不像普通张量那样可以流动。创建一个变量张量,使用tf.Variable()构造函数,这个构造函数需要一个初始值,初始值的形状和类型决定了这个变量的形状和类型。
Tensorflow还提供了填充机制,可以在构建图时使用tf.placeholder()临时替代任意操作的张量,在调用Session对象的run()方法去执行图时,使用填充数据作为调用的参数,调用结束后,填充数据就消失了。
output = tf.Variable(0)
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1, input2)
with tf.Session() as sess:
feed_dict={input1:[7.], input2:[8.]}
result = sess.run([output],feed_dict=feed_dict)
print(result)
# [array([ 56.], dtype=float32)]
1.4例子
tensorflow运行分为4步:
- 加载数据定义超参数
- 构建网络
- 训练模型
- 评估模型、进行预测
同个一个例子来学习方程:
生成和加载数据
import tensorflow as tf
import numpy as np
# 在[-1,1]之间创建300个数据,并将形状从(3,)->(300,1)
x_data = np.linspace(-1,1,300)[:, np.newaxis]
# 加入一些噪声,与x_data的维度一致
noise = np.random.normal(0, 0.05, x_data.shape)
# y = x^2 - 0.5 + 噪声
y_data = np.square(x_data) - 0.5 + noise
# 定义占位符,用于输入神经网络的变量
xs = tf.placeholder(tf.float32, [None, 1])
ys = tf.placeholder(tf.float32, [None, 1])
构建网络模型
# 定义构建网络的函数
def add_layer(inputs, in_size, out_size, activation_function=None):
# 构建权重,是一个in_size*out_size的矩阵,正态随机初始化
weights = tf.Variable(tf.random_normal([in_size, out_size]))
# 构建偏置,1*out_size的矩阵
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
# 矩阵相乘
Wx_plus_b = tf.matmul(inputs, weights) + biases
# 激活函数
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b)
return outputs
# 构建隐藏层1,假设有20个单元,用relu激活函数
h1 = add_layer(xs, 1, 20, activation_function=tf.nn.relu)
# 输出层,将隐藏层的数据放到输出层中,与label y作比较
prediction = add_layer(h1, 20, 1, activation_function=None)
# 定义损失函数
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction), reduction_indices = [1]))
# 用梯度下降法,以0.1为学习率
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
训练模型
#初始化所有变量
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(1000):
sess.run(train_step, feed_dict={xs : x_data, ys : y_data})
if i%100 == 0:
print(sess.run(loss, feed_dict={xs : x_data, ys : y_data}))
# 可以看到损失值一直减少
"""
6.78231
0.00632235
0.00436786
0.00395835
0.00373421
0.00363523
0.00357616
0.00354066
0.00351801
0.00349816
"""
2 批标准化(batch normalization BN)
深度神经网络随着网络深度加深,会有梯度弥散问题,导致训练起来会变得困难,当训练样本和目标样本分布不一致的时候无法很好的泛化,BN就是在每一层都对训练样本做一个矫正。
2.1 方法
在激活函数之前做一个非线性映射,对
2.2 优点:
- 加大探索步长,加快收敛速度
- 更容易跳出局部最小值
- 破坏原来的数据分布,一定程度上缓解过拟合
2.3 示例
import tensorflow as tf
W = tf.constant([[-2.,12.,6.],[3.,2.,8.]],)
print(W.shape)
mean,var = tf.nn.moments(W, axes = [0])
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
resultMean = sess.run(mean)
print(resultMean)
resultVar = sess.run(var)
print(resultVar)
size = 3
scale = tf.Variable(tf.ones([size]))
shift = tf.Variable(tf.zeros([size]))
epsilon = 0.001
W = tf.nn.batch_normalization(W, mean, var, shift, scale, epsilon)
#W = (W - mean) / tf.sqrt(var + 0.001)
#W = W * scale + shift
with tf.Session() as sess:
#必须要加这句不然执行多次sess会报错
sess.run(tf.global_variables_initializer())
resultW = sess.run(W)
print(resultW)
#观察初始W第二列 12>2 返回BN的W值第二列第二行是负的,其余两列相反
"""
[[-0.99992001 0.99997997 -0.99950027]
[ 0.99991995 -0.99997997 0.99950027]]
"""
3优化方法
3.1 BGD (batch gradient descent)
提取训练集中所有内容
- 优缺点:
- 不需要减少学习率,但是训练时间长
3.1 SGD (stochastic gradient descent)
拆分成一个个小的批次。随机抽取放进模型计算并更新参数
- 优点:
- 收敛速度快。
- 缺点:
- 不同的批次有会有不同梯度,应该用不同的学习率,但是调整比较困难
- 容易收敛到局部最优或者鞍点
3.2 Momentum
模拟物理中动量的概念,在更新时在一定程度上保留之前的方向,直观上讲就是,要是当前时刻的梯度与历史时刻梯度方向相似,这种趋势在当前时刻则会加强;要是不同,则当前时刻的梯度方向减弱。能抑制震荡,加快收敛。
3.3 Adagrad
能自适应的调整学习率,如果梯度比较大学习率衰减得快一些,梯度比较小学习率衰减得慢一些。
- 优点
- 收敛速度比较好,性能比较稳定
- 缺点:
- 容易过早的减小学习率使得训练提前结束,特别是在网络结果比较深的情况下。
3.4 RMSprop
RMSProp通过引入一个衰减系数,让r每回合都衰减一定比例,类似于Momentum中的做法。
- 优点:
- 相比于AdaGrad,这种方法很好的解决了深度学习中过早结束的问题 ,适合处理非平稳目标,对于RNN效果很好
3.5 Adam
Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。