本章根据TensorFlow的中文文档学习
我也是跟着博客一步步往下学,并作出自己的理解。
1. 构建图
文档指出,构建图的第一步是要创建一个源op,源op不需要任何输入,它的输出也可以给别的op做运算。
Python 库中, op 构造器的返回值代表被构造出的 op 的输出, 这些返回值可以传递给其它 op 构造器作为输入.
TensorFlow Python 库有一个默认图 (default graph), op 构造器可以为其增加节点. 这个默认图对 许多程序来说已经足够用了
文档给出代码:
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)
默认图中现在有三个节点, 两个 constant() op, 和一个matmul() op.
1.1 constant
constant节点表示常量,函数签名为:
def constant(value, dtype=None, shape=None, name="Const", verify_shape=False)
通过constant创建一个常量tensor后。所得的tensor为dtype
型的值,由参数value
和shape
(可选地)指定。
参数dtype
可以是常量值,也可以是dtype
类型的值的列表。如果value
是一个列表,那么该列表的长度必须小于或等于由shape
参数所包含的元素的数量(如果指定了shape
)。在列表长度小于由shape
指定的元素的数量的情况下,列表中的最后一个元素将用于填充其余条目。
参数shape
是可选的。如果存在,则指定所得张量的维数。如果不存在,则使用value
的shape。
如果未指定参数dtype
,则从value
类型推断类型。
# 一维tensor:用列表填充
tensor = tf.constant([1, 2, 3, 4, 5, 6, 7]) => [1 2 3 4 5 6 7]
# 二维tensor:用-1填充
tensor = tf.constant(-1.0, shape=[2, 3]) => [[-1. -1. -1.]
[-1. -1. -1.]]
参数:
value | dtype | shape | name | verify_shape |
---|---|---|---|---|
一个dtype 型的常量(或列表)值 |
所得tensor的元素类型 | 所得tensor的可选维数 | tensor的名字(可选) | 布尔值,指定tensor是否支持shape |
结果 | 异常 |
---|---|
一个常量tensor | TypeError:如果shape不支持或不正确 |
因此,前面文档中给的代码中
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.], [2.]])
分别产生一个 1x2 矩阵和一个 2x1 矩阵
然后,在
product = tf.matmul(matrix1, matrix2)
中,创建了一个矩阵乘法 matmul , 把 ‘matrix1’ 和 ‘matrix2’ 作为输入
1.2 matmul
matmul的函数签名为:
def matmul(a,
b,
transpose_a=False,
transpose_b=False,
adjoint_a=False,
adjoint_b=False,
a_is_sparse=False,
b_is_sparse=False,
name=None):
该op用矩阵‘b’乘以举证’a’,输出 ‘a’ * ‘b’
在任意交换后,输出必须是秩>=2的张量,其中内部的两个维度指定有效的矩阵乘法参数。并且和任何外部维度相匹配。
两个矩阵必须是同类型的,支持的类型有: float16
, float32
, float64
, int32
, complex64
, complex128
矩阵可被转换或共轭,这些设置默认为False,可通过将transpose_a, transpose_b,adjoint_a,adjoint_b设置为True实现。
如果一个矩阵或两个矩阵中都包含了一些0,那将相应的a_is_sparse或(和)b_is_sparse设置为True能使乘法计算更高效。
这种优化仅适用于数据类型为“bfloat16”或“float32”的普通矩阵(秩为2的张量)。
比如:
# 2维 tensor 'a'
# [[1, 2, 3],
# [4, 5, 6]]
a = tf.constant([1, 2, 3, 4, 5, 6], shape=[2, 3])
# 二维 tensor `b`
# [[ 7, 8],
# [ 9, 10],
# [11, 12]]
b = tf.constant([7, 8, 9, 10, 11, 12], shape=[3, 2])
# `a` * `b`
# [[ 58, 64],
# [139, 154]]
c = tf.matmul(a, b)
# 三维 tensor `a`
# [[[ 1, 2, 3],
# [ 4, 5, 6]],
# [[ 7, 8, 9],
# [10, 11, 12]]]
a = tf.constant(np.arange(1, 13, dtype=np.int32),
shape=[2, 2, 3])
# 三维 tensor `b`
# [[[13, 14],
# [15, 16],
# [17, 18]],
# [[19, 20],
# [21, 22],
# [23, 24]]]
b = tf.constant(np.arange(13, 25, dtype=np.int32),
shape=[2, 3, 2])
# `a` * `b`
# [[[ 94, 100],
# [229, 244]],
# [[508, 532],
# [697, 730]]]
c = tf.matmul(a, b)
自从python3.5以后,就支持了@操作符,在TensorFlow中,就是tf.matmul()
函数,所以,下面两行是等价的:
d = a @ b @ [[10.], [11.]]
d = tf.matmul(tf.matmul(a, b), [[10.], [11.]])
参数:
a和b | transpose_a(b) | adjoint_a(b) | a(b)_is_sparse | name |
---|---|---|---|---|
float16 ..等类型(前面介绍过)且秩大于1的Tensor |
矩阵a或b在乘法前置换 | 矩阵a或b在乘法前共轭 | a或b为一个稀疏矩阵 | 给该op一个名字 |
结果 | 异常 |
---|---|
输出和a、b同类型的矩阵,a、b矩阵的乘积。 | ValueError:如果transpose_a,adjoint_a, or transpose_b和adjoint_b都设为True |
所以文档中:
product = tf.matmul(matrix1, matrix2)
product表示matrix1和matrix2两个矩阵的乘积
1.3 启动默认图
为了真正进行矩阵相乘运算, 并得到矩阵乘法的结果, 你必须在会话里启动这个图.
sess = tf.Session()
result = sess.run(product)
# 整个执行过程是自动化的, 会话负责传递 op 所需的全部输入. op 通常是并发执行的
# 函数调用 'run(product)' 触发了图中三个 op (两个常量 op 和一个矩阵乘法 op) 的执行.
1.4 输出结果
最后打印结果result:
print(result) # ==> [[ 12.]]
1.5 关闭会话
Session 对象在使用完后需要关闭以释放资源. 除了显式调用 close 外, 也可以使用 “with” 代码块 来自动完成关闭动作:
with tf.Session() as sess:
result = sess.run([product])
print result
在实现上, TensorFlow 将图形定义转换成分布式执行的操作, 以充分利用可用的计算资源(如 CPU 或 GPU). 一般你不需要显式指定使用 CPU 还是 GPU, TensorFlow 能自动检测. 如果检测到 GPU, TensorFlow 会尽可能地利用找到的第一个 GPU 来执行操作.
如果机器上有超过一个可用的 GPU, 除第一个外的其它 GPU 默认是不参与计算的. 为了让 TensorFlow 使用这些 GPU, 你必须将 op 明确指派给它们执行. with…Device 语句用来指派特定的 CPU 或 GPU 执行操作:
with tf.Session() as sess:
with tf.device("/gpu:1"):
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])
product = tf.matmul(matrix1, matrix2)
...
“/cpu:0”: 机器的 CPU.
“/gpu:0”: 机器的第一个 GPU, 如果有的话.
“/gpu:1”: 机器的第二个 GPU, 以此类推.