Tensor Control

张量形状

形状shape,用来描述张量的大小和数量。张量的形状表示为列表的形式,其中第i个元素表示维度i的大小,列表的长度标书张量的阶(维数)。

形状 维数 示例
0 [] 0-D 0 维张量。标量。
1 [D0] 1-D 形状为 [6] 的 1 维张量。
2 [D0, D1] 2-D 形状为 [4, 3] 的 2 维张量。
3 [D0, D1, D2] 3-D 形状为 [1, 2, 3] 的 3 维张量。
n [D0, D1, … Dn-1] n 维 形状为 [D0, D1, … Dn-1] 的张量。

文档中介绍得更详细。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# show the shape of tensor
import tensorflow as tf

g = tf.Graph()

with g.as_default():
scalar = tf.ones([]) # a scalar / 0-D tensor :1
vector = tf.ones([6]) # a vector with 6 elements: [1,1,1 ,1,1,1]
matrix = tf.ones([2, 3]) # a matrix with 2 rows and 3 columns

with tf.Session() as sess:
# use tf.get_shape()
print("Scalar shape: ",scalar.get_shape(), " value: ", sess.run(scalar))
print("Vector shape: ",vector.get_shape(), " value: ", sess.run(vector))
print("Matrix shape: ",matrix.get_shape(), " value: ", sess.run(matrix))
D:\Anaconda3\Anaconda3_py36\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters


Scalar shape:  ()  value:  1.0
Vector shape:  (6,)  value:  [1. 1. 1. 1. 1. 1.]
Matrix shape:  (2, 3)  value:  [[1. 1. 1.]
 [1. 1. 1.]]

获取张量形状

可以通过查看张量对象的shape属性来获取。

1
vector.shape
TensorShape([Dimension(6)])
1
matrix.shape[1]
Dimension(3)

获取张量的数据类型

查看张量对象的dtype属性。

1
matrix.dtype
tf.float32

改变张量数据类型

tf.cast

1
2
3
4
c = tf.constant([1,9,8,3])
print(c.dtype)
f = tf.cast(c, dtype=tf.float32)
print(f.dtype)
<dtype: 'int32'>
<dtype: 'float32'>

获取张量的阶

tf.rank()

1
tf.rank(scalar)
<tf.Tensor 'Rank:0' shape=() dtype=int32>

张量切片

对于n阶张量,要访问其中某一元素,需要制定n个索引。

:是Python切片语法,也意味着不要变更该维度。可以帮助访问张量的子向量,子矩阵和子张量。

Broadcasting | 广播

tensorflow支持广播,借鉴了Numpy中的做法,Numpy Broadcasting.

数学中,相同形状的张量才能进行元素级的运算,例如相加和等于。由于广播,使得不同形状的张量运算可以像对标量进行运算一样。

当张量被广播时,相当于对张量进行复制,实际上并不复制,广播专门为实现性能优化而设计。

举例,假设你和四个小伙伴,年龄分别为[18, 17, 20, 22, 21],每年年龄+1,模拟这个过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 向量加法
with tf.Graph().as_default():
# method 1
ages = tf.constant([18, 17, 20, 22, 21])
one = tf.constant([1, 1, 1, 1, 1])
new_ages = tf.add(ages, one)

with tf.Session() as sess:
print(new_ages.eval())

# method 2
one_ = tf.constant(1)
new_ages_ = tf.add(ages, one_)

with tf.Session() as sess:
print(new_ages_.eval())
[19 18 21 23 22]
[19 18 21 23 22]

张量变形

可以使用tf.reshape()来改变张量的形状。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np 

arr = np.arange(1, 13).reshape(3, 4)
np.random.shuffle(arr)

with tf.Graph().as_default():
x = tf.constant(arr, dtype=tf.int32) # create a 3x4 matrix/ 2-D tensor
reshaped_4x3_x = tf.reshape(x, [4, 3])
reshaped_2x6_x = tf.reshape(x, [2, 6])
reshaped_3x2x2_x = tf.reshape(x, [3, 2, 2]) # reshape the rank

with tf.Session() as sess:
print("Original matrix (3x4):")
print(x.eval())

print("Reshaped matrix (4x3)")
print(reshaped_4x3_x.eval())

print("Reshaped matrix (2x6)")
print(reshaped_2x6_x.eval())

print("Reshaped matrix (3x2x2)")
print(reshaped_3x2x2_x.eval())
Original matrix (3x4):
[[ 9 10 11 12]
 [ 1  2  3  4]
 [ 5  6  7  8]]
