深度学习框架 TensorFlow:张量、自动求导机制、tf.keras模块(Model、layers、losses、optimizer、metrics)、多层感知机(即多层全连接神经网络 MLP)

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


安装

TensorFlow2、CUDA10、cuDNN7.6.5

Anaconda3 python 3.7、TensorFlow2、CUDA10、cuDNN7.6.5

TensorFlow 2.0 环境搭建

window下安装 Keras、TensorFlow(先安装CUDA、cuDNN,再安装Keras、TensorFlow)


4.1 深度学习框架-TensorFlow

4.1.1 常见深度学习框架对比

为什么需要深度学习框架

但是如果您需要实现更复杂的模型,如卷积神经网络(CNN)或循环神经网络(RNN)时,会发现从头开始实现复杂模型是不切实际的,因此深度学习框架应运而生,它可以帮助您轻松实现您自己的神经网络:

  • 不需要手写CUDA 代码能跑GPU;
  • 容易构建大的计算图(computational graphs)

3、PyTorch在研究领域日益占据主导地位

首先当然是先用数据说话。下图显示了顶级研究会议接受论文中,使用TensorFlow或Pythorch的比率。可以发现,所有的折线都向上倾,并且在2019年,主要会议的论文中,多数使用的都是PyTorch。

4、TensorFlow版本变化缺点

  • 频繁变动的接口。TensorFlow的接口一直处于快速迭代之中,并且没有很好地考虑向后兼容性,这导致现在许多开源代码已经无法在新版的TensorFlow上运行,同时也间接导致了许多基于TensorFlow的第三方框架出现BUG。接口设计过于晦涩难懂,对初学者来说较难上手。(不过,最新2.0版本对接口设计有了重大改进,使用起来比较方便)

tensorflow的github地址:https://github.com/tensorflow/tensorflow

框架选择:TensorFlow 是市场需求最多,也是增长最快的框架,它的领先地位不会在短期内被颠覆。 PyTorch 也在迅速发展,它在工作列表中的大量增加证明了其使用和需求的增加。在过去的六个月里,Keras 也有了很大的发展。最后,值得注意的是,FastAI 是从较小的基数开始发展的,它是最年轻的深度学习框架。TensorFlow 和 PyTorch 都是很好的值得学习的框架。

注:前几年一直关注AI框架,但是近年来框架的同质化说明了它不再是一个需要花大精力解决的问题,TensorFlow、Pytorch这样的框架在工业界的广泛应用,以及各种框架利用 Python 在建模领域的优秀表现,已经可以帮助我们解决很多以前需要自己编程实现的问题,如果作为 AI 工程师,我们应该跳出框架的桎梏,往更广泛的领域寻找价值。

4.1.2 TensorFlow介绍

官网:https://www.tensorflow.org/, 介绍:An open source machine learning platform

TensorFlow 可以为以上的这些需求提供完整的解决方案。具体而言,TensorFlow 包含以下特性:

  • 模型的建立与调试: 使用动态图模式 Eager Execution 和著名的神经网络高层 API 框架 Keras,结合可视化工具 TensorBoard,简易、快速地建立和调试模型;
  • 模型的训练: 支持 CPU / 单 GPU / 单机多卡 GPU / 多机集群 / TPU 训练模型,充分利用海量数据和计算资源进行高效训练;
  • 模型的部署: 通过 TensorFlow Serving、TensorFlow Lite、TensorFlow.js 等组件,使 TensorFlow 模型能够无缝地部署到服务器、移动端、嵌入式端和网页端等多种使用场景;
  • 预训练模型调用: 通过 TensorFlow Hub 和 Tensor2Tensor,可以方便地调用预训练完毕的已有成熟模型。

作为开发者和工程师你可能希望在你的产品中加入一些与人工智能相关的功能,抑或需要将已有的深度学习模型部署到各种场景中。具体而言,包括:

  • 如何导出训练好的模型?
  • 如何在本机使用已有的预训练模型?
  • 如何在服务器、移动端、嵌入式设备甚至网页上高效运行模型?

4.1.2.1 TF2.0 模型使用最新架构图

  • 饱受诟病TF1.0的API混乱
    • 删除 queue runner 以支持 tf.data。删除图形集合。
    • API 符号的移动和重命名。
    • tf.contrib 将从核心 TensorFlow 存储库和构建过程中移除

TensorFlow 2.0 将专注于 简单性 和 易用性,具有以下更新:

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

1、使用tf.data加载数据。使用输入管道读取训练数据,输入管道使用tf.data创建。利用tf.feature_column描述特征,如分段和特征交叉。

2、使用tf.keras构建、训练并验证模型,或者使用Premade Estimators。

  • Keras与TensorFlow的其余部分紧密集成,因此用户可以随时访问TensorFlow的函数。如线性或逻辑回归、梯度上升树、随机森林等也可以直接使用(使用tf.estimatorAPI实现)。
  • 如果不想从头开始训练模型,用户也可以很快利用迁移学习来训练使用TensorFlow Hub模块.

3、使用分布式策略进行分布式训练。对于大型机器学习训练任务,分布式策略API可以轻松地在不同硬件配置上分配和训练模型,无需更改模型的定义。由于TensorFlow支持各种硬件加速器,如CPU,GPU和TPU,因此用户可以将训练负载分配到单节点/多加速器以及多节点/多加速器配置上(包括TPU Pod)。

4、导出到Saved Model。 TensorFlow将对Saved Model进行标准化,作为TensorFlow服务的一部分,他将成为TensorFlow Lite、TensorFlow.js、TensorFlow Hub等格式的可互换格式。

工作流程

