TensorFlow 基础:Tensor、Shape、Type、Session & Operators

什么是 Tensor?

Tensorflow 的名称直接来源于其核心框架:Tensor。在 Tensorflow 中,所有计算都涉及张量。张量是 n 维的向量或矩阵,表示所有类型的数据。张量中的所有值都具有相同的数据类型,并且形状已知(或部分已知)。数据的形状是矩阵或数组的维度。

张量可以来源于输入数据或计算结果。在 TensorFlow 中,所有操作都在图内进行。图是一系列连续发生的计算。每个操作称为一个 op 节点,它们相互连接。

图描绘了 op 及其节点之间的连接。但是,它不显示值。节点之间的边是张量,即用于填充数据的操作。

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

张量表示

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

Representation of a Tensor
张量表示

TensorFlow 表示此矩阵为

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

如果我们创建从 1 到 8 的三维矩阵,则为:

Representation of a Tensor

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)

Create a Tensor of n-Dimension

# 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 依赖于一种巧妙的方法来渲染操作。所有计算都以数据流方案表示。数据流图是为了查看各个操作之间的数据依赖关系而开发的。数学公式或算法由许多连续的操作组成。图是一种可视化计算如何协调的便捷方法。

图显示一个节点和一个。节点是操作的表示,即计算单元。边是张量,它可以产生新的张量或消耗输入数据。它取决于各个操作之间的依赖关系。

图的结构将操作(即节点)连接在一起,并显示如何馈送这些操作。请注意,图不显示操作的输出,它只帮助可视化各个操作之间的连接。

让我们看一个例子。

假设您想评估以下函数:

Graph

TensorFlow 将创建一个图来执行该函数。图如下所示:

TensorFlow Graph example

TensorFlow 图示例

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

例如,您可以看到 add 操作不能在 和 之前完成。图解释说它将:

  1. 计算 和
  2. 将 1) 相加
  3. 将 2) 相加
  4. 将 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