Reshaped matrix (4x3)
[[ 9 10 11]
 [12  1  2]
 [ 3  4  5]
 [ 6  7  8]]
Reshaped matrix (2x6)
[[ 9 10 11 12  1  2]
 [ 3  4  5  6  7  8]]
Reshaped matrix (3x2x2)
[[[ 9 10]
  [11 12]]

 [[ 1  2]
  [ 3  4]]

 [[ 5  6]
  [ 7  8]]]

变量、初始化和赋值

TensorFlow变量初始化不是自动进行的,调用tf.global_variables_initializer()。不初始化就会报错。

1
2
3
4
5
6
7
with tf.Graph().as_default():
v = tf.Variable([3])
with tf.Session() as sess:
try:
sess.run(v)
except tf.errors.FailedPreconditionError as e:
print("Caught excepted error: ", e)
Caught excepted error:  Attempting to use uninitialized value Variable
     [[Node: _retval_Variable_0_0 = _Retval[T=DT_INT32, index=0, _device="/job:localhost/replica:0/task:0/device:CPU:0"](Variable)]]
1
2
3
4
5
6
7
8
9
with tf.Graph().as_default():
v = tf.Variable([3])
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
try:
print(sess.run(v))
except tf.errors.FailedPreconditionError as e:
print("Caught excepted error: ", e)
[3]

assign

要变更变量的值,使用tf.assign()指令,仅仅创建assign指令也不能起作用。和初始化一样,也需要运行赋值指令才能变更变量值。

1
2
3
4
5
6
7
8
9
with tf.Graph().as_default():
v = tf.Variable([3])
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
assignment = tf.assign(v, [9])
print(v.eval()) # the variable has not been changed yet.
sess.run(assignment)
print(v.eval()) # now the variable is updated
[3]
[9]

评估张量

eval()
方法仅在默认 tf.Session 处于活动状态时才起作用。Tensor.eval()会返回一个和张量内容相同的Numpy数组。

仅仅只有占位符的情况下无法进行评估。

1
2
3
4
5
6
with tf.Graph().as_default():
p = tf.placeholder(tf.float32)
t = p+1.0
with tf.Session() as sess:
# t.eval() # this will fail, since the placeholder did not give a value
print(t.eval(feed_dict={p:23.3}) )# this will success, because a value is fed to the placeholder
24.3

举例:模拟投掷两个骰子10次

素材来自这里.

模拟《活着》中富贵儿赌钱投骰子(6个面,点数从1到6)的过程,在模拟中生成一个 10x4 二维张量,其中:

  • 12 均存储一个骰子的一次投掷值。
  • 3 存储同一行中列 12 的值的总和。
  • 4 表示开大开小,若列 3 点数大于7,开大(如用1表示);小于等于7开小(如用0表示)。

例如,第一行中可能会包含以下值:

  • 1 存储 4
  • 2 存储 3
  • 3 存储 7
  • 4 存储 0

要完成此任务,可能需要浏览 TensorFlow 文档

问题
如何随机并分配值给变量?(TensorFlow不支持动态计算图)
如何赋值十次,循环?最后张量结果如何表示?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# import numpy as np
import tensorflow as tf

g = tf.Graph()
with g.as_default():
# 使用随机均匀分布 tf.random_uniform 来模拟投掷 n 次, 不需要循环。
dice1 = tf.Variable(tf.random_uniform([10, 1],
minval=1,
maxval=7,
dtype=tf.int32))

dice2 = tf.Variable(tf.random_uniform([10, 1],
minval=1,
maxval=7,
dtype=tf.int32))

dice_sum = tf.add(dice1, dice2)

seven = tf.constant(7)
# 关于TensorFlow条件控制
# https://www.tensorflow.org/versions/r1.8/api_guides/python/control_flow_ops#Control_Flow_Operations
comp = tf.cast(tf.greater(dice_sum, seven), tf.int32)

# 使用 tf.concat 连接向量,axis=1 水平方向连接
result = tf.concat(values=[dice1, dice2, dice_sum, comp], axis=1)

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

print(result.eval())
[[ 4  4  8  1]
 [ 6  1  7  0]
 [ 5  6 11  1]
 [ 4  2  6  0]
 [ 4  1  5  0]
 [ 5  3  8  1]
 [ 6  2  8  1]
 [ 4  2  6  0]
 [ 4  6 10  1]
 [ 1  3  4  0]]