Tensorflow2.x 中的张量、变量

目录

  • 张量(tensor)
    • 基础知识
      • 创建不同轴数的张量
      • 张量转换为numpy数组
      • 张量的运算
    • 形状术语
    • 索引
    • 重构张量
    • DTypes
    • 广播
    • tf.convert_to_tensor
    • 不规则张量
    • 字符串张量
    • 稀疏张量
  • 变量(Variable)
    • 变量的创建与重构
    • 生命周期、命名
    • 冻结变量
    • 放置变量与张量

张量(tensor)

基础知识

张量是具有统一数据类型的多维数组,与numpy的np.arrays具有相似之处。
张量一旦创建就不可变:永远无法更新张量的内容,只能创建新的张量。

创建不同轴数的张量

创建0-轶张量:
标量称为0-轶张量,具有单个的值。

rank_0_tensor = tf.constant(4)
rank_0_tensor

创建1-轶张量:
向量称为1-轶张量,就像一个列表。

rank_1_tensor = tf.constant([2.0,3.0,4.0])
rank_1_tensor

创建2-轶张量:
矩阵称为2-轶张量。

rank_2_tensor = tf.constant([[1,2],
                             [3,4],
                             [5,6]], dtype=float)
rank_2_tensor

array([[1., 2.],
[3., 4.],
[5., 6.]], dtype=float32)>

更多轴的张量:

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]],
])
rank_3_tensor

对于包含 2 个以上的轴的张量,您可以通过多种方式加以呈现。
Tensorflow2.x 中的张量、变量_第1张图片

张量转换为numpy数组

import numpy as np

np.array(rank_2_tensor)   # 利用np.array()方法
rank_2_tensor.numpy()     # 利用tensor.numpy()方法

张量的运算

您可以对张量执行基本数学运算,包括加法、逐元素乘法和矩阵乘法。

tf.add(a, b)            # 加法
tf.multiply(a, b)       # 元素乘法
tf.matmul(a, b)         # 矩阵乘法

或者:

a + b                   # 加法
a * b                   # 元素乘法
a @ b                   # 矩阵乘法

其他各种运算也可以应用于张量

c = tf.constant([[4.0, 5.0], [10.0, 1.0]])

print(tf.reduce_max(c))         # 找最大值
print(tf.argmax(c))             # 最大值的索引
print(tf.nn.softmax(c))         # 归一化

形状术语

张量有形状,下面是几个相关术语:

术语 含义
形状 张量的每个轴的长度(元素数量)
张量轴数。标量秩为0,向量秩为1,矩阵秩为2
轴或维度 张量的某个维度
大小 张量的元素总数

虽然通常用索引来指代轴,但是您始终要记住每个轴的含义。轴一般按照从全局到局部的顺序进行排序:首先是批次轴,随后是空间维度,最后是每个位置的特征。这样,在内存中,特征向量就会位于连续的区域。
Tensorflow2.x 中的张量、变量_第2张图片

索引

tensorflow遵从python索引规则:

  • 索引从0开始
  • 负索引表示按倒序索引
  • 冒号:用于切片 start : end :step
  • 多轴索引 tensor[ : , : ]

重构张量

通过重构可以改变张量的形状。重构的速度很快,资源消耗很低,因为不需要复制底层数据。

tensor = tf.constant([[1],[2],[3]])
tensor       # 创建张量

将tensor从3*1 改为1*3

reshaped = tf.reshape(tensor, [1,3])
reshaped

Tensorflow采用“行优先”的内存访问顺序,如果您展平张量,则可以看到它在内存中的排列顺序。

rank_3_tensor

tf.reshape(rank_3_tensor, [-1])

array([ 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])>

Tensorflow2.x 中的张量、变量_第3张图片
注意:重构可以处理总元素个数相同的任何新形状,但是如果不遵从相邻轴的规则,没有意义。

Tensorflow2.x 中的张量、变量_第4张图片

DTypes

创建 tf.Tensor 时,您可以选择指定数据类型。
如果不指定,TensorFlow 会选择一个可以表示您的数据的数据类型。TensorFlow 将 Python 整数转换为 tf.int32,将 Python 浮点数转换为 tf.float32。另外,当转换为数组时,TensorFlow 会采用与 NumPy 相同的规则。

使用 Tensor.dtype 属性可以检查 tf.Tensor 的数据类型。

the_f64_tensor = tf.constant([2.2, 3.3, 4.4], dtype=tf.float64)
the_f16_tensor = tf.cast(the_f64_tensor, dtype=tf.float16)
the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8)
print(the_u8_tensor)

tf.Tensor([2 3 4], shape=(3,), dtype=uint8)

广播

在一定条件下,对一组张量执行组合运算时,为了适应大张量,会对小张量进行“扩展”。
(和R语言中的循环补齐,Numpy中的等效功能相似)

tf.convert_to_tensor

Tensorflow会在非张量参数上自动调用 convert_to_tensor,以此完成针对tensor的运算。

