大多数浏览器和
Developer App 均支持流媒体播放。
-
用 Metal Performance Shaders 图形 构建自定义 ML 模型
了解能够将 Metal 的计算能力提升至多维张量的 Metal Performance Shader(MPS)图形。MPS 图形基于对机器学习极为重要的高效数据并行图元资料库,并充分利用了 GPU 的强大功能。探索 MPS 如何协助实现复杂的动态神经网络训练架构,并通过对其优化来提升 GPU 速度。 若希望对此部分所提到的概念进行更为深入的理解,请观看 WWDC19 “机器学习方面的 Metal 应用”视频。
资源
相关视频
WWDC21
Tech Talks
WWDC19
-
下载
(你好 WWDC 2020)
你好 欢迎参加 WWDC (用 Metal Performance Shaders 图形 构建自定义 ML 模型) 嗨 我叫 Dhruv 是 Apple 的图形处理器软件工程师 我要谈论的是如何用 全新 Metal Performance Shaders 图形 实现自定义机器学习运算 我们开始吧 MPS 是一个基于 Metal 的高性能 图形处理器加速图元库 该图元适用于各个领域 如图像处理 线性代数、光线追踪和机器学习
MPS 团队对 Metal 内核进行优化 使其在 Apple 的各种平台上的 每种硬件上都能获得最佳性能 (Metal Performance Shaders) 我们今天有一组激动人心的新功能要讨论 我们会谈论在 MPS 上进行的性能改进 探讨如何利用机器学习中的 全 32 位浮点支持…
展示新的 MPSNDArray 图元 最后 我们将介绍全新的 Metal Performance Shaders 图形
请允许我谈谈我们 为 MPS 中的图像处理 添加的一些绝佳改进 我们调整和改进了距离变换滤镜 在 Final Cut Pro 中 它使功能速度提高了 15 倍 MPS 还有一个新的 使用 EDLines 算法的边缘检测图元 它改进了测距仪 app 使其速度加快了 10 倍 从而能以更高的分辨率 进行更好的线段检测
我们还扩展了对 CNN 图元的支持 (MPSCNN 更新) 我们现在完全支持 FP32 卷积 以及全连接图元 因此开发人员无需重新计算超参数 或重构代码来获得同样的精确度
要实现这一点 请在数据源提供程序上 实现 kernelWeightsDataType 方法 并将其设置为 float32
有关如何实现 卷积数据源提供程序的详细信息 请参阅我们前几年的讲座 (用 METAL 加速机器学习 - WWDC18)
有一个名为 MPSNDArray 的 新的 MPS 图元 MPSNDArray 和相应的运算 可支持多达 16 个维度 这对于机器学习和其它各种科学领域来说 绰绰有余 而且 只要你能将其装入内存 这个新图元 对维度尺寸没有任何限制
要创建 MPSNDArray 首先用 MPSNDArrayDescriptor 来指定元素的形状和数据类型 然后将其与要分配 MPSNDArray 的 Metal 设备一起传递给初始化器
MPSNDArray 提供 与现有的基于 MTLTexture 的 MPSImageBatch 类型之间的转换器
它甚至可以用 Metal 缓冲区导入和导出数据
现在让我们来谈谈重要的部分 全新的 Metal Performance Shaders 图形框架
MPSGraph 在堆栈中位于 MPS 框架顶部 我们用它来将 Metal 的计算功能 扩展到多维张量
新的 MPSGraph 框架将与 MPS 框架一样 在 macOS、iOS、iPadOS 和 tvOS 上得到支持
你可以从 Xcode 的“构建阶段”标签 将新框架包含在项目中 它就在 Metal Performance Shaders 框架旁边
我们有很多东西要讲 我们会介绍新的 MPSGraph 谈谈可用于编写自定义计算函数的 不同 API 最后看看编写和执行机器学习训练图形
让我们先来看看 MPSGraph 的基础知识
MPSGraph 代表运算和张量的 DAG
运算是代表计算单元的图形节点 这里有三个基本数学运算的例子 乘法、加法、减法
与运算一起 张量是定义图形中数据流的图形边缘 在例子中 我们可以看到 张量在流经我们的基本数学运算
这一符号表征 使我们能抽象出大量数据图元 并提供一个统一的接口 以获得最佳的图形处理器性能
MPSGraph 对象保留 对使用图形上的方法创建的 所有张量和运算的所有权
MPSGraphTensors 代表数据的符号抽象 它由形状、数据类型 和对负责创建张量的运算的引用组成
这里我们可以看到 如何通过调用图形上的常量方法 来创建 constantTensor
图形中的运算通过三种边缘相互连接…
输入张量 代表作为运算数据输入的张量…
输出张量 由运算本身创建…
最后是一种称为控制依赖的特殊边缘
这些是图形会在当前运算之前 执行的一组运算 即便该运算本身不依赖于这组运算
就像常量运算一样 运算可通过 调用图形上简单直观的方法来创建 我们来看看如何在图形中添加两个张量
MPSGraph 提供大量运算 来操作图形中的张量 例如 可将一维张量 重塑成二维张量
可以分开该张量 取其中一小部分
可将这部分连接回原来的张量 以创建更大的张量
可在任何维度上转置张量
最后 你甚至可以创建 一个长度为零的部分 MPSGraph 支持尺寸为零的张量 这使一些动态用例成为可能 比如可变长度序列上的递归神经网络运算
我们支持 MPSGraph 上的大量运算 从卷积和归约的多种变体 到计算图形中可能需要的 所有基本数学运算
让我们开始组合其中一些运算 以便用我们的第一个 MPSGraph 创建并执行自定义计算函数
近年来 机器学习研究发现了 进行自然语言处理的新方法 其中一个创新是用于 BERT 的 一种新的激活函数
这种激活被称为高斯误差线性单元 俗称 GeLU
在例子中 我们会尝试使用 MPSGraph 在图形处理器上 实现一个自定义 GeLU 函数
这是一个简单的三步流程 定义图形的输入 编写一组要执行的运算 最后在提供的数据上执行图形
让我们从定义图形的输入开始
我们的 GeLU 激活函数由单个输入组成
输入张量使用图形中的占位符运算创建 顾名思义 在运行时充当占位符 它们被调用者提供的输入数据所代替
我们在此处展示 API 调用 以创建有三列两行的 float32 类型的 示例占位符
用户可能有不同尺寸的输入 输入到只有在运行时才知道的图形 例如 在机器学习领域 用户经常传递可变长度序列 或不同批大小的输入图像
对于这些情况 MPSGraph 支持 动态尺寸的占位符 只需将维度的尺寸指定为 -1 图形会在运行时评估 来自相应的 fed 输入的形状
即便传入输入的维数未知 只需向占位符形状传递一个空值 MPSGraph 完全支持类型推断 并会在运行时将形状传播到整个图形
既然定义了图形的输入 我们可以进入第二步 在图形中写出自定义计算函数
通常 我们希望在神经网络的各个点 使用 GeLU 激活 对于模块化 我们会在图形上 定义以张量作为输入的辅助函数 让我们添加必要的运算 以将激活应用于给定的输入张量
首先 让我们定义一些 用于 GeLU 神经元的常量
我们只需在图形上调用 传递了标量的常量方法 并将其设置为 float32 dataType
接下来是一个一元数学运算:即平方根
MPSGraph 提供基本的一元数学运算 我们只需要用半常量张量作为输入 在图形上调用 squareRoot 方法
现在准备好了常量和输入 我们开始用几个乘法进行一些计算
这些运算隐式支持广播 因此将自动推断结果张量形状 与输入到神经元的形状相同
我们将两个输入张量传递到 图形上的乘法方法来实现这一点
这个小一元方法 是 GeLU 神经元的核心部分 被称为误差函数
再一次 我们只需将输入传递到一元运算 并在左侧返回输出张量 为进一步的计算做好准备
最后 我们用加法和乘法完成激活
和以前一样 我们创建二进制数学运算 乘法的输出从 GeLU 函数返回
我们成功并相当轻松地构建了 代表 GeLU 神经元的运算图形
我们可以用第三个 也是最后一个步骤来完成 这就是如何执行这个图形
运行图形非常容易 首先 传递映射到图形中的占位符的 feeds 的字典
接下来 指定希望图形评估并返回结果的 targetTensors 列表 这些结果将在左侧的字典中返回
最后 用户可以选择传递 图形保证执行的 targetOperations 列表
如我们所见 在执行时 开发人员可通过 传递 MPSGraphTensorData 对象 来提供占位符 该对象又用相同的 MPSGraphTensorData 对象 返回一组输出
MPSGraphTensorData 有助于 对 Metal 生态系统中可用的 大量数据图元进行抽象 可用 Metal 缓冲区对其进行初始化
可用 MPSImageBatch 创建四维张量数据
我们还对 MPSVectors 和 MPSMatrices 进行抽象 最后 新的 MPSNDArray 图元 也可以用来初始化 MPSGraphTensorData
我们把这些总结一下
从创建 MPSGraph 开始 用占位符定义图形的输入 调用 GeLU 辅助函数 以在图形中写出必要的运算
最后 通过将输入数据作为 feeds 传递 请求将 GeLU 张量作为目标 来执行图形 这就是在图形处理器上对任何多维张量 执行自定义计算函数所需的
我们刚刚看到了如何在 MPSGraph 中 使用基本的数学运算 来创建自定义计算函数 通常 对于每个运算 输出都会被写入内存
下一个运算会从同一个全局内存读取 这会导致不必要的内存流量和性能问题 尤其是在图形处理器上
但 MPSGraph 编译器应用了特殊的优化 来自动地为用户融合这些运算 我们称之为拼接
MPSGraph 编译器识别所有相邻的运算 并将其传递到 Metal 编译器
Metal 编译器将这些运算融合在一起 以创建一个优化的 Metal shader 这会导致无内存开销并提高性能
MPSGraph 编译器甚至更进了一步 对于任何围绕手动调整的 MPS 内核的数学操作 如卷积、矩阵乘法或归约 MPSGraph 会识别相邻的可拼接运算 以创建一个区域…
并再次将运算区域传递到 Metal 编译器 使其直接融合到手动调整的 MPS 内核中 为每个硬件提供 最好的手动调整 MPS 优化 并通过 Metal 编译器自动融合运算 节省内存
使用拼接优化可使 GeLU 的速度 提高近 10 至 50 倍
我们甚至可以节省大量内存
所有这些始终是自动完成的 不需要任何代码
其中一个自定义计算函数是机器学习推断 推断是将网络应用于输入 并产生输出的过程
该网络由一系列运算组成 如卷积和神经元激活层 如我们所示 可以用 MPSGraph 中的运算来表示
这些层又依赖一组经过训练的参数
在推断过程中 这些参数是固定的 它们的值在训练阶段确定 因此 对于推断 我们可以在 MPSGraph 中 用常量来代表这些参数
通过支持 MPSGraph 中的多种运算 我们现在还支持图形中的递归神经网络 我想介绍一下我的同事 Chris 他会向我们展示一个关于运行中的文本 生成推断网络的激动人心的演示
谢谢 Dhruv 我叫 Chris 是图形处理器软件工程师 我来让你的 iPad Pro 编写一个莎士比亚戏剧
我们使用基于长短时记忆的 文本生成器模型来实现这一点
生成器循环处理单个字符输入 在本例中是字母 O 它是初始化字符串“Romeo” 中的最后一个字母 我们将字符索引输入到嵌入层 这是 MPSGraph 中的收集运算
这会产生一个向量 我们将这个一阶张量输入到长短时记忆层 该层有一组恒定的经过训练的参数
长短时记忆层的结果被输入到非嵌入层 可通过 MPSGraph 中的 矩阵乘法运算来实现...
并为下一次迭代更新长短时记忆层的状态
然后将结果乘以温度倒数
MPSGraph 自动 将这个标量值广播到向量长度 然后将结果输入到 softmax 层 这会为我们提供 下一个可能字符的概率分布
我们从 softmax 层 对预测字符的分布进行采样 这为我们提供了下一个字符的索引 可在 index-to-character 表中查找
最后 我们将新生成的结果 作为输入移动到下一次迭代 以生成下一个字符
现在让我们看看这个 用运行中的 MPSGraph 创建的网络 我们用在 iPad Pro 上的 app 中运行的 新的 MPSGraph 实现了基于长短时记忆的文本生成器网络 MPSGraph 使用户能实现这些模型 并且由于新的图形界面的灵活性 很容易对模型进行调整以运行实验 并且仍能享受优化内核的益处 该网络在一个包含莎士比亚著作的 大文本文件上接受了训练 可通过点击顶部的 “显示训练数据集”链接查看 在这里 我们可以看到文本的简短摘录
现在让我们看看是否能用网络生成 莎士比亚风格的文本 默认情况下 我们将初始文本设置为“Romeo” 让我们看看点击“生成”时会发生什么
我们可以看到 这个模型在生成 看起来像莎士比亚作品的文本 至少在我这个外行看来是这样
我们可以选择另一个初始字 在这里输入“Juliet”
然后再次点击“生成”
现在生成的文本以“Juliet”这个词开头
生成文本的长度可由底部的滑动条来控制
这会生成一段较长的文本
我们也可以用滑块条来更改温度变量 该值的倒数 用于乘以进入 softmax 层的输入值 这会为高温值创建更光滑平整的分布 为低温值创建更清晰的分布 这会使采样过程在高温下变得更随机 而在低温下更不随机 让我们将温度滑动条移动到大约 2 看看它是否会生成更令人惊讶的文本
在我看来确实更随意 但我不确定这是不是正确的英语了 让我们试着把它设置为 3 然后再次点击“生成”
好了 是的 现在它开始看起来 像是纯随机的字母组合
我想回到更传统的莎士比亚 让我们将温度滑动条移回 0.1 看看会发生什么
好 这样好多了 现在这个模型似乎在生成 与训练数据集更为相似的文本
MPSGraph 不仅使我们 能在图形中运行这些模型 它还使用户能对模型 进行各种各样的自定义 同时由于拼接功能 仍能享受经过调整的内核带来的益处 这样可以支持多种模型 实现快速原型设计 并减少支持模型所需的环境和技术的数量 我就说这么多 交回给你 Dhruv
谢谢 Chris 我们看到了用 MPSGraph 编写自定义计算函数 有多容易和直观 现在让我们看看 MPSGraph 中的一些功能 你可以利用这些轻松地以最佳方式 训练神经网络
训练过程包括 反复尝试在已知数据上执行网络
每次尝试都会更新参数集 提高网络正常运行的能力
在网络正常运行时 训练过程会停止 (用 Metal 2 进行计算 WWDC17) (用 Metal 加速机器学习 - WWDC18) 现在我们来看看如何用新的 MPSGraph 来实现其中一些想法
在这次讲座中 我们会实现一个简单的数字分类网络
正如我们之前看到的 用 MPSGraph 进行计算有三个主要步骤
这是我们训练神经网络的路线图 第一步和最后一步保持不变 我们会深入了解第二步 看看我们必须创建什么运算 来训练神经网络的参数
和以前一样 首先定义输入集
为输入和目标标签定义占位符 用 -1为网络指定可变长度 batchSize
接下来 必须指定之前提到的可训练参数 对于 MPSGraph 这些参数是图形本身的一部分
作为一个简单的例子 我们会看看训练 一个单层卷积神经网络
该网络有一组与卷积相对应的权重 和要添加到卷积结果中的偏差 这些是我们会在训练过程中 更新的参数
要指定这些参数 我们会在 MPSGraph 中使用变量支持 变量会在图形运行中保留值 因此你无需为每次迭代 将这些作为输入传递到图形
要创建变量 在图形上调用变量方法 提供初始值、形状和元素dataType
现在有了要训练的参数 让我们指定顺推法 这恰好也是模型的推断网络
首先 我们来看看如何创建卷积层
卷积层是神经网络的主力 大部分计算发生在这里 MPSGraphConvolution 层支持多种变体
要创建卷积层 首先创建卷积描述符
接下来 将这个描述符 传递到图形上的卷积方法
我们在卷积上支持多种填充样式
开发人员可以显式设置填充的高度和宽度 或使用便利填充模式 SAME 和 VALID 它们的填充方式与 TensorFlow 完全相同
有时 为了方便起见 张量维数有附加的语义 这是 MPSGraphTensorNamed- DataLayout 有帮助的地方 它传达哪个维度对应什么名称 比如批、通道、高度或宽度
MPSGraph 支持 NCHW 和 NHWC 格式 这两种格式通常用于 TensorFlow 和 Pythorch 中的图像数据
权重也可以指定为多种格式 例如 MPS 中使用的 OIHW 格式 或 TensorFlow 等第三方框架 使用的 HWIO 格式
在将权重变量的值传递到卷积时 我们会使用 readVariable 运算 它返回一个张量 代表在图形执行过程中 此时的变量值
在训练网络中 我们读取权重变量 并将返回的张量传递到卷积
卷积层会用传入的权重张量的形状 来推断内核尺寸和输出特征通道的数量
MPSGraph 提供无需显式调用 readVariable 运算的便利 如果将变量张量直接传递给任何运算 为了方便起见 图形会隐式添加 readVariable 运算
对于卷积后的偏差 我们会调用隐式支持广播的添加节点
对于非线性 我们采用修正线性单元函数 它是一种常用的激活
我们将四维 reLU 输出 重塑为二维张量 它恰好与标签的形状相同 它的维数代表未知的批大小 和要分类的类别数 在我们的例子中为十位数
最后 添加一个 softMax 层 来估计每个类别的概率 将轴设置为 -1 这有助于指示移动最快的轴
我们成功地定义了神经网络的顺推法 现在定义损失函数 我们会尝试使其最小化 来训练我们的神经网络
我们会使用常用的 Softmax 交叉熵损失函数
通过传递标签 和评估的 reshapeTensor 定义损失 利用 reductionSum 将整个批次的损失累积为单个标量损失值
现在定义了要最小化的损失值 我们需要计算出 针对可训练参数的计算损失的梯度 为此 必须用链式法则反向传播梯度
要开始链式法则 第一步是计算损失与自身的梯度 恰好是 1
之后需要利用梯度运算 和图形中可用的其它运算
我们用它们来应用链式法则 将每一层的偏导数相乘 直到获得针对每个可训练参数的损失梯度
但 MPSGraph 提供了一种便利的方法 它提供针对张量列表的张量梯度 我们称之为自动微分
它会自动写出图形的逆推法 并返回张量字典和相应的梯度
你甚至可以用梯度法为任何基本数学函数 写出梯度函数 我们以一个简单的对数运算为例
梯度法正确创建 作为偏导数的倒数运算 并将其与起始梯度相乘 正如我们所讨论的 起始梯度始终为 1
但我们得到了一组未使用的运算 图形编译器再一次帮了我们
图形被修剪以清除 任何结果未使用的死代码 任何像 1 这样的常量会被折叠并清除
在神经网络的情况下 我们会采用损失张量 针对权重和偏差的梯度
有了针对可训练参数的损失梯度后 我们就可以更新变量
要计算张量的更新 使用随机梯度下降优化器 它接受 learningRate、初始权重值 以及我们使用梯度字典 获得的权重的梯度
最后 在图形中使用赋值变量运算 将新的更新张量值分配给变量
最后一步和以前一样 我们写出了训练图形 现在需要执行它
我们的训练循环相当简单 对于每次迭代 我们获得训练输入图像和相应标签的样本 将这些作为 feeds 传递到图形
然后请求将 lossTensor 作为目标并返回 每次迭代 权重和偏差变量都会更新 因为我们还将图形中的赋值运算作为目标
在第一次调用时 图形为每种唯一的 输入和输出类型编译一次 可执行文件会为任何进一步的迭代 自动缓存 以获得最佳性能
MPSGraph 还提供异步运行方法 该执行调用为非阻塞 会立即返回 而无需等待图形处理器完成计算 可选的 executionDescriptor 可用于 中央处理器和图形处理器之间的同步
我们在描述符上使用这样的同步方法 用户可以注册自己的完成处理程序 将在图形处理器完成执行图形后调用
在过去几年里 我们展示了 重叠图形处理器编码 和图形处理器执行的优点 我们执行的训练迭代可以使用相同的原则
创建一个值为 2 的信号量
从执行描述符的完成处理程序 向信号量发出信号
在循环中等待信号量 一旦通过 异步执行图形 以便它立即返回
对于希望将 MPSGraph 集成到 现有 Metal 工作流中的用户 MPSGraph 提供低级执行方法 你可以通过它们传递 自己现有的 MTLCommandQueues
MPSGraph 甚至提供 MPS 风格的功能 以在 MPSCommandBuffers 上 对图形进行编码
用户可指定自己的 resultsDictionary 使其能对输出分配进行细粒度控制
现在回到 Chris 他会展示运行中的数字分类器训练网络
现在 Dhruv 向我们展示了 用于训练的新的 MPSGraph 让我们看看如何用它 在 iPhone 11 上实现数字分类 我们用新的 MPSGraph 框架 实现了一个简单的卷积神经网络 我们可以用它来 对用户绘制的数字进行分类
打开 app 后 我们从一个完全未经训练的图形开始
在推断标签上 我们可以看到 目前网络在试图标记这些数字方面 做得很糟糕 它不能预测这个为 1 也不能预测这个为零
但如果返回训练标签 我可以按下“播放”按钮以开始一小批训练 我们用 MPSGraph 的自动微分功能 来获取权重梯度 并用目标运算来更新权重变量 以轻松实现训练 每次迭代的损失都标在顶部 我们可以看到它随着网络经过训练而下降
我们仅以小批量进行了数百次迭代训练 测试集上的准确率已接近95%
回到推断标签…
我们可以测试新训练的图形
我们可以看到 它已经学会了对输入进行准确分类 新的 MPSGraph 可轻松构建 自定义机器学习模型 并将其用于训练和推断 将作为在线示例代码提供 这个关于如何用 MPSGraph 构建 训练和执行数字分类器的例子 现在回到 Dhruv 了解更多关于训练的信息
Chris 感谢你在 iPhone 上向我们展示了 MPSGraph 训练的强大功能 MPSGraph 添加了 支持更复杂的神经网络架构的功能
让我们看一个这样的例子 这次 我们想创建一组新的 逼真的手写数字 但有一个问题 机器无法确定 什么是逼真的手写数字
解决这个问题的方法是竞争 多年来 人类一直在利用竞争来共同进步 达到他们自己无法企及的高度 我们在这里也一样 通过让两个神经网络互相竞争来训练它们 一个尝试创建手写数字 另一个尝试评估其质量
第一个网络是生成器 艺术家 它的作用是以随机的一组值作为种子 生成逼真的手写数字
生成器网络相当简单 提取随机的一组值 将其传递到三个阶段 逐步增大图像尺寸 以创建手写数字 让我们快速看一下这里的一些新的层
首先 我们看到一些卷积转置
卷积转置是源自卷积运算的梯度的 独特的层 因此 对于第二步 输出尺寸会是输入尺寸的两倍 而不是一半 要描述卷积转置 传递相应卷积的描述符 和预期的输出形状
另一个新的层是批量规范化
规范化层是神经网络的重要组成部分 它们帮助我们确保经过训练的值 和相应的梯度 不会消失或爆炸
要规范化张量 需要使用张量的统计数据
MPSGraph 有一些方法可以获得所选轴上 张量的均值和方差
我们选择的轴使我们有机会选择 是否需要批量规范化、实例规范化 或任何其它变体
对于批量标准化 我们会选择 批、高度和宽度维度
然后用可训练的 gamma 和 beta 参数 调用规范化层
第二层是鉴别器 我们的侦探 它的作用是提取一个手写数字 并将其分类为真或假
我们已经了解了如何编写分类器网络 这个网络非常相似 唯一不同的是 现在我们要预测一个类别 而不是十位数 这就是传入图像的真实性
鉴别器有另一个新的层:即舍弃
舍弃层通过以给定速率将输入值设为零 来随机丢弃输入值 同时 它以速率的倒数来提升其余的值 以保留传播功能的能量
看过两个网络的顺推法后 我们会研究两个网络的训练
让我们从鉴别器网络开始
我们控制是将真的还是假的图像 传入鉴别器 鉴别器的目的是 预测传入图像的真实性 对于真的图像 它应该预测真实概率为 1 对于假的图像 它应该预测概率为零
对于生成的图像 我们从 1 减去鉴别器结果 从而得知输入图像为假
我们用常用的交叉熵损失 来量化鉴别器与正确的真或假预测之间 有多大差异
最后 我们希望为鉴别器提供平等的机会 来学习如何在不引入偏差的情况下 对真假图像进行分类 对于每次迭代 我们传递相同数量的真假图像 并将它们的损失相加
有了损失在手 我们使用 MPSGraph 的自动微分功能 请注意我们如何仅请求 鉴别器变量列表的梯度 这是因为我们只希望 在本次传递中训练鉴别器
我们具备成为优秀的侦探的能力 现在让我们看看 如何训练艺术家生成逼真的数字
如前所述 我们用鉴别器来量化生成图像的真实程度 生成器会试着学习骗鉴别器 预测生成的图像为真
再一次 我们用交叉熵损失 来量化真实概率的程度
我们用该生成器损失来获得梯度
再次注意 我们仅获得生成器变量的梯度 这是因为我们不想让鉴别器 学会将假的图像预测为真
MPSGraph 会自动通过两个网络进行区分 并且仅为生成器变量返回梯度
利用两个网络的梯度 我们可以像以前一样 通过应用优化器来更新变量
现在我们来看看如何为两个网络执行训练
MPSGraph 使这非常容易执行 我们只需将两个损失都作为目标传递 并在一次运行调用中 请求生成器和鉴别器更新运算 MPSGraph 会在两个网络上 进行编译和优化 并一起执行它们
我们刚刚看到在一个 MPSGraph 中 写出两个网络 并通过一个执行调用 一起执行它们有多容易 让我们请 Chris 为我们生成一些数字
又见面了 现在知道了这些网络如何运作 让我们 看看它们在 iPad Pro 上的实际应用 我会点击“训练”标签上的“播放”按钮 以开始训练
在顶部 我们可以看到生成器网络的损失 底部则显示鉴别器网络的损失
在中间 我们可以看到由生成器网络生成的图像 并且随着网络进行训练 我们会看到这些生成的数字开始像数字
正如我们在数字分类器演示中看到的 我们用 MPSGraph 的自动微分功能来更新 生成器和鉴别器网络中的可训练层 使用单个 MPSGraph 训练两个网络
我们可以看到这些网络已经在相互竞争了 但还需要一段时间 生成器才能生成可信的数字 我们可以暂停该训练...
并在网络进行数百代训练后 跳转到“推断”标签以测试网络
这里我们看到5、9
我不知道那是什么 7、9
在我看来它们像是数字 所有这些都是用 MPSGraph 在 iPad Pro 上运行的 好 回到 Dhruv 那里
再次感谢 Chris 综上所述 我们介绍了新的 MPSGraph 框架
我们学习了如何用 MPSGraph 编写和执行 自定义计算函数
我们看到了 MPSGraph 编译器如何 拼接和优化整个图形的运算 以提供最佳性能
最后 我们看到了 用支持变量和自动微分等功能的 MPSGraph 训练神经网络有多容易
感谢你听我的讲座 请查看我们的示例代码和说明文档 尽情享受 WWDC
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。