API级别:其中Keras是一个用Python编写的开源神经网络库,能够在TensorFlow、Microsoft Cognitive Toolkit、Theano或PlaidML之上运行。Keras旨在快速实现深度神经网络,专注于用户友好、模块化和可扩展性,是ONEIROS(开放式神经电子智能机器人操作系统)项目研究工作的部分产.2017年,Google的TensorFlow团队决定在TensorFlow核心库中支持Keras。 Chollet解释道,Keras被认为是一个接口,而非独立的机器学习框架。它提供了更高级别、更直观的抽象集

  1. 高层API (High level): 包括Estimators、Keras以及预构建好的Premade estimator(如线性回归、逻辑回归这些、推荐排序模型wide&deep);
  2. 中层API (Mid level): 包括layers, datasets, loss和metrics等具有功能性的函数,例如网络层的定义,Loss Function,对结果的测量函数等;
  3. 底层API (Low level): 包括具体的加减乘除、具有解析式的数学函数、卷积、对Tensor属性的测量等。

4.1.2.2 TensorFlow 资源

模型和数据集

TensorFlow提供了很多常见开源数据集,并且相应模型库也包含在TensorFlow中,用于迁移学习中重复利用模型

工具

探索可支持和加速 TensorFlow 工作流程的工具。可以支持我们分析模型、构建流水线工程等等。

  • Tensorboard:可视化学习
  • What-if:模型理解、调试分析
  • TFX:部署生产型机器学习流水线
  • TensorFlow Lite:移动和IOT设备部署

库和扩展程序

探索使用TensorFlow构建高级模型或方法的库,并访问可扩展TensorFlow的特定领域的应用程序。举几个例子

  • Tensorflow Agents:用于强化学习库
  • TensorFlow Ranking:用于排序学习技术的库

4.1.3 TensorFlow的安装(2.0版本)

安装 TensorFlow在64 位系统上测试这些系统支持 TensorFlow:

  • Ubuntu 16.04 或更高版本
  • Windows 7 或更高版本
  • macOS 10.12.6 (Sierra) 或更高版本(不支持 GPU)

进入虚拟环境当中再安装。刚开始的环境比较简单,只要下载tensorflow即可

  • 环境包:

安装较慢,指定镜像源,请在带有numpy等库的虚拟环境中安装

  • 1、非GPU版本安装

ubuntu安装

pip install tensorflow==2.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 2、GPU版本安装
pip install tensorflow-gpu==2.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

注:如果需要下载GPU版本的(TensorFlow只提供windows和linux版本的,没有Macos版本的)参考的官网网址:https://www.tensorflow.org/install/gpu?hl=zh-cn, 这里我们给大家提供了centos的安装教程,会易懂些,参考本地文件:TensorFlow2.0GPU安装教程.pdf

拓展:

1、TensorFlow 所需的硬件配置

在很多人的刻板印象中,TensorFlow 乃至深度学习是一件非常 “吃硬件” 的事情,以至于一接触 TensorFlow,第一件事情可能就是想如何升级自己的电脑硬件。不过,TensorFlow 所需的硬件配置很大程度是视任务和使用环境而定的:

  • 对于 TensorFlow 初学者,大部分教学示例,大部分当前主流的个人电脑(即使没有 GPU)均可胜任,无需添置其他硬件设备。如果涉及计算量较大的示例(例如 在 cats_vs_dogs 数据集上训练 CNN 图像分类),一块主流的 NVIDIA GPU 会大幅加速训练。如果自己的个人电脑难以胜任,可以考虑在云端训练
  • 对于参加数据科学竞赛(比如 Kaggle)或者经常在本机进行训练的个人爱好者或开发者,一块高性能的 NVIDIA GPU 往往是必要的。核心数和显存大小是决定显卡机器学习性能的两个关键参数,前者决定训练速度,后者决定可以训练多大的模型以及训练时的最大 Batch Size,对于较大规模的训练而言尤其敏感。
  • 对于前沿的机器学习研究(尤其是计算机视觉和自然语言处理领域),多 GPU 并行训练是标准配置。为了快速迭代实验结果以及训练更大规模的模型以提升性能,4 卡、8 卡或更高达到10块的 GPU 数量是常态。

2、常见显卡速度对比,以及目前较好的显卡对比,详情请参考官网:https://developer.nvidia.com/cuda-gpus

  • CUDA compute capability,这是英伟达公司对显卡计算能力的一个衡量指标;

  • FLOPS 每秒浮点运算次数,TFLOPS表示每秒万亿(10^12)次浮点计算;

  • 显存大小也决定了实验中能够使用的样本数量和模型复杂度, 越高越好。

两种主要系列:

GTX 系列显卡优缺点:优点:单精度计算能力强大,显存最大12Gb,性价比高;缺点:双精度计算能力弱,没有计算纠错ECC 内存,对于超高精度计算不利

Tesla 优缺点优点:双精度计算能力最强,拥有ECC内存增强计算准确率,缺点:单精度计算能力差,价格较高

GeForce and TITAN 系列:

GPU Compute Capability
NVIDIA TITAN RTX 7.5
Geforce RTX 2080 Ti 7.5
Geforce RTX 2080 7.5
Geforce RTX 2070 7.5
Geforce RTX 2060 7.5
NVIDIA TITAN V 7.0
NVIDIA TITAN Xp 6.1
NVIDIA TITAN X 6.1
GeForce GTX 1080 Ti 6.1

Tesla系列:

GPU Compute Capability
Tesla T4 7.5
Tesla V100 7.0
Tesla P100 6.0
Tesla P40 6.1
Tesla P4 6.1
Tesla M60 5.2
Tesla M40 5.2
Tesla K80 3.7
Tesla K40 3.5

4.1.4 tf.keras介绍

Keras是一个用Python编写的开源神经网络库。它能够运行在TensorFlow,Microsoft Cognitive Toolkit,Theano或PlaidML之上。TensorFlow 1.9 新增 tf.keras,Keras与TF的深度集成。

为什么选择 Keras?

在如今无数深度学习框架中,为什么要使用 Keras 而非其他?以下是 Keras 与现有替代品的一些比较。

  • Keras 遵循减少认知困难的最佳实践: 它提供一致且简单的 API,它将常见用例所需的用户操作数量降至最低,并且在用户错误时提供清晰和可操作的反馈。
  • 因为 Keras 与底层深度学习语言(特别是 TensorFlow)集成在一起,所以它可以让你实现任何你可以用基础语言编写的东西。特别是,tf.keras 作为 Keras API 可以与 TensorFlow 工作流无缝集成。

  • Keras 被工业界和学术界广泛采用

