Skip to main content

Command Palette

Search for a command to run...

TensorFlow 2 基础概念语法与常用模块

Updated
3 min read

TensorFlow 2 简介

TensorFlow 是由谷歌在 2015 年 11 月发布的深度学习开源工具,我们可以用它来快速构建深度神经网络,并训练深度学习模型。运用 TensorFlow 及其他开源框架的主要目的,就是为我们提供一个更利于搭建深度学习网络的模块工具箱,使开发时能够简化代码,最终呈现出的模型更加简洁易懂。

2019 年,TensorFlow 推出了 2.0 版本,也意味着 TensorFlow 从 1.x 正式过度到 2.x 时代。根据 TensorFlow 官方 介绍内容 显示,2.0 版本将专注于简洁性和易用性的改善,主要升级方向包括:

  • 使用 Keras 和 Eager Execution 轻松构建模型。
  • 在任意平台上实现稳健的生产环境模型部署。
  • 为研究提供强大的实验工具。
  • 通过清理废弃的 API 和减少重复来简化 API。

当然,如果你对 TensorFlow 1.x 本来就不熟悉,可能无法看明白这些升级的内容。不用担心,本次直接对 TensorFlow 2 进行学习,我们不再回首过去,直接展望未来。

接下来,我们将从 TensorFlow 基础概念语法入手,一步一步学习 TensorFlow 的使用。

建议先学习 Python 数值计算库 NumPy 的使用,能帮助你更清楚地理解 TensorFlow 2 中的一些函数用法和概念。


张量

介绍

张量,如果你第一次听说,一定会感觉到它是一个很厉害的东西吧。它的确很厉害,但是不难理解。

张量的概念贯穿于物理学和数学中,如果你去看它的很多理论描述,可能并不那么浅显易懂。例如,下面有两种关于 张量的定义

  • 通常定义张量的物理学或传统数学方法,是把张量看成一个多维数组,当变换坐标或变换基底时,其分量会按照一定规则进行变换,这些规则有两种:即协变或逆变转换
  • 通常现代数学中的方法,是把张量定义成某个矢量空间或其对偶空间上的多重线性映射,这矢量空间在需要引入基底之前不固定任何坐标系统。例如协变矢量,可以描述为 1-形式,或者作为逆变矢量的对偶空间的元素

上面的定义不知道你看懂了没有?估计会有点困难。下面,我们进行通俗易懂的说明:

首先,你应该知道什么是向量和矩阵。先前的介绍中,我们把 1 维的数组称之为向量2维的数组称之为矩阵。那么,现在告诉你张量其实代表着更大的范围,你也可以把其看作是 N 维数组

所以,如果现在重新描述向量和矩阵,就可以是:

一阶张量为向量,二阶张量为矩阵。当然,零阶张量也就是标量,而更重要的是 N 阶张量,也就是 N 维数组。

数学实例
0标量(只有大小)
1矢量(大小和方向)
2矩阵(数据表)
33 阶张量(数据立体)
NN 阶张量(自行想象)

image-20211012140051313

所以,张量并不是什么晦涩难懂的概念。如果不严谨的讲,张量就是 N 维数组。前面提到的向量、矩阵,也是张量

TensorFlow 中对张量的定义

你即将了解到的大多数深度学习框架都会使用张量的概念,这样做的好处是统一对数据的定义NumPy 中,数据都使用 Ndarray 多维数组进行定义TensorFlow 中,数据都会用张量进行表述。

下面就来了解 TensorFlow 中对张量的定义。

在 TensorFlow 中,每一个 Tensor 都具备两个基础属性

  • 数据类型(默认:float32)
  • 形状

其中,数据类型大致如下表所示:

Tensor 类型描述
tf.float3232 位浮点数
tf.float6464 位浮点数
tf.int6464 位有符号整型
tf.int3232 位有符号整型
tf.int1616 位有符号整型
tf.int88 位有符号整型
tf.uint88 位无符号整型
tf.string可变长度的字节数组
tf.bool布尔型
tf.complex64实数和虚数

另外,TensorFlow 通过三种符号约定来描述张量维度:阶,形状和维数

三者之间的关系如下:

