第二章 TensorFlow 环境搭建
简单示例代码:1
2
3
4
5
6
7
8import tensorflow as tf
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
sess = tf.Session()
sess.run(result)
---输出---
array([3., 5.], dtype=float32)
第三章 TensorFlow 入门
3.1 计算图
- 系统默认维护一个计算图,通过
tf.get_default_graph
获取当前默认计算图。 - 通过
a.graph
查看张量a
所属计算图。示例:
1 | print(a.graph is tf.get_default_graph()) |
- 在不同计算图上定义和使用变量
1 | import tensorflow as tf |
- 对计算图指定计算设备
1 | g = tf.Graph() |
- 在一个计算图中,可以通过集合(collection)管理不同类别的资源。通过
tf.add_to_collection
函数可以将资源加入一个或多个集合中,然后通过tf.get_collection
获取一个集合里面的所有资源。这里的资源可以是张量、变量或者运行TensorFlow 程序所需要的队列资源,等等。TensorFlow 也自动管理了一些最常用的集合:
集合名称 | 集合内容 | 使用场景 |
---|---|---|
tf.GraphKeys.VARIABLES | 所有变量 | 持久化 TensorFlow 模型 |
tf.GraphKeys.TRAINABLE_VARIABLES | 可学习的变量(一般指神经网络中的参数) | 模型训练、生成模型可视化内容 |
tf.GraphKeys.SUMMARIES | 日志生成相关的张量 | TensorFlow 计算可视化 |
tf.GraphKeys.QUEUE_RUNNERS | 处理输入的QueueRunner | 输入处理 |
tf.GraphKeys.MOVING_AVERAGE_VARIABLES | 所有计算了滑动平均值的变量 | 计算变量的滑动平均值 |
3.2 张量
张量可以理解为多维数组,一阶张量为标量(scalar),二阶张量为向量(vector),n阶张量可以理解为n维数组。张量不保存数值,保存的是计算数值的过程。1
2
3
4
5
6
7
8import tensorflow as tf
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = tf.add(a, b, name="add")
print result
---输出--
Tensor("add:0", shape=(2,), dtype=float32)
张量保存了三个属性:名字(name), 维度(shape), 类型(type)。
- 名字:张量的命名可以通过“node:src_output”的形式来给出。其中 node 为节点的名称,src_output表示当前张量来自节点的第几个输出。
上面”add:0”说明result是计算节点”add”输出的第一个结果。 - 维度:描述张量的维度信息。shape=(2,)说明了result是一个一维数组,这个数组的长度为2。
- 类型:计算类型需匹配否则报错。例,若将以上代码的a小数点去掉,成为
a = tf.constant([1 , 2], name="a")
则运行报错:ValueError: Tensor conversion requested dtype int32 for Tensor with dtype float32:'Tensor("b:0", shape=(2,), dtype=float32)'
可以指定a的类型则不会出问题:a = tf.constant([1,2], name="a", dtype=tf.float32)
TensorFlow支持的14种不同类型:
实数(tf.float32, tf.float64), 整数(tf.int8, tf.int16, tf.int32, tf.int64, tf.unit8), 布尔型(tf.bool)和复数(tf.complex64, tf.complex128)。
通过result.get_shape函数可以获取结果张量的维度信息。
张量没有存储计算结果,但是可以通过会话获得,例如通过tf.Session().run(result)获得result结果。
3.3 会话(TensorFlow运行模型)
使用会话的方式:
- 手动释放:
1 | # 创建一个会话。 |
- 自动释放:
1 | # 创建一个会话,并通过 Python 中的上下文管理器来管理这个会话。 |
TensorFlow 不会自动生成默认的会话,而是需要手动指定。当默认的会话被指定之后可以通过tf.Tensor.eval 函数来计算一个张量的取值 。1
2
3sess = tf.Session()
with sess.as default():
print(result. eval())
以下代码功能相同1
2
3
4sess = tf.Session()
# 以下两个命令有相同的功能。
print(sess.run(result))
print(result.eval(session=sess))
使用tf.lnteractiveSession函数会自动将生成的会话注册为默认会话。1
2
3sess = tf.InteractiveSession()
prirnt(result. eval())
sess.close()
以上,无论使用哪种方法都可以通过 ConfigProto Protocol BufferCD来配置需要生成的会话,方法:
1 | config = tf.ConfigProto(allow soft placement=True, log_device_placement=True) |
ConfigProto常用配置参数:
- allow_soft_placement:
这是一个布尔型的参数,默认为False,当它为 True 时,在以下任意一个条件成立时, GPU 上的运算可以放到 CPU 上进行 :- 运算无法在 GPU 上执行。
- 没有 GPU 资源 (比如运算被指定在第二个 GPU 上运行,但是机器只有一个 GPU)。
- 运算输入包含对 CPU 计算结果的引用。
- log_device_placement:
这也是一个布尔型的参数,当它为 True 时日志中将会记录每个节点被安排在哪个设备上以方便调试。生产环境中设置为 False 可以减少日志量。
3.4 TensorFlow实现神经网络
矩阵乘法:1
2a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
变量初始化
1 | #产生一个 2×3 的矩阵,矩阵中的元素是均值为 0,标准差为 2 的随机数。可以通过参数 mean 来指定平均值,默认为0。 |
TensorFlow 随机数生成函数表
函数名称 | 随机数分布 | 主要参数 |
---|---|---|
tf.random_normal | 正态分布 | 平均值、标准差、取值类型 |
tf.truncated_normal | 正态分布,但如果随机出来的值偏离平均值超过2个标准差就重新随机 | 平均值、标准差、取值类型 |
tf.random_uniform | 均匀分布 | 最小、最大取值,取值类型 |
tf.random_gamma | Gamma分布 | 形状参数alpha、尺度参数 beta、取值类型 |
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] |
一些以常数初始化数值的方法:1
2
3
4
5
6biases = tf.Variable(tf.zeros([3]))
# 生成一个初始值全部为 0 且长度为 3 的变量
w2 = tf.Variable(weights.initialized_value())
# w2 的初始值被设置成了与 weights 变量相同
w3 = tf.Variable(weights.initialized_value() * 2.0)
# w3 的初始值则是 weights 初始值的两倍
一个前向传播过程:
1 | import tensorflow as tf |
当需要初始化的变量变多,可以使用以下方法初始化:1
2init_op = tf.global_variables_initializer()
sess.run(init_op)
- 通过 tf.global_variables() 函数可以拿到当前计算图上所有的变量。
- 可以通过变量声明函数中的 trainable 参数来区分需要优化的参数(比如神经网络中的参数)和其他参数(比如选代的轮数)。如果声明变量时参数 trainable 为 True,那么这个变量将会被加入到GraphKeys.TRAINABLE_VARIABLES 集合。
- 类似张量,维度(shape)和类型 (type) 也是变量最重要的两个属性,一个变量在构建之后,它的类型就不能再改变了。
1 | w1 = tf.Variable(tf.random_normal([2, 3], stddev=1), name="w1") |
- 维度在程序运行中是有可能改变的,但是需要通过设置参数validate_shape=False。
1 | w1 = tf.Variable(tf.random_normal([2, 3], stddev=1), name = "w1") |
完整训练模型
- placeholder预占用输入数据位置
1 | x = tf.placeholder(tf.float32, shape = (3, 2), name="input") |
- 定义一个简单的损失函数
1 | # 使用 sigmoid 函数将 y 转换为 0~1 之间的数值。转换后 y 代表预测是正样本的概率, 1-y 代表 |
以上代码中,train_step定义了反向传播优化方法,通常包括三种tf.train.GradientDescentOptimizer、 tf.train.AdamOptimizer和tf.train.MomentumOptimizer。
在定义了反向传播算法之后,通过运行 sess.run(train_ step)就可以对所有在 GraphKeys .TRAINABLE_VARIABLES 集合中的变量进行优化,使得在当前 batch 下损失函数更小。
完整样例程序
1 | import tensorflow as tf |