截至 2018 年中期,Keras 拥有超过 250,000 名个人用户。与其他任何深度学习框架相比,Keras 在行业和研究领域的应用率更高(除 TensorFlow 之外,且 Keras API 是 TensorFlow 的官方前端,通过 tf.keras 模块使用)。

  • Keras 拥有强大的多 GPU 和分布式训练支持

    • Keras内置对多 GPU 数据并行的支持。
  • Keras 的发展得到深度学习生态系统中的关键公司的支持

Keras API 以 tf.keras 的形式包装在 TensorFlow 中。

4.1.4.1 tf.keras与keras API

keras与tf.keras相关API设置一样,主要有以下常用模块

  • applications 模块:Keras应用程序是具有预训练权重的固定架构。

  • callbacks module:回调:在模型训练期间在某些点调用的实用程序。

  • datasets module:Keras内置数据集。

  • initializers 模块:Keras初始化器序列化/反序列化。

  • layers 模块:Keras层API。

  • losses 模块:内置损失功能。

  • metrics 模块:内置指标。

  • models module:模型克隆代码,以及与模型相关的API。

  • optimizers module:内置优化器类。

  • preprocessing 模块:Keras数据预处理工具。

  • regularizers 模块:内置正规化器。

  • utils 模块:Keras实用程序。

4.1.4.2 tf.keras 数据集

1、CIFAR10 小图片分类数据

50000张32x32大小的训练数据和10000张测试数据,总共100个类别。

from keras.datasets import cifar100

(x_train, y_train), (x_test, y_test) = cifar100.load_data()
  • 返回值:
    • 两个元组:
      • x_train, x_test: uint8 数组表示的 RGB 图像数据,尺寸为 (num_samples, 3, 32, 32) 或 (num_samples, 32, 32, 3),基于 image_data_format 后端设定的 channels_first 或 channels_last
      • y_train, y_test: uint8 数组表示的类别标签,尺寸为 (num_samples,)。
1、默认下载置于用户目录的 `.keras/dataset` 目录下(Windows 下用户目录为 C:\Users\用户名 ,Linux 下用户目录为 `/home/用户名` )
2、mnist = tf.keras.datasets.mnist将从网络上自动下载 MNIST 数据集并加载。如果运行时出现网络连接错误,可以从 https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 或 https://s3.amazonaws.com/img-datasets/mnist.npz 下载 MNIST 数据集 mnist.npz文件

2、时装分类Mnist数据集

60,000张28x28总共10个类别的灰色图片,10,000张用于测试。

类别编号 类别
0 T-shirt/top
1 Trouser
2 Pullover
3 Dress
4 Coat
5 Sandal
6 Shirt
7 Sneaker
8 Bag
9 Ankle boot
from keras.datasets import fashion_mnist

