快速了解 TensorFlow 基础 (三) 数据类型

TensorFlow 的内部数据保存在张量(Tensor)对象上, 所有的运算操作(Operation, 简称 op)也都是基于张量对象进行的. 复杂的神经网络算法本质上就是各种张量相乘、相加等基本运算操作的组合.

数据类型

数据类型分为 数值类型, 字符串类型, 布尔类型.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# float, str, bool 类型(python 内置)
n = 1.2
s = 'Hello Tensor'
b = True

# 数值类型
n1 = tf.constant(1.2, name='n1')
n2 = tf.constant([1, 2, 3.0], name='n2')
n3 = tf.constant([[1, 2], [3, 4.0]], name='n3')

# 字符串类型
s1 = tf.constant('Hello TensorFlow!')
s2 = tf.strings.lower(s1)

# 布尔类型
b1 = tf.constant(True)
b2 = tf.constant([False, False, True])

# numpy.ndarray 类型
np1 = c.numpy()

获取变量的类型 type(v), 判断变量是否是 TensorFlow 类型 tf.is_tensor(v), 获取 TensorFlow 变量的形状 v.shape

张量的类型

  • Scalar 标量: 普通实数数字, Dimension 维度为 0, Shape 为 []
  • Vector 向量: n 个实数有序集合, 维度为 1, Shape 为 [n]
  • Matrix 矩阵: m 行 ✖ n 列实数有序集合, 维度为 2, Shape 为 [m,n]
  • Tensor 张量: 维度 >2 的实数有序集合数组. 比如图片张量 Shape 为 [数量,高,宽,通道数].

其中, Scalar Vector 和 Matrix 都看作是 Tensor 的特殊情况.

张量类型的应用

  • 标量: Loss 误差值, Accuracy 准确度, Precision 精度, Recall 召回率, Step 训练步数,
  • 向量: 𝒃 偏置向量.
  • 矩阵: shape[b,v] b 样本数(Batch size), v 特征长度.
  • 3 维张量: shape[b,d,v], b 样本数, d 天数, v 特征长度. 多种商品(A,B,..)连续天数(60 天)内不同指标(价格,销量..)的张量.
  • 4 维张量: shape[b,h,w,c], b 样本数, h 高度, w 宽度, c 通道数. 图片张量.

张量数值类型的精度

1
2
3
4
5
6
# 指定精度为 int32
i32 = tf.constant([1, 2, 3], dtype=tf.int32)
# 指定精度为 float32
f32 = tf.constant([1, 2, 3], dtype=tf.float32)
# 转换 int32 精度到 int64
i64 = tf.cast(i32, tf.int64)

一般情况, 使用 int32, float32 就可以满足大部分计算需求. 如需要高精度运算时候, 再使用 int64, float64.

获取变量精度 v.dtype, 判断精度 if v.dtype != tf.int32:

待优化张量

为了区分需要计算梯度信息的张量与不需要计算梯度信息的张量, TensorFlow 增加了一种专门的数据类型来支持梯度信息的记录: tf.Variable.

tf.Variable 类型在普通的张量类型基础上添加了 name, trainable 等属性来支持计算图的构建. 由于梯度运算会消耗大量的计算资源, 而且会自动更新相关参数, 对于不需要的优化的张量, 如神经网络的输入 𝑿, 不需要通过 tf.Variable 封装; 相反, 对于需要计算梯度并优化的张量, 如神经网络层的 𝑾𝒃, 需要通过 tf.Variable 包裹以便 TensorFlow 跟踪相关梯度信息.

1
2
pos = tf.constant([[-1, 0], [1, 2]])
p1 = tf.Variable(pos, name='pos')

获取待优化张量的名称 v.name, 获取张量是否启用了优化 v.trainable.

张量的创建

张量可以与 np.ndarray, list 直接相互转换.

1
2
3
4
5
6
7
8
9
10
# 显示转换类型
tf.convert_to_tensor(np.ndarray)
tf.convert_to_tensor(list)
# 或直接声明 tf.constant
tf.constant(np.ndarray)
tf.constant(list)
# 转换成 np.ndarray
tf.Tensor.numpy()
# 转换成 list
tf.Tensor.numpy().tolist()

需要注意的是, list 转换后的数据一般情况默认为 tf.float32, np.ndarray 转换后的数据默认为 tf.float64.

全 0, 全 1, 自定义值

全 0 张量 tf.zeros(shape), 其中 shape 为 [] Scalar, [n] Vector, [m,n] Matrix, [m,n,u,v] Tensor, s.shape 来源于其他 Tensor 张量

全 1 张量 tf.ones(shape), 与全 0 张量类似.

复制张量 shape 创建全 0 张量 tf.zeros_like(s)tf.zeros(s.shape), 全 1 张量 tf.ones_like(s)tf.ones(s.shape).

自定义值 tf.fill(shape, v), 张量形状来源于 shape, 默认值全部以实数 v 填充.

基于已知分布创建张量

正态分布(Normal Distribution, 又称为高斯分布 Gaussian Distribution) 一般用作 𝑾 的初始采样, 均匀分布(Uniform Distribution) 一般用作 𝒛 的初始采样.

基于正态分布创建张量: tf.random.normal(shape, mean=0.0, stddev=1.0) 可以创建形状为 shape, 均值为 mean, 标准差为 stddev 的正态分布 𝒩(mean, stddev2).

基于均匀分布创建张量: tf.random.uniform(shape, minval=0, maxval=None, dtype=tf.dtype), 可以创建形状为 shape, 区间为 [minval, maxval), 值类型为 dtype 的张量.

创建张量序列(向量)

通过 tf.range(start=0, limit=len, delta=1) 创建 start 为起点 delta 为步长的 limit 个数组成的序列. start 默认为 0, delta 默认为 1.

索引与切片

使用索引取值 v[m][n]..v[m,n,...]

1
2
3
4
5
6
7
8
9
10
# 创建 4D 图片张量
t = tf.random.normal([100,32,32,3])
# 第一张图片 shape [32,32,3]
t[0]
# 第一张图片的第一行像素点集合 shape [32,3]
t[0][0] 或 t[0,0]
# 第一张图片的第一行, 第一列像素点 shape [3]
t[0][0][0] 或 t[0,0,0]
# 第一张图片的第一行, 第一列像素点, R 通道 shape []
t[0][0][0][0] 或 t[0,0,0,0]

使用切片截取一个范围 v[start:end:step], start 默认 0, end 默认 len, step 默认 1, 可以选择性省略, 全省略情况 :: 可以简写成 :. 其中切片截取不包含 end 位置值, 即为 [start,end). step 为负数表示逆序.

1
2
3
4
5
6
# 创建 4D 图片张量
t = tf.random.normal([100,32,32,3])
# 第一张, 第二张图片
t[0:2] 或 t[0:2:1]
# 第一张, 第二张图片 隔行采样缩放
t[0:2,0:32:2,0:32:2,:]

可以使用 ... 省略多个 : 全切片采样的维度, 避免出现 [:,:,:,0] 这样的情况.

Donate - Support to make this site better.
捐助 - 支持我让我做得更好.