TensorFlow中操作和传递的主要对象就是张量,在TensorFlor中叫做tf.Tensor,TensorFlow中的张量可以是0阶~n阶,阶也可以称为秩,等级或者n维,定义一个最简单的变量,可以认为是定义一个0阶张量。
TensorFlow中有以下几类特殊张量
以下展示定义0阶变量的过程,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)
以下展示定义1阶变量(也可以理解成就是个列表)的过程:
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)
1阶张量可以通过传递一个索引访问某个数值,例如
my_scalar = cool_numbers[1]
以下展示定义2阶变量的过程,对象至少需要包含一行和一列:
mymat = tf.Variable([[7],[11]], tf.int16) # 1行1列
myxor = tf.Variable([[False, True],[True, False]], tf.bool) # 2行2列
linear_squares = tf.Variable([[4], [9], [16], [25]], tf.int32) # 4行1列
squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32) # 2行2列
rank_of_squares = tf.rank(squarish_squares) # 用tf.rank方法可以获取对象的阶
mymatC = tf.Variable([[7],[11]], tf.int32) # 1行1列
在图像处理过程中,一般会使用许多 4 阶张量,各个维度分别对应批次大小、图像宽度、图像高度和颜色通道,可以用如下方法进行定义:
my_image = tf.zeros([10, 299, 299, 3]) # batch x height x width x color
对于2阶的张量,传递一对儿(两个)数字索引,会返回一个标量,而只传递一个数字索引,则会返回一个矩阵子矢量,例子如下。而对于2阶以上的张量,则可以展开想象,以此类推
my_matrix = tf.Variable([[4,5,7],[2,7,6],[5,9,2],[8,2,5]]) # 4行3列的2阶张量
my_scalar = my_matrix[1, 2] # 返回第1行,第2列的数值:6
my_row_vector = my_matrix[2] # 返回第2行的标量:[5,9,2]
my_column_vector = my_matrix[:, 1] # 返回第1列的标量:[5,7,9,2]
访问一个高阶张量中的子张量(或者子矢量,子标量)的方法,我们称之为Tensor切片,其中冒号“:”是切片语法,意思是“不要碰触该维度”。
张量的形状表示的是每个维度中元素的个数,TensorFlow通过三种符号约定来描述张量的维度:阶,形状,维数,下表描述了3者的关联。而形状可以通过整型 Python 列表/元组或者 tf.TensorShape
表示
阶 | 形状 | 维数 | 示例 |
---|---|---|---|
0 | [] | 0维 | 0 维张量。标量。 |
1 | [D0] | 1维 | 形状为 [5] 的 1 维张量。 |
2 | [D0, D1] | 2维 | 形状为 [3, 4] 的 2 维张量。 |
3 | [D0, D1, D2] | 3维 | 形状为 [1, 4, 3] 的 3 维张量。 |
n | [D0, D1, ... Dn-1] | n维 | 形状为 [D0, D1, ... Dn-1] 的张量。 |
可以通过tf.Tensor对象的shape属性来获取张量的形状,该方法将返回一个TensorShape对象,例如如下代码展示了如果创建大小与给定张量大小相关的张量。
my_matrix = tf.Variable([[4,5,7],[2,7,6],[5,9,2],[8,2,5]]) # 4行3列的2阶张量
zeros_a = tf.zeros(my_matrix.shape) # 返回一个与my_matrix形状相同(4行3列)的张量
zeros_b = tf.zeros(my_matrix.shape[1]) # 返回一个与my_matrix第一行[2,7,6]形状相同的矢量
## zeros_a.shape: (4, 3)
## zeros_b.shape: (3,)
一个张量tf.Tensor只能有一种数据类型,但是可以通过tf.cast方法将tf.Tensor从一种数据类型转换为另一种数据类型,例如:
# 把一个整形常量张量转换为浮点型32位
float_tensor = tf.cast(tf.constant([1, 2, 3]), dtype=tf.float32)
可使用Tensor.dtype属性来查看张量tf.Tensor的数据类型。
用 python 对象创建tf.Tensor时,如果不指定数据类型,TensorFlow 会选择一个可以表示您的数据的数据类型。TensorFlow 会将 Python 整数转型为tf.int32,并将 python 浮点数转型为tf.float32
获得张量的值,直接引用张量的名称是不行的,需要采用张量的Tensor.eval()方法,例如:
myconstant = tf.constant([1, 2, 3])
mytensor = myconstant * myconstant # 这里不是矩阵乘法,而是用两个列表的每个对应元素依次相乘
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(mytensor.eval())
### 打印的结果为[1,4,9]
如果直接采用张量的名称进行打印,则打印的结果为:Tensor("mul:0", shape=(3,), dtype=int32),但这并不是张量的值
另外,需要注意的是,如果采用 placeholder定义了张量,在没有为placeholder
提供值的情况下,无法得到依赖于 placeholder
的张量的值,例如:
p = tf.placeholder(tf.float32)
t = p + 1.0
t.eval() # 由于placeholder并没有获取到值,所以这一条语句会执行失败.
t.eval(feed_dict={p:2.0}) # 因为我们给placeholder喂了数据,因此这条语句可以成功执行