[程序员指南2]张量
TensorFlow如名称所示,是定义和运行涉及张量的计算的框架。甲张量是向量和矩阵的一般化到潜在的更高的尺寸。在内部,TensorFlow表示张量作为基本数据类型的n维数组。
在编写TensorFlow程序时,您操作和传递的主要对象是tf.Tensor
。一个tf.Tensor
对象代表最终产生一个值的部分定义的计算。TensorFlow程序首先构建tf.Tensor
对象图,详细说明如何根据其他可用的张量计算每个张量,然后运行该图的部分以实现所需的结果。
A tf.Tensor
具有以下属性:
- 数据类型(
float32
,int32
或string
,例如) - 一个形状
Tensor中的每个元素具有相同的数据类型,数据类型始终是已知的。形状(即,它所具有的维数以及每个维度的大小)可能只是部分已知的。如果输入的形状也是完全知道的,大多数操作会产生一个已知形状的张量,但在某些情况下,只能在图形执行时找到张量的形状。
一些类型的张量是特殊的,这些将在程序员指南的其他单位中被覆盖。主要有:
tf.Variable
tf.Constant
tf.Placeholder
tf.SparseTensor
除了tf.Variable
,张量的值是不可变的,这意味着在单个执行的上下文中,张量只有一个值。然而,两次评估相同的张量可以返回不同的值; 例如,张量可以是从磁盘读取数据或生成随机数的结果。
秩
一个对象的等级tf.Tensor
是它的维数。等级的同义词包括顺序或程度或n维。请注意,TensorFlow中的等级与数学中的矩阵等级不同。如下表所示,TensorFlow中的每个等级对应于不同的数学实体:
秩 | 数学实体 |
---|---|
0 | 标量(仅限量表) |
1 | 矢量(大小和方向) |
2 | 矩阵(数字表) |
3 | 3-Tensor(数字立方体) |
ñ | n-Tensor(你得到的想法) |
排名0
以下代码段演示了创建几个0级变量:
注意:字符串在TensorFlow中被视为单个项目,而不是字符序列。可以使用标量字符串,字符串向量等
排名1
要创建1级tf.Tensor
对象,可以将项目列表作为初始值传递。例如
mystr = tf.Variable(["Hello"], tf.string) cool_numbers = tf.Variable([3.14159, 2.71828], tf.float32) first_primes = tf.Variable([2, 3, 5, 7, 11], tf.int32) its_very_complicated = tf.Variable([(12.3, -4.85), (7.5, -6.23)], tf.complex64)
更高级
2级tf.Tensor
对象由至少一行和至少一列组成:
mymat = tf.Variable([[7],[11]], tf.int16) myxor = tf.Variable([[False, True],[True, False]], tf.bool) linear_squares = tf.Variable([[4], [9], [16], [25]], tf.int32) squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32) rank_of_squares = tf.rank(squarish_squares) mymatC = tf.Variable([[7],[11]], tf.int32)
较高级的传感器类似地由n维阵列组成。例如,在图像处理期间,使用许多等级4的张量,其尺寸对应于批次间图像,图像宽度,图像高度和颜色通道。
my_image = tf.zeros([10, 299, 299, 3]) # batch x height x width x color
获得tf.Tensor
对象的等级
要确定tf.Tensor
对象的排名,请调用该tf.rank
方法。例如,以下方法以编程方式确定tf.Tensor
上一节中定义的排名:
r = tf.rank(my3d) # After the graph runs, r will hold the value 3.
参考tf.Tensor
切片
由于a tf.Tensor
是单元格的n维数组,要访问单个单元格,tf.Tensor
您需要指定n个索引。
对于等级0张量(标量),不需要索引,因为它已经是单个数字。
对于等级1张(矢量),传递单个索引可以访问一个数字:
my_scalar = my_vector[2]
请注意,如果要从向量中动态选择一个元素,则[]
可以在本身内部传递的索引本身是一个标量tf.Tensor
。
对于2级以上的张量,情况更有意思。对于 tf.Tensor
2级,通过两个数字返回一个标量,如预期的:
my_scalar = my_matrix[1, 2]
然而,传递单个数字返回矩阵的子向量,如下所示:
my_row_vetor = my_matrix[2]
my_column_vector = my_matrix[:, 3]
该:
标记是作为“离开这个维度单独”蟒蛇切片语法。这在高级Tensors中是有用的,因为它允许您访问其子向量,子矩阵,甚至其他子传感器。
形状
张量的形状是每个维度中元素的数量。在图形构建期间,TensorFlow自动推断形状。这些推测的形状可能具有已知或未知的等级。如果排名是已知的,每个维度的大小可能是已知的或未知的。
TensorFlow文档使用三个符号约定来描述张量维数:等级,形状和维数。下表显示了这些如何相互关联:
秩 | 形状 | 尺寸数 | 例 |
---|---|---|---|
0 | [] | 0-D | 0-D张量。一个标量 |
1 | [D0] | 1-D | 具有形状的1-D张量[5]。 |
2 | [D0,D1] | 2-D | 形状为[3,4]的2-D张量。 |
3 | [D0,D1,D2] | 3-D | 形状为[1,4,3]的3-D张量。 |
ñ | [D0,D1,... Dn-1] | ND | 形状为[D0,D1,... Dn-1]的张量。 |
形状可以通过Python列表/元组的ints或者 tf.TensorShape
。
获取tf.Tensor
对象的形状
访问a的形状有两种方式tf.Tensor
。在构建图形时,询问已知的张量形状通常是有用的。这可以通过读取对象的shape
属性来完成tf.Tensor
。该方法返回一个TensorShape
对象,它是表示部分指定形状的方便方法(因为,当构建图形时,并不是所有形状都将被完全知道)。
在运行时也可以获得一个tf.Tensor
代表另一个的完全定义的形状tf.Tensor
。这是通过调用tf.shape
操作完成的。这样,您可以构建一个图形,通过构建依赖于输入的动态形状的其他张量来操纵张量的形状 tf.Tensor
。
例如,这里是如何使一个与给定矩阵中的列数相同大小的零向量:
zeros = tf.zeros(tf.shape(my_matrix)[1])
的要素数的张量的是其所有的形状的尺寸的乘积。始终是标量的元素数1
。由于通常有许多不同的形状具有相同数量的元素,所以能够改变形状tf.Tensor
,保持其元素固定是非常方便的。这可以做到tf.reshape
。
以下示例演示如何重塑张量:
# coding=utf-8 import tensorflow as tf rank_three_tensor = tf.ones([3, 4, 5]) matrix = tf.reshape(rank_three_tensor, [6, 10]) # Reshape existing content into # a 6x10 matrix matrixB = tf.reshape(matrix, [3, -1]) # Reshape existing content into a 3x20 # matrix. -1 tells reshape to calculate # the size of this dimension. matrixAlt = tf.reshape(matrixB, [4, 3, -1]) # Reshape existing content into a #4x3x5 tensor with tf.Session() as sess: print sess.run(rank_three_tensor) print sess.run(matrix) print sess.run(matrixB) print sess.run(matrixAlt)
[[[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]]] rank_three_tensor = tf.ones([3, 4, 5]) [[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]] matrix = tf.reshape(rank_three_tensor, [6, 10]) [[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]] matrixB = tf.reshape(matrix, [3, -1]) [[[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]] [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]]] matrixAlt = tf.reshape(matrixB, [4, 3, -1])
数据类型
除了维度之外,Tensors有一个数据类型。tf.DataType
有关数据类型的完整列表,请参阅程序员指南中的 页面。
不可能有tf.Tensor
多个数据类型。然而,可以将任意数据结构序列化为string
s并将其存储在tf.Tensor
s中。
可以使用以下方式将tf.Tensor
s从一个数据类型转换为另一个数据类型 tf.cast
:
# coding=utf-8 import tensorflow as tf a = tf.constant([1, 2, 3]) # Cast a constant integer tensor into floating point. float_tensor = tf.cast(a, dtype=tf.float32) with tf.Session() as sess: print sess.run(a) print sess.run(float_tensor) 输出: [1 2 3] [ 1. 2. 3.]
检查tf.Tensor
数据类型使用Tensor.dtype
属性。
tf.Tensor
从python对象创建时,您可以选择指定数据类型。如果没有,TensorFlow会选择一个可以表示数据的数据类型。TensorFlow将Python整数转换为tf.int32
和python浮点数tf.float32
。否则TensorFlow在转换为数组时使用与numpy相同的规则。
评估传感器
一旦建立了计算图,就可以运行生成特定的计算,tf.Tensor
并获取分配给它的值。这通常对于调试以及TensorFlow的大部分工作都是必需的。
评估Tensor的最简单的方法是使用该Tensor.eval
方法。例如:
# coding=utf-8 import tensorflow as tf constant = tf.constant([1, 2, 3]) tensor = constant * constant with tf.Session() as sess: print sess.run(tensor) print tensor.eval() 输出: [1 4 9] [1 4 9]
该eval
方法仅在默认tf.Session
为活动状态时有效(有关详细信息,请参阅“图表和会话”)。
Tensor.eval
返回与张量相同内容的numpy数组。
有时无法评估tf.Tensor
没有上下文,因为它的值可能取决于不可用的动态信息。例如,依赖于Placeholder
s的张量不能在没有提供值的情况下进行评估Placeholder
。
# coding=utf-8 import tensorflow as tf p = tf.placeholder(tf.float32) t = p + 1.0 with tf.Session() as sess: print t.eval() # This will fail, since the placeholder did not get a value. print t.eval(feed_dict={p: 2.0}) # This will succeed because we're feeding a value to the placeholder.
请注意,可以喂养任何一个tf.Tensor
,而不仅仅是占位符。
其他模型构造可能会使评估tf.Tensor
变得复杂。TensorFlow不能直接评估tf.Tensor
定义的内部函数或内部控制流构造。如果a tf.Tensor
取决于队列中的值,则评估该值tf.Tensor
只有在某些进入队列之后才会生效; 否则,评估它会挂起。在使用队列时,请记住tf.train.start_queue_runners
在评估任何tf.Tensor
s 之前调用。
印刷传感器
为了进行调试,您可能需要打印a的值tf.Tensor
。当 tfdbg提供高级调试支持时,TensorFlow还有一个操作直接打印a的值tf.Tensor
。
请注意,打印时您很少想使用以下模式 tf.Tensor
:
t = <<some tensorflow operation>> print t # This will print the symbolic tensor when the graph is being built. # This tensor does not have a value in this context.
此代码打印tf.Tensor
对象(表示延迟计算),而不是其值。相反,TensorFlow提供的tf.Print
操作,它返回其第一张张参数不变,同时打印tf.Tensor
作为第二个参数传递的集合 。
tf.Print
必须使用正确使用其返回值。见下面的例子
t = <<some tensorflow operation>> tf.Print(t, [t]) # This does nothing t = tf.Print(t, [t]) # Here we are using the value returned by tf.Print result = t + 1 # Now when result is evaluated the value of `t` will be printed.
当你评估result
你会评估一切result
取决于。由于result
取决于t
,评估t
具有打印其输入(旧值t
)的副作用t
。