形状维数示例
[]00-D0 维张量。标量。
[D0]11-D形状为 [5] 的 1 维张量。
[D0, D1]22-D形状为 [3, 4] 的 2 维张量。
[D0, D1, D2]33-D形状为 [1, 4, 3] 的 3 维张量。
[D0, D1, ... Dn-1]nn-D形状为 [D0, D1, ... Dn-1] 的张量。

值得注意的是,上表中的示例都是形容张量的形状。例如 [3, 4] 指的张量的形状为 [3, 4],而不是张量 [3, 4]

张量的类型

根据不同的用途,TensorFlow 中主要有 2 种张量类型,分别是:

  • tf.Variable变量 Tensor,需要指定初始值,常用于定义可变参数例如神经网络的权重
  • tf.constant常量 Tensor,需要指定初始值,定义不变化的张量

我们可以通过传入列表NumPy 数组来新建变量和常量类型的张量

(1)查看 TensorFlow 版本:

image-20211012144331702

(2)定义形状为 (3, 3) 的二维变量:

image-20211012144504564

(3)定义现状为 (2,2) 二维常量

image-20211012144612426

张量的属性

仔细观察,你会发现输出包含了张量的 3 部分属性,分别是

  • 形状 shape
  • 数据类型 dtype
  • 对应的 NumPy 数组。

你还可以直接通过 .numpy() 输出张量的 NumPy 数组。

image-20211012143937499

特殊常量张量

上面我们已经介绍了常量张量,这里再列举几个经常会用到的新建特殊常量张量的方法:

  • tf.zeros:新建指定形状且全为 0 的常量 Tensor
  • tf.zeros_like:参考某种形状,新建全为 0 的常量 Tensor
  • tf.ones:新建指定形状且全为 1 的常量 Tensor
  • tf.ones_like:参考某种形状,新建全为 1 的常量 Tensor
  • tf.fill:新建一个指定形状且全为某个标量值的常量 Tensor

(1)3x3 全为 0 的常量 Tensor

image-20211012145035811

(2)c 形状一致全为 1 的常量 Tensor

image-20211012145125912

(3)2x3 全为 6 的常量 Tensor

image-20211012145446893

创建序列

除此之外,我们还可以创建一些序列,例如:

  • tf.linspace:创建一个等间隔序列。
  • tf.range:创建一个数字序列。

image-20211012145924371

image-20211012150204359

实际上,如果你熟悉 NumPy 的话,你会发现这与 NumPy 中创建各式各样的多维数组方法大同小异。数据类型是一切的基础,了解完张量我们就可以继续学习张量的运算了。


Eager Execution

TensorFlow 2 带来的最大改变之一是将 1.x 的 Graph Execution(图与会话机制)更改为 Eager Execution(动态图机制)。在 1.x 版本中,低级别 TensorFlow API 首先需要定义数据流图,然后再创建 TensorFlow 会话,这一点在 2.0 中被完全舍弃。

TensorFlow 2 中的 Eager Execution 是一种命令式编程环境,可立即评估操作,无需构建图

所以说,TensorFlow 的张量运算过程可以像 NumPy 一样直观且自然了。接下来,我们以最简单的加法运算为例:

image-20211012150330470

如果你接触过 1.x 版本的 TensorFlow,你要知道一个加法运算过程十分复杂。我们需要初始化全局变量 → 建立会话 → 执行计算,最终才能打印出张量的运算结果。

init_op = tf.global_variables_initializer()  # 初始化全局变量
with tf.Session() as sess:  # 启动会话
    sess.run(init_op)
    print(sess.run(c + c))  # 执行计算

Eager Execution 带来的好处显而易见,其进一步降低了 TensorFlow 的入门门槛。之前的 Graph Execution 模式,实际上让很多人在入门时都很郁闷,因为完全不符合正常思维习惯。

TensorFlow 中提供的数学计算,包括线性代数计算方面的方法也是应有尽有,十分丰富。下面,我们再列举一个示例。

(1)矩阵乘法

image-20211012151019775

(2)转置矩阵

image-20211012152031819

你应该能够感觉到,这些常用 API 都能在 NumPy 中找到对应的方法,这也就是需要你预先熟悉 NumPy 的原因。

由于函数实在太多太多。一般来讲,除了自己经常使用到的,都会在需要某种运算的时候,查阅官方文档。

所以说,你可以把 TensorFlow 理解成为 TensorFlow 式的 NumPy + 为搭建神经网络而生的 API


自动微分

在数学中,微分是对函数的局部变化率的一种线性描述