(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
  • 返回两个元组:
    • x_train, x_test: uint8 数组表示的灰度图像,尺寸为 (num_samples, 28, 28)。
    • y_train, y_test: uint8 数组表示的数字标签(范围在 0-9 之间的整数),尺寸为 (num_samples,)。

4.1.5 总结

  • Tensorflow框架的组成、接口
  • TensorFlow框架的安装
  • tf.keras的特点和使用

4.2 TensorFlow基础

4.2.1 Tensorflow 计算

TensorFlow 视为一个科学计算库。导入TensorFlow

import tensorflow as tf

TensorFlow 使用 张量 (Tensor)作为数据的基本单位。TensorFlow 的张量在概念上等同于多维数组,我们可以使用它来描述数学中的标量(0 维数组)、向量(1 维数组)、矩阵(2 维数组)等各种量,示例如下:

# 定义一个随机数(标量)
random_float = tf.random.uniform(shape=())

# 定义一个有2个元素的零向量
zero_vector = tf.zeros(shape=(2))

# 定义两个2×2的常量矩阵
A = tf.constant([[1., 2.], [3., 4.]])
B = tf.constant([[5., 6.], [7., 8.]])

张量的重要属性是其形状、类型和值。可以通过张量的 shape 、 dtype 属性和 numpy() 方法获得。例如:

# 查看矩阵A的形状、类型和值
print(A.shape)      # 输出(2, 2),即矩阵的长和宽均为2
print(A.dtype)      # 输出<dtype: 'float32'>
print(A.numpy())    # 输出[[1. 2.]
                    #      [3. 4.]]

4.2.1.1 张量的类型

4.2.1.2 张量的阶

4.2.2 张量操作

  • 固定值张量

  • 随机值张量

  • 张量的变换

类型变换

  • 张量的数学运算

  • 算术运算符

  • 基本数学函数
  • 矩阵运算
  • reduce操作
  • 序列索引操作

参考官网链接:https://www.tensorflow.org/api_docs/python/tf/Tensor

4.2.3 自动求导机制

在机器学习中,我们经常需要计算函数的导数。TensorFlow 提供了强大的自动求导机制来计算导数。

import tensorflow as tf

x = tf.Variable(initial_value=3.)
with tf.GradientTape() as tape:     # 在 tf.GradientTape() 的上下文内,所有计算步骤都会被记录以用于求导
    y = tf.square(x)
y_grad = tape.gradient(y, x)        # 计算y关于x的导数
print([y, y_grad])

输出:

[array([9.], dtype=float32), array([6.], dtype=float32)]
  • 1、这里x是一个初始化为 3 的 变量 (Variable),使用 tf.Variable()声明。与普通张量一样,变量同样具有形状、类型和值三种属性。使用变量需要有一个初始化过程,可以通过在 tf.Variable()中指定 initial_value 参数来指定初始值。

    • 变量与普通张量的一个重要区别是其默认能够被 TensorFlow 的自动求导机制所求导,因此往往被用于定义机器学习模型的参数。
  • tf.GradientTape() 是一个自动求导的记录器,在其中的变量和计算步骤都会被自动记录。在上面的示例中,变量 x和计算步骤 y = tf.square(x) 被自动记录,因此可以通过 y_grad = tape.gradient(y, x) 求张量 y 对变量 x 的导数。

2、多元函数求导

通常我们实际应用中更多的是对多元函数求偏导数,以及对向量或矩阵的求导。如下面例子:

X = tf.constant([[1, 2], [3., 4.]])
y = tf.constant([[1], [2.]])
w = tf.Variable(initial_value=[[1.], [2.]])
b = tf.Variable(initial_value=1.)
with tf.GradientTape() as tape:
    L = 0.5 * tf.reduce_sum(tf.square(tf.matmul(X, w) + b - y))
w_grad, b_grad = tape.gradient(L, [w, b])
print([L.numpy(), w_grad.numpy(), b_grad.numpy()])

输出:

[62.5, array([[35.],
       [50.]], dtype=float32), 15.0]

求导公式如下:

  • 1、tf.reduce_sum()操作代表对输入张量的所有元素求和,输出一个形状为空的纯量张量(可以通过 axis 参数来指定求和的维度,不指定则默认对所有元素求和)

4.2.4 案例:线性回归

考虑一个实际问题,某城市在 2013 年 - 2017 年的房价如下表所示:

年份 2013 2014 2015 2016 2017
房价 12000 14000 15000 16500 17500

现在,我们希望通过对该数据进行线性回归,即使用线性模型y = ax + by=ax+b来拟合上述数据,此处 a 和 b 是待求的参数。首先,我们定义数据,进行基本的归一化操作。

import numpy as np

X_raw = np.array([2013, 2014, 2015, 2016, 2017], dtype=np.float32)
y_raw = np.array([12000, 14000, 15000, 16500, 17500], dtype=np.float32)

X = (X_raw - X_raw.min()) / (X_raw.max() - X_raw.min())
y = (y_raw - y_raw.min()) / (y_raw.max() - y_raw.min())

https://zh.wikipedia.org/wiki/%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E6%B3%95

1、NumPy 下的线性回归

NumPy 提供了多维数组支持,可以表示向量、矩阵以及更高维的张量。下面为实现过程:

a, b = 0, 0
num_epoch = 10000
learning_rate = 1e-3
for e in range(num_epoch):
    # 手动计算损失函数关于自变量(模型参数)的梯度
    y_pred = a * X + b
    grad_a, grad_b = (y_pred - y).dot(X), (y_pred - y).sum()

    # 更新参数
    a, b = a - learning_rate * grad_a, b - learning_rate * grad_b
print(a, b)

使用常规的科学计算库实现机器学习模型的问题:

  • 1、需要手工求函数关于参数的偏导数,但一旦函数的形式变得复杂(尤其是深度学习模型),手工求导的过程将变得非常痛苦,甚至不可行。
  • 2、需要手工根据求导的结果更新参数。这里使用了最基础的梯度下降方法,因此参数的更新还较为容易。但如果使用更加复杂的参数更新方法(例如 Adam 或者 Adagrad),这个更新过程的编写同样会非常繁杂。

而 TensorFlow 等深度学习框架的出现很大程度上解决了这些痛点,为机器学习模型的实现带来了很大的便利。

2、TensorFlow 下的线性回归

TensorFlow 的 Eager Execution(动态图)模式与上述 NumPy 的运行方式十分类似,然而提供了更快速的运算(GPU 支持)、自动求导、优化器等一系列对深度学习非常重要的功能。

  • 使用 tape.gradient(ys, xs) 自动计算梯度;
  • 使用 optimizer.apply_gradients(grads_and_vars) 自动更新模型参数。
  • 使用tf.keras.optimizers.SGD(learning_rate=)进行指定优化器
# 1、定义Tensor类型
X = tf.constant(X)
y = tf.constant(y)

# 2、参数使用变量初始化
a = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)
variables = [a, b]

num_epoch = 10000
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)
for e in range(num_epoch):
    # 使用tf.GradientTape()记录损失函数的梯度信息
    with tf.GradientTape() as tape:
        y_pred = a * X + b
        loss = 0.5 * tf.reduce_sum(tf.square(y_pred - y))
    # TensorFlow自动计算损失函数关于自变量(模型参数)的梯度
    grads = tape.gradient(loss, variables)
    # TensorFlow自动根据梯度更新参数
    optimizer.apply_gradients(grads_and_vars=zip(grads, variables))

print(a, b)
  • tf.keras.optimizers.SGD(learning_rate=1e-3) 声明了一个梯度下降 优化器 (Optimizer),其学习率为 1e-3。优化器可以帮助我们根据计算出的求导结果更新模型参数,从而最小化某个特定的损失函数,具体使用方式是调用其 apply_gradients() 方法。
  • 更新模型参数的方法 optimizer.apply_gradients() 需要提供参数 grads_and_vars,具体而言,这里需要传入一个 Python 列表(List),列表中的每个元素是一个 (变量的偏导数,变量) 对,比如这里是 [(grad_a, a), (grad_b, b)]。

在实际应用中,我们编写的模型往往比这里一行就能写完的线性模型 y = a * x + b 要复杂得多。所以,我们往往会编写并实例化一个模型类model = Model(),然后使用 y_pred = model(X)调用模型,使用 model.variables 获取模型参数。

4.2.5 总结

  • TensorFlow基本张量操作
  • TensorFlow自动求导机制

gradient.py 

import tensorflow as tf


