张量和操作
可以使用tf.constant()创建张量
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity='all'
import tensorflow as tf
tf.constant([[1., 2., 3.], [4., 5., 6.]])
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[1., 2., 3.],
[4., 5., 6.]], dtype=float32)>
像 ndarray 一样,tf.Tensor 具有形状和数据类型(dtype):
t = tf.constant([[1., 2., 3.], [4., 5., 6.]])
t.shape
TensorShape([2, 3])
t.dtype
tf.float32
索引工作的方式也类似于NumPy
t[:, 1:]
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[2., 3.],
[5., 6.]], dtype=float32)>
t[..., 1]
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([2., 5.], dtype=float32)>
t[..., 1, tf.newaxis] # 提取所有行,第一列的数据并增加一个维度 所以形状是(2,1),上面没有增加新的维度形状就是(2,)
<tf.Tensor: shape=(2, 1), dtype=float32, numpy=
array([[2.],
[5.]], dtype=float32)>
可以使用各种张量操作
t+10
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[11., 12., 13.],
[14., 15., 16.]], dtype=float32)>
tf.square(t)
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ 1., 4., 9.],
[16., 25., 36.]], dtype=float32)>
t@tf.transpose(t) # @运算符是矩阵乘法,相当于tf.matmul()函数
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[14., 32.],
[32., 77.]], dtype=float32)>
张量和 NumPy
张量可以与NumPy配合使用:可以使用NumPy数组创建张量,也可以将TensorFlow操作应用于NumPy数组,将NumPy操作应用于张量:
import numpy as np
a=np.array([2.,4.,5.])
tf.constant(a)
<tf.Tensor: shape=(3,), dtype=float64, numpy=array([2., 4., 5.])>
t.numpy()
array([[1., 2., 3.],
[4., 5., 6.]], dtype=float32)
tf.square(a)
<tf.Tensor: shape=(3,), dtype=float64, numpy=array([ 4., 16., 25.])>
np.square(a)
array([ 4., 16., 25.])
类型转换
类型转换会严重影响性能,并且自动完成转换很容易被忽视。为了避免这种情况TensorFlow不会自动执行任何类型转换:如果对不兼容类型的张量执行操作,会引发异常。例如:不能把浮点张量和整数张量相加,甚至不能相加32位浮点和64位浮点
tf.constant(2.0)+tf.constant(40)
---------------------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_12252/3002758296.py in <module>
----> 1 tf.constant(2.0)+tf.constant(40)
InvalidArgumentError: cannot compute AddV2 as input #1(zero-based) was expected to be a float tensor but is a int32 tensor [Op:AddV2]
tf.constant(2.0)+tf.constant(40,dtype=tf.float64)
---------------------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_12252/2939420824.py in <module>
----> 1 tf.constant(2.0)+tf.constant(40,dtype=tf.float64)
InvalidArgumentError: cannot compute AddV2 as input #1(zero-based) was expected to be a float tensor but is a double tensor [Op:AddV2]
需要转换类型时,可以使用tf.cast():
t2=tf.constant(40.,dtype=tf.float64)
tf.constant(2.)+tf.cast(t2,tf.float32)
<tf.Tensor: shape=(), dtype=float32, numpy=42.0>
变量
目前看到的tf.Tensor值是不变的,无法修改它们。不能使用常规张量在神经网络中实现权重,因为它们需要通过反向传播进行调整。另外还可能需要随时间改变其他参数(例如动量优化器跟踪过去的梯度)。这时就需要使用tf.Variable:
v=tf.Variable([[1.,2.,3.],[4.,5.,6.]])
v
<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32, numpy=
array([[1., 2., 3.],
[4., 5., 6.]], dtype=float32)>
tf.Variable的行为和tf.Tensor的行为非常相似:可以使用它执行相同的操作,它在NumPy中也可以很好地发挥作用,并且对类型也很挑剔。但是可以使用assign()方法(或assign_add()或assign_sub(),给变量增加或减少给定值)进行修改。还可以使用切片的的assign()方法或使用scatter_update()或scatter_nd_update()方法来修改单个切片
v.assign(2*v)
v[0,1].assign(42)
v[:,2].assign([0.,1.])
v.scatter_nd_update(indices=[[0,0],[1,2]],updates=[100.,200.])
<tf.Variable 'UnreadVariable' shape=(2, 3) dtype=float32, numpy=
array([[ 2., 4., 6.],
[ 8., 10., 12.]], dtype=float32)>
<tf.Variable 'UnreadVariable' shape=(2, 3) dtype=float32, numpy=
array([[ 2., 42., 6.],
[ 8., 10., 12.]], dtype=float32)>
<tf.Variable 'UnreadVariable' shape=(2, 3) dtype=float32, numpy=
array([[ 2., 42., 0.],
[ 8., 10., 1.]], dtype=float32)>
<tf.Variable 'UnreadVariable' shape=(2, 3) dtype=float32, numpy=
array([[100., 42., 0.],
[ 8., 10., 200.]], dtype=float32)>
其他数据结构
- 稀疏张量(tf.SparseTensor)
有效地表示主要包含零的张量。tf.sparse程序包包含稀疏张量的操作 - 张量数组(tf.TensorArray)
张量的列表。默认情况下,它们的大小是固定的,但可以选择动态设置。它们包含的所有张量必须具有相同的形状和数据类型 - 不规则张量(tf.RaggedTensor)
表示张量列表的静态列表,其中每个张量具有相同的形状和数据类型。tf.ragged程序包包含用于不规则的张量的操作 - 字符串张量
tf.string类型的常规张量。它表示字节字符串,而不是Unicode字符串,因此如果使用Unicode字符串创建字符串张量,则它将被自动编码为UTF-8。或者,可以使用类型为tf.int32的张量来表示Unicode字符串,其中每个项都表示一个Unicode代码点。tf.strings包包含用于字节字符串和Unicode字符串的操作(并将转换为另一个)。重要的是要注意,tf.string是原子级的,这意味着它的长度不会出现在张量的形状当中。一旦将其转换为Unicode张量(即包含Unicode代码点的tf.int32l类型的张量)后,长度就会显示在形状中 - 集合
表示为常见张量(或稀疏张量)。例如,tf.constant([[1,2.],[3.4]])代表两个集合{1,2}和{3,4}。通常,每个集合由张量的最后一个轴上的向量表示。可以使用tf.sets包中的操作来操作集。 - 队列
跨多个步骤存储的张量。TenorFlow提供了各种队列:简单的先进先出(FIFO)队列(FIFOQueue),可以区分某些元素优先级的队列(Priority Queue),将其元素(RandomShuffleQueue)随机排列,通过填充(PaddingFIFOQueue)批量处理具有不同形状的元素。这些类都在tf.queue包中。