虽然微分和导数是两个不同的概念。

但是,对一元函数来说,可微与可导是完全等价的。

如果你熟悉神经网络的搭建过程,应该明白梯度的重要性。而对于复杂函数的微分过程是及其麻烦的,为了提高应用效率,大部分深度学习框架都有自动微分机制。

TensorFlow 中,你可以使用 tf.GradientTape 跟踪全部运算过程,以便在必要的时候计算梯度。

image-20211012152522624

上面,我们演示了一个自动微分过程,它的数学求导过程如下: $$ loss = w^2 \rightarrow \frac {\partial loss}{\partial w} = 2w $$ 所以,当 w 等于 2.3 时,计算结果为 4.6。

tf.GradientTape 会像磁带一样记录下计算图中的梯度信息,然后使用 .gradient 即可回溯计算出任意梯度,这对于使用 TensorFlow 低阶 API 构建神经网络时更新参数非常重要。


常用模块

常用模块

上面,我们已经学习了 TensorFlow 核心知识,接下来将对 TensorFlow API 中的常用模块进行简单的功能介绍。

对于框架的使用,实际上就是灵活运用各种封装好的类和函数。

由于 TensorFlow API 数量太多,迭代太快,所以大家要养成随时 查阅官方文档 的习惯。

  • tf.:包含了张量定义,变换等常用函数和类。
  • tf.data:输入数据处理模块,提供了像 tf.data.Dataset 等类用于封装输入数据,指定批量大小等。
  • tf.image:图像处理模块,提供了像图像裁剪,变换,编码,解码等类。
  • tf.keras:原 Keras 框架高阶 API。包含原 tf.layers 中高阶神经网络层。
  • tf.linalg:线性代数模块,提供了大量线性代数计算方法和类。
  • tf.losses:损失函数模块,用于方便神经网络定义损失函数。
  • tf.math:数学计算模块,提供了大量数学计算函数。
  • tf.saved_model:模型保存模块,可用于模型的保存和恢复。
  • tf.train:提供用于训练的组件,例如优化器,学习率衰减策略等。
  • tf.nn:提供用于构建神经网络的底层函数,以帮助实现深度神经网络各类功能层。
  • tf.estimator:高阶 API,提供了预创建的 Estimator 或自定义组件。

在构建深度神经网络时,TensorFlow 可以说提供了你一切想要的组

不同形状的张量、激活函数、神经网络层,到优化器、数据集等,一应俱全。

More from this blog

【两万字总结】Spark 部署与入门

Spark 介绍 核心概念 Spark 是 UC Berkeley AMP lab 开发的一个集群计算的框架,类似于 Hadoop,但有很多的区别。 最大的优化是让计算任务的中间结果可以存储在内存中,不需要每次都写入 HDFS,更适用于需要迭代的 MapReduce 算法场景中,可以获得更好的性能提升。 例如一次排序测试中,对 100TB 数据进行排序,Spark 比 Hadoop 快三倍,并且只需要十分之一的机器。 Spark 集群目前最大的可以达到 8000 节点,处理的数据达到 PB 级别...

Oct 20, 202115 min read

【引言】浙大机器学习课程记录

机器学习的定义 第一种定义 ARTHUR SAMUEL对Machine learning 的定义 Machine Learning is Fields of study that gives computers the ability to learn without being explicitly programmed 机器学习是这样的领域,它赋予计算机学习的能力,(这种学历能力)不是通过显著式编程获得的 显著式编程 提前人为指定规律的编程方式 非显著式编程 让计算机自己总结规律的...

Oct 19, 20212 min read

TensorFlow 2 Keras实现线性回归

介绍 线性回归是入门机器学习必学的算法,其也是最基础的算法之一。 接下来,我们以线性回归为例,使用 TensorFlow 2 提供的 API 和 Eager Execution 机制对其进行实现。 线性回归是一种较为简单,但十分重要的机器学习方法,它也是神经网络的基础。 如下所示,线性回归要解决的问题就是如何找到最理想的直线去拟合散点样本。 对于一个线性回归问题,一般来讲有 2 种解决方法,分别是: 最小二乘法 代数求解 矩阵求解 梯度下降法。 本次,我们将使用梯度下降方法来解决线性回...

Oct 12, 20211 min read

uiu's log

27 posts

Insist on programming & Love open source