# 一、TensorFlow 2 简介

TensorFlow 于 2011 年以 Google 的内部封闭源代码项目 DisBelief 诞生。 DisBelief 是采用深度学习神经网络的机器学习系统。 该系统演变为 TensorFlow，并在 2015 年 11 月 9 日根据 Apache 2.0 开源许可证发布到开发人员社区。版本 1.0.0 于 2017 年 2 月 11 日出现。此后有许多版本发布。 合并了许多新功能。

在撰写本书时，最新版本是 TensorFlow 2.0.0 alpha 版本，该版本在 2019 年 3 月 6 日的 TensorFlow 开发峰会上宣布。

TensorFlow 的名字来源于张量。 张量是向量和矩阵到更高维度的一般化。 张量的等级是唯一指定该张量的每个元素所用的索引数。 标量（简单数字）是等级 0 的张量，向量是等级 1 的张量，矩阵是等级 2 的张量，三维数组是等级 3 的张量。张量具有数据类型和形状（张量中的所有数据项必须具有相同的类型）。 4 维张量的示例（即等级 4）是图像，其中维是例如`batch`，`height`，`width`和`color`通道内的示例：

```py
image1 = tf.zeros([7, 28, 28, 3]) #  example-within-batch by height by width by color

```

尽管 TensorFlow 通常可以用于许多数值计算领域，尤其是机器学习，但其主要研究和开发领域是**深层神经网络**（**DNN**）的应用，它已在语音和声音识别等不同领域使用，例如，在如今广泛使用的声控助手中； 基于文本的应用，例如语言翻译器； 图像识别，例如系外行星搜寻，癌症检测和诊断； 以及时间序列应用（例如推荐系统）。

在本章中，我们将讨论以下内容：

*   现代 TensorFlow 生态系统
*   安装 TensorFlow
*   急切操作
*   提供有用的 TensorFlow 操作

# 现代 TensorFlow 生态系统

让我们讨论**急切执行**。 TensorFlow 的第一个化身包括构造由操作和张量组成的计算图，随后必须在 Google 所谓的会话中对其进行评估（这称为声明性编程）。 这仍然是编写 TensorFlow 程序的常用方法。 但是，急切执行的功能（以研究形式从版本 1.5 开始可用，并从版本 1.7 被烘焙到 TensorFlow 中）需要立即评估操作，结果是可以将张量像 NumPy 数组一样对待（这被称为命令式编程）。

谷歌表示，急切执行是研究和开发的首选方法，但计算图对于服务 TensorFlow 生产应用将是首选。

`tf.data`是一种 API，可让您从更简单，可重复使用的部件中构建复杂的数据输入管道。 最高级别的抽象是`Dataset`，它既包含张量的嵌套结构元素，又包含作用于这些元素的转换计划。 有以下几种类：

*   `Dataset`包含来自至少一个二进制文件（`FixedLengthRecordDataset`）的固定长度记录集
*   `Dataset`由至少一个 TFRecord 文件（`TFRecordDataset`）中的记录组成
*   `Dataset`由记录组成，这些记录是至少一个文本文件（`TFRecordDataset`）中的行
*   还有一个类表示通过`Dataset`（`tf.data.Iterator`）进行迭代的状态

让我们继续进行**估计器**，这是一个高级 API，可让您构建大大简化的机器学习程序。 估计员负责训练，评估，预测和导出服务。

**TensorFlow.js** 是 API 的集合，可让您使用底层 JavaScript 线性代数库或高层 API 来构建和训练模型。 因此，可以训练模型并在浏览器中运行它们。

**TensorFlow Lite** 是适用于移动和嵌入式设备的 TensorFlow 的轻量级版本。 它由运行时解释器和一组工具组成。 这个想法是您在功率更高的机器上训练模型，然后使用工具将模型转换为`.tflite`格式。 然后将模型加载到您选择的设备中。 在撰写本文时，使用 C++ API 在 Android 和 iOS 上支持 TensorFlow Lite，并且具有适用于 Android 的 Java 包装器。 如果 Android 设备支持 **Android 神经​​网络**（**ANN**）API 进行硬件加速，则解释器将使用此 API，否则它将默认使用 CPU 执行。