def main():

    # 1、单变量函数导数 y = x^2
    # x = tf.Variable(initial_value=3.)
    #
    # with tf.GradientTape() as tape:
    #     y = tf.square(x)
    #
    # # 使用tape中的gradient的方法计算导数
    # y_grad = tape.gradient(y, x)
    # print(y, y_grad)

    # 2、多元函数求导
    # X = tf.constant([[1., 2.], [3., 4.]])
    #     # y = tf.constant([[1.], [2.]])
    #     # # 函数参数
    #     # w = tf.Variable(initial_value=[[1.], [2.]])
    #     # b = tf.Variable(initial_value=1.)
    #     #
    #     # with tf.GradientTape() as tape:
    #     #     L = 0.5 * tf.reduce_sum(tf.square(tf.matmul(X, w) + b - y))
    #     #
    #     # w_grad, b_grad = tape.gradient(L, [w, b])
    #     # print(L.numpy(), w_grad.numpy(), b_grad.numpy())

    # 3、线性回归求解模型参数
    import numpy as np

    X_raw = np.array([2013, 2014, 2015, 2016, 2017], dtype=np.float32)
    y_raw = np.array([12000, 14000, 15000, 16500, 17500], dtype=np.float32)

    X = (X_raw - X_raw.min()) / (X_raw.max() - X_raw.min())
    y = (y_raw - y_raw.min()) / (y_raw.max() - y_raw.min())


    # 1、定义好数据类型以及参数类型
    X = tf.constant(X)
    y = tf.constant(y)

    a = tf.Variable(initial_value=0.)
    b = tf.Variable(initial_value=0.)
    variables = [a, b]

    # 2、应用gradientTape进行迭代计算导数更新
    num_epoch = 1000
    optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)
    for i in range(num_epoch):
        # gradientTape
        with tf.GradientTape() as tape:
            y_pred = a * X + b
            loss = 0.5 * tf.reduce_sum(tf.square(y_pred - y))

        # tensorflow自动求导
        grads = tape.gradient(loss, variables)

        # 进行梯度更新参数
        optimizer.apply_gradients(grads_and_vars=zip(grads, variables))

    print(a, b)
    return None


# 1、定义一个线性回归模型
class Linear(tf.keras.Model):
    """自定义线性回归类
    """
    def __init__(self):
        super(Linear, self).__init__()
        # 实现一个线性回归层
        self.dense = tf.keras.layers.Dense(
            units=1,
            activation=None,
            kernel_initializer=tf.zeros_initializer(),
            bias_initializer=tf.zeros_initializer()
        )

    def call(self, input):
        """调用模型的实现函数
        :param input: 模型输入值
        :return: 模型输出值
        """
        output = self.dense(input)
        return output


def linear_with_model():

    X = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    y = tf.constant([[10.0], [20.0]])

    # 2、进行训练步骤定义
    model = Linear()
    optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
    for i in range(100):
        with tf.GradientTape() as tape:
            y_pred = model(X)
            loss = 0.5 * tf.reduce_mean(tf.square(y_pred - y))

        # 梯度计算和更新
        grads = tape.gradient(loss, model.variables)
        optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

    print(model.variables)
    print(model.layers)
    print(model.inputs)
    print(model.outputs)
    print(model.summary())
    return None


if __name__ == '__main__':
    # main()
    linear_with_model()

4.3 TensorFlow快速入门模型

4.3.1 模型构建-Model与Layer

在 TensorFlow 中,推荐使用 Keras( tf.keras)构建模型。Keras 是一个广为流行的高级神经网络 API,简单、快速而不失灵活性,现已得到 TensorFlow 的官方内置和全面支持。

Keras 有两个重要的概念: 模型(Model) 和 层(Layer) 。

  • 层将各种计算流程和变量进行了封装(例如基本的全连接层,CNN 的卷积层、池化层等)
    • Keras 在tf.keras.layers下内置了深度学习中大量常用的的预定义层,同时也允许我们自定义层。
  • 模型则将各种层进行组织和连接,并封装成一个整体,描述了如何将输入数据通过各种层以及运算而得到输出。在需要模型调用的时候,使用y_pred = model(X)的形式即可。

Keras 模型以类的形式呈现,我们可以通过继承 tf.keras.Model这个 Python 类来定义自己的模型。在继承类中,我们需要重写 __init__() (构造函数,初始化)和 call(input) (模型调用)两个方法,同时也可以根据需要增加自定义的方法。

class MyModel(tf.keras.Model):
    def __init__(self):
        super().__init__()
        # 此处添加初始化代码(包含 call 方法中会用到的层),例如
        # layer1 = tf.keras.layers.BuiltInLayer(...)
        # layer2 = MyCustomLayer(...)

    def call(self, input):
        # 此处添加模型调用的代码(处理输入并返回输出),例如
        # x = layer1(input)
        # output = layer2(x)
        return output

    # 还可以添加自定义的方法

继承 tf.keras.Model 后,我们同时可以使用父类的若干方法和属性,例如在实例化类 model = Model() 后,可以通过 model.variables 这一属性直接获得模型中的所有变量,免去我们一个个显式指定变量的麻烦。

4.3.1.1 案例:使用Model构建模型

对于上面的 y_pred = w * X + b ,我们可以通过模型类的方式编写如下:

import tensorflow as tf

X = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
y = tf.constant([[10.0], [20.0]])

