TensorFlow 中的张量是什么?形状、类型和特性 Opera职权范围

⚡ 智能摘要

张量是 TensorFlow 所有计算都会读取和写入的 n 维数组,每个张量都包含名称、形状和数据类型。本教程将构建常量、变量、占位符和运算符,然后在会话中对它们进行求值。

  • 🔘 三个特性: 每个 tf.Tensor 对象都公开一个唯一的名称、一个形状和一个数据类型。
  • ☑️ 四种张量类型: tf.constant、tf.Variable、tf.placeholder 和 tf.SparseTensor 涵盖了经典 API。
  • 等级等于嵌套: 每增加一对括号,形状元组就会增加一个维度。
  • 🧪 延期评估: 打印一个操作时,显示的是它的定义,而不是它的值,直到会话运行它为止。
  • 🛠️ 图表和会话: 该图表保存着会话执行操作并返回结果时所进行的操作。
  • ⚠️ 版本说明: 会话和占位符属于 TensorFlow 1.x,目前位于 tf.compat.v1 下。

TensorFlow 基础知识:张量、形状、类型、会话和 Opera职权范围

什么是张量?

拼音作为的姓名 TensorFlow TensorFlow 的核心对象是张量,它直接衍生自张量。在 TensorFlow 中,所有计算都涉及张量。张量是一个 n 维向量或矩阵,可以表示所有类型的数据。张量中的所有值都具有相同的数据类型,并且具有已知(或部分已知)的形状,而数据的形状就是矩阵或数组的维度。

张量可以来源于输入数据,也可以来源于计算结果。在TensorFlow中,所有操作都在一个图中执行。该图是一系列按顺序进行的计算。每个操作称为一个操作节点(op node),节点之间相互连接。

该图概述了运算及其节点间的连接,但并未显示具体值。节点间的边代表张量,即一种向运算中填充数据的方法。

在机器学习中,模型会接收一个称为特征向量的对象列表作为输入。特征向量可以是任何数据类型,它通常是填充张量的主要输入。这些值通过张量流入操作节点,该操作的结果会创建一个新的张量,而这个新张量又会用于下一个操作。所有这些操作都可以在图中查看。

张量的表示

在 TensorFlow 中,张量是 n 维特征向量(即数组)的集合。例如,如果我们有一个 2×3 的矩阵,其值从 1 到 6,我们可以将其写成如下所示的矩阵:

二乘三矩阵,数值从一到六用括号表示。

TensorFlow 将此矩阵表示为:

[[1, 2, 3], 
   [4, 5, 6]]

如果我们创建一个取值范围为 1 到 8 的三维矩阵,那么相同的数据就可以用一个由两个堆叠面组成的方框来表示:

三维张量以方框的形式表示,其两个堆叠面上的值分别为 1 到 8。

TensorFlow 将此矩阵表示为:

