Tensorflow 1.x与以前版本有兼容性问题,具体问题Google都会有答案,bu部分可以参考 TensorFlow 1.0后与以前代码不兼容解决
1. 背景
Google开源框架,详细见官网:TensorFlow
2. 安装
Windows安装:Windows 64位下安装TensorFlow
Ubuntu/Linux Or Mac: TensorFlow安装
3. 编程思想
TensorFlow 使用图来表示计算任务. 图中的节点被称之为 op (operation 的缩写). 一个 op 获得 0 个或多个 Tensor
, 执行计算, 产生 0 个或多个 Tensor
. 每个 Tensor 是一个类型化的多维数组. 例如, 你可以将一小组图像集表示为一个四维浮点数数组, 这四个维度分别是 [batch, height, width, channels]
.
一个 TensorFlow 图描述了计算的过程. 为了进行计算, 图必须在 会话
里被启动. 会话
将图的 op 分发到如 CPU 或 GPU 之类的 设备
上, 同时提供执行 op 的方法. 这些方法执行后, 将产生的 tensor 返回. 在 Python 语言中, 返回的 tensor 是 numpy ndarray
对象; 在 C 和 C 语言中, 返回的 tensor 是tensorflow::Tensor
实例.
4. 关键概念
使用 TensorFlow, 你必须明白 TensorFlow:
- 图 (graph) :使用图 (graph) 来表示计算任务.
- 会话 (Session):在被称之为
会话 (Session)
的上下文 (context) 中执行图. - tensor:使用 tensor 表示数据.
- 变量 (Variable):通过
变量 (Variable)
维护状态. - feed 和 fetch:使用 feed 和 fetch 可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据.
简单例子
代码语言:javascript复制import tensorflow as tf
#定义‘符号’变量,也称为占位符
a = tf.placeholder("float")
b = tf.placeholder("float")
y = tf.mul(a, b) #构造一个op节点
sess = tf.Session()#建立会话
#运行会话,输入数据,并计算节点,同时打印结果
print sess.run(y, feed_dict={a: 3, b: 3})
# 任务完成, 关闭会话.
sess.close()
4.1 图
TensorFlow 程序包含一个构建阶段和一个执行阶段.
- 构建阶段, op 的执行步骤 被描述成一个图.
- 执行阶段, 使用会话执行执行图中的 op.
在构建阶段创建一个图来表示和训练神经网络, 然后在执行阶段反复执行图中的训练 op.
Graph-构建图
首先是创建源 op (source op),源 op 不需要任何输入。op 构造器的返回值代表被构造出的 op 的输出, 这些返回值可以传递给其它 op 构造器作为输入.
图文档: Graph 类
代码语言:javascript复制import tensorflow as tf
# 创建一个常量 op, 产生一个 1x2 矩阵. 这个 op 被作为一个节点
# 加到默认图中.
#
# 构造器的返回值代表该常量 op 的返回值.
matrix1 = tf.constant([[3., 3.]])
# 创建另外一个常量 op, 产生一个 2x1 矩阵.
matrix2 = tf.constant([[2.],[2.]])
# 创建一个矩阵乘法 matmul op , 把 'matrix1' 和 'matrix2' 作为输入.
# 返回值 'product' 代表矩阵乘法的结果.
product = tf.matmul(matrix1, matrix2)
在这一阶段,并不会进行计算,所以不要傻傻的输出变量。
Session-启动图
构造阶段完成后, 才能启动图. 启动图的第一步是创建一个 Session 对象, 如果无任何创建参数, 会话构造器将启动默认图.
Session文档:Session 类。下面是接上面的例子:
代码语言:javascript复制# 启动默认图.
sess = tf.Session()
# 调用 sess 的 'run()' 方法来执行矩阵乘法 op, 传入 'product' 作为该方法的参数.
# 上面提到, 'product' 代表了矩阵乘法 op 的输出, 传入它是向方法表明,
# 函数调用 'run(product)' 触发了图中三个 op (两个常量 op 和一个矩阵乘法 op) 的执行.
#
# 返回值 'result' 是一个 numpy `ndarray` 对象.
result = sess.run(product)
print result
# ==> [[ 12.]]
# 任务完成, 关闭会话.
sess.close()
python中可以直接用with隐式启动和关闭会话:
代码语言:javascript复制with tf.Session() as sess:
result = sess.run([product])
print result
TensorFlow 能自动检测. 如果检测到 GPU, TensorFlow 会尽可能地利用找到的第一个 GPU 来执行操作。但是多个GPU的时候就需要指定GPU了。
交互式启动
为了便于使用诸如 IPython 之类的 Python 交互环境, 可以使用 InteractiveSession
代替 Session
类, 使用 Tensor.eval()
和 Operation.run()
方法代替 Session.run()
. 这样可以避免使用一个变量来持有会话.
进入一个交互式 TensorFlow 会话.
import tensorflow as tf
sess = tf.InteractiveSession()
x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])
# 使用初始化器 initializer op 的 run() 方法初始化 'x'
x.initializer.run()
# 增加一个减法 sub op, 从 'x' 减去 'a'. 运行减法 op, 输出结果
sub = tf.sub(x, a)
print sub.eval()
# ==> [-2. -1.]
4.2 Tensor
TensorFlow 程序使用 tensor 数据结构来代表所有的数据, 计算图中, 操作间传递的数据都是 tensor. 你可以把 TensorFlow tensor 看作是一个 n 维的数组或列表. 一个 tensor 包含一个静态类型 rank, 和 一个 shape. 详细参见 Rank, Shape, 和 Type.
Variables-变量
Variables for more details. 变量维护图执行过程中的状态信息. 下面的例子演示了如何使用变量实现一个简单的计数器. 参见 变量
代码语言:javascript复制# 创建一个变量, 初始化为标量 0.
state = tf.Variable(0, name="counter")
# 创建一个 op, 其作用是使 state 增加 1
one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)
# 启动图后, 变量必须先经过`初始化` (init) op 初始化,
# 首先必须增加一个`初始化` op 到图中.
init_op = tf.initialize_all_variables()
# 启动图, 运行 op
with tf.Session() as sess:
# 运行 'init' op
sess.run(init_op)
# 打印 'state' 的初始值
print sess.run(state)
# 运行 op, 更新 'state', 并打印 'state'
for _ in range(3):
sess.run(update)
print sess.run(state)
# 输出:
# 0
# 1
# 2
# 3
代码中 assign()
操作是图所描绘的表达式的一部分, 正如 add()
操作一样. 所以在调用 run()
执行表达式之前, 它并不会真正执行赋值操作.
通常会将一个统计模型中的参数表示为一组变量. 例如, 你可以将一个神经网络的权重作为某个变量存储在一个 tensor 中. 在训练过程中, 通过重复运行训练图, 更新这个 tensor.
Fetch-获取
为了取回操作的输出内容, 可以在使用 Session
对象的 run()
调用 执行图时, 传入一些 tensor, 这些 tensor 会帮助你取回结果. 在之前的例子里, 我们只取回了单个节点 state
, 但是你也可以取回多个 tensor:
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)
with tf.Session():
# 获取多个tensor:mul, intermed
result = sess.run([mul, intermed])
print result
# 输出:
# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]
需要获取的多个 tensor 值,在 op 的一次运行中一起获得(而不是逐个去获取 tensor)。
Feed-填充
上述示例在计算图中引入了 tensor, 以常量或变量的形式存储. TensorFlow 还提供了 feed 机制, 该机制 可以临时替代图中的任意操作中的 tensor 可以对图中任何操作提交补丁, 直接插入一个 tensor.
feed 使用一个 tensor 值临时替换一个操作的输出结果. 你可以提供 feed 数据作为 run()
调用的参数. feed 只在调用它的方法内有效, 方法结束, feed 就会消失. 最常见的用例是将某些特殊的操作指定为 “feed” 操作, 标记的方法是使用 tf.placeholder() 为这些操作创建占位符.
# 创建占位符,一边使用feed填充数据。
input1 = tf.placeholder(tf.types.float32)
input2 = tf.placeholder(tf.types.float32)
output = tf.mul(input1, input2)
with tf.Session() as sess:
print sess.run([output], feed_dict={input1:[7.], input2:[2.]})
# 输出:
# [array([ 14.], dtype=float32)]
for a larger-scale example of feeds. 如果没有正确提供 feed, placeholder()
操作将会产生错误. MNIST 全连通 feed 教程 (source code) 给出了一个更大规模的使用 feed 的例子.
5. 曲线拟合例子
曲线拟合计算。官网将此作为刚开始介绍的示例程序。
代码语言:javascript复制# 简化调用库名
import tensorflow as tf
import numpy as np
# 模拟生成100对数据对, 对应的函数为y = x * 0.1 0.3
x_data = np.random.rand(100).astype("float32")
y_data = x_data * 0.1 0.3
# 指定w和b变量的取值范围(注意我们要利用TensorFlow来得到w和b的值)
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data b
# 最小化均方误差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
# 初始化TensorFlow参数
init = tf.initialize_all_variables()
# 运行数据流图(注意在这一步才开始执行计算过程)
sess = tf.Session()
sess.run(init)
# 观察多次迭代计算时,w和b的拟合值
for step in xrange(201):
sess.run(train)
if step % 20 == 0:
print(step, sess.run(W), sess.run(b))
# 最好的情况是w和b分别接近甚至等于0.1和0.3
更多的例子:
- 『DeepLearning』tensorFlow搭建CNN-mnist上手
- TensorFlow-CIFAR10 CNN代码分析
- 去噪自编码网络
6. 保存和加载
最简单的保存和恢复模型的方法是使用tf.train.Saver
对象。构造器给graph的所有变量,或是定义在列表里的变量,添加save
和restore
ops。saver对象提供了方法来运行这些ops,定义检查点文件的读写路径。
保存变量
用tf.train.Saver()
创建一个Saver
来管理模型中的所有变量。
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add an op to initialize the variables.
init_op = tf.initialize_all_variables()
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, initialize the variables, do some work, save the
# variables to disk.
with tf.Session() as sess:
sess.run(init_op)
# Do some work with the model.
# ...
# Save the variables to disk.
save_path = saver.save(sess, "/tmp/model.ckpt")
print "Model saved in file: ", save_path
恢复变量
用同一个Saver
对象来恢复变量。注意,当你从文件中恢复变量时,不需要事先对它们做初始化。
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
# ...
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:
# Restore variables from disk.
saver.restore(sess, "/tmp/model.ckpt")
print "Model restored."
# Do some work with the model
选择存储和恢复哪些变量
如果你不给tf.train.Saver()
传入任何参数,那么saver将处理graph中的所有变量。其中每一个变量都以变量创建时传入的名称被保存。
有时候在检查点文件中明确定义变量的名称很有用。举个例子,你也许已经训练得到了一个模型,其中有个变量命名为"weights"
,你想把它的值恢复到一个新的变量"params"
中。
有时候仅保存和恢复模型的一部分变量很有用。再举个例子,你也许训练得到了一个5层神经网络,现在想训练一个6层的新模型,可以将之前5层模型的参数导入到新模型的前5层中。
你可以通过给tf.train.Saver()
构造函数传入Python字典,很容易地定义需要保持的变量及对应名称:键对应使用的名称,值对应被管理的变量。
注意:
- 如果需要保存和恢复模型变量的不同子集,可以创建任意多个saver对象。同一个变量可被列入多个saver对象中,只有当saver的
restore()
函数被运行时,它的值才会发生改变。 - 如果你仅在session开始时恢复模型变量的一个子集,你需要对剩下的变量执行初始化op。详情请见
tf.initialize_variables()
。
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore only 'v2' using the name "my_v2"
saver = tf.train.Saver({"my_v2": v2})
# Use the saver object normally after that.
更多
- tensorfly.cn
- 『DeepLearning』tensorFlow搭建CNN-mnist上手
- TensorFlow-CIFAR10 CNN代码分析
- TensorFlow-Examples