# 1、构建线性模型
class Linear(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.dense = tf.keras.layers.Dense(
            units=1,
            activation=None,
            kernel_initializer=tf.zeros_initializer(),
            bias_initializer=tf.zeros_initializer()
        )

    def call(self, input):
        output = self.dense(input)
        return output


# 以下代码结构与前节类似
model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for i in range(100):
    with tf.GradientTape() as tape:
        y_pred = model(X)
        loss = 0.5 * tf.reduce_mean(tf.square(y_pred - y))
    # 使用 model.variables 这一属性直接获得模型中的所有变量
    grads = tape.gradient(loss, model.variables)
    optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
print(model.variables)

这里,我们没有显式地声明a 和 b 两个变量并写出 y_pred = wX + b 这一线性变换,而是建立了一个继承了 tf.keras.Model 的模型类 Linear 。这个类在初始化部分实例化了一个 全连接层 ( tf.keras.layers.Dense ),并在 call 方法中对这个层进行调用,实现了线性变换的计算。

4.3.1.1 Keras 当中的layer(层)接口

在 Keras 中,您可以通过组合层来构建模型。模型(通常)是由层构成的图。最常见的模型类型是层的堆叠,keras.layers中就有很多模型

from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.layers import DepthwiseConv2D
from tensorflow.python.keras.layers import Dot
from tensorflow.python.keras.layers import Dropout
from tensorflow.python.keras.layers import ELU
from tensorflow.python.keras.layers import Embedding
from tensorflow.python.keras.layers import Flatten
from tensorflow.python.keras.layers import GRU
from tensorflow.python.keras.layers import GRUCell
from tensorflow.python.keras.layers import LSTMCell

Dense:添加一层神经元

  • Dense(units,activation=None,**kwargs)
    • units:神经元个数
    • activation:激活函数,参考tf.nn.relu,tf.nn.softmax,tf.nn.sigmoid,tf.nn.tanh
    • **kwargs:输入上层输入的形状,input_shape=()

4.3.1.2 Models

Model(inputs=a, outputs=b)

  • inputs:定义模型的输入,Input类型
  • outpts:定义模型的输出
  • def call(self, inputs):接收来自上层的输入

Models属性

  • model.layers:获取模型结构列表
print(model.layers)
[<tensorflow.python.keras.layers.core.Flatten object at 0x10864a780>, <tensorflow.python.keras.layers.core.Dense object at 0x10f95b128>, <tensorflow.python.keras.layers.core.Dense object at 0x125bd6fd0>, <tensorflow.python.keras.layers.core.Dense object at 0x125bf9240>]
  • model.inputs 是模型的输入张量列表
print(model.inputs)
[<tf.Tensor 'flatten_input:0' shape=(?, 28, 28) dtype=float32>]
  • model.outputs 是模型的输出张量列表
print(model.outputs)
[<tf.Tensor 'dense_2/Softmax:0' shape=(?, 10) dtype=float32>]
  • model.summary()打印模型的摘要表示
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 64)                50240     
_________________________________________________________________
dense_1 (Dense)              (None, 128)               8320      
_________________________________________________________________
dense_2 (Dense)              (None, 10)                1290      
=================================================================
Total params: 59,850
Trainable params: 59,850
Non-trainable params: 0

4.3.2 案例:多层感知机(MLP)识别Mnist手写数字

一个最简单的多层感知机(Multilayer Perceptron, MLP),或者说 “多层全连接神经网络” 开始,介绍 TensorFlow 的模型编写方式。

  • 目的:我们使用多层感知机完成 MNIST 手写体数字图片数据集的分类任务

  • 步骤:

    • 1、使用 tf.keras.datasets 获得数据集并预处理
    • 2、使用 tf.keras.Model 和 tf.keras.layers 构建模型
    • 3、构建模型训练流程,使用 tf.keras.losses 计算损失函数,并使用 tf.keras.optimizer 优化模型
    • 4、构建模型评估流程,使用 tf.keras.metrics 计算评估指标

1、数据获取及预处理: tf.keras.datasets

先进行预备工作,实现一个简单的 MNISTLoader 类来读取 MNIST 数据集数据。这里使用了 tf.keras.datasets 快速载入 MNIST 数据集。

import tensorflow as tf
import numpy as np
class MNISTLoader(object):
    """数据加载处理类
    """
    def __init__(self):
        """
        """
        # 1、获取数据    
        (self.train_data, self.train_label), (self.test_data, self.test_label) = tf.keras.datasets.mnist.load_data()
        # 2、处理数据,归一化,维度以及类型
        # MNIST中的图像默认为uint8(0-255的数字)。以下代码将其归一化到0-1之间的浮点数,并在最后增加一维作为颜色通道
        # 默认下载是(60000, 28, 28),扩展到四维方便计算理解[60000, 28, 28, 1]
        self.train_data = np.expand_dims(self.train_data.astype(np.float32) / 255.0, axis=-1)
        # [10000, 28, 28, 1]
        self.test_data = np.expand_dims(self.test_data.astype(np.float32) / 255.0, axis=-1)
        self.train_label = self.train_label.astype(np.int32)    # [60000]
        self.test_label = self.test_label.astype(np.int32)      # [10000]
        # 获取数据的大小
        self.num_train_data, self.num_test_data = self.train_data.shape[0], self.test_data.shape[0]

    def get_batch(self, batch_size):
        """
        随机获取获取批次数据
        :param batch_size: 批次大小
        :return:
        """
        # 从数据集中随机取出batch_size个元素并返回
        index = np.random.randint(0, np.shape(self.train_data)[0], batch_size)
        return self.train_data[index, :], self.train_label[index]


if __name__ == '__main__':
    mnist = MNISTLoader()
    train_data, train_label = mnist.get_batch(50)
    print(train_data.shape, train_label)

注:在 TensorFlow 中,图像数据集的一种典型表示是 [图像数目,长,宽,色彩通道数]的四维张量。

2、模型的构建:tf.keras.Model 和 tf.keras.layers

多层感知机的模型类实现与上面的线性模型类似,使用 tf.keras.Model 和 tf.keras.layers 构建,引入了非线性激活函数(这里使用了 ReLU 函数 , 即下方的 activation=tf.nn.relu ),模型输出 10 维的向量,分别代表这张图片属于 0 到 9 的概率。

  • 为了使得模型的输出能始终满足这两个条件,我们使用 Softmax 函数 (归一化指数函数, tf.nn.softmax )对模型的原始输出进行归一化。
class MLP(tf.keras.Model):
    """自定义MLP类
    """
    def __init__(self):
        super().__init__()
        # 定义两层神经网络,第一层100个神经元,激活函数relu,第二层10个神经元输出给softmax
        self.flatten = tf.keras.layers.Flatten()
        self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(units=10)

    def call(self, inputs):
        # [batch_size, 28, 28, 1]
        x = self.flatten(inputs)
        # [batch_size, 784]
        x = self.dense1(x)
        # [batch_size, 100]
        x = self.dense2(x)
        # [batch_size, 10]
        output = tf.nn.softmax(x)
        return output

3、模型的训练: tf.keras.losses 和 tf.keras.optimizer

定义一些模型超参数:

num_epochs = 5
batch_size = 50
learning_rate = 0.001