[ [[1, 2],  
       [[3, 4],  
       [[5, 6],  
       [[7,8] ]

注:张量可以用标量表示,也可以具有三维以上的维度。只是高维张量更难可视化。

张量的类型

在 TensorFlow 中,所有计算都通过一个或多个张量进行。tf.Tensor 是一个具有三个属性的对象:

  • 唯一标签(名称)
  • 尺寸(形状)
  • 数据类型 (dtype)

使用 TensorFlow 执行的每个操作都涉及对张量的操作。您可以创建四种主要的张量类型:

  • tf.Variable
  • tf.constant
  • tf.placeholder
  • tf.SparseTensor

在本教程中,您将学习如何创建一个 tf.constant 配备 tf.Variable.

在运行代码之前,请记住一点:本教程遵循 TensorFlow 1.x 的原始 API,其中先构建计算图,然后在会话中执行。TensorFlow 2 默认采用即时执行,因此下面的一些符号已被移动或删除。但它们仍然可以通过以下方式访问: tf.compat.v1 命名空间,该表将每个命名空间映射到其现代对应物。

TensorFlow 1.x 符号 TensorFlow 2 等效版本
tf.placeholder() 无需。积极执行即可。 Python 或者直接使用 NumPy 值,以及 tf.function 该参数在图形模式下起着相同的作用。
tf.Session()sess.run() 直接调用该操作并读取结果,或者将计算过程封装起来。 tf.function.
tf.get_variable() tf.Variable(),平铺 Python 对象 trac将变量而非集合视为国王。
tf.global_variables_initializer() 不需要。 tf.Variable 在创建时立即初始化。
tf.div() tf.divide()另请注意子程序traction op 的拼写是 tf.subtract(),不 tf.substract().

在开始学习本教程之前,请确保已激活安装了 TensorFlow 的 conda 环境。该环境名为 hello-tf。

对于 macOS 用户:

source activate hello-tf

对于 Windows 用户:

activate hello-tf

完成上述步骤后,就可以导入 TensorFlow 了。

# Import tf
import tensorflow as tf

创建 n 维张量

首先创建一个具有一维的张量,即标量。

要创建张量,您可以使用 tf.constant() 如下面的 TensorFlow 张量形状示例所示:

tf.constant(value, dtype, name = "")
arguments

- `value`: Value of n dimension to define the tensor. Optional
- `dtype`: Define the type of data:    
    - `tf.string`: String variable    
    - `tf.float32`: Float variable    
    - `tf.int16`: Integer variable
- "name": Name of the tensor. Optional. By default, `Const_1:0`

要创建维度为 0 的张量,请运行以下代码。

## rank 0
# Default name
r1 = tf.constant(1, tf.int16) 
print(r1)			

输出

Tensor("Const:0", shape=(), dtype=int16)

如下带注释的版本所示,该输出的三个部分分别对应于三个张量属性。

张量输出带有标注,标明名称、形状和数据类型。

您还可以使用以下方式为张量指定一个自定义名称: name 论据。

# Named my_scalar
r2 = tf.constant(1, tf.int16, name = "my_scalar") 
print(r2)

输出

Tensor("my_scalar:0", shape=(), dtype=int16)

每个张量都以其张量名称显示。每个张量对象都由诸如唯一标签(名称)、维度(形状)和 TensorFlow 数据类型(dtype)等属性定义。

您可以通过更改数据类型来定义具有十进制值或字符串的张量。

# Decimal
r1_decimal = tf.constant(1.12345, tf.float32)
print(r1_decimal)
# String
r1_string = tf.constant("Guru99", tf.string)
print(r1_string)

输出

Tensor("Const_1:0", shape=(), dtype=float32)
Tensor("Const_2:0", shape=(), dtype=string)

可以按如下方式创建一维张量:

## Rank 1
r1_vector = tf.constant([1,3,5], tf.int16)
print(r1_vector)
r2_boolean = tf.constant([True, True, False], tf.bool)
print(r2_boolean)

输出

Tensor("Const_3:0", shape=(3,), dtype=int16)
Tensor("Const_4:0", shape=(3,), dtype=bool)

您可以注意到 TensorFlow 形状仅由 1 列组成。

要创建一个二维张量数组,需要在每一行之后加上右括​​号。请查看下面的张量形状示例。

## Rank 2
r2_matrix = tf.constant([ [1, 2],
                          [3, 4] ],tf.int16)
print(r2_matrix)

输出

Tensor("Const_5:0", shape=(2, 2), dtype=int16)

该矩阵有 2 行 2 列,分别填充了值 1、2、3 和 4。

通过添加另一层括号,可以构造一个三维矩阵。

## Rank 3
r3_matrix = tf.constant([ [[1, 2],
                           [3, 4], 
                           [5, 6]] ], tf.int16)
print(r3_matrix)

输出

Tensor("Const_6:0", shape=(1, 3, 2), dtype=int16)

结果与本教程前面所示的三维盒状图相符。

张量的形状

当你打印一个张量时,TensorFlow 会推断其形状。但是,你也可以直接使用 TensorFlow 读取其形状。 shape 属性。

下面,你需要构建一个包含 10 到 15 之间数字的矩阵,并检查其形状。 m_shape.

# Shape of tensor
m_shape = tf.constant([ [10, 11],
                        [12, 13],
                        [14, 15] ]                      
                     ) 
m_shape.shape

输出

TensorShape([Dimension(3), Dimension(2)])

该矩阵有 3 行、2 列。

TensorFlow 有一些有用的命令来创建一个用 0 或 1 填充的向量或矩阵。例如,如果你想创建一个特定形状为 1 、用 10 填充的一维张量,你可以运行以下代码:

# Create a vector of 0
print(tf.zeros(10))

输出

Tensor("zeros:0", shape=(10,), dtype=float32)

该属性也适用于矩阵。这里,您创建一个 10×10 的矩阵,其中所有元素均为 1。

# Create a vector of 1
print(tf.ones([10, 10]))

输出

Tensor("ones:0", shape=(10, 10), dtype=float32)

你可以利用给定矩阵的形状构造一个全为 1 的向量。该矩阵 m_shape 具有 3×2 维度,因此以下代码创建一个包含 3 行且全部填充为 1 的张量:

# Create a vector of ones with the same number of rows as m_shape
print(tf.ones(m_shape.shape[0]))

输出

Tensor("ones_1:0", shape=(3,), dtype=float32)

如果将值 1 传递给括号,则会构造一个全为 1 的向量,其值等于矩阵的列数。 m_shape.

# Create a vector of ones with the same number of column as m_shape
print(tf.ones(m_shape.shape[1]))

输出

Tensor("ones_2:0", shape=(2,), dtype=float32)

最后,你可以创建一个完全由 1 填充的 3×2 矩阵。

print(tf.ones(m_shape.shape))

输出

Tensor("ones_3:0", shape=(3, 2), dtype=float32)

资料类型

张量的第二个属性是数据类型。一个张量一次只能存储一种类型的数据,并且你可以用以下方式读取该类型的数据: dtype 属性。

print(m_shape.dtype)

输出

<dtype: &#x27;int32'>

有时,您需要更改数据类型。在 TensorFlow 中,这可以通过以下方式实现: tf.cast 方法。

例如:

下面,浮点张量被转换为整数。 cast 方法。

# Change type of data
type_float = tf.constant(3.123456789, tf.float32)
type_int = tf.cast(type_float, dtype=tf.int32)
print(type_float.dtype)
print(type_int.dtype)

输出

<dtype: &#x27;float32'>
<dtype: &#x27;int32'>

如果在创建张量时未指定数据类型参数,TensorFlow 会自动选择数据类型。TensorFlow 会猜测最可能的数据类型:例如,如果您传递文本,它会推断为字符串。

创造 Opera器

一些有用的 TensorFlow Opera职权范围

您已经了解如何使用 TensorFlow 创建张量。现在是时候学习如何执行数学运算了。

TensorFlow 包含了所有基本操作。你可以从一个简单的操作入手,使用 TensorFlow 方法计算一个数的平方根。这个操作很简单,因为构建张量只需要一个参数。

一个数的平方根是用以下方法构造的: tf.sqrt(x)其中 x 为浮点数。

x = tf.constant([2.0], dtype = tf.float32)
print(tf.sqrt(x))

输出

Tensor("Sqrt:0", shape=(1,), dtype=float32)

注意:输出结果是一个张量对象,而不是 2 的平方根。在本例中,您打印的是张量的定义,而不是运算的实际结果。在下面的“会话”部分,您将学习 TensorFlow 如何执行这些运算。

以下列出一些常用操作。其原理相同:每个操作都需要一个或多个参数。

  • tf.add(a, b)
  • tf.subtract(a, b)
  • tf.multiply(a, b)
  • tf.divide(a, b)
  • tf.pow(a, b)
  • tf.exp(a)
  • tf.sqrt(a)

例如:

# Add
tensor_a = tf.constant([[1,2]], dtype = tf.int32)
tensor_b = tf.constant([[3, 4]], dtype = tf.int32)

tensor_add = tf.add(tensor_a, tensor_b)
print(tensor_add)

输出

Tensor("Add:0", shape=(1, 2), dtype=int32)

Code 说明

创建两个张量:

  • 一个张量,分别为 1 和 2
  • 一个张量,分别为 3 和 4

将两个张量相加。

请注意,两个张量必须具有相同的形状。您还可以对这两个张量执行乘法运算。

# Multiply
tensor_multiply = tf.multiply(tensor_a, tensor_b)
print(tensor_multiply)

输出

Tensor("Mul:0", shape=(1, 2), dtype=int32)

变量

到目前为止,你只创建了常量张量,这本身用途有限。数据总是以不同的值到达,为了捕捉这种变化,你可以使用 Variable 类。变量表示一个节点,其值随时间变化。

要创建变量,您可以使用 tf.get_variable() 方法。

tf.get_variable(name = "", values, dtype, initializer)
argument
- `name = ""`: Name of the variable
- `values`: Dimension of the tensor
- `dtype`: Type of data. Optional
- `initializer`: How to initialize the tensor. Optional
If initializer is specified, there is no need to include the `values` as the shape of `initializer` is used.

例如,以下代码创建了一个包含两个随机值的二维变量。默认情况下,TensorFlow 返回一个随机值。您可以将变量命名为 var。

# Create a Variable
## Create 2 Randomized values
var = tf.get_variable("var", [1, 2])
print(var.shape)

输出

(1, 2)

在这个例子中,你创建了一个包含一行两列的变量,因此你将 [1, 2] 作为变量的维度传递。

张量的初始值也可以为零。例如,在训练模型时,需要在计算特征权重之前设置初始值。下面,我们将这些初始值设置为零。

var_init_1 = tf.get_variable("var_init_1", [1, 2], dtype=tf.int32,  initializer=tf.zeros_initializer)
print(var_init_1.shape)

输出

(1, 2)

您还可以将常量张量的值传递给变量。您可以使用以下方法创建常量张量: tf.constant() 并使用该张量初始化变量。

该变量的前几个值为 10、20、30 和 40。新张量的形状为 2×2。

# Create a 2x2 matrix
tensor_const = tf.constant([[10, 20],
[30, 40]])
# Initialize the first value of the tensor equals to tensor_const
var_init_2 = tf.get_variable("var_init_2", dtype=tf.int32,  initializer=tensor_const)
print(var_init_2.shape)

输出

(2, 2)

占位符

占位符的作用是为张量提供数据。占位符初始化将流入张量的数据。要提供占位符,您可以使用…… feed_dict 参数,占位符仅在会话内提供。

在下一个示例中,您将看到如何使用该方法创建占位符。 tf.placeholder在“会话”部分,您将学习如何向占位符提供实际的张量值。

语法是:

tf.placeholder(dtype,shape=None,name=None )
arguments:
- `dtype`: Type of data
- `shape`: dimension of the placeholder. Optional. By default, shape of the data
- `name`: Name of the placeholder. Optional			
data_placeholder_a = tf.placeholder(tf.float32, name = "data_placeholder_a")
print(data_placeholder_a)

输出

Tensor("data_placeholder_a:0", dtype=float32)

时间

TensorFlow 围绕 3 个主要组件运行:

  • 图表
  • 张量
  • 时间
组件 描述
图表 图是 TensorFlow 的基础。所有数学运算(操作)都在图中执行。您可以将图想象成一个项目,所有操作都在其中进行。节点代表这些操作,它们可以吸收或创建新的张量。
张量 张量表示操作之间不断变化的数据。您之前已经了解了如何初始化张量。常量和变量的区别在于,变量的初始值会随时间变化。
时间 会话用于执行图中的操作。要将张量的值输入到图中,需要打开一个会话。在会话中,必须运行一个运算符才能生成输出。

图表和会话是相互独立的。您可以运行一个会话,并将值保存下来以供后续计算。

在下面的示例中,您将:

  • 创建两个张量
  • 创建操作
  • 打开一个会话
  • 打印结果

步骤 1)创建两个张量 x 和 y

## Create, run  and evaluate a session
x = tf.constant([2])
y = tf.constant([4])

步骤 2)通过将 x 和 y 相乘来创建运算符。

## Create operator
multiply = tf.multiply(x, y)

步骤 3)打开一个会话。所有计算都在会话内进行,完成后需要关闭会话。

## Create a session to run the code
sess = tf.Session()
result_1 = sess.run(multiply)
print(result_1)
sess.close()

输出

[8]

Code 解释

  • tf.Session()打开一个会话。所有操作都在会话内进行。
  • run(multiply)执行步骤 2 中创建的操作
  • print(result_1)最后,您可以打印结果。
  • close()关闭会话

结果显示8,即x与y的乘积。

另一种创建会话的方法是在一个代码块内。它的优点是会自动关闭会话。

with tf.Session() as sess:
    result_2 = multiply.eval()
print(result_2)

输出

[8]

在会话的上下文中,您可以使用 eval() 执行操作的方法。它等价于 run() 并使代码更易读。

您可以创建一个会话并查看迄今为止创建的张量内的值。

## Check the tensors created before
sess = tf.Session()
print(sess.run(r1))
print(sess.run(r2_matrix))
print(sess.run(r3_matrix))

输出

1
[[1 2] 
 [3 4]]
[[[1 2]  
  [3 4]  
  [5 6]]]

变量默认为空,即使在创建张量之后也是如此。您需要先初始化变量才能使用它。 tf.global_variables_initializer() 调用此函数可以一次性初始化所有变量的值,这在训练模型之前很有帮助。

您可以查看之前创建的变量的值。请注意,您需要使用 run 函数来评估张量。

sess.run(tf.global_variables_initializer())
print(sess.run(var))
print(sess.run(var_init_1))
print(sess.run(var_init_2))

输出

[[-0.05356491  0.75867283]]
[[0 0]]
[[10 20] 
 [30 40]]

您可以使用之前创建的占位符,并为其赋一个实际值。您需要将数据传递给 feed_dict 论据。

例如,您将取占位符 data_placeholder_a 的 2 的幂。

import numpy as np
power_a = tf.pow(data_placeholder_a, 2)
with tf.Session() as sess:
    data = np.random.rand(1, 10)
    print(sess.run(power_a, feed_dict={data_placeholder_a: data}))  # Will succeed.

Code 说明

  • import numpy as np:导入 NumPy的 用于创建数据的库
  • tf.pow(data_placeholder_a, 2)创建操作
  • np.random.rand(1, 10)创建一个随机数据数组
  • feed_dict={data_placeholder_a: data}:向占位符填充数据

输出

[[0.05478134 0.27213147 0.8803037  0.0398424  0.21172127 0.01444725  0.02584014 0.3763949  0.66022706 0.7565559 ]]

图表

TensorFlow 使用数据流图来呈现每个操作。数据流图旨在展现各个操作之间的数据依赖关系。数学公式或算法由一系列连续的操作组成,而图表则是一种便捷的方式来可视化这些计算是如何协调进行的。

该图展示了节点和边。节点代表一个操作,即计算单元。边代表张量:它可以生成新的张量,也可以消耗输入数据,具体取决于各个操作之间的依赖关系。

图的结构将各个操作(即节点)连接起来,并展示了每个操作的输入方式。请注意,该图并不显示操作的输出;它仅用于可视化操作之间的连接。

我们来看一个例子。假设你想计算以下函数的值:

x 和 z 的公式 f 等于 x 乘以 z 加 x² 加 z 加 5

TensorFlow 会构建一个用于执行函数的计算图。该计算图如下所示:

TensorFlow 图,其 X 和 Z 变量节点为 Mul、Pow 和三个加法运算提供输入。

您可以轻松看到张量到达最终目的地所采用的路径。

例如,该 add 节点不能在两者之前运行 MulPow 他们已经得出结果。图表显示 TensorFlow 将:

  1. 计算 x·z Mul 节点和 x² 在 Pow 节点
  2. 将这两个结果加在一起。 add 节点
  3. 将 z 加到该总和中。 add_1 节点
  4. 在公式中加入常数 5 add_2 节点
x = tf.get_variable("x", dtype=tf.int32,  initializer=tf.constant([5]))
z = tf.get_variable("z", dtype=tf.int32,  initializer=tf.constant([6]))
c = tf.constant([5], name =	"constant")
square = tf.constant([2], name =	"square")
f = tf.multiply(x, z) + tf.pow(x, square) + z + c

Code 说明

  • x:用常数值 5 初始化名为 x 的变量
  • z:初始化一个名为 z 的变量,其值为常数 6
  • c:初始化一个名为 c 的常量张量,其值为 5
  • square:用常数值 2 初始化一个名为 square 的常量张量
  • f:构造运算符

在这个例子中,变量的值保持不变。常数张量 c 是函数 f 中的常数参数,其值固定为 5;在图中,你可以看到这个参数位于名为“常数”的张量中。

此外,还为算符中的幂创建了一个常数张量。 tf.pow()这不是必须的,但这意味着指数在图中表现为称为正方形的圆圈。

从图中可以看出张量发生了什么变化,以及为什么函数返回 66:5 × 6 加 5² 加 6 加 5 等于 66。

以下代码在会话中执行函数。

init = tf.global_variables_initializer() # prepare to initialize all variables
with tf.Session() as sess:
    init.run() # Initialize x and y
    function_result = f.eval()
print(function_result)

输出

[66]

TensorFlow 基础知识快速参考

下面四个表格汇总了本教程中使用的所有命令,方便您查找所需命令,而无需返回示例进行浏览。

创建一个常量张量

常数 对象
D0 tf.constant(1, tf.int16)
D1 tf.constant([1,3,5], tf.int16)
D2 tf.constant([ [1, 2], [3, 4] ],tf.int16)
D3 tf.constant([ [[1, 2],[3, 4], [5, 6]] ], tf.int16)

创建运算符

创建运算符 摆件
a + b tf.add(a, b)
a*b tf.multiply(a, b)

创建变量张量

创建变量 对象
随机值 tf.get_variable("var", [1, 2])
初始化第一个值 tf.get_variable("var_init_2", dtype=tf.int32, initializer=[ [1, 2], [3, 4] ])

打开一个会话

时间 对象
创建会话 tf.Session()
运行会话 tf.Session.run()
评估张量 variable_name.eval()
关闭会话 sess.close()
按区块划分的会话 with tf.Session() as sess:

常见问题

后缀是生成该张量的操作的输出索引。Const:0 表示名为 Const 的操作的第一个输出。具有多个输出的操作分别编号为 :0、:1 等。

在立即执行模式下,调用张量的 `numpy()` 方法,或将其传递给 `np.array()`。在本文所示的图会话风格中,`sess.run()` 返回的值已经是一个张量。 NumPy的 数组。

不规则张量可以容纳长度不同的行,这是普通张量无法做到的。它使用 `tf.ragged.constant` 创建,适用于可变长度数据,例如句子,因为将每一行都填充到相同宽度会浪费内存。

TensorFlow 采用广播机制:它从尾部维度开始反向比较形状,并将任意长度为 1 的轴拉伸以匹配。无法以这种方式对齐的形状会抛出 InvalidArgumentError 错误,而不是进行猜测。

TensorFlow 会自动将操作分配到可见的 GPU 上。要强制指定设备,请将代码包裹在 `with tf.device('/GPU:0')` 代码块中。请先使用 `tf.config.list_physical_devices('GPU')` 确认设备已被实际检测到。

两者都存储类型化的n维数据,但张量是不可变的,可以驻留在GPU或TPU上,并且会记录对其执行的操作,以便计算梯度。NumPy数组则不具备这三项特性。

静态类型检查器和形状注释库会将声明的形状与代码中的操作进行比较,并在运行开始前标记不匹配项。编辑器助手会直接显示相同的警告,从而避免了大部分反复试错的情况。ping.

GitHub 副驾驶 建议快速重写会话和占位符代码,并立即执行。请验证每条建议,因为它经常会推荐使用 tf.compat.v1 的 shim,而实际上已经有了真正的 TensorFlow 2 替代方案。

总结一下这篇文章: