TensorFlow¶
构建计算图¶
OPS¶
切片¶
Tensorflow 提供了方法对 Tensor 进行切片:
tf.strided_slice(
input_,
begin,
end,
strides=None,
begin_mask=0,
end_mask=0,
ellipsis_mask=0,
new_axis_mask=0,
shrink_axis_mask=0,
var=None,
name=None
)
start 与 end 的长度应与 Tensor 的维度相同, 代表某个维度从多少到多少.
乘法¶
与 Numpy 相同, tensorflow 的乘法也有普通乘法与矩阵乘法.
- 普通乘法
tf.multiply(a, b, name=None)
普通乘法与 Numpy 的普通乘法一样, element-wise 乘法, 也有广播机制, 只不过是对 Tensor 操作.
>>> a = tf.constant(np.arange(12), dtype=np.int32, shape=[3,4])
>>> b = tf.constant(np.arange(4), dtype=np.int32, shape=[1,4])
>>> a * b
<tf.Tensor 'mul:0' shape=(3, 4) dtype=int32>
小技巧
对 Tensor 操作会自动重载 * 乘法操作符.
- 矩阵乘法
tf.matmul(a, b, name=None)
矩阵乘法也与 numpy.dot() 相同. 有二维矩阵乘法与三维矩阵乘法.
二维矩阵 乘法就是正常的矩阵乘法 [m, n] * [n, p] = [m, p] .
三维矩阵 乘法要求第 0 维大小相同, 相当于在第 0 维进行 metric-wise 批量矩阵相乘.
>>> a = tf.constant(np.ones([2,3,4]))
>>> b = tf.constant(np.ones([2,4,5]))
>>> a @ b
<tf.Tensor 'matmul:0' shape=(2, 3, 5) dtype=float64>
小技巧
Python 3.5 版本加入 @ 矩阵乘法操作符, Tensorflow也已实现重载.
TensorFlow 优化¶
显存占用¶
增加环境变量, 控制可见GPU
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
随着进程逐渐增加显存占用, 而不是再初始化 Session 时一下占用所有空闲显存:
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
## tf.Session()
tf.Session(config = config)
日志级别¶
TimeLine 查看运行时间线¶
使用 timeline 查看一个 step 的运行时间线, 并保存为 json 文件, 使用 chrome 查看时间线:
from tensorflow.python.client import timeline
运行计算图之前定义 metadata 和 options:
run_metadata = tf.RunMetadata()
run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
运行计算图时, 加上 metadata 和 options:
with tf.Session() as sess:
result = sess.run(fetch, feed, options=run_options, run_metadata=run_metadata)
运行后, 创建 Timeline 对象, 并将数据写入 json 文件:
fetched_timeline = timeline.Timeline(run_metadata.step_stats)
# Chrome Trace 格式
chrome_trace = fetched_timeline.generate_chrome_trace_format()
# 保存, step 是当前的步数.
with open('timeline_%d.json' % step, 'w') as f:
f.write(chrome_trace)
保存后, 在 Chrome 输入:
chrome://tracing/
最后点击 load 加载 timeline 文件.
TensorBoard¶
TensorBoard 是 TensorFlow 提供的可视化平台, 可以将训练模型时的各种数据以网页应用的方式直观的展示出来.
包括计算图, 运行时的标量, 变量, 嵌入层的映射等等.
使用方法¶
首先定义一个 FileWriter, 用来将 summary 数据写入文件:
with tf.Session() as sess:
writer = tf.summary.FileWriter(save_path, sess.graph)
常用参数:
| logdir: | 保存路径 |
|---|---|
| graph: | 一个图对象, 例如 sess.graph. |
| max_queue: | 整数. 记录 summary 的队列大小. |
| flush_secs: | 多少秒将队列中的数据写入硬盘. |
注意
FileWriter 需要定义在初始化 Session() 以后.
然后在每次运行计算图并获得 summary 的结果时, 将结果写入到文件:
# summ 是运行 summary op 得到的结果
writer.add_summary(summ, global_step=step)
在训练完成以后, save_path 目录下会出现 events 文件, 在命令行使用以下命令打开 TensorBoard 服务:
tensorboard --logdir=save_path --host=127.0.0.1
| --logdir | summary 保存路径 |
| --host | 主机IP地址 |
如果默认 host 地址即为 127.0.0.1 可以不添加 host 参数.
Summaries¶
TensorFlow 的 summary 是用来在 TensorBoard 中直观显示标量或者变量的.
重要
summary 也是计算图里的一个 operation.
词嵌入映射¶
词嵌入映射可以将 TensorFlow 的嵌入层学习到的变量降维后以 2D 或着 3D 的形式在
TensorBoard 中展示出来.
提示
TensorBoard 中提供的降维方式有 PCA 与 t-SNE.
首先从 tensorboard 插件中导入 projector:
from tensorflow.contrib.tensorboard.plugins import projector
创建 projector_config 并增加 embedding 层, 通过名称指定 Tensor 变量:
proj_config = projector.ProjectorConfig()
embed = proj_config.embeddings.add()
embed.tensor_name = train_model.embedding.name
如果需要显示单词在嵌入空间点上, 则需要指定单词表:
embed.metadata_path = "vocab.tsv"
然后指定 writer 与 proj_config, 即 summary 的 FileWriter, 写入文件.
重要
proj_config 会以文件形式写入 FileWriter 的相同目录下, 所以单词表的路径应该是 FileWriter 的相对路径.
将以上信息配置好以后, 就可以在 tensorboard 的 PROJECTOR 标签内查看映射.
保存与恢复¶
变量¶
变量的保存与恢复使用 Saver 类.
首先实例化一个 Saver 类:
saver = tf.train.Saver(vars)
# vars 为要保存的变量, 默认保存所有全局变量
| max_to_keep: | 最大保存个数, 默认为 5 |
|---|
保存变量¶
保存通过 saver.save():
path = os.path.join(save_path, 'after-epoch')
saver.save(sess, path, global_step=i+1)
| path: | 保存变量的文件名称 |
|---|---|
| global_step: | 文件名后缀 |
提示
可以使用当前的 epoch 作为文件的后缀, 如上.
保存后, 在保存目录下会出现四个文件, 其中:
| data: | 变量数据 |
|---|---|
| index: | 变量索引 |
| meta: | 模型数据 |
| checkpoint: | 最新检查点 |
恢复变量¶
恢复变量通过:
saver.restore(sess, restore_path)
| restore_path: | 保存点的文件 |
|---|
如果 restore_path 是目录, 则需要首先使用 tf.train.latest_checkpoint(restore_path) 获取最新的检查点文件.
可以在开始训练前恢复上一次训练的变量, 继续训练.
# Reload weights if exits
if os.path.exists(restore_path):
print("Restoring parameters from {}".format(restore_path))
if os.path.isdir(restore_path):
restore_path = tf.train.latest_checkpoint(restore_path)
# Begin at epoch
bae = int(restore_path.split('-')[-1])
saver.restore(sess, restore_path)
| bae: | Begin of epoch, 开始的 epoch |
|---|
注意
使用这段代码时, 循环 epoch 应该使用 range(bae, bae+num_epoch).