**TensorFlow Hub** 是一个旨在促进机器学习模型的可重用模块的发布，发现和使用的库。 在这种情况下，模块是 TensorFlow 图的独立部分，包括其权重和其他资产。 该模块可以通过称为迁移学习的方法在不同任务中重用。 这个想法是您在大型数据集上训练模型，然后将适当的模块重新用于您的其他但相关的任务。 这种方法具有许多优点-您可以使用较小的数据集训练模型，可以提高泛化能力，并且可以大大加快训练速度。

例如，ImageNet 数据集以及许多不同的神经网络架构（例如`inception_v3`）已非常成功地用于解决许多其他图像处理训练问题。

**TensorFlow Extended**（**TFX**）是基于 TensorFlow 的通用机器学习平台。 迄今为止，已开源的库包括 TensorFlow 转换，TensorFlow 模型分析和 TensorFlow 服务。

`tf.keras`是用 Python 编写的高级神经网络 API，可与 TensorFlow（和其他各种张量工具）接口。 `tf.k` `eras`支持快速原型设计，并且用户友好，模块化且可扩展。 它支持卷积和循环网络，并将在 CPU 和 GPU 上运行。 Keras 是 TensorFlow 2 中开发的首选 API。

**TensorBoard** 是一套可视化工具，支持对 TensorFlow 程序的理解，调试和优化。 它与急切和图执行环境兼容。 您可以在训练期间使用 TensorBoard 可视化模型的各种指标。

TensorFlow 的一项最新开发（在撰写本文时仍处于实验形式）将 TensorFlow 直接集成到 Swift 编程语言中。 Swift 中的 TensorFlow 应用是使用命令性代码编写的，即命令急切地（在运行时）执行的代码。 Swift 编译器会自动将此源代码转换为一个 TensorFlow 图，然后在 CPU，GPU 和 TPU 上以 TensorFlow Sessions 的全部性能执行此编译后的代码。

在本书中，我们将重点介绍那些使用 Python 3.6 和 TensorFlow 2.0.0 alpha 版本启动和运行 TensorFlow 的 TensorFlow 工具。 特别是，我们将使用急切的执行而不是计算图，并且将尽可能利用`tf.keras`的功能来构建网络，因为这是研究和实验的现代方法。

# 安装 TensorFlow

TensorFlow 的最佳编程支持是为 Python 提供的（尽管确实存在 Java，C 和 Go 的库，而其他语言的库正在积极开发中）。

Web 上有大量信息可用于为 Python 安装 TensorFlow。

Google 也建议在虚拟环境中安装 TensorFlow，这是一种标准做法，该环境将一组 API 和代码与其他 API 和代码以及系统范围的环境隔离开来。

