本文是 Tensorflow:实战Google深度学习框架的第三章与第四章。
第3章 TensorFlow入门
0.1 查看已安装tensorflow版本
由于tensorflow版本不同,可能一些函数的调用也有变换,这时候可能需要查看tensorflow版本,可以在终端输入查询命令如下:
查询tensorflow安装路径为:
0.2 Tensorflow:实战Google深度学习框架 源码下载
3.2 TensorFlow数据模型——张量
3.2.1 张量的概念
一个张量中主要保存了三个属性:名字(name)、维度(shape)、类型(type)。
3.2.2 张量的使用
两大类。
一是对中间结果的引用。
二是用来获得计算的结果。tf.Session().run(result)
3.3 TensorFlow运行模型——会话
3.3.1 创建和关闭会话
|
|
3.3.2 使用with statement 来创建会话
|
|
3.3.3 指定默认会话
|
|
3.3.4 通过ConfigProto配置会话
|
|
3.4 TensorFlow实现神经网络
3.4.2 前向传播算法简介
tf.matmul 矩阵乘法
3.4.3 神经网络参数与tensorflow变量
|
|
产生一个[2,3]的矩阵,矩阵中元素是均值为0,方差为2的随机数。
1.TensorFlow随机数生成函数
函数名称 | 随机数分布 | 主要参数 |
---|---|---|
tf.random_normal | 正态分布 | 平均值、标准差、取值类型 |
tf.truncated_normal | 正太分布,但如果随机出来的值离平均值超过2个标准差,那么这个数将会被重新随机 | 平均值、标准差、取值类型 |
tf.random_uniform | 平均分布 | 最小、最大取值、取值类型 |
tf.random_gramma | Gramma分布 | 形状参数alpha、尺度参数beta、取值类型 |
2.TensorFlow常数生成函数
函数名称 | 功能 | 样例 |
---|---|---|
tf.zeros | 产生全0的数组 | tf.zeros([2,3],int32)->[[0,0,0],[0,0,0]] |
tf.ones | 产生全1的数组 | tf.ones([2,3],int32)->[[1,1,1],[1,1,1]] |
tf.fill | 产生一个全部为给定数字的数组 | tf.fill([2,3],9)->[[9,9,9],[9,9,9]] |
tf.constant | 产生一个给定值的常量 | tf.constant([1,2,3])->[1,2,3] |
声明了变量之后,程序的第二步会声明一个会话(session)。并通过会话计算结果。
在真正开始计算之前,必须对变量进行初始化:
变量分为需要优化的参数(比如神经网络中的参数)和其他参数。trainable = True
,则该变量会加入GraphKeys.TRAINABLE_VARIABLES
集合。
维度(shape)和类型(type)是变量最重要的两个属性。
3.4.4 通过tensorflow训练神经网络模型
监督学习的思想。
神经网络优化算法中,最常用的是反向传播算法。
x = tf.constant([[0.7, 0.9]])
常量表示样例导致计算图特变大。使用placeholder机制提供输入数据。
在placeholder定义的时候,这个位置上的数据类型是需要指定的。和其他张量一样,placeholder的类型不可以被改变。
feed_dict时一个字典(map),在字典中需要给出每个用到的placeholder的取值,否则运行会报错。
输入的数据一般是一个batch,不止一个,placeholder也支持输入多个数据。
在得到一个batch的前向传播结果之后,需要定义一个损失函数来刻画当前的预测值与真实答案之间的差距。然后通过反向传播算法来调整网络参数之间的取值使得差距可以被缩小。
3.4.5 完整的神经网络样例程序
|
|
输出为:
训练之前的神经网络的参数值:
w1: [[-0.81131822 1.48459876 0.06532937]
[-2.4427042 0.0992484 0.59122431]]w2: [[-0.81131822]
[ 1.48459876]
[ 0.06532937]]
可以发现,随着训练的进行,交叉熵是逐渐减小的。交叉熵越小说明预测的结果和真实的结果差距越小。
After 0 training step(s), cross entropy on all data is 0.0674925
After 1000 training step(s), cross entropy on all data is 0.0163385
After 2000 training step(s), cross entropy on all data is 0.00907547
After 3000 training step(s), cross entropy on all data is 0.00714436
After 4000 training step(s), cross entropy on all data is 0.00578471
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 训练之后的神经网络的参数值:>> w1: [[-1.9618274 2.58235407 1.68203783]> [-3.46817183 1.06982327 2.11789012]]>> w2: [[-1.82471502]> [ 2.68546653]> [ 1.41819513]]# 第4章 深层神经网络## 4.1 深度学习与深层神经网络### 4.1.1 线性模型的局限性### 4.1.2 激活函数实现去线性化激活函数:tf.nn.relu、tf.sigmoid和tf.tanh。### 4.1.3 多层网络解决异或运算单层感知机无法模拟异或运算。加入了隐含层之后,就可以解决异或问题。## 4.2损失函数的定义### 4.2.1 经典损失函数交叉熵(cross entropy)。用q来表示p的交叉熵为:$$H(p,q)=-\sum_x p(x)\text{log} q(x)$$p代表的是正确答案,q代表的是预测值。交叉熵刻画的是两个概率分布的距离,也就是说交叉熵越小,两个概率分布越接近。`softmax`回归:将神经网络的输出变成一个概率分布。交叉熵的代码实现:cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))其中,`tf.clip_by_value`的用法`tf.clip_by_value(A, min, max):`输入一个张量A,把A中的每一个元素的值都压缩在`min`和`max`之间。小于`min`的让它等于`min`,大于`max`的元素的值等于`max`。import tensorflow as tf;import numpy as np;A = np.array([[1,1,2,4], [3,4,8,5]])with tf.Session() as sess:print sess.run(tf.clip_by_value(A, 2, 5))输出:> [[2 2 2 4]>> [3 4 5 5]]`tf.log`是对张量中所有元素依次求对数。`*`操作是元素之间直接相乘,矩阵乘法是`tf.matmul`。上面三个计算得到的结果是nxm的矩阵。`tf.reduce_mean`的用法。v = tf.constant([[1.0, 2.0, 3.0, 4.0], [4.0, 5.0, 6.0, 7.0]])sess = tf.Session()init_op = tf.global_variables_initializer()sess.run(init_op)print(tf.reduce_mean(v).eval(session=sess))# 程序输出为:4.0 = sum/8### 4.2.2 自定义损失函数当然tensorflow也支持自定义损失函数。## 4.3 神经网络优化算法假设用$\theta$表示神经网络中的参数,$J(\theta)$表示在给定的参数取值下,训练集上损失函数的大小,那么整个优化过程可以抽象为:寻找一个参数$\theta$,使得$J(\theta)$最小。对于参数$\theta$,其梯度为$\frac{\partial}{\partial\theta}J(\theta)$。有了梯度,还需要学习率$\eta $(learning rate)来控制每次参数更新的幅度。因此,参数更新的公式为:$$\theta_{n+1} = \theta_n - \eta \frac{\partial}{\partial\theta}J(\theta)$$需要注意的是梯度下降算法并不能保证达到全局最优解,此外还存在计算时间过长的问题。为了加速训练过程,可以使用随机梯度下降(stochastic gradient descent)算法。每一轮迭代中随机优化某一条训练数据的损失函数。在实际应用中,采用折中的方法:**每次计算一小部分训练数据的损失函数**。这一小部分数据被称为<font color=AA00AA>**batch**</font>。## 4.4 神经网络进一步优化### 4.4.1 学习率的设置假设我们要最小化函数 $y=x^2$, 选择初始点 $x_0=5$。#### 1. 学习率为1时```pythonimport tensorflow as tfTRAINING_STEPS = 10LEARNING_RATE = 1x = tf.Variable(tf.constant(5, dtype=tf.float32), name="x")y = tf.square(x)train_op = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(y)with tf.Session() as sess:sess.run(tf.global_variables_initializer())for i in range(TRAINING_STEPS):sess.run(train_op)x_value = sess.run(x)print "After %s iteration(s): x%s is %f."% (i+1, i+1, x_value)
结果是:
学习率为1的时候,x在5和-5之间震荡。
2. 学习率为0.001时
将上述代码中的学习率设为0.001(很小),如下:
运行结果为:
学习率为0.001的时候,下降速度过慢,在901轮时才收敛到0.823355。
3. 使用指数衰减的学习率
将上述代码中的学习率设为指数衰减的方式,如下:
运行结果:
使用指数衰减的学习率,在迭代初期得到较高的下降速度,可以在较小的训练轮数下取得不错的收敛程度。
4.4.2 过拟合问题
为了避免过拟合,一个非常常用的方法是正则化(regularization),加入刻画模型复杂程度的指标$R(w)$,优化时优化$J(\theta)+\lambda R(w) $。
常用的正则化方法有:L1正则化和L2正则化。
$$R(w) =||w||_1 =\sum_i|w_i|$$
$$R(w) =||w||_2^2 =\sum_i|w_i^2|$$
无论哪一种正则化的方式,其思想都是通过限制权重的大小,使得模型不能任意拟合训练数据中的随机噪声。
区别在于,L1正则化会使得参数变得更加稀疏,而L2正则化则不会;此外,L1正则化的计算公式不可导,而L2正则化公式可导。