不规则张量

不规则张量:某个轴上元素个数可变的张量,使用> tf.ragged/RaggedTensor
Tensorflow2.x 中的张量、变量_第5张图片

ragged_list = [
    [0,1,2,3],
    [4,5],
    [6,7,8],
    [9]
]

# 创建不规则张量
ragged_tensor = tf.ragged.constant(ragged_list)
ragged_tensor

tf.RaggedTensor 的形状将包含一些具有未知长度的轴:

ragged_tensor.shape

TensorShape([4, None])

字符串张量

在张量中,你可以用字符串来表示数据,数据类型为df.string

字符串是原子类型,无法像 Python 字符串一样编制索引。字符串的长度

scalar_string_tensor = tf.constant("Marlowe")
scalar_string_tensor

如果传递 Unicode 字符,则会使用 utf-8 编码:

tf.constant("")

常用的字符串函数

函数 作用
tf.strings.split 字符串分割
tf.string.to_number 字符串转换为数值型数据
tf.cast 虽然不能用tf.cast转换为数值型,但可以先转换为字节(tf.unit8),再转换为数值
tf.io 该模块包含在数据与字节类型之间进行相互转换的函数,包括解码图像和解析csv

稀疏张量

为了高效存储稀疏数据,TensorFlow 支持 tf.sparse.SparseTensor 和相关运算。
Tensorflow2.x 中的张量、变量_第6张图片

# 创建稀疏张量
sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],
                                       values=[1, 2],
                                       dense_shape=[3, 4])
print(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.sparse.to_dense() 将稀疏变量转换为密集变量。

print(tf.sparse.to_dense(sparse_tensor))

tf.Tensor(
[[1 0 0 0]
[0 0 2 0]
[0 0 0 0]], shape=(3, 4), dtype=int32)

变量(Variable)

Tensorflow中通过 tf.Variable 创建与操控变量。
变量可以是各种类型的数据,像张量一样。

变量的创建与重构

创建变量:

# 创建变量
import tensorflow as tf

my_tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]])
my_variable = tf.Variable(my_tensor)

bool_varible = tf.Variable([False,False,False,True])
complex_varible = tf.Variable([5+4j,6+1j])

与张量类似,变量也有 dtype 和形状,并且可以导出至 NumPy

print("Shape:", my_variable.shape)
print("DType:", my_variable.dtype)
print("As numpty:", my_variable.numpy)

Shape: (2, 2)
DType:
As numpty: array([[1., 2.],
[3., 4.]], dtype=float32)>>

大部分适用于tensor的运算,也适用于变量。需要注意的是,变量无法重构形状 ,当调用 reshape()方法时,创建了一个新的变量,而非重构原始变量。

assign()函数可以重新分配变量(改变变量的值),但 assign() 只能在原始变量上操作,而不会创建新变量。

a = tf.Variable([2.0,3.0])
# 改变变量的值,可以
a.assign([1, 2]) 

# 改变形状+变量的值,不行
try:
  a.assign([1.0, 2.0, 3.0])
except Exception as e:
  print(f"{type(e).__name__}: {e}")

ValueError: Cannot assign to variable Variable:0 due to variable shape (2,) and value shape (3,) are incompatible

复制变量意味着创建新变量,两个变量内存id不同,复制变量不会跟着原始变量的改变而改变。

a = tf.Variable([2,3])
b = tf.Variable(a)

print("a:",a.assign_add([4,5]).numpy())
print("b:",b)

a: [6 8]
b:

生命周期、命名

tf.Variable 与其他python对象的声明周期相同,若不使用,则自动回收。
可以为变量命名,两个变量可以使用相同的名称;若不命名,Tensorflow默认为每个变量分配唯一的变量名。

a = tf.Variable(my_tensor, name="Mark")
b = tf.Variable(my_tensor+1, name="Mark")

print(a==b)

tf.Tensor(
[[False False]
[False False]], shape=(2, 2), dtype=bool)

冻结变量

名词解释:

冻结变量,指的是在训练模型时,控制该变量不被优化器更新。即仅参与前向loss计算,不参与后向传播,一般用于模型的finetuning等场景。

方式:在创建变量时,将 trainable 设置为 False

ice_variable = tf.Variable(1, trainable=False)

放置变量与张量

为提高性能,Tensorflow会尝试将张量与变量放在与其dtype兼容的最快设备上(这意味着大部分变量都在GPU上),不过你也可以重写变量的位置。
ps:通过打开设备分配日志记录(这里不作讨论),可以查看变量的位置。

指定变量在CPU上:

with tf.device('CPU:0'):

  # Create some tensors
  a = tf.Variable([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
  c = tf.matmul(a, b)

print(c)

您可以将变量或张量的位置设置在一个设备上,然后在另一个设备上执行计算。但这样会产生延迟,因为需要在两个设备之间复制数据。

你可能感兴趣的:(深度学习,tensorflow)