TensorFlow 有两种不同的版本-一个用于在 CPU 上执行，另一个用于在 GPU 上执行。 最后，这需要安装数值库 CUDA 和 CuDNN。 Tensorflow 将在可能的情况下默认执行 GPU。 参见[这里](https://www.tensorflow.org/alpha/guide/using_gpu)。

与其尝试重新发明轮子，不如跟随资源来创建虚拟环境和安装 TensorFlow。

总而言之，可能会为 Windows 7 或更高版本，Ubuntu Linux 16.04 或更高版本以及 macOS 10.12.6 或更高版本安装 TensorFlow。

有关虚拟环境的完整介绍，请参见[这里](http://docs.python-guide.org/en/latest/dev/virtualenvs/)。

[Google 的官方文档](https://www.tensorflow.org/install/)中提供了有关安装 TensorFlow 所需的所有方面的非常详细的信息。

安装后，您可以从命令终端检查 TensorFlow 的安装。 [这个页面](http://www.laurencemoroney.com/tensorflow-to-gpu-or-not-to-gpu/)有执行此操作，以及安装 TensorFlow 的夜间版本（其中包含所有最新更新）的说明。

# 急切的操作

我们将首先介绍如何导入 TensorFlow，然后介绍 TensorFlow 编码风格，以及如何进行一些基本的整理工作。 之后，我们将看一些基本的 TensorFlow 操作。 您可以为这些代码片段创建 Jupyter 笔记本，也可以使用自己喜欢的 IDE 创建源代码。 该代码在 GitHub 存储库中都可用。

# 导入 TensorFlow

导入 TensorFlow 很简单。 请注意几个系统检查：

```py
import tensorflow as tf
print("TensorFlow version: {}".format(tf.__version__))
print("Eager execution is: {}".format(tf.executing_eagerly()))
print("Keras version: {}".format(tf.keras.__version__))
```

# TensorFlow 的编码风格约定

对于 Python 应用，Google 遵守 PEP8 标准约定。 特别是，他们将 CamelCase 用于类（例如`hub.LatestModuleExporter`），将`snake_case`用于函数，方法和属性（例如`tf.math.squared_difference`）。 Google 还遵守《Google Python 风格指南》，该指南可在[这个页面](https://github.com/google/styleguide/blob/gh-pages/pyguide.md)中找到。

# 使用急切执行

急切执行是 TensorFlow 2 中的默认设置，因此不需要特殊设置。

以下代码可用于查找是否正在使用 CPU 或 GPU，如果它是 GPU，则该 GPU 是否为`#0`。

我们建议键入代码，而不要使用复制和粘贴。 这样，您将对以下命令有所了解：

```py
var = tf.Variable([3, 3])

if tf.test.is_gpu_available(): 
 print('Running on GPU')
 print('GPU #0?')
 print(var.device.endswith('GPU:0'))
else: 
 print('Running on CPU')
```

# 声明急切变量

声明 TensorFlow 急切变量的方法如下：

```py
t0 = 24 # python variable
t1 = tf.Variable(42) # rank 0 tensor
t2 = tf.Variable([ [ [0., 1., 2.], [3., 4., 5.] ], [ [6., 7., 8.], [9., 10., 11.] ] ]) #rank 3 tensor
t0, t1, t2
```

输出将如下所示：

```py
(24,
 <tf.Variable 'Variable:0' shape=() dtype=int32, numpy=42>,
 <tf.Variable 'Variable:0' shape=(2, 2, 3) dtype=float32, numpy=
 array([[[ 0.,  1.,  2.],
         [ 3.,  4.,  5.]],
         [[ 6.,  7.,  8.],
         [ 9., 10., 11.]]], dtype=float32)>)
```

TensorFlow 将推断数据类型，对于浮点数默认为`tf.float32`，对于整数默认为`tf.int32`（请参见前面的示例）。

或者，可以显式指定数据类型，如下所示：

```py
f64 = tf.Variable(89, dtype = tf.float64)
f64.dtype
```

TensorFlow 具有大量的内置数据类型。

示例包括之前看到的示例`tf.int16`，`tf.complex64`和`tf.string`。 参见[这里](https://www.tensorflow.org/api_docs/python/tf/dtypes/DType)。 要重新分配变量，请使用`var.assign()`，如下所示：

```py
f1 = tf.Variable(89.)
f1

# <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=89.0>

f1.assign(98.)
f1

# <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=98.0>
```

# 声明 TensorFlow 常量

TensorFlow 常量可以在以下示例中声明：

```py
m_o_l = tf.constant(42)

m_o_l

# <tf.Tensor: id=45, shape=(), dtype=int32, numpy=42>

m_o_l.numpy()

# 42
```

同样，TensorFlow 将推断数据类型，或者可以像使用变量那样显式指定它：

```py
unit = tf.constant(1, dtype = tf.int64)

unit

# <tf.Tensor: id=48, shape=(), dtype=int64, numpy=1>
```

# 调整张量

张量的形状通过属性（而不是函数）访问：

```py
t2 = tf.Variable([ [ [0., 1., 2.], [3., 4., 5.] ], [ [6., 7., 8.], [9., 10., 11.] ] ]) # tensor variable
print(t2.shape)
```

输出将如下所示：

```py
(2, 2, 3)
```

张量可能会被重塑并保留相同的值，这是构建神经网络经常需要的。

这是一个示例：

```py
r1 = tf.reshape(t2,[2,6]) # 2 rows 6 cols
r2 = tf.reshape(t2,[1,12]) # 1 rows 12 cols
r1
# <tf.Tensor: id=33, shape=(2, 6), dtype=float32, 
numpy= array([[ 0., 1., 2., 3., 4., 5.], [ 6., 7., 8., 9., 10., 11.]], dtype=float32)>
```

这是另一个示例：

```py
r2 = tf.reshape(t2,[1,12]) # 1 row 12 columns
r2
# <tf.Tensor: id=36, shape=(1, 12), dtype=float32, 
numpy= array([[ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.]], dtype=float32)>
```

# 张量的等级（尺寸）

张量的等级是它具有的维数，即指定该张量的任何特定元素所需的索引数。

张量的等级可以这样确定，例如：

```py
tf.rank(t2)
```

输出将如下所示：

```py
<tf.Tensor: id=53, shape=(), dtype=int32, numpy=3>
(the shape is () because the output here is a scalar value)
```

# 指定张量的元素

正如您期望的那样，通过指定所需的索引来指定张量的元素。

以这个为例：

```py
t3 = t2[1, 0, 2] # slice 1, row 0, column 2
t3
```

输出将如下所示：

```py
<tf.Tensor: id=75, shape=(), dtype=float32, numpy=8.0>
```

# 将张量转换为 NumPy/Python 变量

如果需要，可以将张量转换为`numpy`变量，如下所示：

```py
print(t2.numpy())
```

输出将如下所示：

```py
[[[ 0\. 1\. 2.] [ 3\. 4\. 5.]] [[ 6\. 7\. 8.] [ 9\. 10\. 11.]]]

```

也可以这样：

```py
print(t2[1, 0, 2].numpy())
```

输出将如下所示：

```py
8.0
```

# 查找张量的大小（元素数）

张量中的元素数量很容易获得。 再次注意，使用`.numpy()`函数从张量中提取 Python 值：

```py
s =  tf.size(input=t2).numpy()
s
```

输出将如下所示：

```py
12
```

# 查找张量的数据类型

TensorFlow 支持您期望的所有数据类型。 完整列表位于[这里](https://www.tensorflow.org/versions/r1.1/programmers_guide/dims_types)，其中包括`tf.int32`（默认整数类型），`tf.float32`（默认浮动点类型）和`tf.complex64`（复数类型）。

要查找张量的数据类型，请使用以下`dtype`属性：

```py
t3.dtype
```

输出将如下所示：

```py
tf.float32
```

# 指定按元素的基本张量操作

如您所料，使用重载运算符`+`，`-`，`*`和`/`来指定逐元素基本张量操作，如下所示：

```py
t2*t2
```

输出将如下所示：

```py
<tf.Tensor: id=555332, shape=(2, 2, 3), dtype=float32, numpy= array([[[ 0., 1., 4.], [ 9., 16., 25.]], [[ 36., 49., 64.], [ 81., 100., 121.]]], dtype=float32)>
```

# 广播

按元素张量操作以与 NumPy 数组相同的方式支持广播。 最简单的示例是将张量乘以标量：

```py
t4 = t2*4
print(t4)
```

输出将如下所示：

```py
tf.Tensor( [[[ 0\. 4\. 8.] [12\. 16\. 20.]] [[24\. 28\. 32.] [36\. 40\. 44.]]], shape=(2, 2, 3), dtype=float32) 
```

在该示例中，在概念上至少将标量乘法器 4 扩展为一个数组，该数组可以与`t2`逐元素相乘。 在[上对广播进行了非常详细的讨论，网址为](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)。

# 转置 TensorFlow 和矩阵乘法

要紧急转置矩阵和矩阵乘法，请使用以下命令：

```py
u = tf.constant([[3,4,3]]) 
v = tf.constant([[1,2,1]])
tf.matmul(u, tf.transpose(a=v))
```

输出将如下所示：

```py
<tf.Tensor: id=555345, shape=(1, 1), dtype=int32, numpy=array([[14]], dtype=int32)>
```

再次注意，默认整数类型为`tf.int32`，默认浮点类型为`tf.float32`。

可用于构成计算图一部分的张量的所有操作也可用于急切执行变量。

在[这个页面](https://www.tensorflow.org/api_guides/python/math_ops)上有这些操作的完整列表。

# 将张量转换为另一个（张量）数据类型

一种类型的 TensorFlow 变量可以强制转换为另一种类型。 可以在[这个页面](https://www.tensorflow.org/api_docs/python/tf/cast)中找到更多详细信息。

请看以下示例：

```py
i = tf.cast(t1, dtype=tf.int32) # 42
i
```

输出将如下所示：

```py
<tf.Tensor: id=116, shape=(), dtype=int32, numpy=42>
```

截断后，将如下所示：

```py
j = tf.cast(tf.constant(4.9), dtype=tf.int32) # 4
j
```

输出将如下所示：

```py
<tf.Tensor: id=119, shape=(), dtype=int32, numpy=4>
```

# 声明参差不齐的张量

参差不齐的张量是具有一个或多个参差不齐尺寸的张量。 参差不齐的尺寸是具有可能具有不同长度的切片的尺寸。

声明参差不齐的数组的方法有很多种，最简单的方法是常量参差不齐的数组。

以下示例显示了如何声明一个常数的，参差不齐的数组以及各个切片的长度：

```py
ragged =tf.ragged.constant([[5, 2, 6, 1], [], [4, 10, 7], [8], [6,7]])

print(ragged)
print(ragged[0,:])
print(ragged[1,:])
print(ragged[2,:])
print(ragged[3,:])
print(ragged[4,:])
```

输出如下：

```py
<tf.RaggedTensor [[5, 2, 6, 1], [], [4, 10, 7], [8], [6, 7]]>
tf.Tensor([5 2 6 1], shape=(4,), dtype=int32)
tf.Tensor([], shape=(0,), dtype=int32)
tf.Tensor([ 4 10  7], shape=(3,), dtype=int32)
tf.Tensor([8], shape=(1,), dtype=int32)
tf.Tensor([6 7], shape=(2,), dtype=int32)
```

注意单个切片的形状。

创建参差不齐的数组的常用方法是使用`tf.RaggedTensor.from_row_splits()`方法，该方法具有以下签名：

```py
@classmethod
from_row_splits(
    cls,
    values,
    row_splits,
    name=None
)

```

在这里，`values`是要变成参差不齐的数组的值的列表，`row_splits`是要拆分该值列表的位置的列表，因此行`ragged[i]`的值存储在其中 `ragged.values[ragged.row_splits[i]:ragged.row_splits[i+1]]`：

```py
print(tf.RaggedTensor.from_row_splits(values=[5, 2, 6, 1, 4, 10, 7, 8, 6, 7],
row_splits=[0, 4, 4, 7, 8, 10]))
```

`RaggedTensor`如下：

```py
<tf.RaggedTensor [[5, 2, 6, 1], [], [4, 10, 7], [8], [6, 7]]>
```

# 提供有用的 TensorFlow 操作

在[这个页面](https://www.tensorflow.org/api_docs/python/tf)上有所有 TensorFlow Python 模块，类和函数的完整列表。

可以在[这个页面](https://www.tensorflow.org/api_docs/python/tf/math)中找到所有数学函数。

在本节中，我们将研究一些有用的 TensorFlow 操作，尤其是在神经网络编程的上下文中。

# 求两个张量之间的平方差

在本书的后面，我们将需要找到两个张量之差的平方。 方法如下：

```py
tf.math.squared.difference( x,  y, name=None)
```

请看以下示例：

```py
x = [1,3,5,7,11]
y = 5
s = tf.math.squared_difference(x,y)
s
```

输出将如下所示：

```py
<tf.Tensor: id=279, shape=(5,), dtype=int32, numpy=array([16, 4, 0, 4, 36], dtype=int32)>
```

请注意，在此示例中，Python 变量`x`和`y`被转换为张量，然后`y`跨`x`广播。 因此，例如，第一计算是`(1 - 5)^2 = 16`。

# 求平均值

以下是`tf.reduce_mean()`的签名。

请注意，在下文中，所有 TensorFlow 操作都有一个名称参数，当使用急切执行作为其目的是在计算图中识别操作时，可以安全地将其保留为默认值`None`。

请注意，这等效于`np.mean`，除了它从输入张量推断返回数据类型，而`np.mean`允许您指定输出类型（默认为`float64`）：

```py
tf.reduce_mean(input_tensor, axis=None, keepdims=None, name=None)
```

通常需要找到张量的平均值。 当在单个轴上完成此操作时，该轴被称为减少了。

这里有些例子：

```py
numbers = tf.constant([[4., 5.], [7., 3.]])
```

# 求所有轴的均值

求出所有轴的平均值（即使用默认的`axis = None`）：

```py
tf.reduce_mean(input_tensor=numbers)
#( 4\. + 5\. + 7\. + 3.)/4 = 4.75
```

输出将如下所示：

```py
<tf.Tensor: id=272, shape=(), dtype=float32, numpy=4.75>
```

# 求各列的均值

用以下方法找到各列的均值（即减少行数）：

```py
tf.reduce_mean(input_tensor=numbers, axis=0) # [ (4\. + 7\. )/2 , (5\. + 3.)/2 ] = [5.5, 4.]
```

输出将如下所示：

```py
<tf.Tensor: id=61, shape=(2,), dtype=float32, numpy=array([5.5, 4\. ], dtype=float32)>

```

当`keepdims`为`True`时，缩小轴将保留为 1：

```py
 tf.reduce_mean(input_tensor=numbers, axis=0, keepdims=True)
```

输出如下：

```py
array([[5.5, 4.]])        (1 row, 2 columns) 
```

# 求各行的均值

使用以下方法找到各行的均值（即减少列数）：

```py
tf.reduce_mean(input_tensor=numbers, axis=1) # [ (4\. + 5\. )/2 , (7\. + 3\. )/2] = [4.5, 5]
```

输出将如下所示：

```py
<tf.Tensor: id=64, shape=(2,), dtype=float32, numpy=array([4.5, 5\. ], dtype=float32)>
```

当`keepdims`为`True`时，缩小轴将保留为 1：

```py
tf.reduce_mean(input_tensor=numbers, axis=1, keepdims=True)
```

输出如下：

```py
([[4.5], [5]])      (2 rows, 1 column)
```

# 生成充满随机值的张量

开发神经网络时，例如初始化权重和偏差时，经常需要随机值。 TensorFlow 提供了多种生成这些随机值的方法。

# 使用`tf.random.normal()`

`tf.random.normal()`输出给定形状的张量，其中填充了来自正态分布的`dtype`类型的值。

所需的签名如下：

```py
tf. random.normal(shape, mean = 0, stddev =2, dtype=tf.float32, seed=None, name=None)
```

以这个为例：

```py
tf.random.normal(shape = (3,2), mean=10, stddev=2, dtype=tf.float32, seed=None,  name=None)
ran = tf.random.normal(shape = (3,2), mean=10.0, stddev=2.0)
print(ran)
```

输出将如下所示：

```py
<tf.Tensor: id=13, shape=(3, 2), dtype=float32, numpy= array([[ 8.537131 , 7.6625767], [10.925293 , 11.804686 ], [ 9.3763075, 6.701221 ]], dtype=float32)>
```

# 使用`tf.random.uniform()`

所需的签名是这样的：

```py
tf.random.uniform(shape, minval = 0, maxval= None, dtype=tf.float32, seed=None,  name=None)
```

这将输出给定形状的张量，该张量填充了从`minval`到`maxval`范围内的均匀分布的值，其中下限包括在内，而上限不包括在内。

以这个为例：

```py
tf.random.uniform(shape = (2,4),  minval=0, maxval=None, dtype=tf.float32, seed=None,  name=None)
```

输出将如下所示：

```py
tf.Tensor( [[ 6 7] [ 0 12]], shape=(2, 2), dtype=int32)
```

请注意，对于这两个随机操作，如果您希望生成的随机值都是可重复的，则使用`tf.random.set_seed()`。 还显示了非默认数据类型的使用：

```py
tf.random.set_seed(11)
ran1 = tf.random.uniform(shape = (2,2), maxval=10, dtype = tf.int32)
ran2 =  tf.random.uniform(shape = (2,2), maxval=10, dtype = tf.int32)
print(ran1) #Call 1
print(ran2)

tf.random.set_seed(11) #same seed
ran1 = tf.random.uniform(shape = (2,2), maxval=10, dtype = tf.int32)
ran2 = tf.random.uniform(shape = (2,2), maxval=10, dtype = tf.int32)
print(ran1) #Call 2
print(ran2)
```

`Call 1`和`Call 2`将返回相同的一组值。

输出将如下所示：

```py
tf.Tensor(
[[4 6]
 [5 2]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[9 7]
 [9 4]], shape=(2, 2), dtype=int32)

tf.Tensor(
[[4 6]
 [5 2]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[9 7]
 [9 4]], shape=(2, 2), dtype=int32)
```

# 使用随机值的实际示例

这是一个适合从[这个页面](https://colab.research.google.com/notebooks/mlcc/creating_and_manipulating_tensors.ipynb#scrollTo=6UUluecQSCvr)执行的小示例。

请注意，此示例显示了如何通过调用 TensorFlow 函数来初始化急切变量。

```py
 dice1 = tf.Variable(tf.random.uniform([10, 1], minval=1, maxval=7, dtype=tf.int32))
 dice2 = tf.Variable(tf.random.uniform([10, 1], minval=1, maxval=7, dtype=tf.int32))

 # We may add dice1 and dice2 since they share the same shape and size.
 dice_sum = dice1 + dice2

 # We've got three separate 10x1 matrices. To produce a single
 # 10x3 matrix, we'll concatenate them along dimension 1.
 resulting_matrix = tf.concat(values=[dice1, dice2, dice_sum], axis=1)

 print(resulting_matrix)
```

示例输出如下：

```py
tf.Tensor( 
[[ 5 4 9] 
[ 5 1 6] 
[ 2 4 6] 
[ 5 6 11]
[ 4 4 8] 
[ 4 6 10]
[ 2 2 4]
[ 5 6 11] 
[ 2 6 8] 
[ 5 4 9]], shape=(10, 3), dtype=int32)
```

# 查找最大和最小元素的索引

现在，我们将研究如何在张量轴上查找具有最大值和最小值的元素的索引。

这些函数的签名如下：

```py
tf.argmax(input, axis=None, name=None, output_type=tf.int64 )

tf.argmin(input, axis=None, name=None, output_type=tf.int64 )
```

以这个为例：

```py
# 1-D tensor
t5 = tf.constant([2, 11, 5, 42, 7, 19, -6, -11, 29])
print(t5)
i = tf.argmax(input=t5)
print('index of max; ', i)
print('Max element: ',t5[i].numpy())

i = tf.argmin(input=t5,axis=0).numpy()
print('index of min: ', i)
print('Min element: ',t5[i].numpy())

t6 = tf.reshape(t5, [3,3])

print(t6)
i = tf.argmax(input=t6,axis=0).numpy() # max arg down rows
print('indices of max down rows; ', i)
i = tf.argmin(input=t6,axis=0).numpy() # min arg down rows
print('indices of min down rows ; ',i)

print(t6)
i = tf.argmax(input=t6,axis=1).numpy() # max arg across cols
print('indices of max across cols: ',i)
i = tf.argmin(input=t6,axis=1).numpy() # min arg across cols
print('indices of min across cols: ',i)
```

输出将如下所示：

```py
tf.Tensor([ 2 11 5 42 7 19 -6 -11 29], shape=(9,), dtype=int32) 

index of max; tf.Tensor(3, shape=(), dtype=int64) 
Max element: 42 

index of min: tf.Tensor(7, shape=(), dtype=int64) 
Min element: -11 

tf.Tensor( [[ 2 11 5] [ 42 7 19] [ -6 -11 29]], shape=(3, 3), dtype=int32) 
indices of max down rows; tf.Tensor([1 0 2], shape=(3,), dtype=int64) 
indices of min down rows ; tf.Tensor([2 2 0], shape=(3,), dtype=int64) 

tf.Tensor( [[ 2 11 5] [ 42 7 19] [ -6 -11 29]], shape=(3, 3), dtype=int32) 
indices of max across cols: tf.Tensor([1 0 2], shape=(3,), dtype=int64) 
indices of min across cols: tf.Tensor([0 1 1], shape=(3,), dtype=int64)
```

# 使用检查点保存和恢复张量值

为了保存和加载张量值，这是最好的方法（有关保存完整模型的方法，请参见第 2 章和 “Keras，TensorFlow 2” 的高级 API）：

```py
variable = tf.Variable([[1,3,5,7],[11,13,17,19]])
checkpoint= tf.train.Checkpoint(var=variable)
save_path = checkpoint.save('./vars')
variable.assign([[0,0,0,0],[0,0,0,0]])
variable
checkpoint.restore(save_path)
print(variable)

```

输出将如下所示：

```py
<tf.Variable 'Variable:0' shape=(2, 4) dtype=int32, numpy= array([[ 1, 3, 5, 7],  [11, 13, 17, 19]], dtype=int32)>
```

# 使用`tf.function`

`tf.function`是将采用 Python 函数并返回 TensorFlow 图的函数。 这样做的好处是，图可以在 Python 函数（`func`）中应用优化并利用并行性。 `tf.function`是 TensorFlow 2 的新功能。

其签名如下：

```py
tf.function(
    func=None,
    input_signature=None,
    autograph=True,
    experimental_autograph_options=None
)

```

示例如下：

```py
def f1(x, y):
    return tf.reduce_mean(input_tensor=tf.multiply(x ** 2, 5) + y**2)

f2 = tf.function(f1)

x = tf.constant([4., -5.])
y = tf.constant([2., 3.])

# f1 and f2 return the same value, but f2 executes as a TensorFlow graph

assert f1(x,y).numpy() == f2(x,y).numpy()
```

断言通过，因此没有输出。

# 总结

在本章中，我们通过查看一些说明一些基本操作的代码片段开始熟悉 TensorFlow。 我们对现代 TensorFlow 生态系统以及如何安装 TensorFlow 进行了概述。 我们还研究了一些管家操作，一些急切操作以及各种 TensorFlow 操作，这些操作在本书的其余部分中将是有用的。 在 [www.youtube.com/watch?v=k5c-vg4rjBw](https://www.youtube.com/watch?v=k5c-vg4rjBw) 上对 TensorFlow 2 进行了出色的介绍。

另请参阅“附录 A”，以获得`tf1.12`到`tf2`转换工具的详细信息。 在下一章中，我们将介绍 Keras，这是 TensorFlow 2 的高级 API。