「MIT 6.S191 (2025)- 1」深度学习导论
MIT 深度学习入门课程 (6.S191) - 第一讲:深度学习导论
本文更适合收听,仅用于辅助学习相关课程。
简介
欢迎来到 MIT 深度学习入门课程 (6.S191) 的精彩旅程!在第一讲中,Alexander Amini 和 Ava 为我们揭开了深度学习的神秘面纱,带领我们快速回顾了该领域令人瞩目的发展历程,并以一场震撼的语音克隆现场演示,生动展现了生成式 AI 的强大能力。
本讲首先定义了智能、人工智能、机器学习与深度学习之间的层层递进关系,明确了课程的核心目标:掌握让计算机从数据中自主学习任务的技能。随后,课程概述了为期一周的强化训练营结构,包括技术讲座、动手实验、行业前沿客座讲座以及最终项目竞赛,内容丰富且实用。
讲座深入浅出地介绍了神经网络的基础——感知器,并逐步构建出多层神经网络的架构。核心概念如激活函数、密集层、深度网络等被清晰阐释。训练神经网络的关键环节,包括损失函数的定义、梯度下降优化算法以及反向传播的原理也得到了细致讲解。
此外,讲座还着重强调了训练深度学习模型的实践考量,如学习率的调整、随机梯度下降的优势,以及过拟合与正则化等重要问题,并介绍了 Dropout 和早停法等有效策略。
通过第一讲,学员们不仅对深度学习有了宏观认识,更掌握了构建和训练神经网络的基础知识,为后续深入学习奠定了坚实的基础。课程最后预告了下一讲将由 Ava 主讲的深度序列建模,预示着更精彩的内容即将展开。这门课程不仅仅是理论学习,更是一次通往深度学习前沿技术的实践之旅。
纲要
深度学习导论 - MIT 6.S191
├── 课程介绍
│ ├── 欢迎和课程概述
│ ├── 深度学习的吸引力
│ ├── 回顾深度学习的演变
│ └── 现场语音克隆演示
│ ├── 演示与互动
│ └── 对比2020年技术
├── 深度学习概念定义
│ ├── 智能
│ ├── 人工智能
│ ├── 机器学习
│ └── 深度学习
├── 课程结构概览
│ ├── 课程组成
│ ├── 今年更新
│ ├── 客座讲座
│ ├── 招待会
│ ├── 软件实验介绍
│ │ ├── Lab 1: 音乐语言模型
│ │ ├── Lab 2: 面部检测
│ │ └── Lab 3: 大型语言模型微调
│ ├── 最终项目竞赛
│ └── 课程资源
├── 为什么选择深度学习及当下时机
│ ├── 传统机器学习的局限
│ ├── 深度学习的核心思想
│ ├── 深度学习的层次特征学习
│ └── 深度学习爆发的原因
│ ├── 数据
│ ├── 计算力
│ └── 开源工具箱
├── 神经网络基础:感知器/神经元
│ ├── 感知器的前向传播
│ ├── 数学公式与线性代数
│ ├── 激活函数的重要性
│ ├── 激活函数类型
│ └── 激活函数示例
├── 构建神经网络
│ ├── 多输出神经网络
│ ├── 密集层/线性层
│ ├── 从零实现密集层
│ ├── 密集层的应用
│ ├── 单隐层神经网络
│ └── 深度神经网络
├── 训练神经网络
│ ├── 训练目标与损失函数
│ │ ├── 损失函数的重要性
│ │ ├── 经验损失
│ │ └── 损失函数类型
│ ├── 梯度下降
│ │ ├── 优化算法的流程
│ │ └── 反向传播
├── 训练神经网络的实践考量
│ ├── 损失景观的复杂性
│ ├── 学习率
│ ├── 自适应学习率
│ ├── 随机梯度下降 vs 梯度下降
│ └── 小批量梯度下降
├── 过拟合与正则化
│ ├── 过拟合的问题
│ ├── 泛化能力的重要性
│ ├── 正则化技术
│ │ └── Dropout
│ └── 早停法
└── 总结与展望
├── 本讲总结
└── 下一讲预告
讲座实录
课程介绍
大家下午好!非常感谢各位今天能加入我们。我叫 Alexander Amini,今天将和 Ava 一起担任今年这门课程的讲师。这里是 MIT 深度学习入门课程,或者按我们的官方课程名称,6.S191。
我们非常高兴欢迎大家来到这门课。我想,一个好的开始总是要先问问自己,MIT 深度学习入门课程到底是什么?这是一门为期一周的深度学习强化训练营,内容涵盖深度学习的方方面面。这将会是非常有趣,但同时也非常紧张的一周,因为我们将在短短五天内 कवर 大量内容。
今年是我们第 8 年教授这门课程。这个领域的发展速度,尤其是在过去几年里,真的非常惊人。每次我们教授这门课,介绍这门课,特别是这第一堂课,都变得越来越有趣,而且我们的介绍方式也在不断调整和演变。
在座的各位可能很多人已经开始对过去几年深度学习的进展感到有些麻木,因为进步实在太快了。所以我认为,重要的是不要忘记几年前我们是从哪里起步的。我想给大家看这张图片,作为今天的开场。没有什么比亲眼见证进步更好的方式了。
就在十年前,这是最先进的基于深度学习的面部生成系统的水平。这不是一张真实的面孔,这是当时最先进的模型所能生成的面孔,已经是我们能做到的最好的程度了。快进几年,图像生成领域的进步已经开始突飞猛进。在这里你们可以看到,在创建的图像中,真实感和照片级真实度都大大提升了。然后再快进几年,这些图像开始变得生动起来,开始拥有时间信息,开始有视频,以及图像的 movement。实际上,你们在右边看到的这个视频,是我们几年前在这门课上制作的。对于那些还没有看过的人,它在网上流传很广。如果还没看过,我播放前 10 秒,让大家也看看。
(播放视频片段)
大家好,欢迎来到 MIT 6.S191,麻省理工学院官方深度学习入门课程。
我不会播放完整视频,但大家已经了解这个视频的大概内容了。这个视频是五年前制作的,是我们这门课的一部分,当时我们用它来介绍这门课程。在 2020 年我们发布这个视频时,即使在当时也引起了很大的轰动,尤其是那个时候。也许今天的你们对它已经不那么 impressed 了,但在当时,这个视频绝对是一件大事。对于深度学习模型的能力来说,这是一个照片级真实度上的巨大飞跃。这个短片迅速传播开来,很多人评论它的真实度。但实际上,有一个有趣的点是,人们只看到了最终结果,但当时人们没有看到的是,为了生成那个两分钟的短片——你们只看到了前 10 秒,但整个短片是两分钟——为了生成这两分钟的短片,我们花费了大约两小时的专业音频数据录制,speaker 不是我们。还花费了大约 50 小时的高清专业视频数据来构建面部模型。并且需要大约 15.5 万美元的计算资源来生成那两分钟的视频。所有这些都只是为了生成一个预定义的脚本,静态的,你无法与之对话,无法互动,只是一个预定义的、静态的、完全不灵活的脚本。但是,仍然需要投入大量资源,包括时间、数据、能源和财务资源。
我想通过提出这个问题来开始今天的课程:如果今天再做同样的事情,会是什么样子?那个视频是在 2020 年制作的,但现在是 2025 年。在今天的世界里,克隆技术和生成式 AI 会是什么样子?特别是考虑到我们在 2020 年所面临的所有限制。我认为,没有什么比直接展示给大家看更好的方式了。与 2020 年我们花费的所有计算和资源相比,让我们今天现场、未经编辑地完成这件事。
实际上,我有一个小秘密要分享。我将共享我的另一个屏幕,并把它移过来。这是一个终端窗口,大家可以看到,在我说话的时候,有些东西一直在后台录制音频。我一直运行着我们制作的一个程序,它在监听我的音频,录制我的声音。接下来我要做的就是暂停录制。我们将看看它能以多快的速度立即开始,仅仅使用我的声音就进行即时克隆,而不是之前我们看到的那些耗时的资源。
我现在暂停它,大家会看到它瞬间完成克隆。是的,现在我的声音已经被克隆了。接下来我们要用这个克隆的声音尝试做一些事情,不再像以前那样使用预定义的脚本。我将与这个声音进行现场、未经编辑的对话,看看今天的生成式 AI 模型已经变得多么 dynamic 和 flexible。让我们试一下。
(演示语音克隆对话)
Alexander: 你好,你能听到我吗?
克隆 Alexander: 嗨,是的,声音洪亮清晰。你好吗?
Alexander: 等等,实际上你听起来很像我,不是吗?
克隆 Alexander: 很有趣,你说得对。我们比我想象的更相似。我们要做什么?
Alexander: 嗯,实际上我刚刚开始今年的 MIT 深度学习课程。你知道,我现在就站在 audience 面前。
克隆 Alexander: MIT 深度学习入门课程真是一门很棒的课!这门课怎么样?
Alexander: 实际上我们才刚开始。我有一个主意,我正要介绍什么是深度学习,不如你来接替我介绍这部分内容?
克隆 Alexander: 深度学习是一种机器学习类型,它使用人工神经网络从数据中学习。这些网络受到人脑结构的启发,能够从大量数据中学习复杂的模式。深度学习被广泛应用于图像识别、自然语言处理和自动驾驶汽车等领域。
Alexander: 非常好!实际上,我想告诉 audience 的 amazing 之处在于,今天的深度学习状态非常 flexible,非常 dynamic。你怎么看?
克隆 Alexander: 你说得对,深度学习非常 dynamic。它不断发展,新的架构、算法和应用层出不穷。
Alexander: 等等,让我打断你一下,只是为了展示它有多么 dynamic。我要打断你,我们来试试这个。别再谈论深度学习了,不如你给我讲一个关于乌龟的故事,要 wild 一点的那种。
克隆 Alexander: 哦,乌龟?你想要 wild 的乌龟故事?好的,想象一下,有一只名叫 Shell 的乌龟,它不是你想象中的普通乌龟。哦,不,Shell 有梦想,它梦想着飞行。它每天都在练习拍打它的小鳍,试图离地起飞。有一天,它遇到了一位疯狂的发明家,一位名叫 Sheldon 博士的 mad scientist 乌龟,他制造了一个火箭动力龟壳。Shelly 跳了进去,boom!他们 blast off into space。他们 Zoom past 行星,遇到了喜欢吃…
Alexander: 我打断一下,我再打断一下,这真是 Turtle-tastic!我们在这里结束吧,好吗?非常感谢你,这真是一个很酷的课程介绍方式。
克隆 Alexander: 我很高兴能帮上忙。
Alexander: 好的,谢谢,再见!
克隆 Alexander: 再见!
(掌声)
Alexander: 好的,太棒了!这只是一个有趣的方式,来展示这个领域我们已经取得了多大的进步。仅仅在几年前,我们还在生成非常 static 的内容,而现在我们可以生成 live 的、未经编辑的、极其 dynamic 的内容。大家刚刚听到了一个非常简短的关于什么是深度学习的介绍。实际上,在那个演示中,以及大家在过去几年里看到的所有进展,你们在本课程的接下来一周里将学到的,正是驱动所有这些进步的基础技术。
深度学习概念定义
让我们先从奠定一些基础开始,准确了解这个领域是关于什么的。要做到这一点,我认为首先我必须向大家介绍什么是智能。对我来说,“智能”这个词意味着处理信息以指导未来决策的能力。这是智能的含义。我们每个人每天都在展现这种能力,有些人比其他人更明显。而人工智能只是构建算法来做同样的事情,使用信息、使用数据来指导未来的决策。
那么,什么是机器学习呢?机器学习是人工智能的一个子集,它侧重于不显式编程计算机如何使用数据、如何处理信息来指导决策,而是尝试学习数据中的一些模式来做出这些决策。
最后,深度学习只是机器学习的一个子集,它专注于使用神经网络,深度神经网络来完成完全相同的过程。我们将在本课程中详细学习什么是深度神经网络。但实际上,从 high level 来看,整个课程都围绕着这个核心思想。这就是我们将要教授的内容,大家将在整整一周的时间里牢牢掌握它。你们将学习如何教计算机如何从观察、直接从数据中学习执行任务。我们将通过讲座为大家提供坚实的基础,并通过软件实验提供实践理解,让大家能够亲自动手实践。
课程结构概览
这可能是一个很好的过渡,可以向大家介绍一下整个课程的 high level 概况。正如我所说,这将是技术讲座和软件实验的结合。今年,我们特别进行了一些新的更新,因为这个领域发展得非常迅速,我们将真正尝试开始强调许多关键点,尤其是在更 modern 的深度学习方面。为此,我们将在最后安排一些行业领导者的客座讲座,介绍行业正在开发的最先进的深度学习方法和 AI 方法。这将真正开始进一步提升大家的知识水平。
另外,是的,没错,今天晚上 4:30 我们还将举办一场招待会,欢迎大家参加,与各位交流,更多地了解深度学习。我们还准备了食物。今年,我们在软件实验方面也进行了很多很棒的更新。我们将引入 TensorFlow 和 PyTorch 软件实验。首先,这些实验对于大家 hands-on 实践在讲座中学到的一切来说,是非常好的学习体验。其次,它们也是大家参加竞赛、赢取丰厚现金奖励的途径。
那么,具体是如何运作的呢?每天我们都会安排一场专门的讲座,以及一个与讲座内容对应的专门软件实验。软件实验基本上会 reinforce 当天讲座中讲授的内容。从今天开始,大家将进行 Lab 1 实验,主要 focus 构建一种语言模型。实际上,它会是一个非常小的语言模型,但它是一个 next token predictor 语言模型,学习如何生成音乐并预测音乐的下一个 token,这样大家就可以生成 novel 的民歌。明天我们将转向面部检测系统。大家将 hands-on 构建自己的计算机视觉系统,从 scratch 开始,同时理解一些 automated 技术来修复这些系统中的不平衡数据。最后,Lab 3 将是一个全新的实验,今年首次推出,关于大型语言模型。大家实际上将在实验的这部分 fine-tune 一个 20 亿参数的大型语言模型,在大家控制的 compute 上,以一种 mystery style 进行。大家还将构建一个 AI judge 来评估该语言模型的质量。所有这三个实验都将非常有趣。
最后,在课程的最后一天,我们将举办 final project pitch 竞赛。每个小组可以由最多 3-5 人组成,每个小组进行最多 3-5 分钟的演示,类似于 Shark Tank 风格的 pitch 竞赛。大家将有机会赢取更多奖金。
好的,这张幻灯片我就不详细介绍了。这门课有很多很棒的资源。这张幻灯片以及所有讲座都已发布在网上,大家现在就可以查看网站,应该已经上线了。如果大家需要任何帮助,请在 Piazza 上发帖提问。今年我们有一个由出色的助教和讲师组成的团队,大家可以随时联系他们,提出任何问题或疑问。我和 Ava 将是课程大部分内容的主要讲师,但大家也会在课程的剩余时间里听到许多客座讲师的分享。这里是一些客座讲师的名字。总的来说,如果没有我们所有 amazing 的赞助商,这门课程不可能每年都顺利举办,所以我真的要衷心感谢他们多年来的支持。
为什么选择深度学习及当下时机
好的,现在我们已经介绍了所有这些内容,我想开始进入一些有趣的内容。
(观众提问)
提问者:这门课已经教了多久了?
Alexander: 是的,没错。这门课已经教了 8 年了。我们已经教过大约 1300 万人次了。仅在 MIT 本地,因为 MIT 的 audience 是全球性的,MIT 的 audience 大约有 3000 人。每年在线上大约有 10 万人参加这门课。所以大家身处一个非常棒的群体之中,很多非常 amazing 的人都参加过这门课。我们真的很高兴大家今天能来到这里。
现在我想开始进入这门课的技术部分。我想首先问大家一个 fundamental 的问题:为什么是深度学习?为什么是现在?希望大家在今天来这里之前都问过自己这个问题。真正理解深度学习的基础对于我们理解如何前进,如何构建驱动这个领域的更好算法至关重要。
传统机器学习,如果我们从这里开始说起,传统机器学习通常定义所谓的“特征集”。我稍后会详细解释“特征”这个词,但通常这些特征基本上是逐步完成任务的规则。问题在于,如果我们人类来定义这些特征,我们通常不擅长构建非常 robust 的特征。例如,假设我想告诉大家,或者让大家构建一个 AI 模型,它可以检测面孔。大家会怎么做?大家会在图像中构建哪些特征来检测面孔?大家可以先检测图像中的线条,也就是边缘,非常简单的线条。然后大家可以将这些线条组合起来,检测诸如曲线和边缘之类的东西,以及曲线,基本上就是线条的曲线,不仅仅是直线。然后大家可以将这些组合起来,开始形成更 composite 的对象,比如眼睛、鼻子和耳朵。然后,大家实际上可以开始构建面部结构。为什么要这样做呢?因为这应该是大家自然而然会想到的方法,因为很难一步到位地检测到面孔。实际上,大家首先不会这样处理面孔。大家实际上首先处理更 Co 的特征,首先是 low-level 特征,或者说是 high level 特征,然后再将这些组合起来,真正形成大家自己对面孔的 intuition。
现在,深度学习的关键思想与这个过程没有什么不同。关键思想是学习这些特征,而不是我告诉大家或者大家告诉我这些特征到底是什么。深度学习的关键思想是,在观察了大量面孔之后,我能否学习到我应该以这种 hierarchical 的方式逐步检测事物,首先检测线条,然后检测曲线,然后检测 composite,比如眼睛、鼻子和耳朵,然后再构建到面部结构?事实证明,这正是深度学习能够做到的,我们将在整个讲座中看到这是如何实现的。
但重要的是要理解,即使我们看到了过去几年深度学习的这么多 amazing 的事物,大家将要学习的一切,尤其是在今天的讲座中——这是一堂入门讲座,所以今天大家看到的大部分内容都是几十年前发明或开发的。这不是什么新鲜事物。在今天的讲座、明天的讲座以及之后几天的讲座中,大家将开始看到更多最近的进展。但为什么我们今天会看到这一切呢?原因有三点:
- 数据 (Data):数据在全球范围内变得越来越丰富,这真正推动了深度学习的进步。
- 计算力 (Compute):计算力变得越来越强大,越来越 commoditized。GPU 架构尤其推动了学习的进步,而 GPU 最近才开始变得 commoditized。
- 开源工具箱 (Open Source Toolboxes):比如大家在右手边看到的 TensorFlow、PyTorch、Keras 等等,使得大家在一个为期一周的课程中就能 hands-on 实践这些架构并开始直接构建模型变得非常 streamlined 和容易。
神经网络基础:感知器 / 神经元
让我们首先了解每个神经网络的基本 building block,那就是单个神经元或感知器。什么是感知器呢?感知器或单个神经元的思想非常简单。让我们首先 purely 通过信息的前向传播来定义感知器。给定一些输入,感知器如何计算输出?
让我们首先定义一组输入 X1 到 XM。这些输入中的每一个数字都将乘以相应的权重 W1 到 WM。我们要做的是,在完成乘法后,我们将所有这些数字加在一起。我们将把得出的单个数字传递给所谓的非线性激活函数。这只是一个非线性的一维函数,大家可以通过它传递这个输出上的单个数字。这里用 G 表示。
我漏掉了一个小细节,我现在就纠正它。我们必须记住的一件事是,在我们将所有权重乘以输入后,我们还要加上一个称为偏置项的数字。如果大家看这个方程,偏置项实际上是让我们沿着激活函数 G 左右移动的一种方式。这只是一个在方程中设计的 scalar shifting approach。在这张幻灯片的右手边,大家实际上可以看到左边的图表,在数学上被 illustration 或者 mathematically 写成一个简单的方程。现在,为了简洁起见,我将使用线性代数,用向量和点积的形式重写它。
现在,不再是 X1 到 XM,我将只写一个向量大写 X。大写 X 将是所有输入的集合。大写 W 将是所有权重的集合或向量。然后,输出 Y 仅仅通过对 X 和 W 进行点积,加上偏置,并通过 G,通过非线性函数来获得。
大家可能想知道,我已经提到过几次非线性函数,这到底是什么东西?我说过它是一个非线性函数,但它到底是什么?这里一个常见的例子是所谓的 Sigmoid 函数。大家可以在这里看到 Sigmoid 函数,它基本上可以作用于 x 轴上的任何实数,但它只输出 0 到 1 之间的值。所以通常 Sigmoid 函数非常适合处理概率之类的事情,如果大家想将感知器或神经元的输出转换为概率。但实际上,有很多类型的非线性函数,这只是神经网络中常用的一种函数。但在整个演示过程中,大家将基本上看到几个不同的非线性函数的例子。我还会在幻灯片底部指出一些 TensorFlow 和 PyTorch 的代码片段,这将有助于大家将数学公式与稍后在软件实验中将要用到的代码对齐。
大家之前看到的 Sigmoid 函数的输出非常适合用于概率。大家还会看到像右手边这样的函数,这叫做 修正线性单元 (Rectified Linear Unit, ReLU)。它输出严格为正的值。它是分段线性的,所以在零之前是线性的,在零之后也是线性的,但在 x 等于 0 处有一个单一的非线性。
为什么我们需要激活函数呢?实际上,这是一个希望大家都会问的问题。乍一看,它似乎是不必要的。激活函数的目的实际上很简单:将非线性引入到模型中。如果没有非线性激活函数,大家就拥有了一个线性模型。那么我们为什么要非线性呢?仅仅是因为现实世界中的真实数据 heavily 是非线性的。
也许一个好的例子可以说明这一点。假设我给大家看这张图片,如果我要求大家构建一个分类器,画一条线将红点和绿点分开。大家能画出这条线吗?乍一看,是的,大家可以画出这条线。但如果我告诉大家,这条线必须是直线呢?如果我告诉大家这是一条直线,那么就真的不可能完成这个任务了。这就使问题变得非常困难。这就是拥有线性模型的问题。拥有非线性的好处在于,它允许我们用模型中足够的深度来 approximate 任意复杂的函数。这正是使非线性神经网络,也就是神经网络,变得极其强大的原因。
让我用一个简单的例子帮助大家理解这一点。假设我现在给大家一个训练好的神经网络,大家可以在这里看到。它有一个感知器,但它有两个输入 X1 和 X2。它也有两个权重 W1 和 W2,顶部还有一个偏置项。我们如何处理这些信息呢?这和以前一样。我们将计算点积,加上偏置,并通过非线性函数 G。如果我们 plug in 我们的数据,我们已经知道这里的输入。我们的输入将是,positive 3 是第一个输入 X1,-2 是第二个输入 X2。我们可以将这些输入以及权重 plug into 我们的方程,我们实际上可以看到,我们可以获得这条线,它将是一条二维线,parameterizes 我们神经元的整个函数空间。由于它只有二维,我们甚至可以 plot 这条线,这样我们就可以确切地看到整个空间会是什么样子。对于这个模型看到的任何新输入,它相对于这条线会落在哪里。
例如,假设我有一个新点,这个点在 x1x2 空间中,它将在点 1 by 2 处。我们可以 graphically 看到它相对于这条线落在 plot 中的哪个位置。我们也可以 plug it back into 我们的方程,我们可以确切地看到,如果我们 plug in -1 作为 X1 的输入,positive 2 作为 X2 的输入,我们可以 plug it into 左下角的方程。我们通过非线性函数,这里的非线性函数是 Sigmoid 函数,它将一切 squash 到 0 和 1 之间,具体取决于它落在线的哪一侧。我们得到了 final answer,在本例中,final answer 是 0.2。这小于 0.5。0.5 将是 divider,因为我们所有的输出都将在 0 和 1 之间分离。我们也可以 graphically represent 这一点。如果大家直接落在直线上,那么在非线性函数之后的输出将是 0.5。大家越靠近蓝色一侧,就越低于 0.5。大家越靠近绿色一侧,就越高于 0.5。所以这条线基本上代表了空间这两侧的分界点。根据大家输入落在哪一侧,这是一种将该点 classify 为 positive 点或 negative 点的方式。
构建神经网络
现在,重要的是要理解,我们只是对一个具有两个输入的单个神经元做了这件事。大家可以想象,如果大家有一个模型,它的输入远多于两个,那么就不可能再画出这个 plot 了。这是我们在理解和建立 intuition 方面必须处理的事情。但希望即使在 small scale 上,大家也可以通过这个 plot 建立一定程度的 intuition。
让我们看看现在如何开始将这些东西 tie together,超越单个神经元,开始构建网络。因为这才是我们真正构建 powerful 系统的地方,不仅仅来自一个神经元,而是来自 full 网络。为此,让我们再次 revisit 我们的图表。如果大家从这门课中只能带走几件事,希望这张幻灯片就是其中之一。我已经说过好几次了,我会再说一遍。如何通过神经元传递信息?大家进行点积运算,应用偏置,并应用非线性函数。就是这三个步骤,而且这些步骤不断地重复。既然我已经告诉大家这么多次了,希望大家已经开始记住了。我将简化图表,从图中删除所有的权重,并删除偏置项。现在大家可以始终假设这两样东西都在那里。为了保持简洁,我将在接下来的 illustration 中删除它们。这里的 Z 将是该项的结果,它将是点积加上偏置的结果,它将是非线性函数 G 之前的状态。然后我们将 Z 通过 G,这将给我们 Y。大家可以在这里看到表示。
如果我们想要一个多输出神经网络,不是一个输出而是两个输出,我们该如何更改这张图呢?实际上,非常简单,我们现在只需创建第二个感知器。我们现在有两个神经元而不是一个神经元。两个神经元都具有完全相同的输入,但由于它们的权重不同,它们将具有两个不同的输出。所以它们都以 onep put 相同的信息,它们用自己的权重以自己的方式处理信息,并从 scratch 生成两个不同的输出。这些类型的 NK,这些类型的层,让我称它们为“层”,通常被称为 密集层 (Dense Layer),因为我的输入中的所有内容都连接到我的输出中的所有内容。如果大家排除非线性函数,这也是一个 线性层 (Linear Layer)。这是一个线性层,因为它获取所有的输入 X,并只是用权重 W 对它们进行线性运算,并加上偏置,这也是一个线性运算。我们现在实际上可以用 Python 从 scratch 实现整个运算。让我们试一下。
我们将首先定义这两个权重。我们定义 self.w,这是我们的权重向量。我们还有 self.b,这是我们的偏置 scaler。这只是一个数字,但这里,由于它是一个完整的 n 维输出,我们实际上也会在输出中拥有 n 个神经元。当我们想要通过这一层进行前向传递时,我们该怎么做?这和以前一样。我们进行点积运算,这里是 multiply,我们加上偏置,然后应用我们的非线性函数。这里是非线性函数 sigmoid,但大家可以将其更改为 PyTorch 中的任何非线性函数。大家实际上可以看到,左侧和右侧几乎完全 analog,故事是相同的。大家创建权重和偏置,应用矩阵乘法,加上偏置,并应用非线性函数,和以前完全相同。幸运的是,TensorFlow 和 PyTorch 已经为我们实现了这种类型的密集层或线性层。所以我们不需要自己做。刚才我们经历的只是一个很好的学习练习。但在这里,大家可以直接 call 它。大家可以在底部看到函数调用。
现在让我们看一下 单层神经网络,单隐层神经网络。不是输出直接来自单个感知器,而是我们必须通过两层。单隐层神经网络,其中单隐层 placed 基本上位于输出层和输入层之间。为什么我们称之为“隐层”呢?只是因为我们没有直接观察到该层中发生的数据。输入层是我们提供给模型的数据,输出层通常是我们 supervise over 的事物,隐层是在过程中学习到的。由于我们现在有了从输入到隐层以及从隐层到输出的 transformation,我们现在有了两层。这也意味着我们需要两个权重矩阵 W。所以我们实际上将在左侧有一个 W1,在右侧有一个 W2。如果我们看隐层中的单个单元,单个感知器,单个神经元,比如 Z2,它只是我们之前看到的感知器。故事是一样的,没有什么变化。它的答案是通过进行点积运算,加上偏置,并通过这个非线性函数来计算的。如果我们取不同的 node,不同的神经元,比如它下面的 Z3,它也将通过点积、偏置和非线性函数来计算。它将采用与 Z2 相同的输入,但它将具有不同的权重。因此,点积和偏置将是不同的。
这张图片看起来又有点 messy 了,所以我将进一步简化它。我将用单个 icon 来替换所有的箭头,这个简单的 symbol 将表示密集层,也就是发生在两个 components 之间的线性连接层。同样,我们可以看到,为了在 TensorFlow PyTorch 中构建这样的网络,这些 convenience 函数真的开始帮助我们很多,因为我们不必从 scratch 实现很多东西。
如果我们想创建一个 深度神经网络,我们该怎么做?什么是深度神经网络?它只不过是 sequentially 堆叠越来越多的线性层,然后是非线性函数,然后是更多的线性层,然后是更多的非线性函数,一遍又一遍,以 hierarchical 的方式。这只是一个模型,其中最终输出是通过 hierarchical 组合 created 的,这种组合方式是越来越深入地进行线性运算,然后是非线性运算。
(观众提问)
提问者:你能否给出一个关于为什么我们会有不同层的现实世界例子?
Alexander: 当然。问题是关于,也许只是一个快速的现实世界例子,说明为什么我们会有不同的层,在 depth 轴上不同的层,以及在上下轴上不同的输出。基本上,xaxis 上的不同层对应于更多的 depth,网络中更多的复杂度。对于更复杂的任务,大家会想要更多的 depth,因为大家引入了更多的 hierarchical 非线性函数。在一个层之后,如果大家只有一个 dense connection,然后是一个非线性函数,大家可以提取的复杂度量是有限的,它只来自一个非线性函数。因此,随着任务变得越来越复杂,大家需要更深层次的表达函数。这就是这个轴。在另一个轴上,更多的输出只是问题定义。如果大家想要预测更多的事情,那么大家就需要更多的输出。一个好的例子是,如果大家想要进行生成,比如生成图像,大家需要生成图像中每个像素的值。这有很多输出。与大家只想预测,比如明天的天气(温度值,只是一个输出,一个数字)相比,取决于大家的问题定义,这两件事可能会改变。
构建神经网络 (续)
现在我们对神经网络的架构有了一个概念。我认为现在是时候将所有这些信息 tie together,并实际上,为了配合刚才提出的问题,让我们尝试通过一个例子,将一些理论应用于实践,并真正理解如何应用神经网络来解决一个非常实际的问题。也许不是那么实际,但也许对大家来说是实际的,大家一直在思考这个问题。
这里有一个问题,也许大家都在问自己:我会通过这门课吗?让我们尝试构建一个神经网络,它可以 infer 或 predict 大家所有人的答案。我们将通过构建一个非常简单的模型来做到这一点。它将采用两个输入,一个输出。一个输出将是“我会通过这门课吗?是或否”。所以是一个数字,通过这门课的概率。它将有两个输入,由以下内容定义:
- 大家在本周课程中参加的讲座次数。
- 大家在 final project 上花费的小时数。
让我们 plot 一下,因为我们已经教这门课很多年了,我们实际上有过去学生关于这个操作的数据。我们可以查看所有绿点,它们是通过这门课的人。所有红点是没有通过的人。我们还可以 plot 大家的位置,或者大家可以 guess 大家将在这门课上花费多少小时,大家将在 final project 上花费多少小时。我们想要做的是构建一个神经网络,它将从所有这些过去的学生数据中,determine 大家将落在哪个位置,通过与不通过的概率 chance。
让我们开始吧。我们实际上已经学到了所有这些内容,所以让我们一步一步来。我们有两个输入。这是这个新来的人,大家参加了四次讲座,在 final project 上花费了 5 个小时。这两个数字可以作为左侧模型的输入 feed in。我们还有一个单层神经网络,一个非常基本的神经网络。我们现在将从这个开始,我们将看到我们的隐层有三个隐层单元,我们的输出将只有一个输出,这是一个 binary 输出,是或否通过这门课。我们将看到,实际上这个模型得到的答案非常错误。它 predict 大家会以 0.1 或 10% 的概率通过这门课,而实际上大家做得非常好,大家肯定通过了这门课。有人能告诉我,大家认为为什么这个网络会失败得这么惨吗?
(观众回答)
观众:因为它没有训练过。
Alexander: 完全正确!答案是它没有训练过。完全正确。这里的模型还没有看到我们在上一张幻灯片中展示的任何数据。它基本上像一个没有见过任何关于现实世界知识的婴儿。它也不了解这个问题。它需要首先了解这个问题。这是我们目前还没有讨论过的内容。为了训练我们的模型,我们的模型还必须理解,当它做出错误的预测时,错误的预测意味着什么。这意味着它必须能够 quantify 预测有多糟糕,以及预测有多好。这就是所谓的 神经网络的损失 (Loss of a Neural Network)。神经网络的损失将衡量其预测与 ground truth 答案或 ground truth 数据观察值之间的距离。大家的损失越小,就意味着这两件事越接近。所以大家的预测真的与 ground truth 相匹配,这会导致损失很小。
现在,假设我们的数据不仅仅来自一个学生,我们实际上有来自很多学生的过去数据。现在我们想 Care on 模型不仅仅对这一个学生做得如何,而是 aggregate empirically 整个过去课程的表现。这就是我们所说的 training on,不仅仅是一个数据点,而是 training on 整个数据集。当我们训练神经网络时,我们想要找到神经网络,它不仅在一个学生身上,而且在 aggregate empirical 数据集上 minimize 我们的损失或 maximize 我们的准确率。这叫做 经验损失 (Empirical Loss),它只是简单地将每个数据点在我的数据集中的损失平均。
现在,我们一直 focus 在 binary 分类问题,是或否的答案。对于这些类型的损失,我们可以使用所谓的 Softmax 交叉熵损失 (Softmax Cross Entropy Loss)。我们稍后会了解更多关于这方面的内容,但这衡量的是两个概率分布,两个 binary 概率分布之间的差异或距离。
现在,假设我们不是 predict 二进制输出,而是想要 predict 最终输出是一个实数,比如连续值,比如 grade,百分制 grade,而不是“我会通过这门课吗?还是不会?” 而是“我做得有多好的百分制 grade”。对于做类似的事情,我们将无法再使用 binary 损失。所以我们必须实际更改我们的损失函数。例如,我们可以将其更改为 均方误差损失 (Mean Squared Error Loss, MSE)。我们可以取我们的两个 grade,predicted grade 和 true grade,将它们相减,然后平方,以创建一个距离度量。这些大致是大家将看到的两种类型的损失,categorical discreet 损失,如 binary 损失,以及 continuous 损失,如 MSE 损失。当然,还有很多其他类型的损失,大家将在课程中接触到,但这两种损失具有非常广泛的 coverage。
训练神经网络 (续)
让我们把所有这些信息放在一起,现在开始讨论实际找到网络权重的问题。我们已经讨论了定义网络,我们已经讨论了 basically 当网络出错时 penalizing 网络,我们还没有讨论如何实际改进网络或训练网络。让我们在接下来的部分中讨论这个问题。
这里的 objective 是什么?我们最终想要做什么?在这整个课程的最后,我们试图找到并构建网络或模型,构建在数据集上 minimize 损失的模型。损失衡量 predicted 和 true 之间的差异。我们想要 minimize,我们想要找到一个网络,它在数据集上 minimize 损失。这意味着,mathematically 来说,walking through 这个方程,这意味着我们想要找到 W,我们想要找到权重,这将导致从 1 到 n 的整个数据集上的最小 L,损失。
请记住,W 权重只是所有网络中所有权重的集合。它是我们网络中每一层的权重。我们将把它们 combine into 一个整体,这些就是我们将尝试优化的权重。我们如何进行这种优化过程呢?请记住,我们的损失函数只是权重的函数。给定一组权重,我们的损失函数将返回一个值。它是我们的 predicted 答案与我们的 true 答案之间的距离有多远。如果我们网络中只有两个权重,那么我们将能够 plot 我们的损失景观,像这样的图片。我们可以在权重 1 和权重 2 的数据网格中 plot 它。对于我的权重的每种 configuration,都能够看到该 configuration 的权重获得了多少误差或多少损失。我们想要做的是 basically 找到这个景观中的最低点。我们想找到哪个权重 1 和权重 2 corresponds,并给我们最小的损失。
我们如何做到这一点?我们可以从一些随机点开始。我们在景观中 pick 一个随机点,任何点,我们从这个点开始。我们将计算所谓的梯度。梯度将告诉我们从这个点开始哪个方向是向上的。这是一个 local 度量,它只告诉我们从我站立的地方,哪个方向是向上的。我将采取一小步,在相反的方向上迈出一小步,并采取一小步,使损失下降。然后我将一遍又一遍地重复这个过程,直到我最终到达山丘的底部,并 converge 到所谓的 局部最小值 (Local Minimum)。大家可以将这个算法,这个过程 summarize 为所谓的 梯度下降 (Gradient Descent) 伪代码。让我们再简单回顾一下。我们首先随机初始化权重。这意味着我们随机 pick 我们景观中的一个位置。我们计算梯度,这里叫做 DJ/DW。这是一个小的权重变化如何改变我们的损失。所以这告诉我们,我们应该朝哪个方向改变权重以增加损失。我们在相反的方向上迈出一小步。大家可以看到,实际上我们取梯度,我们乘以 -1,我们朝相反的方向走,然后我们将其乘以一个小步长,我们称之为 Ada。这里的 Ada 将是步长大小,我们在该方向上实际移动多少。然后我们循环重复这个过程。在 TensorFlow 中,大家可以看到这完全以相同的方式表示。但在这里,我想引起大家注意这个项。这是方向项,它告诉我们梯度。梯度将告诉我们哪个方向是向上的,或者如果大家取它的负数,哪个方向是向下的。但我从未真正告诉大家如何计算这个梯度。我只是告诉大家我们需要计算这个。
在神经网络中计算梯度的过程称为 反向传播 (Backpropagation)。我认为,快速通过一个 step-by-step 的例子,walking us through 反向传播是如何工作的,以及大家将如何计算特定神经网络的梯度,也会有所帮助。为了演示,我们将从现有的最简单的神经网络开始。它由一个输入、一个输出和一个中间的隐层神经元组成。大家不可能得到比这更简单的网络了。我们想要计算损失 L 在结尾处的梯度,或者 excuse me,这里是 J 在结尾处的梯度,相对于,让我们从相对于 W2 开始。
小的 W2 变化对我们的损失有多大影响?我们可以写出这个导数。我们可以用数学形式写出来,我们可以使用链式法则来 decompose 它。我们为什么要 decompose 它呢?首先,我们将梯度 DJ/dW2 decompose 成两项:dJ/dY 和 dY/dW2。这只是链式法则的基本扩展,没有什么神奇之处。但为什么这成为可能呢?因为它成为可能,是因为 Y 仅依赖于前一层。现在,假设我们现在想要计算 W2 之前的权重的梯度,比如这里的 W1。我们可以做的是用 W1 替换这个方程中的 W2。然后我们必须再次应用链式法则。因为计算最后一项在这里没有明确定义,所以我们必须再次 expand 它。这就是为什么我们称之为反向传播,因为大家实际上必须从输出开始,并不断计算这些 iterative 链式法则,在网络中一步一步向后传播。我们重复这个过程,将梯度从输出传播到输入,across 我们的权重。在这个完整过程结束时,我们得到的是,对于网络中的每个权重,我们都有这样一个方向,基本上说,“如果我们稍微增加这个权重,我们的损失会上升还是下降?” 如果我们的损失要下降,这意味着我们应该稍微增加那个权重,或者我们将朝相反的方向走。这就是反向传播算法。在理论上,它只不过是 differential calculus 中链式法则的应用。但在实践中,它可能变得非常 messy 和 hairy。这是一个非常 computational 的度量,因为大家必须为模型中的每个权重 step-by-step 地执行此操作。因此,在今天的实践中,深度学习框架(如 TensorFlow PyTorch)会自动完成此操作。所以大家不一定需要自己实现它,但重要的是要理解这些东西是如何运作的 theoretical side,以及它在 underneath the hood 做什么。
我还想借此机会与大家讨论训练神经网络在现实中的一些 practical implications。我给大家看过这张之前的图片,它看起来像一个非常漂亮的损失景观,非常 smooth。但在实践中,优化神经网络非常困难。这实际上是一张神经网络的损失景观的图片,神经网络是极其 high-dimensional 的搜索空间,所以我们实际上并不知道这张图片是什么样子,但这只是深度神经网络的损失景观的一个 projection,来自一篇几年前发表的论文,大约在 2017 年。大家现在可以 visualize 一下,有些损失景观看起来有多 messy,应用这些类型的反向传播和优化技术非常具有挑战性。
我想让大家 recall 一下,在我们深入研究反向传播,特别是梯度项之前,我们开始讨论大家在这里看到的这个方程。我们如何更新权重?我们通过在想要的方向上迈出一小步,以小的 increment 来更新它们。现在,这是我想 focus on 的关键项,这个小步长,这叫做模型的 学习率 (Learning Rate)。这个 D basically dictates 我们采取这些步骤有多快,以及我们在计算反向传播时,听取梯度的速度有多快。在实践中,设置学习率可能非常非常困难。如果我们设置的学习率太慢,那么我们基本上从某个点开始,但我们 stuck 在一些局部最小值中,但它们可能不是我们可以达到的最佳最小值。如果我们设置得太大,那么我们就会得到一些不稳定的 Behavior,我们基本上 overshoot。我们开始朝正确的方向迈步,但我们步子迈得太大,然后我们 explode out of 学习的 stable place。理想情况下,我们希望设置 learning rates,它们不会太小,以便它们可以 skip 一些局部最小值,也不会太大,以至于它们也会 diverge,并且可以收敛。
我们如何实际设置学习率呢?一种选择,实际上是一种非常常见的选择是,尝试一堆学习率,看看哪个效果最好。有什么比这更好的方法吗?想法是,大家能否设计自适应算法,根据它们在搜索空间中优化的方式,大家可以 adapt 学习率吗?大家可以根据景观本身更改学习率吗?这 basically 意味着,实际上,大家的学习率将随着梯度和数据的函数而增加或减少,大家学习的速度有多快,景观有多陡峭,所有这些不同的 things 基本上都可以 dictate 所有这些学习率的自适应属性。实际上,这些已经被广泛研究,并且已经创建了许多不同类型的自适应学习率调度器。大家可以在这里看到一些例子,Adam 等等。所有这些都以 Ada 开头,很多都以 Ada 开头,Ada 代表 adaptive。这些都是这些自适应属性的不同变体。尤其是 Adam,是一种使用极其广泛的优化过程,大家将在许多实验中使用它。但我鼓励大家真正尝试并 experiment 所有这些不同类型的学习率调度器,看看哪个效果最好。很多时候,会有不同类型的学习率调度器适用于不同类型的问题。所以大家绝对应该尝试不同的方法。尝试它们就像更改一行代码一样容易。更改大家的学习循环将 just implement 不同的调度器。SGD,随机梯度下降,只是大家之前看到的 base 梯度下降算法。
我想更深入地研究一下,因为大家看到的或我展示的是梯度下降算法,而不是随机梯度下降算法。我想告诉大家一些关于这两种算法之间区别的信息。要理解这一点,我们必须再次 revisit 梯度下降算法。这里的梯度,这是我们用反向传播计算出来的部分,计算量非常大,因为如果大家仔细看,它是作为求和或平均值来计算的,我应该说是平均值,而不是求和,在我的数据集中的所有数据点上求平均值。所以我计算梯度,不是针对一个数据点,而是针对数据集中的所有数据点。这就是为什么它非常昂贵。在大多数现实生活问题中,在每一步迭代中计算整个数据集的梯度实际上是不可行的。因为请记住,我们不仅仅计算一次梯度,我们在优化过程中的每一点都计算它,大家正在优化网络数百万甚至更多的步骤。大家不希望在这些步骤中的每一步都 loop through 整个数据集。
现在让我们定义一种新型的梯度下降,我们称之为 随机梯度下降 (Stochastic Gradient Descent, SGD),就像大家之前看到的那样。与其计算整个数据集的梯度,不如计算一个非常 noisy 的梯度。这将是一个仅在一个数据点上计算的梯度。所以我将随机 pick 一个数据点,我将计算相对于该数据点的梯度,而不是我的整个数据集。这显然会 noisy 得多,因为那一个数据点并不能代表我的整个数据集。但它会更快地给我答案,所以我可以更快地完成更多步骤。这里也存在一个 natural 的 trade-off。我们想走得快,但我们也不想太 noisy。显然这里有一个中间地带。与其在一个示例上计算 noisy 梯度,不如我们可以做所谓的 小批量梯度下降 (Mini-Batched Gradient Descent)。小批量梯度下降是指大家设置一个批量大小,然后在每次迭代中,大家计算梯度,不是相对于一个数据点,而是相对于 k 个数据点,其中 K 非常小,想想 32 或 128 之类的,在这个 scale 上。大家查看相对于这些数据点(比如 32 个)的梯度,然后大家平均梯度。这有助于大家在度量中获得更多可靠性和鲁棒性,但大家也能获得速度。大家没有遍历整个数据集。32 通常远小于大家的整个数据集。这意味着,与随机梯度下降相比,我们现在有了 gradient accuracy 的提高。所以我们可以更 smoothly 地 converge。我们不会 super noisy 地一次只追逐一个数据点。但这也意味着,与 full 梯度下降相比,我们可以更快。full 梯度下降会遍历整个数据集。这意味着,因为我们在一方面更 stable,我们也可以提高我们的学习率。这两件事是极其相关的。梯度和学习率之间的关系应该是大家非常 intuition 的。因为大家的梯度现在更 stable 了,大家在小批量上求平均值,而不仅仅是单个样本,大家现在可以开始采取更大的步骤了。大家可以更信任梯度。在优化过程中,它还允许大家真正 parallelize 训练。因为如果大家想计算 32 个数据点的梯度,大家可以 parallelize 在 GPU 上的 32 个进程上。大家可以 parallelize 计算它们,而不是一次计算一个。这允许大家真正开始进一步利用 GPU 加速。
过拟合与正则化
在进入第二讲之前,我要讲的最后一个 topic 是关于 过拟合 (Overfitting) 和神经网络的正则化 (Regularization)。这是一个巨大的问题,不仅在深度学习中,我们想要 cover 它,因为它也是大家在今天的实验中会接触到的问题,基本上它是所有机器学习中最 fundamental 的 topic 之一。理想情况下,在机器学习中,我们想要构建的模型,不仅仅在训练集上 work well。我们确实在训练集上训练模型,但我们不希望它们只在训练集上 work well。实际上,我们真正想要的是,我们实际上通常并不 care 模型在训练集上的实际工作情况。我们使用它作为 proxy,因为我们真正 care 的是模型在 brand new 数据上的工作情况,当我们将其 deploy 到 wild 中时。那不是我们的训练数据,而是 brand new 的测试数据。这两者之间的关系极其重要。我们使用训练数据作为 proxy,但 ultimately 我们并没有 really really care 它。换句话说,当我们构建模型时,我们想要从训练数据中学习 representation,但我们仍然希望它们 generalize 到 unseen 的测试数据。
以这张图片为例。假设大家想构建一条线来描述这张图片中 X 点和 Y 点之间的关系。在左手边,大家可以看到,大家有一个非常简单的模型,线性模型。它可以描述训练点,并且可能也会在一定程度上 faithful 地描述测试点。但它没有 fully capture 数据集的 richness 和 complexity,无论是在训练集还是测试集中。因此,我们没有利用模型在左手边的 full expressive capacity。一直移动到右手边,大家实际上可以看到,我们开始 memory 数据集中的数据点。我们 memory 训练数据集中的数据点的程度如此之深,以至于我们正在 hurting 我们在 brand new 测试数据上的表现,因为我们太依赖于我们在训练期间看到的内容。基本上,大家始终希望最终落在中间位置。大家希望 leverage 大家的训练点,但不要太依赖它们或 memory 它们。
(观众提问)
提问者:能否给出一个关于过拟合问题的现实生活例子?
Alexander: 当然。过拟合的现实生活例子是,假设大家有一个非常小的数据集,但有一个非常大的网络。大家将学习到一个模型,它只是 memory 大家数据集中的所有数据。这并不是说它在做什么坏事,因为它有能力 memory 训练集中的所有内容。请始终记住,模型看不到测试集,这是 unseen 数据。所以它们能看到的只是大家的训练集,大家给它们的东西。如果大家给它们一个非常小的训练集和一个非常大的模型,模型会做它应该做的事情,并充分学习训练集。但是,当大家向它展示更多测试数据时,它将不会非常 faithful 于训练数据,因为它不会 perfectly 来自相同的分布。
(观众提问)
提问者:随机梯度下降中的随机性来自哪里?梯度计算还是数据选择?
Alexander: 随机性 purely 来自选择算子。也许这会造成 confusion。我们称之为随机梯度下降的原因是,因为选择过程是随机的。我们不针对整个数据集执行此操作,而是 stochastically 选择数据子集,而这种选择是随机的。
(观众提问)
提问者:是否可以进行更自适应的数据选择,而不是完全随机?
Alexander: 答案是肯定的,绝对可以。真正随机的数据 seeing 实际上也不是非常 realistic 的。即使这是 convention 的方式,我们人类也不是这样运作的。我们不会 just randomly 看到数据,我们是 sequentially 随着时间推移看到数据的,我们看到的数据是有意义和目的的。在明天的讲座中,大家将看到一个关于我们如何进行这种自适应选择过程的示例,以及它的好处。
正则化
正则化 (Regularization) 只是一种技术,允许大家 discourage 这些复杂的 memory 协议。如果大家有一个非常小的数据集,一个大的模型,大家希望 discourage 模型仅仅 memory 该数据集。大家如何 discourage 模型学习这些类型的东西呢?正如我们所看到的,这对于模型的 overall 性能至关重要,因为我们不 care 训练结果,我们 ultimately 最 care 测试结果。最流行的正则化技术实际上是一个非常简单的想法,大家几乎会在本课程的所有实验中使用它,这就是 Dropout 的想法。
什么是 Dropout?让我们 revisit 这张深度神经网络的图片。在 Dropout 中,我们所做的就是在训练期间,我们将随机将隐层神经元的一些激活值设置为零,并设置一定的概率。假设我们将 dropout 设置为 50%。我们将要做的是,假设 50% 的神经元,我们将 dropout 激活值或将其激活值设置为零。这迫使网络不过分依赖于任何一个神经元的输出。在神经元 dropout 后,下一层的输入无法依赖,无法过多 memory 先前的输入,因为在模型的前向传递中,不仅仅在数据集 curation 中,而且在 pure 前向传递中,还有一些 stochasticity being implemented。即使我 pick 相同的数据两次,并将其通过模型两次,由于 Dropout,大家也会有另一个级别的 stochasticity,这意味着模型甚至无法 memory 完全相同的数据两次。这是一个极其 powerful 的想法,因为 basically 它所做的只是降低了模型的 capacity。它降低了模型学习 singular pathway through 模型的能力。它迫使模型学习多条路径来做出单个决策。基本上,在每次迭代中,我们只是重复这个过程。每次看到新的数据片段或每次我们进行前向传递时,它总是为该数据创建一条随机路径,以通过模型。
我要展示的最后一个技术是关于 早停法 (Early Stopping) 的概念。早停法 basically 意味着我们监控训练损失和测试损失之间的 deviation。我们可以有一个测试,我们可以有一个测试损失的 proxy,通过拥有一个 hell do 集,也许它不是 true 测试损失,但它又是另一个 proxy,我们不在其上进行训练。我们可以 basically 监控模型在训练集和我们的 heldout 集(我们称之为验证集)上的表现。在开始时,随着我们的训练,这两条线都开始下降,这非常棒,这是有道理的。这是因为模型正在学习,随着训练的进行,它变得越来越强大。最终,大家会看到模型开始 Plateau 它的损失,而在测试集上,它开始增加。所以,如果模型有足够的 capacity,训练准确率应该始终下降,训练损失应该始终变得越来越好。但在某个时候,大家会看到测试损失开始 memory 数据。它开始 memory 训练损失中的数据,这导致测试损失稍微上升。这种模式在剩余的训练中持续下去。这是大家应该真正 focus 的点,如果大家 plot 这条曲线,大家会在每个阶段 save 大家的模型,但大家只会 take checkpoint,大家会 take 在这一刻发生的模型,因为即使在此点之后训练损失变得更好,大家实际上看起来有一个更好的模型,但从测试集来看,大家可以看到它实际上已经开始 memory 训练集的部分内容。所以大家不 take 最右边的模型,大家实际上 take 中间的这些模型。
(观众提问)
提问者:我们应该在每个训练迭代中进行测试损失计算吗?
Alexander: 不是每个迭代,因为这可能会增加不必要的计算。但人们通常的做法是,比如每隔一定迭代次数,大家会进行一次测试运行。同样,大家不需要对整个测试集进行测试运行,大家也可以 stochastically 进行,以 batch 的形式进行。例如,大家可以每隔 1000 次迭代,对测试集中的一批数据点(比如只有 100 个)进行测试,只是为了获得 approximate 的结果。
(观众提问)
提问者:Dropout 节点会更新梯度吗?
Alexander: 不会。dropout 节点不会有梯度,因为我们没有关于它们发生什么的信息。但对于所有其他节点,我们将获得更新。
(观众提问)
提问者:验证集应该与训练集分开吗?
Alexander: 是的,为了使早停法有效,它应该是 separate 的。这是一个关键假设。理想情况下,大家应该 take 大家的训练数据,人们可以 basically 按比例 cut 大家的训练数据。假设大家 take 70% 的训练数据,大家实际上用它来进行训练。大家 take 训练数据的另外 30%,并将其用于测试和验证。
(观众提问)
提问者:训练集和测试集之间的损失差异是否总是有规律的模式?
Alexander: 我认为没有理想的模式。实际上,理想情况下,应该没有差异。但在实践中,在某些情况下,实际上差异非常小。让我举个例子,假设大家的训练集也非常 massive,以至于模型不可能学习 full capacity,模型不可能 memory。那么实际上大家会看到训练和测试非常接近。一个很好的例子是语言建模。即使是 massive 的语言模型,它们仍然难以 memory 整个数据集,仅仅是因为语言是一个如此 massive 的数据集。即使在那里,大家基本上也会看到训练和测试曲线看起来非常非常相似。但这就是为什么我们必须实际进行其他类型的验证。语言模型实际上并没有大家知道的其他类型深度学习模型所具有的 classical 过拟合问题。它们有其他问题,我们稍后会讨论。
总结与展望
好的,现在我将通过总结我们在本次讲座中讨论的三个要点来结束,然后再进入第二讲。首先,我们讨论了构建神经网络,神经网络的架构。我们讨论了基本操作,基本架构称为感知器,单个神经元。我们了解了如何将这些单个神经元堆叠在一起,形成复杂的 hierarchical 网络,以及如何使用数据在 mathematical 上优化这些网络。最后,我们 address 了许多 practical implications,从 batch 梯度下降到过拟合和正则化以及这些模型的优化。在下一讲中,我们将听到 Ava 讲解深度序列建模,这是大型语言模型的 backbone。这是一个非常 exciting 的讲座。我们可能会休息五分钟,以便我和 Ava 可以切换笔记本电脑,然后我们将继续讲座。讲座结束后,我们将进行软件实验,然后是 Link 的招待会和食物。谢谢大家!