本文来源于Tensorflow官方文档,官方介绍的很详细,相信大家看完对Tensor会有一个比较清晰的认识。
正如名称所示,TensorFlow 这一框架定义和运行涉及张量的计算。张量是对矢量和矩阵向潜在的更高维度的泛化。对内,TensorFlow 将张量表现为基本数据类型的 n 维数组。
在编写 TensorFlow 程序时,操控和传递的主要目标是 tf.Tensor
。tf.Tensor
目标表示一个部分定义的计算,最终会产生一个值。TensorFlow 程序首先建立 tf.Tensor
目标图,详细说明如何基于其他可用张量来计算每个张量,然后运行该图的部分内容以获得所期望的结果。
tf.Tensor
有以下属性:
float32
,int32
或 string
)张量中的每个元素都具有相同的数据类型,且该数据类型一定是已知的。形状,即张量的维数和每个维度的大小,可能只有部分已知。如果其输入的形状也完全已知,则大多数指令会生成形状完全已知的张量,但在某些情况下,只能在图的执行时间找到张量的形状。
某些类型的张量是特殊的,《编程人员指南》的其他部分中有所介绍。以下是主要的特殊张量:
tf.Variable
tf.constant
tf.placeholder
tf.SparseTensor
除 tf.Variable
以外,张量的值不可变,这意味着在单一执行的情况下,张量只有一个值。然而,同一张量的两次评估可能会返回不同的值;例如,该张量可以是从磁盘读取数据的结果,或是生成随机数的结果。
tf.Tensor
的阶就是它本身的维数。阶的同义词包括:秩序,等级或 n 维。 请注意,TensorFlow 中的阶与数学中矩阵的阶并不是同一个概念。如下表所示,TensorFlow 中的每个阶都对应一个不同的数学实例:
阶 | 数学实例 |
---|---|
0 | 标量(只有大小) |
1 | 矢量(大小和方向) |
2 | 矩阵(数据表) |
3 | 3 阶张量(数据立体) |
n | n 阶张量(自行想象) |
以下摘要演示了创建 0 阶变量的过程:
mammal = tf.Variable("Elephant", tf.string)
ignition = tf.Variable(451, tf.int16)
floating = tf.Variable(3.14159265359, tf.float64)
its_complicated = tf.Variable(12.3 - 4.85j, tf.complex64)
注意:字符串在 TensorFlow 中被视为单一项,而不是一连串字符。TensorFlow 可以有标量字符串,字符串矢量,等等。
要创建 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.85j, 7.5 - 6.23j], 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(my_image)
# After the graph runs, r will hold the value 4.
tf.Tensor
切片由于 tf.Tensor
n 维单元数组,要访问 tf.Tensor
中的某一单元,则需要指定 n 指数。
0 阶张量(标量)不需要指数,因为其本身便是单一数字。
对于 1 阶张量(矢量)来说,传递单一指数则可以访问一个数字:
my_scalar = my_vector[2]
请注意,如果想从矢量中动态地选择元素,那么 []
内传递的指数本身可以是一个标量 tf.Tensor
。
对于 2 阶及以上的张量来说,情况更为有趣。对于 2 阶张量的 tf.Tensor
来说,传递两个数字会如预期般返回一个标量:
my_scalar = my_matrix[1, 2]
而传递一个数字,则会返回一个矩阵的子矢量,如下所示:
my_row_vector = my_matrix[2]
my_column_vector = my_matrix[:, 3]
符号 :
是 Python 切片语法,意味“不要触碰该维度”。这对更高阶的张量来说很有用,可以帮助访问其子矢量,子矩阵,甚至其他子张量。
张量的形状是每个维度中元素的数量。TensorFlow 在图的构建过程中自动推理形状。这些推理的形状可能具有已知或未知的阶。如果阶已知,则每个维度的大小可能已知或未知。
TensorFlow 文件编制中通过三种符号约定来描述张量维度:阶,形状和维数。下表阐述了三者如何相互关联:
阶 | 形状 | 维数 | 示例 |
---|---|---|---|
0 | [] | 0-D | 0 维张量。标量。 |
1 | [D0] | 1-D | 形状为 [5] 的 1 维张量。 |
2 | [D0, D1] | 2-D | 形状为 [3, 4] 的 2 维张量。 |
3 | [D0, D1, D2] | 3-D | 形状为 [1, 4, 3] 的 3 维张量。 |
n | [D0, D1, ... Dn-1] | n-D | 形状为 [D0, D1, ... Dn-1] 的张量。 |
形状可以通过 Python 的整数列表或元祖来进行表示,也可以用 tf.TensorShape
。
tf.Tensor
目标的形状获得 tf.Tensor
形状的方法有两种。在构建图的时候,询问有关张量形状的已知信息通常很有帮助。这一点可以通过读取 tf.Tensor
目标的 shape
属性来做到。该方法会返回一个 TensorShape
目标,可以方便地表示部分指定的形状(因为在构建图的时候,并不是所有形状都完全已知)。
同时,也可能在运行时获取一个将会表示另一个 tf.Tensor
完全指定的形状的 tf.Tensor
。这一点可以通过调用 tf.shape
指令完成。如此一来,您可以构建一个图,通过构建其他取决于输入 tf.Tensor
的动态形状的张量来控制张量的形状。
例如,以下内容展示了如何制作与给定矩阵中的列数相同大小的零矢量:
zeros = tf.zeros(my_matrix.shape[1])
tf.Tensor 的形状Tensor
张量的元素数量是其所有形状大小的乘积。标量的元素数量永远是 1
。由于通常有许多不同的形状具有相同的元素数量,因此如果能够改变 tf.Tensor
的形状可以带来很多便利,保持其元素固定。这一点可以通过 tf.reshape
来完成。
以下示例演示如何重构张量:
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
# Note that the number of elements of the reshaped Tensors has to match the
# original number of elements. Therefore, the following example generates an
# error because no possible value for the last dimension will match the number
# of elements.
yet_another = tf.reshape(matrixAlt, [13, 2, -1]) # ERROR!
除维度外,张量还有数据类型。请参阅《编程人员指南》中的 tf.DataType
页面,以获取数据类型的完整列表。
一个 tf.Tensor
只可能有一种数据类型。但是,可以将任意数据结构序列化为 string
并将其存储在 tf.Tensor
中。
可以通过 tf.cast
来将 tf.Tensor
从一个数据类型转换到另一种:
# Cast a constant integer tensor into floating point.
float_tensor = tf.cast(tf.constant([1, 2, 3]), dtype=tf.float32)
要检查 tf.Tensor
的数据类型,请使用 Tensor.dtype
属性。
创建来自 Python 目标的 tf.Tensor
时,可以选择指定数据类型。如果不指定数据类型,TensorFlow 会选择一个可以表示数据的数据类型。TensorFlow 将 Python 整数转换为 tf.int32
,并将 Python 浮点数转换为 tf.float32
。此外,TensorFlow 使用 Numpy 在转换至数组时使用的相同规则。
一旦计算图建立完毕,就可以运行生成特定 tf.Tensor
的计算并提取分配给它的值。这对于程序调试很有帮助,也是 TensorFlow 的大部分功能可用所必需的。
评估张量最简单的方法是使用 Tensor.eval
方法。例如:
constant = tf.constant([1, 2, 3])
tensor = constant * constant
print tensor.eval()
eval
方法仅在默认 tf.Session
值处于活动状态时才起作用(请参阅《图和会话》获取更多信息)。
Tensor.eval
会返回一个与张量内容相同的 Numpy 数组。
有时不可能在没有背景的情况下评估 tf.Tensor
,因为它的值可能取决于无法获取的动态信息。例如,在没有提供 placeholder
值的情况下,无法评估依赖于 placeholder
的张量。
p = tf.placeholder(tf.float32)
t = p + 1.0
t.eval() # This will fail, since the placeholder did not get a value.
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
。如果 tf.Tensor
取决于队列中的值,那么只有在某些东西加入队列后才能评估 tf.Tensor
;否则,评估将被搁置。在处理队列时,请先调用 tf.train.start_queue_runners
,再评估 tf.Tensor
。
出于调试目的,可能需要打印 tf.Tensor
值。 提供高级调试支持,而 TensorFlow 也有一个指令可以直接打印 tf.Tensor
的值。
请注意,打印 tf.Tensor
时很少使用以下模式:
t = <
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 = <
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
会被打印。