TensorFlow 基础:Tensor、Shape、Type、Session & Operators
什么是 Tensor?
Tensorflow 的名称直接来源于其核心框架:Tensor。在 Tensorflow 中,所有计算都涉及张量。张量是 n 维的向量或矩阵,表示所有类型的数据。张量中的所有值都具有相同的数据类型,并且形状已知(或部分已知)。数据的形状是矩阵或数组的维度。
张量可以来源于输入数据或计算结果。在 TensorFlow 中,所有操作都在图内进行。图是一系列连续发生的计算。每个操作称为一个 op 节点,它们相互连接。
图描绘了 op 及其节点之间的连接。但是,它不显示值。节点之间的边是张量,即用于填充数据的操作。
在机器学习中,模型通过称为特征向量的对象列表进行输入。特征向量可以是任何数据类型。特征向量通常是填充张量的主要输入。这些值将通过张量流向 op 节点,并且此操作/计算的结果将创建一个新张量,该张量又将用于新操作。所有这些操作都可以在图中查看。
张量表示
在 TensorFlow 中,张量是 n 维特征向量(即数组)的集合。例如,如果我们有一个从 1 到 6 的 2×3 矩阵,我们写道:
TensorFlow 表示此矩阵为
[[1, 2, 3], [4, 5, 6]]
如果我们创建从 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 的 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)
# 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)
可以按如下方式创建 1 维张量:
## Rank 1r1_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 列。
要创建 2 维张量数组,您需要在每行后加上括号。查看下面的 Keras 张量形状示例:
## 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。
通过添加另一个括号级别来构造 3 维矩阵。
## 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 形状属性获取张量的形状。
下面,您构造一个填充了 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 的向量或矩阵。例如,如果您想创建一个形状为 10 的 1D 张量,并用 0 填充,您可以运行以下代码:
# 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 传递到括号中,您可以构造一个等于 m_shape 矩阵列数的全 1 向量。
# 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)
最后,您可以创建一个 3×2 的全 1 矩阵:
print(tf.ones(m_shape.shape))
输出
Tensor("ones_3:0", shape=(3, 2), dtype=float32)
数据类型
张量的第二个属性是数据类型。一个张量一次只能有一种数据类型。您可以为张量返回类型,通过 dtype 属性。
print(m_shape.dtype)
输出
<dtype: '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: 'float32'> <dtype: 'int32'>
在创建张量时未指定参数时,TensorFlow 会自动选择数据类型。TensorFlow 会猜测最可能的数据类型。例如,如果您传递文本,它会猜测是字符串并将其转换为字符串。
创建算子
一些有用的 TensorFlow 算子
您知道如何使用 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.substract(a, b)
- tf.multiply(a, b)
- tf.div(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)
代码解释
创建两个张量
- 一个张量包含 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 matrixtensor_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)
Session
TensorFlow 主要围绕 3 个组件工作:
- 图表
- Tensor
- Session
组件 | 说明 |
---|---|
图表 | 图在 TensorFlow 中是基础。所有数学运算(ops)都在图内进行。您可以将图想象成一个项目,其中所有运算都已完成。节点表示这些 op,它们可以吸收或创建新的张量。 |
Tensor | 张量表示在操作之间传递的数据。您之前已经了解了如何初始化张量。常量和变量之间的区别在于变量的初始值会随时间变化。 |
Session | 会话将执行图中的运算。要用张量的值来填充图,您需要打开一个会话。在会话中,您必须运行一个算子来创建输出。 |
图和会话是独立的。您可以运行一个会话并获取值,以后用于进一步计算。
在下面的示例中,您将:
- 创建两个张量
- 创建运算
- 打开会话
- 打印结果
步骤 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]
代码解释
- 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 的平方。
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.
代码解释
- import numpy as np: 导入 numpy 库来创建数据。
- tf.pow(data_placeholder_a, 2): 创建 op。
- 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 依赖于一种巧妙的方法来渲染操作。所有计算都以数据流方案表示。数据流图是为了查看各个操作之间的数据依赖关系而开发的。数学公式或算法由许多连续的操作组成。图是一种可视化计算如何协调的便捷方法。
图显示一个节点和一个边。节点是操作的表示,即计算单元。边是张量,它可以产生新的张量或消耗输入数据。它取决于各个操作之间的依赖关系。
图的结构将操作(即节点)连接在一起,并显示如何馈送这些操作。请注意,图不显示操作的输出,它只帮助可视化各个操作之间的连接。
让我们看一个例子。
假设您想评估以下函数:
TensorFlow 将创建一个图来执行该函数。图如下所示:
您可以轻松地看到张量到达最终目的地所经过的路径。
例如,您可以看到 add 操作不能在 和 之前完成。图解释说它将:
- 计算 和
- 将 1) 相加
- 将 2) 相加
- 将 3) 加到
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
代码解释
- x: 初始化一个名为 x 的变量,其常量值为 5。
- z: 初始化一个名为 z 的变量,其常量值为 6。
- c: 初始化一个名为 c 的常量张量,其常量值为 5。
- square: 初始化一个名为 square 的常量张量,其常量值为 2。
- f: 构建算子。
在此示例中,我们选择将变量的值固定。我们还创建了一个名为 c 的常量张量,它是函数 f 中的常量参数。它取固定值 5。在图中,您可以在名为 constant 的张量中看到此参数。
我们还为 tf.pow() 算子中的幂创建了一个常量张量。这并非必需。我们这样做是为了让您在图中看到张量的名称。它是名为 square 的圆。
从图中,您可以理解张量将发生什么,以及它如何返回 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 主要围绕
- 图:包含操作和张量的计算环境
- Tensors:表示将在图中流动的数据(或值)。它是图中的边。
- Sessions:允许执行操作。
创建常量张量
常量 | 对象 |
---|---|
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] ]) |
打开会话
Session | 对象 |
---|---|
创建会话 | tf.Session() |
运行会话 | tf.Session.run() |
评估张量 | variable_name.eval() |
关闭会话 | sess.close() |
块内会话 | with tf.Session() as sess |