1.张量
1.1张量的概念
张量:是具有统一类型(称为dtype)、不可变的多维数组。可以分三种分类:
- 标量,只有一个值
- 矢量,一个数组
- 矩阵,多维数组
#标量
rank_0_tensor = tf.constant(4)
print(rank_0_tensor)
#矢量
rank_1_tensor = tf.constant([2.0, 3.0, 4.0])
print(rank_1_tensor)
#矩阵
rank_2_tensor = tf.constant([[1, 2],
[3, 4],
[5, 6]], dtype=tf.float16)
print(rank_2_tensor)
注意shape,以后的创建模型中,经常用到。
比如三维数组的shape如下:
rank_3_tensor = tf.constant([
[[0, 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]],])
print(rank_3_tensor)
张量的几个特征:
- Shape:一个张量各维的长度
- Rank:张量的维度,如标量为0,向量为1,矩阵为2
- Axis 或 Dimension:张量的一个特定维度
- Size:张量的条目数量
import tensorflow as tf
rank_4_tensor = tf.zeros([3, 2, 4, 5])
print("数据类型:", rank_4_tensor.dtype)
print("维数量:", rank_4_tensor.ndim)
print("形状:", rank_4_tensor.shape)
print("Elements along axis 0 of tensor:", rank_4_tensor.shape[0])
print("Elements along the last axis of tensor:", rank_4_tensor.shape[-1])
print("总元素数量 (3*2*4*5): ", tf.size(rank_4_tensor).numpy())
轴(Axis)经常用索引(和python的list索引一样,从0开始)引用,了解每个轴的含义很重要。通常轴线的顺序是从全局到局部的:先是批量轴线,然后是空间维度,最后是每个位置的特征。这种方式的特征向量是在内存中是连续的区域。
1.2张量的特性
1.2.1转换为numpy数组
rank_2_tensor = tf.constant([[1, 2],
[3, 4],
[5, 6]], dtype=tf.float16)
rank_2_tensor.numpy
1.2.2张量的运算:加、乘、矩阵乘
a = tf.constant([[1, 2],
[3, 4]])
b = tf.constant([[1, 1],
[1, 1]])
#加
print(tf.add(a, b), "\n")
#乘
print(tf.multiply(a, b), "\n")
#矩阵乘
print(tf.matmul(a, b), "\n")
1.2.3其他运算
#求张量的最大值
print(tf.reduce_max(b))
1.3操作shape
1.3.1重塑张量
用tf.reshape重塑张量,由于不需要复制底层数据,操作既快速又便宜。
import tensorflow as tf
rank_3_tensor = tf.constant([[[ 0,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]]])
#张量平展(-1表示到最后)
print(tf.reshape(rank_3_tensor, [1,-1]))
1.3.2数据类型
创建张量时需要通过dtype参数指定数据类型,如果没有指定那么tensorflow会采用默认的数据类型。
1.3广播
广播是借用了numPy中的等效特性的概念。简而言之,在一定条件下,当对较小的张量执行组合操作时,它们会自动“拉伸”以适应较大的张量。 最简单和最常见的情况是,您试图将一个张量乘到或添加到标量中。在这种情况下,标量被广播为与另一个参数相同的形状。
广播在时间和空间上都是有效的,因为广播操作从未在内存中实现扩展张量。
例如:
print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))
broadcast_to与数学运算不同,它不会做任何特殊的事情来节省内存。
矩阵相乘:
import tensorflow as tf
x = tf.constant([1, 2, 3])
x = tf.reshape(x,[3,1])
y = tf.range(1, 5)
print(x, "\n")
print(y, "\n")
print(tf.multiply(x, y))
没有广播的常规操作:
import tensorflow as tf
x_stretch = tf.constant([[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]])
y_stretch = tf.constant([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])
print(x_stretch * y_stretch)
结果:
tf.Tensor([
[ 1 2 3 4]
[ 2 4 6 8]
[ 3 6 9 12]
], shape=(3, 4), dtype=int32)
1.4 转换为张量
tf.convert_to_tensor可以把python的其他对象转换为张量。
但NumPy的ndarray、TensorShape、Python列表和tf.Variable,都会自动转换。
1.5粗糙张量
维度元素长度不一致的张量,使用tf.ragged.RaggedTensor来表示,如以下是一个4笔长度不一致的数据,用普通张量无法表示,可以用粗糙张量表示。
ragged_list = [
[0, 1, 2, 3],
[4, 5],
[6, 7, 8],
[9]]
ragged_tensor = tf.ragged.constant(ragged_list)
print(ragged_tensor)
1.6字符张量
tf.string是一个dtype,可以在张量中将数据表示为字符串(可变长度的字节数组)。字符串是原子的,不能像Python字符串那样被索引。tf.strings, including tf.strings.split可以对字符张量进行操作。
scalar_string_tensor = tf.constant("Gray wolf")
1.7稀疏张量
有时数据是稀疏的,就像一个非常宽的嵌入空间。TensorFlow支持tf.sparse.SparseTensor及相关操作,可以高效地存储稀疏数据。
如:
sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],
values=[1, 2],
dense_shape=[3, 4])
print(sparse_tensor, "\n")
# 转为稠密矩阵
print(tf.sparse.to_dense(sparse_tensor))
输出:
SparseTensor(indices=tf.Tensor(
[[0 0]
[1 2]], shape=(2, 2), dtype=int64), values=tf.Tensor([1 2], shape=(2,), dtype=int32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64))
tf.Tensor(
[[1 0 0 0]
[0 0 2 0]
[0 0 0 0]], shape=(3, 4), dtype=int32)
2.变量
变量是在程序中推荐使用的代表共享、固定状态信息。TensorFlow使用tf.Variable实例创建、更新和管理变量。tf.Variable表示一个tensor,其值可以通过ops修改。特定的操作允许你读取和修改这个tensor的值。
import tensorflow as tf
#tf.debugging.set_log_device_placement(True)
my_tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]])
my_variable = tf.Variable(my_tensor)
print("形状: ",my_variable.shape)
print("数据类型: ",my_variable.dtype)
print("转换为 NumPy: ", my_variable.numpy)
#重分配值
my_variable.assign([[2.0, 3.0], [5.0, 8.0]])
print(my_variable.numpy)
2.1生命周期
基于python的tensorflow,变量的生命周期和python对象的生命周期一样。当没有对变量的引用时,它会自动释放。
2.2变量的名称
在创建变量时,可以通过name属性指定名称,方便跟踪和调试
a = tf.Variable(my_tensor, name="amark")
2.3是否需要参加训练
在创建变量时,可以通过trainable属性指定是否需要参加梯度训练
step_counter = tf.Variable(1, trainable=False)
2.4设置变量在不同设备上是否可见
为了获得更好的性能,TensorFlow将尝试将张量和变量放在与其dtype兼容的最快的设备上。比如,在GPU上,有些变量可见,而在其他设备上不可见。
with tf.device('CPU:0'):
a = tf.Variable([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
b = tf.Variable([[1.0, 2.0, 3.0]])
with tf.device('GPU:0'):
# Element-wise multiply
k = a * b