然后迭代进行以下步骤:

  • 1、从 DataLoader 中随机取一批训练数据;

  • 2、将这批数据送入模型,计算出模型的预测值;

  • 3、将模型预测值与真实值进行比较,计算损失函数(loss)。这里使用 tf.keras.losses 中的交叉熵函数作为损失函数;

  • 4、计算损失函数关于模型变量的导数;

  • 5、将求出的导数值传入优化器,使用优化器的 apply_gradients 方法更新模型参数以最小化损失函数(优化器的详细使用方法见 前章 )。

具体代码实现

# 实例化模型和数据读取类,并实例化一个优化器,这里使用 Adam 优化器
model = MLP()
data_loader = MNISTLoader()
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
# 计算出大概需要迭代批次大小
num_batches = int(data_loader.num_train_data // batch_size * num_epochs)
        # 进行批次数据获取
    for batch_index in range(num_batches):
        X, y = data_loader.get_batch(batch_size)
        with tf.GradientTape() as tape:
            y_pred = model(X)
            # 使用tf.keras.losses计算损失
            loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
            # 求出平均损失
            loss = tf.reduce_mean(loss)
            print("batch %d: loss %f" % (batch_index, loss.numpy()))
        grads = tape.gradient(loss, model.variables)
        optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

注:在 tf.keras中,有两个交叉熵相关的损失函数 tf.keras.losses.categorical_crossentropy 和 tf.keras.losses.sparse_categorical_crossentropy 。其中 sparse 的含义是,真实的标签值 y_true可以直接传入 int 类型的标签类别。具体而言:

loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)

loss = tf.keras.losses.categorical_crossentropy(
    y_true=tf.one_hot(y, depth=tf.shape(y_pred)[-1]),
    y_pred=y_pred
)

的结果相同。

4、模型的评估: tf.keras.metrics

最后,我们使用测试集评估模型的性能。这里,我们使用 tf.keras.metrics 中的 SparseCategoricalAccuracy 评估器来评估模型在测试集上的性能。

  • 迭代测试数据集,每次通过 update_state() 方法向评估器输入两个参数: y_pred 和 y_true ,即模型预测出的结果和真实结果。
  • 使用 result() 方法输出最终的评估指标值(预测正确的样本数占总样本数的比例)。

在以下代码中,我们实例化了一个 tf.keras.metrics.SparseCategoricalAccuracy 评估器,并使用 For 循环迭代分批次传入了测试集数据的预测结果与真实结果,并输出训练后的模型在测试数据集上的准确率。

y_pred = model.predict(data_loader.test_data)
# 定义评估函数
sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
# 定义测试数据集一共批次的大小
sparse_categorical_accuracy.update_state(y_true=data_loader.test_label, y_pred=y_pred)
print("测试准确率: %f" % sparse_categorical_accuracy.result())

输出结果:

测试准确率: 0.972300

4.3.5 总结

  • 模型的构建: tf.keras.Model 和 tf.keras.layers
  • 模型的损失函数: tf.keras.losses
  • 模型的优化器: tf.keras.optimizer
  • 模型的评估: tf.keras.metrics

keras_mlp.py

import tensorflow as tf
import numpy as np
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"

num_epochs = 5
batch_size = 64
learning_rate = 0.001


class MnistLoader(object):
    """数据加载处理类
    """
    def __init__(self):
        # 1、获取数据
        (self.train_data, self.train_label), (self.test_data, self.test_label) = \
            tf.keras.datasets.mnist.load_data()

        # 2、处理数据, 归一化,维度拓展,类型
        self.train_data = np.expand_dims(self.train_data.astype(np.float32) / 255.0, axis=-1)
        self.test_data = np.expand_dims(self.test_data.astype(np.float32) / 255.0, axis=-1)

        self.train_label = self.train_label.astype(np.int32)
        self.test_label = self.test_label.astype(np.int32)

        # 获取一个变量接收数据量
        self.num_train_data, self.num_test_data = self.train_data.shape[0], self.test_data.shape[0]

    def get_batch(self, batch_size):
        """按照训练获取指定大小数据的批次数据
        :param batch_size: 每批次数据的大小
        :return:
        """
        # 获取随机生成的batch_size大小的下标
        index = np.random.randint(0, self.train_data.shape[0], batch_size)
        return self.train_data[index, :], self.train_label[index]


class MLP(tf.keras.Model):
    """自定义MLP类
    """
    def __init__(self):
        super().__init__()
        # 卷积到全连接层的数据形状处理
        self.flatten = tf.keras.layers.Flatten()
        self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(units=10)

    def call(self, inputs):
        """
        :param inputs: 模型的输入
        :return:
        """
        # 此例子中输入[batch_size, 28 ,28, 1]
        x = self.flatten(inputs)
        x = self.dense1(x)
        x = self.dense2(x)

        # 经过softmax计算[batch_size, 10]
        output = tf.nn.softmax(x)
        return output


