是一个深度学习库,由 Google 开源,可以对定义在 Tensor(张量)上的函数自动求导。
Tensor(张量)意味着 N 维数组,Flow(流)意味着基于数据流图的计算,TensorFlow即为张量从图的一端流动到另一端。
它的一大亮点是支持异构设备分布式计算,它能够在各个平台上自动运行模型,从电话、单个CPU / GPU到成百上千GPU卡组成的分布式系统。
支持CNN、RNN和LSTM算法,是目前在 Image,NLP 最流行的深度神经网络模型。
深度学习通常意味着建立具有很多层的大规模的神经网络。
除了输入X,函数还使用一系列参数,其中包括标量值、向量以及最昂贵的矩阵和高阶张量。
在训练网络之前,需要定义一个代价函数,常见的代价函数包括回归问题的方差以及分类时候的交叉熵。
训练时,需要连续的将多批新输入投入网络,对所有的参数求导后,代入代价函数,从而更新整个网络模型。
这个过程中有两个主要的问题:1. 较大的数字或者张量在一起相乘百万次的处理,使得整个模型代价非常大。2. 手动求导耗时非常久。
所以 TensorFlow 的对函数自动求导以及分布式计算,可以帮我们节省很多时间来训练模型。
第一,基于Python,写的很快并且具有可读性。
第二,在多GPU系统上的运行更为顺畅。
第三,代码编译效率较高。
第四,社区发展的非常迅速并且活跃。
第五,能够生成显示网络拓扑结构和性能的可视化图。
TensorFlow是用数据流图(data flow graphs)技术来进行数值计算的。
数据流图是描述有向图中的数值计算过程。
有向图中,节点通常代表数学运算,边表示节点之间的某种联系,它负责传输多维数据(Tensors)。
节点可以被分配到多个计算设备上,可以异步和并行地执行操作。因为是有向图,所以只有等到之前的入度节点们的计算状态完成后,当前节点才能执行操作。
极客学院有官方文档翻译版,讲的很清楚,有各种安装方式的讲解。
我选择基于 Anaconda 的安装,因为这个很方便。
Anaconda 是一个集成许多第三方科学计算库的 Python 科学计算环境,用 conda 作为自己的包管理工具,同时具有自己的计算环境,类似 Virtualenv。
安装 Anaconda
我之前已经安装过 Anaconda 了,直接从下面进行:
建立一个 conda 计算环境
# 计算环境名字叫 tensorflow:
# Python 2.7
$ conda create -n tensorflow python=2.7
$ source activate tensorflow
(tensorflow)$ # Your prompt should change
# Mac OS X, CPU only:
(tensorflow)$ pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.8.0rc0-py2-none-any.whl
安装成功后,每次使用 TensorFlow 的时候需要激活 conda 环境
conda 环境激活后,你可以测试是否成功,在终端进入 python,输入下面代码,没有提示错误,说明安装 TensorFlow 成功:
$ python
...
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>
(tensorflow)$ source deactivate
$ # Your prompt should change back
$ source activate tensorflow
(tensorflow)$ # Run Python programs that use TensorFlow.
...
(tensorflow)$ source deactivate
在 Jupyter notebook 里用 TensorFlow
我在 (tensorflow)$ 直接输入 jupyter notebook 后,输入 import tensorflow as tf 是有错误的,可以参考这里。
接下来按照官方文档中的具体代码,来看一下基本用法。
你需要理解在TensorFlow中,是如何:
先看个栗子:
例1,生成三维数据,然后用一个平面拟合它:
# (tensorflow)$ python 用 Python API 写 TensorFlow 示例代码
import tensorflow as tf
import numpy as np
# 用 NumPy 随机生成 100 个数据
x_data = np.float32(np.random.rand(2, 100))
y_data = np.dot([0.100, 0.200], x_data) + 0.300
# 构造一个线性模型
b = tf.Variable(tf.zeros([1]))
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b
# 最小化方差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
# 初始化变量
init = tf.initialize_all_variables()
# 启动图 (graph)
sess = tf.Session()
sess.run(init)
# 拟合平面
for step in xrange(0, 201):
sess.run(train)
if step % 20 == 0:
print step, sess.run(W), sess.run(b)
# 输出结果为:
0 [[-0.14751725 0.75113136]] [ 0.2857058]
20 [[ 0.06342752 0.32736415]] [ 0.24482927]
40 [[ 0.10146417 0.23744738]] [ 0.27712563]
60 [[ 0.10354312 0.21220125]] [ 0.290878]
80 [[ 0.10193551 0.20427427]] [ 0.2964265]
100 [[ 0.10085492 0.201565 ]] [ 0.298612]
120 [[ 0.10035028 0.20058727]] [ 0.29946309]
140 [[ 0.10013894 0.20022322]] [ 0.29979277]
160 [[ 0.1000543 0.20008542]] [ 0.29992008]
180 [[ 0.10002106 0.20003279]] [ 0.29996923]
200 [[ 0.10000814 0.20001261]] [ 0.29998815]
注意这几条代码:
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
sess.run(train)
print step, sess.run(W), sess.run(b)
接下来看具体概念:
1. 构建图
例2,计算矩阵相乘:
import tensorflow as tf
# 创建一个 常量 op, 返回值 'matrix1' 代表这个 1x2 矩阵.
matrix1 = tf.constant([[3., 3.]])
# 创建另外一个 常量 op, 返回值 'matrix2' 代表这个 2x1 矩阵.
matrix2 = tf.constant([[2.],[2.]])
# 创建一个矩阵乘法 matmul op , 把 'matrix1' 和 'matrix2' 作为输入.
# 返回值 'product' 代表矩阵乘法的结果.
product = tf.matmul(matrix1, matrix2)
默认图有三个节点, 两个 constant() op, 和一个 matmul() op. 为了真正进行矩阵相乘运算, 并得到矩阵乘法的结果, 你必须在会话里启动这个图.
2. 张量 Tensor
从向量空间到实数域的多重线性映射(multilinear maps)(v是向量空间,v*是对偶空间)
例如代码中的 [[3., 3.]],Tensor 可以看作是一个 n 维的数组或列表。在 TensorFlow 中用 tensor 数据结构来代表所有的数据, 计算图中, 操作间传递的数据都是 tensor。
3. 在一个会话中启动图
创建一个 Session 对象, 如果无任何创建参数, 会话构造器将启动默认图。
会话负责传递 op 所需的全部输入,op 通常是并发执行的。
# 启动默认图.
sess = tf.Session()
# 调用 sess 的 'run()' 方法, 传入 'product' 作为该方法的参数,
# 触发了图中三个 op (两个常量 op 和一个矩阵乘法 op),
# 向方法表明, 我们希望取回矩阵乘法 op 的输出.
result = sess.run(product)
# 返回值 'result' 是一个 numpy `ndarray` 对象.
print result
# ==> [[ 12.]]
# 任务完成, 需要关闭会话以释放资源。
sess.close()
交互式使用
在 Python API 中,使用一个会话 Session 来 启动图, 并调用 Session.run() 方法执行操作.
为了便于在 IPython 等交互环境使用 TensorFlow,需要用 InteractiveSession 代替 Session 类, 使用 Tensor.eval() 和 Operation.run() 方法代替 Session.run()。
例3,计算 'x' 减去 'a':
# 进入一个交互式 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.]
变量 Variable
上面用到的张量是常值张量(constant)。
变量 Variable,是维护图执行过程中的状态信息的. 需要它来保持和更新参数值,是需要动态调整的。
下面代码中有 tf.initialize_all_variables
,是预先对变量初始化,
Tensorflow 的变量必须先初始化,然后才有值!而常值张量是不需要的。
下面的 assign() 操作和 add() 操作,在调用 run() 之前, 它并不会真正执行赋值和加和操作。
例4,使用变量实现一个简单的计数器:
# -创建一个变量, 初始化为标量 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 初始化,
# 才真正通过Tensorflow的initialize_all_variables对这些变量赋初值
init_op = tf.initialize_all_variables()
# 启动默认图, 运行 op
with tf.Session() as sess:
# 运行 'init' op
sess.run(init_op)
# 打印 'state' 的初始值
# 取回操作的输出内容, 可以在使用 Session 对象的 run() 调用 执行图时,
# 传入一些 tensor, 这些 tensor 会帮助你取回结果.
# 此处只取回了单个节点 state,
# 也可以在运行一次 op 时一起取回多个 tensor:
# result = sess.run([mul, intermed])
print sess.run(state)
# 运行 op, 更新 'state', 并打印 'state'
for _ in range(3):
sess.run(update)
print sess.run(state)
# 输出:
# 0
# 1
# 2
# 3
上面的代码定义了一个如下的计算图:
Ok,总结一下,来一个清晰的代码:
过程就是:建图->启动图->运行取值
计算矩阵相乘:
import tensorflow as tf
# 建图
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])
product = tf.matmul(matrix1, matrix2)
# 启动图
sess = tf.Session()
# 取值
result = sess.run(product)
print result
sess.close()
上面的几个代码介绍了基本用法,通过观察,有没有觉得 tf 和 numpy 有点像呢。
TensorFlow和普通的Numpy的对比
在cs224d的课件中有下面这个代码,来看一下二者之间的区别:
eval()
在 Python 中定义完 a 后,直接打印就可以看到 a。
In [37]: a = np.zeros((2,2))
In [39]: print(a)
[[ 0. 0.]
[ 0. 0.]]
但是在 Tensorflow 中需要显式地输出(evaluation,也就是说借助eval()函数)!
In [38]: ta = tf.zeros((2,2))
In [40]: print(ta)
Tensor("zeros_1:0", shape=(2, 2), dtype=float32)
In [41]: print(ta.eval())
[[ 0. 0.]
[ 0. 0.]]