class CNN(tf.keras.Model):
    """自定义CNN类,两层卷积池化+两个全连接层
    """
    def __init__(self):
        super().__init__()
        # 两层卷积池化+两个全连接层
        # [batch_size, 28 ,28, 1]--->[batch_size, 14, 14, 32]
        # 第一层:32个filter, 5 * 5, padding=same
        self.conv1 = tf.keras.layers.Conv2D(
            filters=32,  # 卷积核数量
            kernel_size=[5, 5],  # 卷积核大小
            padding='same',  # 领填充方式
            activation=tf.nn.relu  # 激活函数
        )
        self.pool1 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)

        # 第二层:64个filter, 5 * 5, padding=same
        # [batch_size, 14 ,14, 32]--->[batch_size, 7, 7, 64]
        self.conv2 = tf.keras.layers.Conv2D(
            filters=64,  # 卷积核数量
            kernel_size=[5, 5],  # 卷积核大小
            padding='same',  # 领填充方式
            activation=tf.nn.relu  # 激活函数
        )
        self.pool2 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)

        # 经过一个形状变化在输入到全连接层网络
        self.flatten = tf.keras.layers.Reshape(target_shape=(7 * 7 * 64,))
        self.dense1 = tf.keras.layers.Dense(units=1024, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(units=10)

    def call(self, inputs):
        """模型输入输出构建
        :param inputs: 输入[batch_size, 28 ,28, 1]
        :return:
        """
        x = self.conv1(inputs)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.pool2(x)
        x = self.flatten(x)
        x = self.dense1(x)
        x = self.dense2(x)
        output = tf.nn.softmax(x)
        return output


def train():
    """模型训练逻辑
    :return:
    """

    # 1、从 DataLoader 中随机取一批训练数据,并且初始化模型
    mnist = MnistLoader()
    # model = MLP()
    model = CNN()
    optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)

    # 2、将这批数据送入模型,计算出模型的预测值;
    # 总共样本len(train_data), 迭代次数epoches表示所有数据过几遍,batch_size:每批次训练的样本32, 64
    # 一共需要多少批次 len(train_data)/ batch_size * epoches举例 1000/10 = 10批次才训练完成,10 * 5
    num_batches = int(mnist.num_train_data // batch_size * num_epochs)
    for batch_index in range(num_batches):
        X, y = mnist.get_batch(batch_size)
        with tf.GradientTape() as tape:
            y_pred = model(X)

            # 3、将模型预测值与真实值进行比较,计算损失函数(loss)。这里使用
            # tf.keras.losses 中的交叉熵函数作为损失函数;
            loss = tf.reduce_mean(tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred))
            print("批次 %d: 损失 %f" % (batch_index, loss.numpy()))

        # 4、计算损失函数关于模型变量的导数;
        grads = tape.gradient(loss, model.variables)

        # 5、将求出的导数值传入优化器,使用优化器的 apply_gradients 方法更新模型参数以最小化损失函数(优化器的详细使用方法见 前章 )。
        optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

    # 3、对测试数据及进行评估
    y_pred = model.predict(mnist.test_data)
    # 初始化一个metrics
    sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
    sparse_categorical_accuracy.update_state(y_true=mnist.test_label, y_pred=y_pred)
    print("测试准确率:%f" % (sparse_categorical_accuracy.result()))

    return None


if __name__ == '__main__':
    # mnist = MnistLoader()
    # train_data, train_label = mnist.get_batch(64)
    # print(train_data, train_label)
    train()

tfrecords_example.py

import os
import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"

train_cats_dir = './cats_vs_dogs/train/cats/'
train_dogs_dir = './cats_vs_dogs/train/dogs/'
tfrecord_file = './cats_vs_dogs/train.tfrecords'


def main():

    train_cat_filenames = [train_cats_dir + filename for filename in os.listdir(train_cats_dir)]
    train_dog_filenames = [train_dogs_dir + filename for filename in os.listdir(train_dogs_dir)]
    train_filenames = train_cat_filenames + train_dog_filenames
    # 将 cat 类的标签设为0,dog 类的标签设为1
    train_labels = [0] * len(train_cat_filenames) + [1] * len(train_dog_filenames)

    with tf.io.TFRecordWriter(tfrecord_file) as writer:
        for filename, label in zip(train_filenames, train_labels):
            # 1、读取数据集图片到内存,image 为一个 Byte 类型的字符串
            image = open(filename, 'rb').read()
            # 2、建立 tf.train.Feature 字典
            feature = {
                'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),  # 图片是一个 Bytes 对象
                'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))  # 标签是一个 Int 对象
            }
            # 3、通过字典建立 Example
            example = tf.train.Example(features=tf.train.Features(feature=feature))
            # 4\将Example序列化并写入 TFRecord 文件
            writer.write(example.SerializeToString())


def read():

    # 1、读取 TFRecord 文件
    raw_dataset = tf.data.TFRecordDataset(tfrecord_file)

    # 2、定义Feature结构,告诉解码器每个Feature的类型是什么
    feature_description = {
        'image': tf.io.FixedLenFeature([], tf.string),
        'label': tf.io.FixedLenFeature([], tf.int64),
    }

    # 3、将 TFRecord 文件中的每一个序列化的 tf.train.Example 解码
    def _parse_example(example_string):
        feature_dict = tf.io.parse_single_example(example_string, feature_description)
        feature_dict['image'] = tf.io.decode_jpeg(feature_dict['image'])  # 解码JPEG图片
        return feature_dict['image'], feature_dict['label']

    dataset = raw_dataset.map(_parse_example)

    for image, label in dataset:
        print(image, label)


if __name__ == '__main__':
    # main()
    read()

model_serving.py

import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"


def main():
    num_epochs = 1
    batch_size = 32
    learning_rate = 0.001

    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(120, activation=tf.nn.relu),
        tf.keras.layers.Dense(100),
        tf.keras.layers.Softmax()
    ])

    (train, train_label), (test, test_label) = \
                tf.keras.datasets.cifar100.load_data()

    model.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),
        loss=tf.keras.losses.sparse_categorical_crossentropy,
        metrics=[tf.keras.metrics.sparse_categorical_accuracy]
    )
    model.fit(train, train_label, epochs=num_epochs, batch_size=batch_size)

    tf.saved_model.save(model, "./saved/mlp/2")


def test():

    model = tf.saved_model.load("./saved/mlp/2")

    (_, _), (test, test_label) = \
        tf.keras.datasets.cifar100.load_data()

    y_predict = model(test)

    sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
    sparse_categorical_accuracy.update_state(y_true=test_label, y_pred=y_predict)
    print("测试集的准确率为: %f" % sparse_categorical_accuracy.result())


def client():
    import json
    import numpy as np
    import requests

    (_, _), (test, test_label) = \
        tf.keras.datasets.cifar100.load_data()

    # 1、构造好请求
    data = json.dumps({"instances": test[:10].tolist()})
    headers = {"content-type": "application/json"}

    json_response = requests.post('http://localhost:8501/v1/models/mlp:predict',
                                  data=data, headers=headers)

    predictions = np.array(json.loads(json_response.text)['predictions'])
    print(predictions)
    print(np.argmax(predictions, axis=-1))
    print(test_label[:10])


if __name__ == '__main__':
    # main()
    # test()
    client()
发布了389 篇原创文章 · 获赞 129 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/zimiao552147572/article/details/104970029