杜克大学机器学习笔记-全-

杜克大学机器学习笔记(全)

001:机器学习为何令人兴奋 🚀

在本节课中,我们将要学习机器学习的基本定义、核心属性,并探讨近年来机器学习备受关注的根本原因。

机器学习实际上是一个相对古老的领域,其研究已持续数十年。近年来真正吸引大众目光的,是机器学习在一些极具挑战性的任务上所展现出的卓越性能。其中一个典型例子就是深度学习在图像分析领域的突破。

以下是八个示例图像。这些图像的特点是复杂且高度贴近现实生活。机器学习在此的任务是分析图像,并为它们分配描述性的标签。

对于每张图像,其下方会显示两个信息:首先是图像的真实标签,其次是机器学习模型为该图像预测出的五个最可能的标签。

观察这些结果可以发现,机器学习模型在总体上为这些相当复杂的图像分配标签时,表现得非常准确。

这个任务被称为ImageNet挑战赛,是多年来持续研究的领域。下图展示了不同年份在ImageNet任务上的最佳性能对比。

我们关注的是算法(即机器学习算法)的最佳性能随年份的变化。纵轴代表错误率,横轴代表进行研究的各个年份。

可以注意到,大约在2012年,性能出现了一个阶梯式的跃升。这正是深度学习,特别是卷积神经网络,首次被大规模应用并真正展现出其强大能力的时候。因此我们看到,在2012年左右,性能有了非常显著的提升。

在随后的几年里,性能持续改善。图中那条大约在5%错误率的水平线,代表的是人类的平均表现水平。

这张幻灯片表明,在过去几年中,以卷积神经网络形式呈现的深度学习,已经发展到能够以超越人类平均水平的准确度来分析非常复杂的图像。

正是机器学习这种超越人类表现的性能水平,引发了广泛的关注。虽然我之前展示的自然图像令人兴奋,但这种超越人类的表现当然也引起了其他许多应用领域的兴趣,例如医学中的眼科或皮肤科,这些领域严重依赖于图像分析。在某些情况下,机器学习的表现已经超过了医生。

近年来,机器学习在另一个领域也取得了非凡的成就,那就是玩复杂的游戏。虽然游戏本身可能并非重点,但机器解决复杂序列问题(这正是游戏所代表的)的能力,以及在与人类竞争中完成该任务并击败人类,是意义非凡的。

围棋是一项主要在亚洲进行的古老游戏。长期以来,人们认为机器无法在这项游戏中击败最优秀的人类选手。然而在过去几年,深度学习在围棋上展现出了超越世界顶尖人类棋手的表现。

这是一个非常、非常重要的里程碑。它是深度学习和机器学习如何解决非常复杂的任务,并且其表现水平常常超越人类的又一个例证。

正是这种水平的性能,引发了机器学习和深度学习领域的所有兴奋点。

本节课中,我们一起学习了机器学习的基本概念,并通过图像识别和围棋等具体实例,看到了机器学习,特别是深度学习,如何在近年来取得突破性进展,甚至在某些任务上超越了人类的表现。这种解决复杂问题并达到卓越性能的能力,是当前机器学习领域备受瞩目的核心原因。

002:什么是机器学习 🧠

在本节课中,我们将学习机器学习的基本概念。我们将了解机器学习如何通过数据示例来“教导”算法进行预测,并探讨其核心组成部分。


概述

机器学习的目标是让机器(即算法)从数据中学习。我们通过提供包含数据样本及其对应标签的示例来训练机器。训练完成后,我们希望机器不仅能准确复现训练数据中的模式,还能对新的、未见过的数据做出准确预测。

核心概念解析

上一节我们概述了机器学习的目标,本节中我们来看看其核心组成部分。

数据与标签

在机器学习中,每个示例都由两部分组成:

  • 数据:通常表示为一个数字向量,记作 X
  • 标签:我们希望为数据分配的结果或类别,记作 y。为简化起见,我们常使用二元标签,例如 y = 0y = 1

例如,在医疗图像分析中:

  • X 可能对应一张像素化的图像。
  • y 则用于分类该图像是否显示恶性肿瘤(例如,1 表示恶性,0 表示良性)。

训练数据

我们通过提供多个示例来教导算法。这些示例的集合称为训练数据

假设我们有 n 个训练示例,可以表示为:
{(X₁, y₁), (X₂, y₂), ..., (Xₙ, yₙ)}

预测模型与参数

我们的目标是构建一个预测模型(或称“机器”)。这个模型本质上是一个数学函数,它接收数据 X 作为输入,并输出预测的标签 ŷ

模型内部包含一些参数(通常用 θw 表示),这些参数最初是未知的。学习的过程就是根据训练数据来调整这些参数,使得模型的预测 ŷ 尽可能接近真实的标签 y

一个具体示例:预测是否会下雨 ☔️

为了让概念更具体,我们来看一个简单的例子:预测某一天是否会下雨。

以下是构建预测模型的步骤:

  1. 收集数据:每天早晨,我们测量一些环境特征,例如云量、湿度、温度和气压。这些测量值构成我们的数据向量 X
  2. 记录标签:当天结束时,我们记录是否下雨。定义 y = 1 表示下雨,y = 0 表示未下雨。
  3. 形成训练集:收集多天的(X, y)配对,就构成了我们的训练数据。
  4. 训练模型:我们使用这个历史训练数据来调整模型的参数。目标是让模型学会根据早晨的测量数据 X 来准确预测当天是否会下雨(即输出 y)。
  5. 进行预测:训练完成后,当新的一天早晨,我们获得新的测量数据 X_new 时,就可以将这个数据输入训练好的模型,模型会输出预测 ŷ,告诉我们它认为今天是否会下雨。

核心任务与目标

上一节我们通过例子了解了流程,本节中我们来明确机器学习的核心任务。

机器学习的关键任务可以概括为以下两步:

  1. 学习/训练:利用训练数据 {(Xᵢ, yᵢ)} 来学习模型的最佳参数,使模型在训练数据上表现准确。
  2. 预测/测试:将学习好的模型应用于新的、未见过的数据 X_new,以预测其对应的标签 y_new。模型在新数据上的表现(即泛化能力)是衡量其成功与否的最终标准。

总结

本节课中,我们一起学习了机器学习的基本框架:

  • 机器学习通过数据(X)标签(y) 组成的示例来训练算法。
  • 训练过程的目标是找到一个模型及其参数,使其能够从数据中捕捉到预测标签的规律。
  • 最终目标是让训练好的模型能够对新的数据做出准确的预测。

接下来,我们将深入探讨这些概念的更多细节,以更清晰地理解机器学习的各个方面。

003:逻辑回归 📊

在本节课中,我们将深入探讨机器学习的一个核心概念——逻辑回归。我们将学习如何构建一个简单的预测模型,该模型能够根据输入数据预测结果,并以概率的形式输出预测。


概述

机器学习的一个关键方面是使用训练集——即包含数据(X)和对应结果(y)的示例集合。我们的目标是学习一个模型,该模型能够根据给定的数据预测结果。学习过程涉及一个算法,该算法由一组参数定义。学习意味着我们要推断出与训练数据一致的模型参数。

为了使这个概念更具体,我们将从最基本且应用广泛的算法之一——逻辑回归开始。逻辑回归是一个很好的起点,也是后续构建更复杂模型的基础。


线性预测模型

在机器学习中,我们的目标是处理一个训练集。这个训练集包含 n 个示例,每个示例包含数据 X 和结果 y。我们希望构建一个能够根据 x 预测 y 的预测模型,该模型由参数定义。

让我们看一个非常简单的模型——线性预测模型

  • X 代表数据。xᵢ 代表第 i 个示例的数据。
  • xᵢ₁ 代表向量 xᵢ 的第一个分量,xᵢ₂ 代表第二个分量,依此类推,直到第 m 个分量 xᵢₘ

一个非常简单的想法是:我们将向量 X 的每个分量乘以一个对应的参数。

  • 参数 B₁ 乘以 xᵢ₁
  • 参数 B₂ 乘以 xᵢ₂
  • 参数 Bₘ 乘以 xᵢₘ

我们将所有这些乘积相加,然后再加上一个额外的常数,我们称之为偏置项 B₀。这样,我们就将数据 xᵢ 映射到了一个数值 zᵢ

公式表示如下:
zᵢ = B₀ + B₁*xᵢ₁ + B₂*xᵢ₂ + ... + Bₘ*xᵢₘ

这是一个非常简单的线性预测模型。


从线性输出到概率预测

回到我们的天气预测例子,yᵢ = 1 表示第 i 天下雨,yᵢ = 0 表示没下雨。我们输入模型的数据(特征)可能是云量、湿度、温度等。

通过上述线性模型,我们得到了一个数值 zᵢ。然而,我们通常希望预测的不是一个绝对的“是”或“否”,而是一个概率。例如,我们可能希望说“有70%的置信度认为今天会下雨”。

我们通过一个称为逻辑函数(或Sigmoid函数)的转换来实现这一点,其符号为 σ

公式表示如下:
P(y=1 | x) = σ(z) = 1 / (1 + e^{-z})

这个函数的关键特性是,它的输出始终在 01 之间。

  • z 是一个很大的正数(例如 5 或 6)时,σ(z) 的输出接近 1。这意味着基于该 z 值,我们高度确信当天会下雨。
  • z 是一个很小的负数(例如 -2, -3, -4)时,σ(z) 的输出接近 0。这意味着基于该数据,我们认为当天降雨的概率很低。

因此,Sigmoid 函数是将我们对结果的预测转换为概率视角的一种方式。

  • 如果 z 很大,则结果 y=1 的概率很高。
  • 如果 z 是负数,则结果 y=0 的概率很高。

逻辑回归模型整合

将上述步骤整合起来,就构成了逻辑回归模型。

  1. 我们拥有数据(例如云量、湿度、温度)。
  2. 我们将每个数据变量乘以对应的参数值(B₁, B₂, B₃...)。这些参数告诉我们各个数据变量对预测的重要性。
  3. 将所有乘积与偏置项 B₀ 相加,得到线性组合 z
  4. 最后,将 z 送入 Sigmoid 函数 σ,得到一个介于 0 和 1 之间的概率值。

这个模型——将观测数据变量与相关参数相乘后求和,映射到变量 z,再通过 Sigmoid 函数处理——是一个非常经典的模型,称为逻辑回归。


机器学习核心概念图示

下图清晰地展示了机器学习的核心流程:

  • 中心(模型):机器学习的心脏是一个参数化模型(如逻辑回归),它由一组我们想要学习的参数(B₀...Bₘ)定义。
  • 左侧(数据):我们有一个包含观测数据 X 和结果 y 的训练集。
  • 学习过程:我们的目标是学习模型的参数,使得模型的预测与训练数据保持一致。这意味着推断出参数 B₀...Bₘ,以提供一个从 Xy 的、与数据一致的映射。

总结

本节课我们一起学习了逻辑回归的基本原理。逻辑回归从模型角度来看是最简单的概念之一,但它应用广泛且非常有效。它在某种意义上抓住了机器学习的核心精髓。

我们了解到:

  1. 逻辑回归使用线性组合将输入特征与参数相结合。
  2. 通过 Sigmoid 函数将线性输出转换为概率预测。
  3. 学习的目标是找到一组参数,使模型的概率预测与训练数据中的实际结果尽可能一致。

随着课程的深入,我们将看到逻辑回归的基本概念在机器学习的许多方面,特别是深度学习中,会被反复使用和扩展。

004:逻辑回归的解读 🧠

在本节课中,我们将深入学习逻辑回归算法。逻辑回归是机器学习中最简单但应用广泛的算法之一,它为我们理解机器学习的工作原理提供了一个绝佳的模型。我们将通过一个手写数字识别的具体问题,来详细解读逻辑回归是如何工作的。


问题定义:手写数字识别 ✍️

上一节我们介绍了逻辑回归的基本概念,本节中我们来看看如何将其应用于一个实际问题。这里展示的是从0到9的手写数字示例,这是一个非常经典的数据集,称为MNIST数据集。我们的目标是构建一个预测模型,使其能够观察这些图像中的一张图片,并将其映射到0到9之间的一个数字。可以想象,这对于分析人类笔迹非常有用。当然,使用0到9只是一个例子,我们可以将这个基本结构用于分析任何手写语言。

那么,问题是我们如何做到这一点?如何利用我们手头的工具,特别是逻辑回归,来实现这个目标?

从图像到数据:像素化处理 🖼️

我们的目标是处理一张图片。例如,左边是一张数字8的图片。我们希望机器观察这张图片并预测它是数字8。我们实现这一点的方式是将图像像素化处理成数字。正如你在右边看到的,每个像素代表了图像在该空间点的强度。

然后,我们获取这些像素,它们将对应于我们之前讨论过的向量 X。为了使这一点更具体,请记住我们目前掌握的工具是逻辑回归,它假设我们模型的输出是二元的。

构建二元分类任务:识别0和1 🔢

因此,我们将考虑一个二元问题:具体来说,我们将考虑一个数字是0还是1的问题。我们希望机器能自动观察图像并正确判断它是0还是1。这是一个非常简单的二元任务。当然,我们可以将其推广到更多类别,但选择二元是因为它符合我们当前正在研究的逻辑回归模型的假设。

回想一下,我们的做法是提供一组训练数据。在左边,你可以看到一些0和1的示例。因此,训练数据表现为图像和真实标签。我们拥有逻辑回归模型:在这里,图像的像素将对应于数据 X,我们通过乘以参数 B₁Bₘ 来加权每个像素值,然后将它们求和。

模型计算过程:从加权求和到概率预测 ⚙️

得到参数 Z 后,Z 被送入Sigmoid函数。然后,我们可以以一定的概率说我们正在看的是数字1或数字0。因此,我们所说的“学习”是指推断出参数 B₀Bₘ 的集合。

为了举例说明这个模型在做什么,这是在那些1和0上训练逻辑回归模型所学到的东西。为了更深入地理解这一点,让我们再次看看这个对应于0的图片示例,以及我们模型的参数(在右侧用蓝色和红色显示)。

参数解读:作为“过滤器”的模型参数 🔍

如果我们进行逐点乘法——对于左边的每个像素,我们将其乘以右边对应的像素。

我们逐个像素地进行这种乘法,然后将所有结果求和。请注意,只有图片的白色部分与我们的“过滤器”的蓝色部分相交时,我们才会得到强烈的贡献。图片的白色与过滤器的蓝色相交,这会产生一个非常负的值,在通过Sigmoid函数后,会产生一个非常低的概率,表明这对应于数字1。

相比之下,当我们看数字对应于1的情况时,黑白图像对应于1。如果我们看下面的例子,如果我们取数字1的图片并将其乘以参数集 B(同样由蓝色和红色的图像表示),如果我们取图像的每个像素并将其乘以参数集 B 的对应像素,那么只有在参数 B 的正分量与图片的正分量重叠的地方,才会有强烈的贡献。然后我们得到一个强正值,该值随后通过Sigmoid函数,从而产生一个高概率,表明这是数字1。

核心概念:内积与Sigmoid函数 🎯

我想提供一些符号表示,这在以后会很有用。为了提供更多细节,请记住我们正在做的是:取对应于我们数据的向量 Xᵢ(一组数字),并将 X 的每个分量乘以我们称为向量的对应分量,这个向量由我们模型的参数 B₁, B₂, ..., Bₘ 表征。

因此,我们可以将其可视化为:数据是一个向量 Xᵢ,由一组像素表征;我们模型的参数是一个向量 B,代表参数 B₁Bₘ;我们将 X 的每个像素与 B 的对应像素相乘,然后将它们全部求和。这实现了顶部的方程。

这个表达式被称为内积。它是向量 Xᵢ 和向量 B 之间的内积。这个简洁的符号 Xᵢ · B 被称为内积。当我们研究更复杂的模型时,这种紧凑的符号表示以后会很有用。

模型工作原理总结:学习一个匹配过滤器 📊

因此,在这个模型中,我们正在做的是:观察图像,展示真实标签 Yᵢ = 0Yᵢ = 1 的案例,过滤器显示在右侧。我们正在做的是取数据 XᵢB 的内积,然后得到我们的 Z,接着将其送入逻辑函数(Sigmoid函数)。

所以,我们可以这样思考:我们模型的参数 B 就像一个过滤器。你可以看到这个过滤器看起来很像数字1。因此,逻辑回归模型所做的是:学习一个参数过滤器 B,然后将该过滤器参数与数据相乘。如果过滤器与数据之间有很强的匹配,那么我们就说结果 Yᵢ = 1 的概率很高。如果过滤器与数据之间的匹配度很低,我们就说过滤器与数据匹配的概率很低。

同样,这最终会通过逻辑函数(Sigmoid函数)发送,然后将其转换为概率。

数据与过滤器进行内积,然后送入逻辑函数(Sigmoid函数) 这一概念是逻辑回归的核心。随着我们继续前进,我们将利用逻辑回归中的这一概念,转向深度学习中将遇到的更复杂的模型。


本节课总结 📝

本节课中,我们一起学习了逻辑回归如何应用于手写数字识别这一具体问题。我们了解到:

  1. 问题转化:将图像识别任务转化为二元分类问题(识别0和1)。
  2. 数据处理:图像被像素化,转化为特征向量 X
  3. 模型核心:逻辑回归模型通过参数向量 B(可视为一个“过滤器”)与数据向量 X 进行内积运算,得到加权和 Z
  4. 概率输出Z 通过 Sigmoid函数 转换为预测概率。公式表示为:P(Y=1) = σ(X · B + B₀),其中 σ 是Sigmoid函数。
  5. 学习本质:“学习”的过程就是找到最优的参数 B,使得这个“过滤器”能最好地区分不同类别的数据。

逻辑回归通过这种“内积+非线性变换”的简洁方式,实现了从原始数据到概率预测的映射,为理解更复杂的神经网络模型奠定了重要基础。

005:多层感知机的动机

在本节课中,我们将要学习如何从逻辑回归模型过渡到更复杂的模型——多层感知机。我们将探讨逻辑回归的局限性,并理解为什么在数据无法被线性分类器有效分离时,需要引入更强大的模型。

逻辑回归回顾

上一节我们介绍了逻辑回归的基本概念。本节中,我们来看看它的具体计算过程。

在逻辑回归中,我们处理一个数据点 X_i。其核心计算步骤如下:

  1. 首先,计算数据 X_i 与一组参数 B(称为滤波器)的内积。
  2. 然后,将这个内积结果加上一个偏置项 b_0
  3. 最终,我们得到一个值 Z_i,其计算公式为:
    Z_i = X_i · B + b_0
  4. 接着,将 Z_i 输入逻辑函数(或称Sigmoid函数),该函数将 Z_i 转换为一个概率值,即样本标签等于1的概率。

逻辑回归是一个强大的模型,但我们希望超越它。那么,逻辑回归存在什么问题呢?

逻辑回归的局限性

逻辑回归在二元分类问题中表现良好,但前提是类别1和类别0之间的分界可以用一条直线(在二维空间中)、一个平面(在三维空间中)或一个超平面(在更高维空间中)来清晰划分。

以下是逻辑回归适用的情况:

  • 数据分布在二维空间中(例如 x_1x_2)。
  • 每个数据点对应一个 (x_1, x_2) 坐标。
  • 红色点代表一个类别,蓝色点代表另一个类别。
  • 一条直线可以有效地将红色类别和蓝色类别分开。

对于这类数据,逻辑回归是合适的,因为它本质上设计了一个线性分类器

引入非线性问题的必要性

然而,存在一些情况,数据无法被线性分类器很好地分离。

以下是一个非线性问题的例子:

  • 蓝色点对应一个类别,红色点对应另一个类别。
  • 红色点和蓝色点之间的决策边界比一条直线复杂得多。
  • 简单的直线无法分离这些类别。

因此,我们需要构建一个能够创建比线性分类器更复杂的决策边界的模型。这促使我们转向更复杂的模型,特别是多层感知机

核心动机总结

本节课中我们一起学习了从逻辑回归过渡到多层感知机的动机。

关键要点是:逻辑回归是一个优秀的模型,但它有一个局限性,即仅在线性分类器能有效区分类别1和类别0的情况下工作良好。在任何其他情况下,例如当决策边界更复杂、线性分类器无效时,我们就需要使用更复杂的模型。这自然引出了对逻辑回归的扩展——多层感知机

006:多层感知机概念

在本节课中,我们将要学习多层感知机的基本概念。多层感知机是逻辑回归的一个直接且自然的扩展。我们将从回顾逻辑回归开始,逐步引入多层感知机的结构,并通过一个手写数字识别的例子来理解其优势。

逻辑回归回顾

上一节我们介绍了逻辑回归的基本模型。现在,让我们简要回顾一下。

在逻辑回归中,对于第 i 个数据样本 x_i(它有 M 个分量 x_i1x_iM),我们执行以下操作:

  1. 将每个数据分量乘以一个对应的参数。
  2. 将这些乘积相加,得到一个变量 Z
  3. 将变量 Z 输入到一个Sigmoid函数(用符号 σ 表示)中,最终输出一个介于0到1之间的概率值。

这个过程可以用以下公式表示:
Z = w_1 * x_i1 + w_2 * x_i2 + ... + w_M * x_iM + b
P(y=1|x_i) = σ(Z)

从逻辑回归到多层感知机

上一节我们回顾了逻辑回归,本节中我们来看看如何将其扩展为多层感知机。

多层感知机的核心思想与逻辑回归相同,但我们不是只执行一次上述过程,而是执行 K 次。这相当于并行地实现了 K 个逻辑回归模型。

以下是多层感知机的构建步骤:

  1. 我们将数据 X 映射到一个 K 维向量。这个向量的每个分量都是一个介于0到1之间的概率值,代表了与数据相关的 K 个潜在过程或特征。
  2. 这些特征被称为“潜在”的,因为它们代表了数据中我们无法直接观察到的某些特性。
  3. 然后,这 K 个潜在特征被送入另一个逻辑回归模型,最终产生一个用于数据分类的二元概率。

因此,这可以看作是K 个特征上执行逻辑回归,而不是直接在原始数据上执行。

为何需要多层感知机?

为了理解为什么简单的逻辑回归可能不够有效,以及为什么需要引入多层感知机,让我们回到手写数字识别的问题。

假设我们的目标是识别手写的数字“4”。下图展示了人们书写数字“4”的几种不同方式:



如果使用逻辑回归,我们通常会得到一个单一的滤波器 B,它可能看起来像一个“平均的4”,如下图所示:

这个“平均的4”看起来并不像上面任何一个具体的“4”。因此,基于这种单一滤波器构建分类器的想法似乎并不理想。

多层感知机的优势

作为替代方案,我们可以考虑拥有多个中间滤波器的情况。这正是多层感知机所做的。

我们不再将自己限制于单个滤波器 B 来检查数据,而是引入 K 个滤波器。例如,我们可以设置 K=3,这三个滤波器可能对应书写数字“4”的三种不同方式,如下图所示:



然后,从这些滤波器中推断出的潜在特征将被用来最终预测数字“4”是否存在。

总结

本节课中我们一起学习了多层感知机的基本概念。我们了解到:

  • 多层感知机是逻辑回归的直接扩展,通过引入一个包含 K 个潜在特征的中间层来工作。
  • 其核心优势在于不再依赖单一的、可能过于简化的特征(如“平均的4”),而是能够并行学习并组合多种不同的特征模式。
  • 这使得模型能够更好地捕捉数据的复杂性和多样性,例如在手写数字识别中处理同一数字的不同书写风格。

通过将数据映射到一组更有表现力的潜在特征上,再进行分类,多层感知机为处理更复杂的模式识别问题提供了强大的基础。

007:多层感知机数学模型 🧠

在本节课中,我们将学习多层感知机的数学模型。多层感知机是神经网络的基础模型之一,理解其数学原理对于掌握更复杂的神经网络至关重要。我们将从逻辑回归出发,逐步引入多层感知机的核心概念,并解释其如何通过增加中间层来提升模型的表达能力。

概述

上一节我们介绍了逻辑回归的基本模型。本节中,我们将看到多层感知机如何作为逻辑回归的自然扩展,通过引入一个包含K个“潜在特征”的中间层,使模型能够学习更复杂的非线性决策边界。

从逻辑回归到多层感知机

在逻辑回归中,我们将数据样本 xᵢ(包含M个特征:xᵢ₁ 到 xᵢₘ)通过一个内积运算映射到一个变量 zᵢ。这个内积是数据 xᵢ 与一个参数向量 b 的点积,可以看作是用一个“模板”或“过滤器”对数据进行处理。

多层感知机的核心思想是,我们不再使用单一模板,而是使用 K 个不同的模板或参考向量:b₁bₖ

以下是处理步骤:

  1. 对于每个数据样本 xᵢ,我们分别计算它与这K个向量的内积。
  2. 与逻辑回归类似,我们为每个内积结果加上一个偏置项。
  3. 这样,我们就得到了K个输出:zᵢ₁zᵢₖ。这K个输出构成了第一层(中间层)的K个特征。

激活函数与潜在特征

上一节我们得到了K个中间特征值。本节中,我们将这些特征值转化为有意义的概率表示。

我们将每个中间特征值 zᵢₖ 输入到一个逻辑函数(Sigmoid函数)中。Sigmoid函数将一个实数(范围从负无穷到正无穷)映射到0到1之间的一个数。

公式:σ(z) = 1 / (1 + e⁻ᶻ)

经过Sigmoid函数处理后,每个中间特征 zᵢₖ 都变成了一个介于0和1之间的概率值。这K个概率值代表了数据样本 xᵢ 中,K个不同的“潜在特征”或“潜在过程”被激活的程度。

输出层:最终的逻辑回归

现在,我们得到了K个潜在特征的概率表示。接下来,我们将这些特征送入一个类似逻辑回归的模型中进行最终决策。

以下是处理步骤:

  1. 我们有一个参数向量 c,其维度与潜在特征数量K相同。
  2. 我们计算潜在特征向量与参数向量 c 的内积,得到一个变量 ζᵢ(读作“zeta”)。
  3. 最后,将 ζᵢ 再次通过Sigmoid函数,得到最终的输出概率 P(yᵢ | xᵢ)。这个概率表示数据样本 xᵢ 属于某个特定二元类别(例如,正类)的可能性。

模型优势与总结

与直接使用逻辑回归将M维数据 xᵢ 映射到二元输出概率不同,多层感知机引入了一个包含K个潜在特征的中间层。

这个增加的中间层显著提升了模型的灵活性。最关键的是,它使得模型能够学习特征空间中的非线性决策边界。因此,多层感知机通常比简单的逻辑回归模型更强大,能够产生更有效的预测结果。

本节课中,我们一起学习了多层感知机的数学模型。我们看到,它通过引入一个由K个潜在特征构成的隐藏层,扩展了逻辑回归的能力,从而能够建模更复杂的非线性关系。理解这个从输入层到隐藏层,再到输出层的计算流程,是理解现代神经网络的基础。

008:深度学习 🧠

在本节课中,我们将要学习深度学习的基本概念。深度学习是机器学习中一个非常重要的领域,我们将通过一个具体的模型——多层感知机(也称为神经网络)来理解“深度”的含义。我们将看到,深度学习模型通过堆叠多个“潜在过程”层,能够学习比逻辑回归更复杂的决策边界。


什么是深度学习? 🤔

在课程开始时,我们提到深度学习是机器学习中一个非常重要的领域。现在,我们来理解一下深度学习的含义。

深度学习是机器学习的一种形式,其“深度”体现在模型具有多层潜在过程。在后续的例子中,我们将解释这些潜在过程的直观含义。


从逻辑回归到多层感知机 🔄

上一节我们介绍了逻辑回归模型。本节中,我们来看看如何通过重复应用逻辑回归来构建一个更深的模型。

我们将重复之前的过程,但这次进行两次。从底部开始,X 是我们的特征向量,它有 M 个分量。对于第 i 个数据样本,其特征 X_iX_i1X_iM 表示,即底部的圆圈。

以下是构建第一层潜在特征的过程:

  • 每个数据特征乘以一个参数向量 B 并求和。我们对 K 个不同的模板(B1Bk)重复此操作。
  • 将结果通过一个逻辑函数(logistic function),我们得到每个潜在特征的概率,这是一个介于 0 和 1 之间的数字。

与之前直接进行逻辑回归以完成二元分类不同,我们现在要预测第二层的潜在过程。现在,你可以开始理解“深度”的概念了,因为我们有了两层潜在过程

在底部是我们的数据,这些数据被映射到第一层潜在过程的概率上。我们重复这个过程,得到第二层潜在过程,同样由概率表示。在这个模型的顶部,我们再进行逻辑回归,以实现二元分类。在顶部,我们得到标签 y 等于 1 或 0 的概率。


模型的深度与结构 🏗️

现在观察这个模型,它显然更复杂了。我们稍后会讨论这种复杂性及其含义。但至少我们现在能理解“深度”的含义了。

在模型的顶部,总是一个逻辑回归分类器,它给出二元输出 y=1y=0 的概率。但在到达顶层之前,中间层对应着第一层的 K 个潜在特征和第二层的 J 个潜在特征。

正如你所想象的,我们可以构建更深的模型。这里展示的是一个两层模型。我们可以构建三层、四层甚至更多层潜在过程的模型。


为什么需要更复杂的模型? 💡

一个关键问题是:我们为什么要使用如此复杂的模型?它确实比逻辑回归更复杂。

但请回忆,逻辑回归有其局限性。其中一个局限是,两类数据(y=1y=0)之间的决策边界必须是线性的

而对于这种更复杂的多层感知机,事实证明我们可以学习复杂得多的决策边界

这里有一个例子:红点代表一类标签的数据,蓝点代表另一类标签的数据。在这个二维特征空间(X 向量有 X1X2 两个分量)中,蓝点和红点无法用一条直线分开。因此,逻辑回归不适合这种形式的数据。而现实中的数据往往就是这种形式。所以,这促使我们转向更复杂的模型——多层感知机。


多层感知机的效果展示 🎨

在这张图中,我们展示的是数据的概率。红色区域表示属于红色数据的概率高,蓝色区域表示属于蓝色数据的概率高。这是多层感知机的输出结果。

可以看到,模型学习到了一个非常复杂、非线性的决策边界,成功地将两类数据区分开来。


核心概念总结 📝

本节课中我们一起学习了:

  1. 深度学习:一种具有多层潜在过程的机器学习模型。
  2. 多层感知机/神经网络:一种经典的深度学习模型,其基本构建块是逻辑回归的重复应用。
  3. 模型深度:通过堆叠更多层,可以构建更深的模型。
  4. 优势:与逻辑回归只能产生线性决策边界不同,多层感知机能够学习复杂的非线性决策边界,从而处理更广泛的数据模式。

关键要点是,这个被称为多层感知机(也叫神经网络)的经典模型,基本上是通过重复应用逻辑回归序列构建起来的。现在我们开始理解为什么逻辑回归是如此基础的模型,因为构成神经网络基本形式的多层感知机的每一个组成部分,都可以被视为逻辑回归的重复应用。

009:文档分析示例 📄

在本节课中,我们将通过一个具体的文档分析示例,深入探讨多层感知机(MLP)的工作原理。我们将尝试理解“潜在特征”和“潜在过程”这些概念的实际含义,并直观地感受神经网络模型如何运作。

在上一节中,我们介绍了多层感知机的基本概念。它在许多方面是神经网络最基础、最核心的模型。虽然它是一个相对复杂且功能强大的模型,但初学者可能对其工作原理和优势感到困惑。

因此,本节我们将花一些时间,通过一个相对简单但重要的例子,来阐述这些潜在特征和过程意味着什么,并建立对模型运作的直观理解。

问题设定:文档分类 📊

让我们假设我们的任务是分析文档。在这里,一个文档就是一组词语的集合。

请记住,X_i 是一个向量,它代表了我们感兴趣的第 i 个数据点的特征集合。在这个例子中,X_i 代表第 i 个文档的特征。

在文档分析的背景下,最简单的方法可能就是统计词语出现的次数。

以下是构建特征向量的具体步骤:

  1. 假设我们有一个由 V 个单词组成的词汇表,即词汇表大小为 V
  2. 为了表征一个给定的文档(例如文档 i),我们只需统计每个单词在该文档中出现的次数。
  3. 然后,我们将基于这个特征向量进行预测。

为了简化问题,我们仍然将自己限制在二元分类的情况下。我们的目标是:给定一个文档及其包含的词语,预测某个特定的人是否会喜欢或觉得这个文档有趣。

在二元分类中,我们规定:如果喜欢,标签 y 为 1;如果不喜欢,标签 y 为 0。

训练数据与学习目标 🎯

当我们进行机器学习时,首先必须假设我们拥有用于学习的数据。这些数据用于“教导”模型或算法。我们所说的“学习”,指的是学习模型的参数。

在本例中,我们假设拥有 n 个文档,由 X1, X2, ..., Xn 表示。这些特征向量简单地代表了每个文档中 V 个单词各自出现的次数。

同时,我们还拥有对应的标签 Y1, Y2, ..., Yn,它们代表了目标个体是否喜欢该文档。

我们的目标是构建一个模型,使得当我们获得一个全新的、该人从未见过的文档的特征向量 X 时,能够预测他是否会喜欢这个文档。

总结 📝

本节课中,我们一起学习了如何将文档分析问题形式化为一个机器学习任务。我们定义了文档的特征表示(词频向量)、二元分类的标签,并明确了模型的学习目标:利用带标签的文档数据训练模型,使其能够预测新文档的受欢迎程度。这个示例为我们后续理解更复杂的模型(如多层感知机)如何处理此类特征并做出决策奠定了基础。

010:多层感知机解读 🧠

在本节课中,我们将学习多层感知机的工作原理,并通过一个文档分类的实例,深入理解其每一层所代表的含义。我们将看到,多层感知机如何通过逐层抽象,从原始数据中提取出有意义的潜在特征,并最终用于预测。


上一节我们介绍了多层感知机的基本结构。本节中,我们来看看如何将其应用于一个具体的例子——预测用户是否喜欢某篇文档。

我们将使用多层感知机来完成这个任务。首先,回顾一下它的工作原理。左侧展示了一个多层感知机结构,我们从底层开始,逐层向上分析。现在,让我们聚焦于第一层。

本质上,第一层会进行K次逻辑回归运算。数据 X 代表第 i 篇文档的词频统计向量。B1, B2, ..., Bk 是我们用来与 X_i 做内积的K个模板或滤波器。

在这个例子中,B1Bk 这些模板可能代表什么含义?它们可能代表文档中一些潜在的、具有代表性的主题。我们能看到文档中的词汇,但数据(或文档)背后存在一些我们无法直接观察到的潜在过程。我们理解文档,知道文档通常围绕某个主题展开。

因此,我们可以这样理解:第一个滤波器 B1 可能代表与某个特定主题(例如“体育”)相关的特征词汇。在包含 V 个词的词汇表中,当主题是“体育”时,会有一个子集的词有很高的出现概率。我们期望,如果滤波器 B1 代表了“体育”这个潜在主题,那么它在与“体育”相关的词汇分量上会有较高的值,而在与“体育”无关的词汇分量上值基本为零。

同理,第二个滤波器 B2 可能对应第二个潜在过程,例如“历史”主题。在这种情况下,我们期望 B2 在与“历史”相关的词汇上有高值,在其他词汇上值接近零。以此类推,每个 K 个潜在主题都可以这样处理,例如第 K 个主题可能与“政治”相关。

我们可以这样总结:给定一个代表文档词频的特征向量 X_i,我们将用它和 K 个滤波器(或模板)做内积。这些滤波器可以理解为代表了 K 个潜在过程;在文档语境下,我们可以将它们视为主题,如体育、历史、政治。因此,从模型第一层输出的特征,代表了在给定观察到的词汇特征向量的情况下,该文档关于体育、历史、政治等主题的概率(一个0到1之间的值)。这些就是第一层输出的 K 个潜在过程或特征。


了解了第一层如何提取主题特征后,现在我们进入第二层。我们将进行完全相同的操作。

我们将第一层的输出(表示为经过Sigmoid函数 σ(Z) 处理后的特征概率)作为第二层的输入。然后,用这些特征与第二层的滤波器 C1, C2, ..., Cj(这里假设有 J 个滤波器)相乘。

那么这些滤波器代表什么?它们可能强调第一层特征中的某些组合。记住,第一层的特征对应着各种主题。因此,我们可以将滤波器 C1Cj 理解为代表“元主题”,即第一层主题的组合。

例如,第一层主题可能对应体育、历史、政治。第二层的滤波器 C1Cj 基本上是对第一层特征进行加权。举例来说,模板 C1 可能对第一层中与“体育”和“历史”主题相关的特征赋予较高的权重。因此,如果滤波器 C1 的输出值很大,那就意味着这篇文档是关于体育和历史的组合,即“体育史”。

再例如,C2 可能强调与“政治”和“体育”相关的第一层特征。这个元主题代表了政治与体育的联系。因此,如果一篇文档同时涉及政治和体育,当我们用 C2 在第二层做内积时,输出值就会很高。这个过程对每个滤波器 C1Cj 都会执行。

我们可以这样概括:在层1,数据 X 是词频统计,滤波器 B1Bk 寻找的是主题(即与特定主题相关的词汇集合)。在层2,滤波器 C1Cj 寻找的是元主题(即主题的组合)。


最后,当我们到达顶层的逻辑回归时,我们是在做决策。我们提出的问题是:给定在第二层潜在特征中显现出来的、具有代表性的元主题,目标用户喜欢这篇文档的概率是多少?

再次审视第二层的元主题:如果一个人对“体育史”感兴趣,那么我们会期望,当代表“体育与历史”的元主题(即滤波器 C1 的输出)很高时,顶层用于决策的滤波器 D 会寻找这种情况。如果目标用户喜欢体育史,那么滤波器 D 就会在代表“体育史”的元主题值高时,给出高的预测概率。

通过这种方式,我们构建了一个具有深层架构的模型,并且这些潜在特征具有直观的含义。当然,这是一个相对简单的例子,是特意为了提供一些直觉而选择的。并非所有情况下潜在特征都如此易于解释。

但希望这个例子能让你对深度学习模型为何有效,以及它如何捕捉我们感兴趣的数据的潜在方面,有一些直观的理解。


本节课总结

本节课中,我们一起学习了多层感知机在文档分类任务中的具体解读。我们通过一个例子看到:

  • 第一层 的滤波器(如 B1, B2)可以理解为在寻找文档的基础主题(如体育、历史)。
  • 第二层 的滤波器(如 C1, C2)则在组合这些基础主题,形成更复杂的元主题(如体育史)。
  • 最终层 的逻辑回归则基于这些元主题,做出最终的预测(如用户是否喜欢)。

这个过程展示了深度学习模型如何通过多层非线性变换,从原始数据中逐层抽象出越来越高级和复杂的特征表示,从而完成复杂的预测任务。

011:迁移学习 🧠

在本节课中,我们将探讨深度学习的一个关键优势:迁移学习。我们将了解它如何通过共享模型底层参数,实现更高效的数据利用,从而构建针对多个个体的预测模型。


上一节我们介绍了多层感知机(MLP)如何通过其深层结构学习复杂的决策边界。本节中,我们来看看MLP的另一个强大能力——迁移学习

考虑一个预测用户是否喜欢某篇文档的模型。模型的第一层和第二层负责从文档中识别主题元主题。因此,这两层实际上是在表征文档本身,而非特定用户的偏好。

以下是迁移学习的核心思路:

  • 共享底层参数:当我们想为多个不同用户构建模型时,可以共享或复用模型的前两层参数。这意味着,我们可以利用所有用户的数据来共同学习如何更好地表征文档。
  • 个性化顶层参数:模型的顶层负责判断特定用户是否喜欢识别出的元主题,这部分参数是用户依赖的,需要针对每个用户单独学习。

这种设计带来了显著的数据效率优势。我们无需为每个用户从头开始、仅用其个人数据训练一个完整模型。相反,我们可以汇集所有用户的数据来学习强大的、通用的文档表征(底层参数),然后仅用单个用户的数据来微调顶层的个性化偏好参数。

回想我们最初的构建模块——逻辑回归模型。它是一个简单的模型,公式如下:

P(y=1|x) = σ(β₀ + β₁x₁ + ... + βₘxₘ)

其中,σ是Sigmoid函数。虽然逻辑回归是一个很好的起点,但它不具备像多层感知机那样的分层结构。在逻辑回归中,所有参数β₁βₘ都与最终的预测直接相关,无法清晰地将“数据表征”与“任务决策”分离开来,因此难以实现同样高效的迁移学习。


本节课中我们一起学习了迁移学习的概念。我们了解到,深度神经网络的分层结构允许我们将模型的底层(靠近数据输入)设计为学习通用数据特征,而将顶层设计为学习特定任务。通过跨多个相关任务或用户共享底层参数,我们可以更充分地利用数据,仅用相对少量的个性化数据来学习顶层参数,从而高效地为多个个体构建强大的预测模型。这是深度学习超越逻辑回归等简单模型的另一个关键优势。

012:模型选择

在本节课中,我们将要学习机器学习中的一个核心问题:模型选择。当面对多种可能的模型时,我们需要决定使用哪一个。我们将通过一个具体的例子,利用目前学到的工具来理解如何进行选择,并探讨一个重要的概念——偏差-方差权衡。

模型选择问题

在机器学习中,我们常常面临模型选择的问题。可能有多种不同的模型可以用来表示数据,我们需要做出选择。做出这些选择的方法通常来自于经验。

利用我们目前开发的工具,我们可以考虑一个具体的模型选择例子。

逻辑回归模型

首先,回顾一下逻辑回归模型。设 X_i 为第 i 个数据样本,它有 M 个分量,因此数据表示为 X_i1X_iM

在逻辑回归中,我们取数据与权重 B1BM 的内积。具体来说,我们将数据的每个分量 X_i 与向量 B 的对应分量相乘,然后将这些乘积求和,得到一个值 z_i。我们通常会加上一个偏置项 b,最后将这个结果送入一个称为 σ 的 sigmoid 函数。这样,我们就得到了一个结果(例如,属于某个类别的)概率。

这是一个非常简单的模型,在某些情况下可能非常有效。

公式表示:
z_i = Σ (B_j * X_ij) + b
P(y=1 | X_i) = σ(z_i) = 1 / (1 + exp(-z_i))

多层感知机模型

我们现在掌握的另一个模型是多层感知机。同样,在底部我们有数据 X_i1X_iM。与直接通过逻辑回归进行分类决策不同,这里我们展示了两个中间层(潜在特征层)。顶层的潜在特征再次通过一个逻辑回归来进行分类。

通过这张图,我们可以看到逻辑回归和多层感知机之间的联系。多层感知机在其模型顶部包含了逻辑回归,但通过这个神经网络或多层感知机,还产生了中间特征。

偏差-方差权衡

那么,我们经常面临的问题是:该使用哪个模型?这在机器学习中被称为偏差-方差权衡

理解这一点的方法是:观察逻辑回归模型,它是一个相对简单的模型,模型中的参数数量相对较少。相比之下,多层感知机是一个相当复杂、精密的模型,因此它也有更多的参数。

当我们谈论方差时,我们考虑的是:如果我取不同的数据样本,如果我有一个包含 N 个不同数据样本的情况,并用这些数据样本来训练我的模型,那么在不同的 N 个训练样本实例下,模型会有多大的变化。

对于简单模型,由于其偏向于简单性,我们预期在不同的训练场景下,使用不同 N 个数据样本进行训练时,所观察到的方差量会较小。在多层感知机的情况下,考虑到其增加的复杂性,我们可能会预期,从一个数据样本训练到另一个数据样本训练,其变化会更大。

这就叫做偏差-方差权衡。我们常常会使模型偏向于简单性,这样方差就不会很大。然而,这种偏差或简单性可能会损害性能。

一个具体例子:MNIST手写数字识别

为了展示一个简单的例子,MNIST 是一个非常广泛用于数字识别的数据集。这里我们处理 0 到 9 这 10 个数字,目标是根据数字的小图片(像素)进行分类,这些像素将构成我们的数据 X_i

以下是我们可以考虑的两种模型及其性能对比:

  • 逻辑回归模型:在这种情况下,图像的像素直接由 B1BM 加权,然后送入 sigmoid 函数进行分类决策。
    • 性能:如果尝试用逻辑回归解决 MNIST 问题,准确率大约在 91% 左右。
  • 多层感知机模型:相比之下,如果我们使用多层感知机,性能通常可以提升到 96% 的准确率。

这是一个例子,说明更复杂的多层感知机(这里实际上只比逻辑回归多了一个层)所带来的精密度提升,确实能显著提高性能。

之所以如此,是因为逻辑回归仅限于线性分类器,而多层感知机允许非线性分类器。分类决策中的这种非线性带来了性能的提升。

另外需要简要说明的是,这是一个 10 类问题(数字 0 到 9),因此不是二分类问题。为了简化,我使用了相同的二分类逻辑回归和多层感知机示意图,但在实际实现中,网络顶部是一个用于 10 类分类的算法,它表现为逻辑或 sigmoid 连接函数的泛化,称为 Softmax 函数。我们将在课程的其他部分更多地讨论 Softmax。

总结

本节课中,我们一起学习了机器学习中的模型选择问题。我们比较了逻辑回归和多层感知机这两种模型,并引入了偏差-方差权衡的核心概念:简单模型(如逻辑回归)通常方差小但可能偏差大(性能受限),而复杂模型(如多层感知机)可能方差大但偏差小(潜力性能更高)。最后,我们通过 MNIST 手写数字识别的例子,看到了更复杂的模型如何通过引入非线性来提升实际性能。理解这种权衡对于在实际问题中选择合适的模型至关重要。

013:神经网络早期历史 📜

在本节课中,我们将回顾多层感知器(神经网络)的发展历史。这段历史不仅有趣,更是一个警示故事,它告诉我们技术发展并非一帆风顺,理解历史有助于我们明智地选择和应用模型。

起源:多层感知器的诞生 👶

上一节我们介绍了多层感知器的基本概念。本节中,我们来看看它的起源。多层感知器是深度学习的核心,因此它看起来像是一项非常新的技术。然而,它实际上诞生于大约1960年。当时,计算能力远不如今天,可用的数据量也少得多,这限制了它的实际应用。

发展:反向传播与卷积神经网络的出现 🌱

从1960年的诞生开始,神经网络进入了下一个重要发展阶段。1986年,一项关键技术——反向传播被提出。反向传播是一种高效学习模型参数的方法,其核心公式可以简化为权重更新规则:w_new = w_old - η * ∇L,其中 η 是学习率,∇L 是损失函数的梯度。这使得模型在计算上变得可行。与此同时,计算能力和数据访问量开始增长,前景似乎一片光明。

紧接着在1989年卷积神经网络被开发出来。这种网络架构特别擅长分析图像数据,其核心操作是卷积计算。我们可以用以下伪代码表示其核心思想:

# 简化的卷积操作概念
for each filter in filters:
    output_feature_map = convolve(input_image, filter)

这一时期是神经网络的“夏季”,充满了希望与热情。

挫折:现实应用的寒冬 ❄️

由于对神经网络抱有热情,人们在20世纪90年代初开始将其应用于现实世界的数据集。然而,结果并不理想,神经网络的表现往往不如预期。这主要是因为神经网络比逻辑回归等模型复杂得多,需要大量数据才能训练好,而当时人们并未完全理解这一点。于是,神经网络的“冬季”来临了。

复苏:长短期记忆网络与沉寂期 🍂

1995年左右,一项名为长短期记忆网络的关键技术被提出。LSTM非常适合分析随时间变化的数据,例如音频或视频。其核心在于引入了“门”机制来控制信息的流动,基本单元结构包含输入门、遗忘门和输出门。

尽管有这些技术进步,当人们再次尝试在现实世界中应用神经网络时,其表现仍然不尽如人意。从大约2005年到2010年,在机器学习的主流圈子里,神经网络甚至一度成为“禁忌”词汇,因为更简单、更容易理解的模型往往效果更好。

复兴:“深度学习”的重生与爆发 🌸

由于“神经网络”一词因历史表现而带有负面色彩,大约在2010年,人们决定为这项技术重新命名,于是“深度学习”诞生了。这本质上是对多层感知器等已有技术的重新包装,但新名字让人们愿意再次审视它。

真正的转折点发生在2013年。诞生于1989年的卷积神经网络,与两项当时不存在的新事物结合:强大的图形处理器和海量的ImageNet数据集(包含超过一百万张标注图像)。这种结合带来了性能的质的飞跃。

随后在2015年,基于卷积神经网络和强化学习的AlphaGo在围棋比赛中击败了人类顶尖选手。在图像分析等领域,深度学习模型的性能也超越了人类。

总结与启示 🤔

本节课中我们一起学习了神经网络的起伏历史。这段历史告诉我们几个关键点:

  1. 核心技术很“古老”:深度学习(神经网络)的核心架构——多层感知器、CNN、LSTM——早在几十年前就已提出。
  2. 成功的催化剂:近年来的爆发性成功主要归功于强大的计算能力海量的数据,而非基础理论的颠覆。
  3. 保持谦逊与务实:历史上有过多次从乐观到失望的循环。在选择模型时,应遵循奥卡姆剃刀原则:如果简单模型(如逻辑回归)和复杂模型(如深度神经网络)表现相当,应优先选择简单模型。我们必须理解深度学习的有效应用场景,同时也要知道在何处更简单的模型可能更合适。

通过理解这段历史,我们可以避免盲目追逐技术潮流,从而更明智地运用机器学习工具来解决实际问题。

014:图像的层次结构 🏞️

在本节课中,我们将学习卷积神经网络(CNN)如何分析图像,以及为什么这种深度架构在处理图像数据时特别有效。我们将通过简单的示例图像来直观理解图像数据的内在层次结构,并探讨如何利用这种结构构建强大的学习模型。

图像的构成与层次结构

上一节我们介绍了多层感知机,本节中我们来看看为什么它并不适用于所有类型的数据,特别是图像数据。卷积神经网络是分析图像等数据的关键技术,其性能甚至在某些任务上超越了人类。

为了直观理解其工作原理,我们将分析一些“玩具图像”。这些图像并非真实照片,而是用于阐明概念的简化图示。我们的数据样本就是这些图像。

以下是三幅示例图像及其局部放大图,每个方块代表一幅图像,其中的形状是构成图像的基本构件。

关于这些图像,需要注意的关键点是:每幅图像都由一组高级图案构成,这些图案在图像内的位置各不相同。并非每幅图像都包含所有图案,但每幅图像的特征都由其包含的图案子集及其位置来定义。

现实世界中的图像也具有类似特性,它们包含重复的结构,例如边缘、角落、纹理和形状。

卷积神经网络正是要利用自然图像的这种特性。让我们更仔细地观察这些图案。

我们发现,每个高级图案本身又由重复的子图案构成。以下图示强调了在某些高级图案内部,我们可以看到重复的子结构。

因此,我们可以这样理解数据的层次结构:

  • 从顶层开始,每幅图像由一组高级图案构成,我们称之为模型的第3层
  • 第3层的每个高级图案,又由一组位置发生偏移的子图案构成。
  • 每个子图案则由基本的原子元素(即这些基础形状)构成。

本张幻灯片的关键要点是:数据可以用一种层次结构来表示。这让我们对“深度”或“多层”结构有了直观感受。我们的目标是构建一个能够捕捉这种图像层次化表示结构的模型。

那么,问题就变成了:我们如何构建一个模型,来捕捉这种形式的层次结构所体现的图像构成直觉?

总结

本节课中,我们一起学习了图像的层次化特性。我们看到,复杂的图像可以由简单的基础元素(原子)组合成子图案,子图案再以不同位置组合成高级图案,最终形成完整的图像。这种从局部到整体、从简单到复杂的层次结构,是卷积神经网络设计灵感的核心来源,也是其能高效处理图像数据的原因。下一节,我们将探讨卷积神经网络如何具体实现对这种层次结构的建模。

015:卷积滤波器 🧠

在本节课中,我们将学习卷积神经网络(CNN)中的一个核心概念——卷积滤波器。我们将了解如何通过滤波器从图像中提取基本元素,并逐步构建更复杂的特征表示。


概述

卷积神经网络通过模拟视觉系统的层次结构来处理图像。这个过程始于识别图像中的基本“原子”元素,然后组合这些元素以识别更复杂的“子图案”和“图案”。本节课将详细解释这一过程,即如何使用卷积滤波器在图像中定位和识别这些元素。


从原子元素开始

上一节我们介绍了视觉层次结构的概念。本节中我们来看看如何构建一个模型来捕捉这种现象。

下图是一个示例图像,我们将用它进行演示。

我们的目标是从层次结构的底部开始,寻找那些原子元素。右下角的三角形就是我们的一个原子元素。

我们将把这个三角形滤波器移动到图像中的每一个位置

在图像的每个二维位置上,我们都会计算一个相关性。这个相关性衡量了图像局部区域与我们的原子元素(即滤波器)的相似程度。

这个过程的结果显示在顶部,我们称之为特征图。它描绘了右下角的原子滤波器与图像中每个位置的匹配或相关程度。

  • 在顶部的图像中,红色表示强相关或高匹配
  • 两个圆形点就是图像中实际存在该三角形的位置。
  • 图像中其他不存在该三角形的位置,滤波器与图像的匹配度或相关性非常小。

将原子元素(三角形)移动到图像中每个位置的过程,有一个专门的名称,叫做卷积。这就是“卷积神经网络”名称的由来。


处理多个原子元素

我们不止有一个原子元素。在层次结构的底部,我们有多个原子元素。

下图左侧是我们的一个图像,右侧是各个原子元素。

以下是处理步骤:

  1. 我们将通过前面提到的二维卷积过程,把每一个基本滤波器依次移动到图像中的每个位置。
  2. 每个原子元素都会生成一个特征图。该图反映了该原子元素与图像的匹配程度。
  3. 我们对所有原子元素都进行此操作,因此会得到多个特征图的堆叠

图中堆叠的矩形或方块就是为了表示各个滤波器对应的特征图。

通过这个过程,我们可以看到如何识别层次结构最底层的每个原子元素。


识别子图案

下一个问题是:如何识别子图案?记住,子图案是由原子元素经过组合和位移后构成的。

现在,我们将重复卷积过程,但对象发生了变化。我们将把滤波器与第一层的特征图进行卷积。不过,这里的滤波器是由多个原子元素堆叠构成的。

下图描绘了一个子图案,它由一个正方形、一个椭圆形和一个三角形组成。

我们试图找到由这三个基本元素构成的子图案。如果图像中存在这个子图案,我们预期对应的特征图层(正方形、椭圆形、三角形)会在空间上彼此邻近的位置出现高强度响应。

我们可以为每个子图案进行此操作。为便于表示,每个原子元素被分配了一种颜色。

第二层的滤波器对应着各个子图案。图中的颜色表示,如果图像中存在相应的子图案,我们预期第二层的这些滤波器会在对应位置产生强响应。

通过在第二层构建这个滤波过程,我们现在可以搜索每一个子图案。


构建更高层特征

然后我们重复这个过程。现在,我们将这些设计用于寻找子图案的第二层滤波器,与第一层的特征图进行卷积。

将第二层的每个滤波器与第一层的特征图进行卷积的过程,将产生一组新的特征图,我们称之为第二层特征图。这些图将告诉我们每个子图案在图像中的位置。

现在我们可以再次重复这个过程。在幻灯片右侧中间的第二层,我们看到对应各个子图案的滤波器。现在我们要寻找的是顶层的图案。

顶层图案由四个子图案构成,每个子图案被分配了一种颜色。我们看到,当使用第三层滤波器来识别该顶层图案时,四个对应的子图案会在物理空间上邻近的位置产生强响应。

我们可以为模型顶层的每个图案进行此操作。现在,我们将拥有为第三层的每个图案设计的滤波器。

最后,经过这次卷积——即将第三层滤波器与第二层特征图在所有二维空间位置上进行卷积——我们将最终构成第三层特征图


总结

本节课中,我们一起学习了卷积滤波器的核心工作原理。我们从识别单个原子元素开始,通过卷积操作生成特征图。然后,我们扩展到多个原子元素,生成特征图堆叠。接着,我们利用这些基础特征,通过更高层的卷积来识别由原子元素组合而成的子图案。最后,我们重复这一过程,构建更深的层次来识别完整的图案。这个过程形象地展示了卷积神经网络如何通过分层抽象,从像素中逐步提取出复杂的语义信息。

016:卷积神经网络

在本节课中,我们将学习卷积神经网络的基本架构和工作原理。这是一种专门用于处理图像等网格状数据的深度学习模型。

概述

卷积神经网络是一种深度架构,其核心思想是通过重复应用相同的过程,从原始图像中逐步提取并组合特征,最终做出分类决策。

网络架构与工作流程

卷积神经网络的工作流程可以概括为:从原始图像开始,通过多层卷积操作,逐步构建出越来越复杂的特征表示,最终基于最高层的特征进行分类。

特征提取过程

以下是卷积神经网络构建特征的核心步骤:

  1. 第一层特征提取:我们从左下角的原始图像开始。使用一组基础的“原子”或基本构建块图像对该图像进行卷积操作。“卷积”意味着我们将每个原子元素移动到图像中的每个位置。完成此操作后,我们得到一个特征图,它反映了每个原子元素在图像中出现的程度。我们对每个原子元素都执行此操作,最终得到一组特征图,即一个特征图堆栈。这为我们提供了图像中基本构建块的表现图谱。

  2. 第二层特征提取:接下来,我们构建第二层滤波器。这些第二层滤波器旨在寻找第一层中彼此邻近且同时被激活的元素组合。如果第一层的原子元素在彼此附近被同时激活,它们就构成了一个“子模式”。因此,第二层滤波器就是在搜索这些子模式。我们将第二层滤波器与第一层特征图进行卷积,从而得到第二层特征图。

  3. 第三层特征提取与分类:然后,我们构建第三层滤波器,这些滤波器被设计用来寻找更复杂的“模式”。将这些滤波器与第二层特征图进行卷积,最终我们得到第三层特征图。这层特征图是我们的最终特征表示。基于这些特征,我们将做出分类决策,例如判断图像的类别。

应用实例

例如,在医学放射学研究中,我们可能进行的分类是确定医学图像对应的是良性肿瘤还是恶性肿瘤。这个分类决策将基于网络顶层的特征做出。

核心概念解析

这种架构被称为卷积神经网络

  • “卷积”通过上述的滑动/移位过程来实现。
  • “神经网络”的称谓源于一些技术细节(为简化起见,此处暂不展开)。
  • 该架构的“深度”特性通过其多层构造得以体现。

总结与展望

本节课我们一起学习了卷积神经网络的基本直觉和架构。我们了解到,它通过多层卷积,从原始像素中逐步构建出用于分类的抽象特征。

现在,我们需要思考的下一个问题是:在现实世界中,我们处理的不是玩具图像或简单形状,那么如何设计一个模型,使其能够从真实图像中学习并构建出这样的网络呢?这将是我们在下一课中要探讨的主题。

017:卷积神经网络数学模型 🧠

在本节课中,我们将学习卷积神经网络的数学模型。我们将从图像分析入手,理解模型如何通过多层卷积操作提取特征,并最终通过分类器进行预测。整个过程的核心在于学习卷积核的参数,而非预先定义好形状。

卷积操作与特征图

上一节我们介绍了卷积的基本概念,本节中我们来看看如何将其数学模型化。模型处理的输入是第 n 张图像,记作 I_n。这强调了我们并非只处理单张图像,而是会使用成千上万乃至数百万张图像进行学习。

模型的第一部分是将原子元素(在示例中是形状)与图像的每个二维位置进行卷积,从而构成一个特征图。该特征图反映了该原子元素在图像中的显现强度。

在数学模型中,我们并不知道这些原子元素是什么。因此,我们将用一系列待学习的参数来表示它们。

以下是第一层卷积的数学描述:

  • φ1, φ2, ..., φK 对应 K 个滤波器。它们不再是示例中的具体形状,而是由待学习的像素值参数构成。
  • 我们的目标是学习与滤波器 φ1, φ2, ..., φK 相关联的像素值。

现在,假设我们已知这些参数 φ1φK。如果知道这些像素值,我们就可以像在示例中那样,将它们滑动到图像的每个位置,从而构成特征图。

这个过程在数学上可以描述为:对于第 n 张图像 I_n,滤波过程(生成特征图)是滤波器 φ1φK 的函数。这将产生一个特征图,我们称之为 M_n,它代表第 n 张图像在第一层的特征图堆栈。

多层卷积堆叠

我们刚刚构建了第一层的特征图,接下来可以重复这个过程。现在,第一层的特征图堆栈将与第二层的一组滤波器进行卷积。

以下是第二层卷积的要点:

  • 我们用 ψ1, ψ2, ..., ψK 表示第二层的滤波器。同样,我们不知道这些滤波器的值。
  • 每个滤波器 ψ1, ψ2, ..., ψK 都是一个数字化的迷你图像堆栈,其维度需与来自下层的特征图匹配。
  • 如果已知这些值,我们可以将每个滤波器 ψ1ψK 与第一层特征图进行卷积,从而生成第二层特征图。

第二层特征图是下层特征图 M_n 和第二层滤波器 ψ1ψK 的函数。我们的目标正是学习这些参数 ψ1ψK

顶层特征与分类器

这个堆叠过程可以继续重复。我们进入第三层,拥有滤波器 ω1ωK。这些同样是滤波器堆栈,具有数值。

我们可以将这些第三层滤波器与第二层特征图进行卷积,最终得到顶层特征图,我们称之为 G_n

最后,基于顶层的特征,我们可以构建一个分类器来为该图像提供标签。

以下是分类阶段的描述:

  • L 表示标签。
  • 标签是顶层特征 G_n 和参数 W 的函数,参数 W 反映了我们分类器的参数。
  • 这个分类器可以采用我们熟悉的形式,例如,它可以是一个多层感知机,也可以是逻辑回归。无论如何,它都由我们记为 W 的一些参数来表征。

模型总结与对比

综上所述,这个模型的结构与我们的玩具示例完全相同。唯一的不同之处在于,我们不再假设那些基本的原子形状,而是拥有了这些参数。参数就是这些滤波器在卷积过滤过程中每个位置上的像素值。在这个模型的顶部,我们得到了顶层特征图 G_n,它们被送入一个由参数 W 表征的分类器。

本节课中我们一起学习了卷积神经网络的数学模型。我们理解了模型如何通过未知的、可学习的滤波器参数在多层级联中进行卷积操作,从原始图像中逐步提取出高层次的特征表示,并最终利用这些特征通过一个参数化的分类器完成预测任务。整个框架的核心思想是将特征提取的过程本身也参数化,并纳入到端到端的学习范式中。

018:模型如何学习

在本节课中,我们将要学习机器学习模型是如何通过数据来“学习”的。我们将以卷积神经网络为例,深入探讨模型参数、学习目标以及学习过程中面临的挑战。

模型参数

上一节我们介绍了卷积神经网络的结构,本节中我们来看看构成这个模型的“可学习”部分——参数。

观察这个模型,我们发现它由一系列参数来刻画。模型的参数包括底层的滤波器、第二层的滤波器、第三层的滤波器,以及分类器的参数。

以下是模型参数的具体构成:

  • 模型的参数是底层的滤波器。
  • 第二层的滤波器。
  • 第三层的滤波器,分别用 φψω 表示。
  • 最后是我们分类器的参数 W

因此,这个模型的未知参数,也就是我们希望学习的目标,就是 φψωW

学习的数据基础

了解了模型参数后,我们来看看学习过程需要什么。学习的关键在于我们假设能够访问一个大型的、带有标签的数据集。

以下是关于学习数据的几个要点:

  • 这项技术(指深度学习)在近年来变得如此强大的一个关键因素是能够获取海量数据。
  • 这里的数据由成对的 (I_n, y_n) 表示,其中 I_n 是第 n 张图像,y_n 是该图像的标签。
  • 为了简化,与之前学习逻辑回归和多层感知机时一样,我们假设标签是二元的,即 +1-1
  • 在其他情况下,标签数量可能非常庞大(成百上千),但这里我们保持简化。

学习的目标:最小化损失

有了数据和模型,我们如何定义“学习”呢?学习的目标是调整模型参数,使其预测尽可能准确。

在右侧的第三个要点中,我们将构建一个所谓的能量函数(用 E 表示),它将计算真实标签 y_n 和模型预测标签 l_n 之间的损失。

观察左侧的图,在网络的顶部,我们利用特征图和分类器参数 W 来预测标签 l。我们可以计算一个损失,这个损失衡量了真实标签 y_n 和预测标签 l_n 之间的差异。我们希望使这个损失尽可能小。损失的计算方式有很多种,它本质上就是 y_nl_n 差异的度量。

因此,我们的目标(见第三个要点后的简单公式)是尝试学习或计算出参数 φψωW,以最小化所有数据点上损失的总和。损失再次体现了我们预测标签的准确性与真实标签之间的差异。这就是我们所说的“学习”。

这张幻灯片将“机器学习”的概念整合在一起。左侧的卷积神经网络就是我们要构建的“机器”,用于刻画图像。而“学习”部分则体现在利用 N 个图像和标签样本 (I_n, y_n) 来尝试学习模型的参数。学习意味着学习我们模型(机器)的参数,使得模型预测 l_n 与真实标签 y_n 之间的差异很小。在最后一个要点中,我们在这些符号上加了“帽子”符号(如 φ̂),这表示它们是我们的预测或估计值。

我们的目标是设计或估计出模型参数 φψωW,使得我们的预测标签与真实标签之间的总损失(体现在中间公式中)最小化。这就是学习的含义。

学习为何困难?

然而,这个学习过程非常具有挑战性,这也是机器学习历史曲折的部分原因。

当我们谈论机器学习的“季节”,经历春天、冬天、再到春天、夏天和冬天时,之所以会有热情期和绝望期,正是因为进行这种学习、估计这些参数面临许多挑战。

其中一个关键方面在于,搜索或估计这些最优参数(φψωW)时,需要估计的参数数量是巨大的。因此,尝试估计这些参数非常困难。

为了让你理解这意味着什么,这里有一个只涉及两个参数的简单示例。在二维底部坐标轴上,我们可能观察参数1和参数2,而在垂直轴上,我们观察函数 E 的值,它衡量了参数对数据拟合的质量。

你在这里会注意到存在多个“山谷”,即参数的多个区域可能导致相对较小的 E 值。

我们发现,存在许多不同的参数集,它们为模型提供了所谓的局部最优解。因此,在这个参数空间中移动以实际优化参数是非常困难的。在这个简单示例中,我只展示了两个参数的情况。同样,垂直轴表示质量(误差 E),另外两个轴表示参数的值。

在这个简单的二维例子中,我还可以画图观察。但对于实际问题,φψωW 中的参数数量可能达到数百万。因此,我们甚至无法画出这样的图,并且在这个极高维的参数空间中搜索,以找到能使模型预测与真实标签最匹配的参数,是极其困难的。

这花费了数十年的研究和探索,才学会了如何有效地进行这种学习。那段时期的研究和发展,除了计算能力和数据获取之外,在现代深度学习的成功中也扮演了关键角色。

总结

本节课中我们一起学习了机器学习模型的核心学习机制。我们明确了模型的参数构成,理解了学习需要依赖带标签的数据,并定义了学习的目标是最小化预测值与真实值之间的损失。最后,我们也认识到,由于参数空间巨大且存在多个局部最优解,模型的学习过程本身是一个复杂且具有挑战性的优化问题,这也是该领域历经多年发展才取得突破的原因之一。

019:层次特征的优势 🏗️

在本节课中,我们将探讨深度架构的核心优势,即通过层次化的特征共享结构,更有效地利用数据并提升模型的学习能力。

深度架构的优势

上一节我们介绍了深度卷积神经网络的基本结构。本节中,我们来看看这种层次化架构的核心优势是什么。

我们回到最初的动机。在那些玩具示例中,我们有由基本形状组成的原子元素。在第一层,我们有最简单的原子元素,即基本形状。在第二层,我们拥有所谓的“子模式”,它们是那些基本形状的基础组合。最后在第三层,我们拥有“模式”,它们是子模式的组合。

为何需要层次结构?

有人可能会问:在这个模型中,最终在架构顶层的学习是基于顶层的特征,这些特征最终被用于做出分类决策。

那么,为什么我们不能直接基于顶层的模式构建模型,而无需关心第二层的子模式和第一层的原子元素呢?这种深度架构的优势究竟在哪里?

如果我们构建一个仅基于第三层过滤器的架构,那么每个第三层的过滤器都将被独立学习。在学习这些过滤器的过程中,模型不会理解它们共享了某些结构。我通过展示第三层和第二层中重复结构的例子来提醒大家,正是这种分层结构构成了深度架构的动机。

共享结构与知识传递

因此,任何时候,当一个特定的子模式出现在第三层的任何模式中时,学习该模式的过程会通过共享的信息,为其他模式提供信息。

其核心思想是:通过在各个层的过滤器元素之间共享结构(这种共享体现在它们都是由更基础的构建块的平移版本组成的),并通过这种深度架构,我们可以更有效地利用数据,并在各个模式之间共享知识。这样一来,对一个模式的知识可以通过它们所拥有的共享子结构,来改进对另一个模式的知识。

本章小结与展望

现在,我们对机器学习如何实现有了一些了解。我们了解了如何在这里构建一个机器——深度卷积神经网络。我们也初步体验了学习是如何发生的:学习通常通过获取大量数据(通常是有标签的数据,即我们同时拥有数据和关联的标签)来体现。我们看到了“学习”的含义:学习是尝试估计模型参数的概念,目的是使我们模型的预测与数据的真实标签保持一致。

我们也获得了一些理解,至少是直觉上的认识:当参数数量很大时,学习可能具有相当的挑战性。

随着我们结束这个机器学习入门模块,在接下来的课程中,将提供一些现代机器学习如何改变世界各地人们生活的例子。这些关于该技术如何在许多领域提供突破的例子,将激励我们更深入地挖掘并尝试学习更多关于现代机器学习的知识。

本节课中我们一起学习了深度层次化架构的核心优势,即通过共享基础构建块的结构,实现知识在不同层级特征间的有效传递与复用,从而提升数据利用效率和模型整体性能。

020:真实图像上的CNN

在本节课中,我们将深入了解卷积神经网络在真实图像数据上的工作原理。我们将观察网络在不同层次学习到的滤波器,并与生物视觉系统的发现进行对比,从而获得对模型学习过程的直观理解。

上一节我们介绍了如何基于数据学习滤波器。现在,我们将从简单的原子元素示例转向分析真实数据。当我们分析真实图像时,这些学习到的滤波器会是什么样子?不同层的滤波器又有什么不同?

为了提供直观的示例和启发,我们将观察一个特定数据集(包含人脸、汽车、摩托车等图像)上学习到的滤波器。

以下是该模型第一层(即最底层)学习到的每个滤波器的可视化。每个小方块代表卷积神经网络学习到的一个滤波器。

在这些顶部的小图像中,您会注意到深色和亮色(白色)区域。深色对应像素的负值,白色对应像素的正值。如果仔细观察这些子图像,您会发现它们的特点是:一个基本形状经过不同角度的旋转。这个基本形状表现为一组相邻且对齐的深色像素和亮色像素。

这类似于正弦波的一个周期,其中一半波谷向下,另一半波峰向上。这个正弦波单周期以二维形状呈现,并且对于每一个第一层滤波器,这个单周期被旋转到不同的角度。因此,每个第一层滤波器大体上都是由一个旋转了不同角度的正弦波单周期构成的。

这些形状在数学中已被广泛研究,具有非常基础的数学特性,被称为Gabor函数

更有趣的是,人们对兔子、老鼠等哺乳动物进行了研究。他们将光照射到哺乳动物的视网膜上,并探究一个问题:应以何种形状的光照射哺乳动物的视网膜,才能激活其视觉皮层中的单个神经元?

如果能激活哺乳动物视觉皮层中的单个神经元,这 arguably 表明该形状是视觉皮层能够识别的最基本形状。因此,研究尝试了用各种非常基础的形状照射哺乳动物的视网膜,目的是找出哪种形状能触发单个神经元的反应,从而反映这是视觉皮层能识别的最基本形状。

研究已经确定,这些形状与卷积神经网络在该模型第一层学习到的“原子”几乎一模一样。因此,图中顶部每个小方块所代表的、由卷积神经网络学习到的基本原子元素,与生物学研究表明的哺乳动物视觉系统能识别的最基本元素高度吻合。

这并不是对卷积神经网络的要求。但许多人认为非常有趣的是,这个计算引擎——卷积神经网络——至少在其架构的第一层,其行为方式与哺乳动物的视觉系统是一致的。

现在,我们来看深度架构的第二层,这对应左下角的图像。

在左下角,每个方块代表我们深度架构第二层的一个滤波器。请记住,我之前称这些为“子基元”。如果仔细观察,您会注意到它们每一个都对应一个比第一层原子元素更复杂的基本形状或结构。

仔细观察这些第二层的图像或滤波器,您会注意到像眼球这样的东西。请记住,我们分析的是包含人脸等的图像。

接着,我们看右下角,这些对应架构第三层(即顶层)的滤波器。

如果仔细观察,其中一些滤波器对应人脸的轮廓草图。

这些完全基于数据学习到的滤波器的有趣之处在于:

  • 在第一层(最基本的一层),滤波器对应的构建块与激发哺乳动物视觉系统神经架构的基本方式是一致的。
  • 在第二层(左下角),我们看到了更复杂的结构。仔细观察,您会看到像眼球这样的东西。这些是图像中子结构的体现。
  • 最后,在更高层(我们看到更复杂结构的地方),我们实际上可以看到人脸的轮廓草图。

这让我们进一步直观地理解了,当给定真实图像时,模型多个层级的滤波器实际在学习什么。

本节课中,我们一起学习了卷积神经网络在真实图像上学习到的滤波器可视化。我们看到,第一层滤波器学习到的是类似Gabor函数的基元,这与生物视觉系统的基础识别单元惊人地相似。随着网络层数加深,滤波器逐渐组合成更复杂的结构(如眼睛)乃至整体对象轮廓(如人脸)。这揭示了CNN如何通过分层抽象从像素中提取有意义的特征。

021:应用与实践 🚀

在本节课中,我们将基于之前建立的直觉,探讨深度学习技术在真实、大规模数据上的表现。我们将回顾其关键发展节点,并通过具体案例展示卷积神经网络在图像分类、复杂游戏及图像描述生成等领域的卓越能力。


深度学习的关键发展:2013年

上一节我们介绍了神经网络的基本概念,本节中我们来看看推动其取得突破性进展的关键因素。深度学习在2013年左右取得显著发展,这主要归功于三者的结合:

  1. 核心模型:卷积神经网络。该模型架构实际上在1989年左右就已提出。
  2. 计算能力:图形处理器单元。
  3. 数据规模:海量数据。

这种结合使得处理极其复杂的任务成为可能。


大规模图像分类:ImageNet数据集

为了理解其性能,我们首先需要了解它处理的数据规模。以下是ImageNet数据集的介绍:

  • 任务:对图像进行1000个不同类别的分类。这远超出我们之前为简化而讨论的二元标签(+1, -1)。
  • 数据量:大约每个类别有1000张训练图像,总计约120万张训练图像。
  • 图像复杂性:如下图所示,这些是真实且复杂的图像,我们的目标就是使用深度卷积神经网络对其进行准确分类。

右侧的图像旨在直观展示所使用的海量数据规模。


技术性能:超越人类水平

那么,这项技术的实际表现如何呢?下图展示了2010年至2017年间,在ImageNet数据集上最佳算法的性能变化:

  • 纵轴:分类准确率。
  • 横轴:时间。
  • 水平线:代表人类在此任务上的表现(约5%的错误率)。

可以观察到,在2012-2013年卷积神经网络成为主流后,性能出现了显著提升。到2017年,深度卷积神经网络的性能已经超越了人类水平。


实际分类示例

为了更具体地感受模型的分类能力,请看以下八个示例:

对于每张测试图像,模型会输出其属于1000个类别的概率分布。图中在每个测试图像下方,列出了模型认为最可能的五个标签及其对应的概率(条形图表示)。

从这些具有高度真实性和复杂性的图像中可以看出,模型的分类表现非常出色,其能力已优于人类进行此类标注的水平。


超越图像分类:AlphaGo的突破

深度学习的另一个里程碑体现在围棋领域。围棋是一种比国际象棋更为复杂的游戏。

DeepMind公司开发的核心算法基于我们讨论的深度卷积神经网络技术。该算法能够分析棋盘图像,并推荐最佳的下一步走法。最终,这项机器学习技术击败了世界顶级的职业围棋选手,完成了一项此前被认为不可能的任务,标志着深度学习技术的成熟。


图像描述生成:多模态融合

该技术还能完成更复杂的任务,例如为图像生成描述性文字。以下是六个示例:

其工作流程如下:

  1. 图像输入:图像被送入一个深度卷积神经网络。
  2. 特征提取:网络顶层的特征被提取出来。
  3. 文本合成:这些特征被输入到另一个神经网络(基于长短期记忆架构)中,用于合成描述文本。

生成的文本质量很高,语法正确,并且准确地描述了图像内容。这展示了现代机器学习如何整合图像分析与文本合成,从而产生令人兴奋的应用。


总结

本节课中我们一起学习了深度学习,特别是卷积神经网络在大规模真实数据上的强大应用。我们看到,自2013年关键要素结合后,该技术在图像分类任务上已超越人类水平。通过AlphaGo的案例,我们了解到它能解决极其复杂的策略性问题。最后,通过图像描述生成的例子,我们看到了多模态模型融合所能实现的更高级、更智能的功能。这些成就共同证明了深度学习已成为解决复杂现实问题的成熟且强大的工具。

022:深度学习与迁移学习 🧠

在本节课中,我们将探讨深度学习在医学影像分析等关键领域的应用,并重点介绍迁移学习这一强大概念。我们将了解如何利用在自然图像上训练好的模型,来帮助解决医学图像分析中数据稀缺的挑战。

深度学习在医学影像中的应用 🏥

上一节我们介绍了深度学习在围棋和图像描述等领域的应用。本节中我们来看看深度学习在医学影像分析中的价值。

医学影像分析在放射学、眼科学和皮肤病学等领域至关重要。医生们需要花费大量时间查看影像,而非与患者沟通。深度学习为此提供了显著的机会。

以下是深度学习已展现出巨大潜力的几个医学领域:

  • 眼科学:例如在糖尿病视网膜病变的诊断中,卷积神经网络的表现已与眼科医生相当,甚至更优。
  • 皮肤病学:深度学习模型在皮肤病图像分析中表现出相似的高性能。
  • 放射学:该领域也是深度学习应用的重要方向。

迁移学习:解决医学数据稀缺的关键 🔄

然而,在医学领域应用深度学习面临一个主要挑战:获取海量标注数据非常困难。例如,要构建一个皮肤病诊断模型,需要数百万张由医生标注的皮肤病图像,这个过程既昂贵又耗时。

这就引出了一个关键问题:我们能否将基于自然图像(如ImageNet)训练出的模型架构和参数,迁移到医学影像分析中?

如果答案是肯定的,那么我们就能利用世界上已有的海量自然图像数据,极大地推动深度学习技术在其他领域的应用。

迁移学习的实践方法 💡

研究发现,这是可行的。我们可以采用为ImageNet设计的深度神经网络架构及其参数,几乎完整地迁移到其他应用上。

具体过程可以用以下伪代码表示:

# 1. 加载在ImageNet上预训练的模型(如ResNet, VGG)
pretrained_model = load_pretrained_model('imagenet')

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-ml/img/3f1750505378c5e3325bcd7d42d70320_17.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-ml/img/3f1750505378c5e3325bcd7d42d70320_18.png)

# 2. 冻结大部分底层参数,保留其学到的通用特征
for param in pretrained_model.early_layers.parameters():
    param.requires_grad = False

# 3. 替换并重新训练顶层的分类器,以适应新任务(如医学影像分类)
pretrained_model.classifier = new_classifier(output_classes=num_medical_classes)

# 4. 使用医学影像数据训练新的顶层分类器
train_model(pretrained_model, medical_dataset)

图中的方框意在说明:我们可以将基于ImageNet学习到的模型权重,迁移到看起来截然不同的图像上(例如这里的共聚焦图像)。然后,我们只学习网络顶层的、直接适用于新图像类别的参数。因此,我们需要学习的参数量大大减少,因为我们无需从头学习所有参数,只需为医学图像学习网络顶层的新参数,而底层参数则从ImageNet模型迁移而来。

迁移学习的广泛应用 🌟

这种将模型参数从ImageNet迁移到不同图像(如医学图像)的概念,是深度神经网络一个显著的积极方面。它已被证明在将技术应用于缺乏足够标注数据的新领域(如医学影像)时极具价值。

以下是迁移学习发挥重要作用的其他领域示例:

  • 数字病理学:用于癌症诊断的细胞图像分析。
  • 其他医学影像模态:如X光、CT、MRI等。

总结 📝

本节课中我们一起学习了深度学习在医学影像等关键领域的应用,并深入理解了迁移学习的核心概念。

关键要点在于,这种深度学习架构——卷积神经网络——正被广泛应用于各种不同类型的任务和图像中,其性能常常超越人类。更重要的是,通过迁移学习,许多在不同(甚至差异很大)应用中的参数几乎可以直接迁移。这种迁移的概念非常强大,随着深度学习被应用到图像分析的其他领域,它将扮演越来越重要的角色。

023:PyTorch简介 🚀

在本节课中,我们将学习PyTorch这一深度学习框架的基本概念、优势以及如何为后续实践部分设置编程环境。

大家好,欢迎来到课程的实践部分。我是Kevin Li Aang,是杜克大学Lawrence Karen教授指导的博士生,我将担任这些部分的讲师。在这些部分中,我们将逐步讲解如何使用Python构建先前视频讲座中学习的神经网络基本组件。这些部分被视为可选内容,但我们坚信,像其他数学或计算机科学课程一样,完成这些练习是深入理解的最佳方式。

为何选择PyTorch?🤔

上一节我们介绍了实践部分的目标,本节中我们来看看为何选择PyTorch作为我们的工具。

我们确实可以使用纯Python或Python的数值计算包NumPy来构建神经网络。然而,我们会发现这些实现方式在编写和运行上都较慢。

尽管如果你想完全掌握实践,这是一个很好的练习,但在实际中,我们通常使用众多机器学习库中的一个来构建深度学习模型。

对于本课程,我们将使用PyTorch,这是一个主要由Facebook AI Research构建的框架。

使用像PyTorch这样的库有许多优势。首先,许多深度学习模型具有某些共同的操作。使用PyTorch意味着我们不必自己编写所有这些函数。

然而,一个关键区别在于,这些库的实现方式与我们可能自己实现的方式不同,它们被编写为计算高效,并且能够利用图形处理单元(GPU)。深度学习模型的训练可能需要很长时间,而GPU实现可以使模型训练时间从几天或几周缩短到几小时。

此外,正如我们将在下一个模块中看到的,几乎所有神经网络都是通过反向传播学习的,这需要计算网络参数的梯度。这些梯度可以手动推导,实际上,如果你使用Python和NumPy,你可能需要自己完成。另一方面,PyTorch的自动梯度引擎可以自动为我们进行这种微分,这使得构建模型变得更加容易。

最后,现在是一个进入机器学习领域的激动人心的时刻,拥有一个庞大的社区,包括研究人员、专业人士和学生。PyTorch拥有增长最快的用户社区之一,很容易找到最先进模型的开源实现、带有代码示例的逐步教程以及充满调试建议或最新趋势的活跃论坛。

实践材料与预备知识 📚

上一节我们了解了PyTorch的优势,本节中我们来看看实践材料的形式和所需的预备知识。

实践部分的大部分材料都组织在Jupyter IPython笔记本中,文本解释和图表嵌入在代码单元格之间。

在引导您进入第一个关于设置环境的笔记本之前,有几点简要说明。

首先,我们假设您对Python和NumPy有基本的了解。请查看“Python预备知识”笔记本,并确保您理解大部分示例代码。如果您有些生疏或从未接触过Python,我们建议在尝试本课程的实践部分之前先进行复习。

其次,虽然GPU极大地加速了训练过程,但并非每个人都有能力处理深度学习模型计算的GPU。因此,我们将坚持使用仅需CPU即可运行的更简单问题。您会发现,为CPU计算编写代码与为GPU编写代码非常相似。

总结与下一步 🎯

本节课中我们一起学习了PyTorch框架的基本介绍、其核心优势以及实践课程的设置要求。我们了解到,PyTorch通过提供高效的GPU计算支持和自动微分功能,简化了深度学习模型的构建过程。实践材料以Jupyter笔记本形式提供,学习前需要具备Python和NumPy的基础知识。

好的,我们的介绍到此结束。现在让我们开始设置编码环境。

024:如何定义学习 📚

在本节课中,我们将要学习如何从数学上定义“学习”这一过程。我们将探讨如何将学习问题形式化,以便能够实际地训练一个神经网络模型。

概述

上一节我们介绍了不同类型的网络,并讨论了深度神经网络是什么以及它们能做什么。本节中,我们来看看如何从数学上定义“学习”,从而将训练网络设定为一个可以求解的优化问题。

从数据到模型

回顾之前的示意图,我们的目标是结合训练数据(左侧)与一个网络模型(右侧),以学习能够根据特征预测结果的参数。

  • 训练数据:包含多个独立的训练样本,每个样本由特征(协变量)和一个特定的结果(标签 Y)组成。
  • 网络模型:以逻辑回归模型为例,特征通过线性组合生成 Z,再通过 Sigmoid 函数转换为预测概率 σ(Z)。

我们的核心任务是:给定训练数据和想要学习的网络结构,如何实际地学习出模型的参数?

学习的核心问题

因此,我们今天要讨论的基本问题是:给定大量数据和我们想要拟合的模型(网络),如何既高效又有效地学习模型参数?

  • 有效性:我们希望学习到的参数能够做出非常准确的预测。
  • 高效性:我们希望利用有限的计算资源高效地完成学习过程。这在手机应用或实时学习等场景中尤为重要。

定义“最佳性能”

具体来说,当我们尝试进行学习时,我们试图做的事情是:学习能给我们带来最佳性能的参数。

这意味着,给定数据,我们要找到对该数据而言最好的参数 B。但我们立刻遇到了第一个问题:我们还没有定义什么是“性能”。我们如何定义这个网络的性能好坏呢?

经验风险最小化

解决这个问题的途径是使用经验风险最小化。这是机器学习领域的术语,其核心是引入一个损失函数

损失函数接受两个输入:

  1. 真实值或真实结果(Y)。
  2. 我们的预测值(Ŷ)。

这个函数的作用是:为糟糕的预测定义惩罚。如果我们预测得很好,就不会受到什么惩罚(损失很小);而每当预测得很差时,我们就会付出很大的损失。

我们的目标就是最小化平均损失。既然损失是对表现差的惩罚,我们自然希望它越小越好。

学习的数学表述

因此,我们可以用数学语言表述如何寻找最优参数 B:

B* = argmin₍ᵦ₎ (1/n) Σᵢ L(Yᵢ, σ(Zᵢ))

其中:

  • B* 是我们的最优参数。
  • argmin 表示寻找使后面表达式值最小的参数 B。
  • n 是数据点的总数。
  • Σᵢ 表示对所有数据点 i 求和。
  • L 是损失函数。
  • Yᵢ 是第 i 个数据点的真实标签。
  • σ(Zᵢ) 是我们的模型对第 i 个数据点的预测概率。注意,Zᵢ 依赖于参数 B,因此预测也由参数 B 决定。

这个公式的含义是:我们希望找到能使所有数据点上平均损失最小的那组参数 B。这就是我们对“学习”的数学定义。

定义损失函数:以二分类为例

我们还需要定义损失函数 L 的具体形式。以二分类问题为例:

  • σ(Z) 是我们的模型预测的“正类”概率。
  • Yᵢ 是来自训练集的真实标签(通常为 0 或 1)。

我们可以将损失函数视为负对数似然。在统计学中,我们通常尝试最大化对数似然。而在损失函数语境下,由于我们要最小化损失,因此直接取对数似然的负数。即:

L(Y, σ(Z)) = -log P(Y | σ(Z))

对于任何二分类问题,这个负对数似然(也称为逻辑损失交叉熵损失)的具体数学形式如下:

L(y, σ(z)) = -[y · log(σ(z)) + (1 - y) · log(1 - σ(z))]

理解逻辑损失函数

这个数学形式可能有些抽象,我们可以通过可视化来理解它的行为。逻辑损失函数根据真实标签 Y 的不同(0 或 1),有两种情况:

以下是损失函数随预测概率 σ(z) 变化的趋势:

  • 当真实标签 y=1(正例)时
    • 如果我们预测概率 σ(z)=1(即100%确信为正例),且预测正确,则损失为 0。
    • 但如果我们过度自信(例如预测概率很高,但实际是负例,y=0),损失会急剧增大直至无穷大。这惩罚了“过度自信的错误预测”。
  • 当真实标签 y=0(负例)时
    • 行为对称,预测概率 σ(z)=0 时损失最小。
    • 同样,对负例做出过度自信的正例预测也会导致巨大损失。

这个损失函数的好处在于:它鼓励模型做出正确预测,但同时惩罚过度自信的预测,其背后有深刻的统计学原理支持。

完整的优化目标

现在,对于使用逻辑回归(或任何进行概率性二分类)的问题,我们可以使用上述逻辑损失/交叉熵损失。我们的完整优化目标变为:

B* = argmin₍ᵦ₎ (1/n) Σᵢ [ -Yᵢ · log(σ(Zᵢ)) - (1 - Yᵢ) · log(1 - σ(Zᵢ)) ]

我们的任务就是找到最小化这个平均损失的参数 B*。

总结

本节课中我们一起学习了如何从数学上定义机器学习中的“学习”过程:

  1. 目标:我们拥有训练集和待学习的模型(网络)。
  2. 定义性能:通过引入损失函数来量化模型预测的好坏。损失函数惩罚错误预测,正确预测则损失小。
  3. 数学形式化:学习的目标被定义为寻找能最小化所有训练样本上平均损失的那组模型参数。这称为经验风险最小化
  4. 具体例子:对于二分类问题,常用的损失函数是逻辑损失(交叉熵损失),它源自负对数似然,能有效工作。

现在,我们已经有了“学习”的精确数学表述(一个优化问题)。接下来的课程中,我们将探讨实际的优化算法,来寻找这些最优参数 B*。

025:如何评估神经网络 📊

在本节课中,我们将学习如何评估神经网络模型的性能。我们将探讨模型复杂性与性能之间的关系,理解过拟合的概念,并介绍一种标准的验证策略,即通过划分数据集来客观地评估模型在真实世界中的表现。


模型复杂性与性能权衡 ⚖️

上一节我们介绍了定义神经网络的各种选项。本节中我们来看看如何评估这些网络的实际效果。

我们可以构建非常浅的网络,例如使用逻辑回归这种相对简单的模型,也可以使用深度神经网络。随着课程的深入,我们将讨论越来越复杂的网络。但一个根本性的问题是:我们如何实际评估这些网络的工作效果?

逻辑回归模型相对简单,其背后有数十年的统计学理论支持,解释了它的工作原理和适用场景。其核心是将特征线性组合后,通过一个函数(如Sigmoid)转换为概率:

公式: P(y=1|x) = σ(w·x + b)

而在右侧,我们展示的是多层感知机,这是一种深度神经网络。这种网络比逻辑回归能捕捉更多、更复杂的特性。现在的问题是:我们是否总是需要如此复杂的模型?


过拟合:复杂性的双刃剑 ⚔️

首先,创建深度模型确实有助于学习复杂关系。例如,著名的“双月”数据集,逻辑回归无法有效分离这两个类别,因为模型能捕捉的模式非常有限。而深度神经网络可以学习并准确预测这种复杂的非线性关系。

然而,在很多情况下,这种复杂性可能是不必要的。深度模型可能在训练数据集上达到完美性能,但在真实世界中却可能完全失败。因此,我们必须验证神经网络的性能是否如我们所想的那样好。

在深入探讨如何进行验证之前,让我们更深入地思考一下过拟合的概念。

过拟合发生在我们的学习模型为了过度拟合已观测的训练数据而增加复杂性时。它会在训练集上预测得极好,但在面对真实数据时却表现不佳。

为什么会发生这种情况?让我们从一个简单的例子开始。假设我们有一些观测数据点,想找到一个函数来预测给定x值时的观测结果。

一种经典的策略是增加多项式的阶数。左侧展示了一个简单的线性回归拟合(一阶)。它表现不错,很多人会对此满意。但问题是:我们能否增加一点复杂性来获得更好的预测?

当我们使用三阶(三次)拟合时,可以看到在绘制的范围内,它似乎对数据点的拟合更好一些。然而,我们可以继续增加复杂性。图中展示的是对相同数据点的八阶拟合。这看起来非常不合理,它完美地拟合了训练数据,但如果我们试图预测未来的点,效果会很差。

在神经网络中,增加深度意味着增加模型中的参数数量。逻辑回归的参数数量是有限的,而每次在多层感知机中添加一个层,我们都会获得更多参数。但请记住,我们必须估计这些参数。如果我们需要估计的参数更多,每个参数的估计误差会累积起来。

另一方面,我们确实喜欢更复杂的模型或网络,因为它们可以学习更复杂的关系。但问题是,这些关系对于现实情况来说是否过于复杂了?我们可以学习任何想要的复杂关系,但这种复杂关系在现实中真的存在吗?

发生过拟合时,意味着模型无法“泛化”。我们希望模型和分析能够泛化,这意味着当我们将其应用于真实世界并做出预测时,这些预测能够成立。因此,我们想知道:我们的网络和模型在实际中到底能工作得多好?


标准验证策略:数据划分 📈

现在,我想介绍一种非常标准的验证策略。

如果我们的最终目标是了解这个网络在真实世界中的表现,那么一个优秀且堪称“黄金标准”的方法就是直接在真实世界中尝试。我们可以用训练数据集估计参数,然后获取新的真实世界数据,用我们的网络进行预测,并以此评估真实世界的性能。

这确实是黄金标准。然而,这种做法成本极高。当我们只是想验证模型是否有效时,我们并不想这样做。相反,我们能否利用现有数据来估计性能?

答案是肯定的。我们将尝试智能地使用现有数据,基于我们已经收集到的可用数据,创建方法来验证我们认为模型在真实世界中的表现。

我们拥有所有可用数据,接下来要做的就是将这些数据分成不同的组。

我们将定义三组数据:训练数据集、验证数据集和测试数据集。我们将随机将数据分配到这些不同的组中,并按不同比例分配。

训练数据的用途我们已经讨论了很多,它用于获取模型参数。验证数据和测试数据是另外两个独立的数据集。我们为什么要这样做?这样做有什么好处?

首先,测试集是机器学习中的标准实践。我们希望在开始任何分析之前就创建测试集,并且在创建测试集之前完全不使用这部分数据。测试集永远不会用于学习或拟合任何参数。在学习网络之后,我们可以在测试集上评估其性能。这意味着这部分数据没有包含在训练或拟合过程中,因此在这个新测试集上尝试模型,类似于进行一次新的实验。关键的一点是,测试集理想情况下只应使用一次。如果重复使用测试集,会导致偏差,这意味着我们的性能估计会过于乐观,即我们认为在真实世界中的性能会比实际更高。

为了解决测试集只能使用一次的问题,我们创建了验证集。验证集的想法是,我们希望能够比较哪种方法最好。如果我们只使用一次测试集,就无法做到这一点。验证集同样不用于学习参数,但可以用于反复估计模型的性能。这样,如果我们想尝试许多不同的网络结构(如逻辑回归模型、多层感知机等),我们可以在验证集上学习所有模型并评估它们的性能。一旦我们选定了要使用的模型,就可以在测试数据上进行最终评估,并且只使用测试数据一次。

为了可视化这个过程:我们从所有可用数据中划分出训练数据,并从中学习参数。然后,使用验证数据来估计性能,并利用这个性能估计来优化我们的模型或网络架构(例如,增加或减少复杂性)。我们将持续这个过程,直到我们认为找到了最适合数据的模型。之后,我们跳出这个循环,结合模型,并使用测试数据一次性估计最终性能。

这就是我们在使用机器学习时希望采用的结构:使用验证数据帮助我们确定使用哪种模型,使用测试数据来估计真实世界的性能。


总结 📝

本节课中,我们一起学习了如何评估神经网络。我们探讨了模型复杂性带来的好处与过拟合的风险。最重要的是,我们介绍了一种通过将数据划分为训练集、验证集和测试集来系统评估模型性能的标准方法。这种方法能帮助我们更客观地选择模型,并对其在未知数据上的表现做出更可靠的估计。

026:如何学习网络 🧠

在本节课中,我们将要学习如何通过优化算法来训练神经网络。我们已经定义了网络结构和学习目标,现在需要探讨如何从数学描述出发,实际地找到最优参数。


上一节我们介绍了如何定义网络和学习目标,本节中我们来看看如何通过优化算法来学习网络参数。

学习本身将转化为一个优化问题。我们的目标是找到能够最小化平均损失的参数。我们可以将最优参数 B ̂ 定义为:

B ̂ = argmin_B [ L(B) ]

其中,平均损失函数 L(B) 是在所有训练数据样本上计算的:

L(B) = (1/N) * Σ_{i=1}^{N} loss( y_i, f(x_i; B) )

那么,我们如何实际找到最小化这个函数的参数呢?如何优化 B 以最小化 L(B)?


为了做到这一点,我们需要讨论梯度下降法。梯度下降法是一个非常著名的数学优化算法,历史悠久。我们不从纯数学角度讨论,而是直观地理解其过程。

我们的目标是,对于某个数学函数(例如我们的平均损失函数),找到其最小值。下图右侧展示了一个简单的一维函数,我们希望找到使该函数值最小的参数 B

虽然在这个可视化图中,我们一眼就能看出最小值在0附近,但对于高维和复杂的函数,我们无法直接绘制并观察其最小值。因此,我们需要一种算法来帮助我们寻找最小值。

一种方法是:从一个特定的参数值开始(例如图中蓝色圆圈标记的1.5附近)。在当前点,我们可以计算出函数的斜率。斜率指示了函数值上升或下降的方向。

如果我们想找到最小值,就应该朝着“下坡”的方向移动。在当前点,斜率告诉我们:向右移动是“上坡”,向左移动是“下坡”。因此,我们应该向左移动一步。

以下是梯度下降的步骤:

  1. 初始化:从一个初始参数值 B^0 开始。
  2. 迭代更新:重复以下步骤,直到满足收敛条件:
    • 计算当前参数点 B^k 处损失函数的梯度(对于单参数是导数,对于多参数是梯度向量)。梯度指向函数值上升最快的方向。
    • 负梯度方向(即函数值下降最快的方向)移动一小步。更新公式为:
      B^{k+1} = B^k - α^k * ∇L(B^k)
      其中,α^k 是第 k 次迭代的学习率(步长),它控制着我们移动的幅度。
  3. 收敛:当参数更新变化很小或达到预设迭代次数时,停止更新。

这个过程就像一个人在山坡上,通过反复感知脚下最陡的下坡方向并迈出一小步,最终走到山谷底部。


我们已经讨论了梯度下降的基本原理。接下来,我们需要探讨如何在拥有海量数据时,让这个方法高效工作。这将在后续的课程中详细展开。


本节课中我们一起学习了:

  1. 网络学习的目标是找到最小化平均损失函数的参数,这是一个优化问题。
  2. 梯度下降法是解决此问题的核心算法。其核心思想是:计算当前点的梯度,并沿着负梯度方向(下降方向)更新参数。
  3. 参数更新遵循公式:B^{k+1} = B^k - α * ∇L(B^k),其中 α 是学习率。
  4. 这个过程迭代进行,直到算法收敛到(接近)最优解。

027:如何处理大数据 🚀

在本节课中,我们将要学习如何从优化算法的角度处理大规模数据集。我们将回顾梯度下降法,并探讨其在面对海量数据时的局限性,最终引出一种更高效的优化方法——随机梯度下降法。

梯度下降法的局限性

上一节我们介绍了梯度下降法,它是一种非常出色的优化算法。然而,当我们面对真正的大数据时,它会遇到麻烦。

梯度下降法的目标是找到一组最优参数 B*,使得在所有数据点上的平均损失函数最小化。其核心更新公式为:

B_{t+1} = B_t - η * ∇L(B_t)

其中,∇L(B_t) 是损失函数在所有训练数据上的梯度。计算这个梯度需要遍历数据集中的每一个数据点。对于包含 N 个样本的数据集,梯度计算如下:

∇L(B) = (1/N) * Σ_{i=1}^{N} ∇l_i(B)

这里,∇l_i(B) 是单个数据点 i 的损失梯度。当 N 非常大时(例如百万甚至十亿级别),每次参数更新都需要完整扫描一遍数据集,这非常耗时且不可扩展。

引入随机梯度下降法

既然计算全部数据的梯度成本高昂,一个自然的想法是:我们能否用一部分数据来近似整个数据集的梯度?本节中,我们来看看随机梯度下降法是如何实现这一点的。

其核心思想是:在每次参数更新时,我们不计算所有数据点的梯度,而是随机选取一个数据点 j,并用这个数据点的梯度来近似整个数据集的平均梯度。更新公式变为:

B_{t+1} = B_t - η * ∇l_j(B_t)

这里的 ∇l_j(B_t) 是随机选出的单个样本 j 的梯度,它是对真实梯度 ∇L(B_t) 的一个估计。

为什么这样做可行?

以下是随机梯度下降法可行的几个关键原因:

  1. 数据冗余性:在许多实际数据集中,样本之间往往存在冗余。例如,在手写数字识别数据集(MNIST)中,虽然可能有6万个样本,但本质上只有0到9这10个类别,每个类别内的样本有相似特征。因此,看一个或几个样本的梯度,就能对整体数据分布有一个大致的了解。
  2. 期望一致性:从数学期望上看,随机选取的单个样本梯度的期望值等于整个数据集的平均梯度。即:
    E[∇l_j(B)] = ∇L(B)
    这意味着,虽然每次更新方向有噪声,但平均来看,更新方向是正确的。
  3. 更新速度的巨大优势:假设数据集有 N 个样本,随机梯度下降法进行一次参数更新的计算量仅为梯度下降法的 1/N。这意味着在相同时间内,随机梯度下降法可以进行更多次的参数更新。

算法对比与可视化

为了更直观地理解两者的区别,让我们对比一下梯度下降法和随机梯度下降法的算法流程。

梯度下降法流程:

  1. 初始化参数 B_0
  2. 计算损失函数在所有训练数据上的梯度 ∇L(B_t)
  3. 按照公式 B_{t+1} = B_t - η * ∇L(B_t) 更新参数。
  4. 重复步骤2和3,直到满足停止条件。

随机梯度下降法流程:

  1. 初始化参数 B_0
  2. 从训练集中随机选择一个样本索引 j
  3. 计算该样本的损失梯度 ∇l_j(B_t),作为真实梯度的估计 ∇̂L(B_t)
  4. 按照公式 B_{t+1} = B_t - η * ∇l_j(B_t) 更新参数。
  5. 重复步骤2到4,直到满足停止条件。

通过可视化模拟可以发现,梯度下降法的优化路径非常平滑,稳步向最小值前进。而随机梯度下降法的路径则充满“噪声”,更新方向时对时错,但在期望上它朝着正确的方向快速前进,通常能以远快于梯度下降的速度接近最优解。

实践中的改进:小批量梯度下降

在实际应用中,我们通常采用一种折中的方法——小批量梯度下降法。它既不是使用全部数据,也不是使用单个数据,而是每次随机选取一小批(Mini-batch)数据(例如32、64或256个样本)来计算梯度估计。

其更新公式为:
B_{t+1} = B_t - η * (1/m) * Σ_{k in Batch} ∇l_k(B_t)
其中 m 是小批量的大小。

以下是采用小批量梯度下降法的优势:

  • 降低方差:相比单样本,使用一批样本估计梯度可以减少更新方向的方差,使收敛过程更稳定。
  • 硬件效率:现代计算硬件(如GPU)能高效并行处理批量数据,计算一批样本的梯度通常比逐个计算快得多。
  • 在计算效率和收敛稳定性之间取得了良好平衡。

总结与核心优势

本节课中,我们一起学习了如何处理大数据下的优化问题。

我们首先指出了经典梯度下降法在大数据场景下的计算瓶颈:每次更新都需要遍历全部数据。接着,我们引入了随机梯度下降法,它通过每次随机使用一个样本来估计梯度,实现了计算复杂度的巨大降低。我们还讨论了其可行的数学基础(期望一致性)和现实基础(数据冗余性),并介绍了更常用的小批量梯度下降法作为实践中的最佳选择。

随机梯度下降法的核心优势在于其卓越的可扩展性

  • 更新速度与数据量无关:无论数据集大小是100万还是10亿,随机梯度下降法进行一次参数更新的时间基本是恒定的。这使得机器学习模型能够处理前所未有的大规模数据。
  • 快速接近解:虽然不一定能找到精确的最优解,但随机梯度下降法通常能非常快速地找到一个足够好的近似解,这对于许多机器学习应用来说已经足够了。

正是由于这些特性,随机梯度下降法及其变体成为了训练几乎所有现代深度学习模型的基础优化算法。

028:早停法 🛑

在本节课中,我们将要学习一种结合了优化算法与验证集评估的技术——早停法。我们将探讨为何仅优化训练集性能可能并非最佳选择,以及如何利用验证集在训练过程中监控模型,从而在计算成本与泛化性能之间取得平衡。


优化目标与泛化目标的错位

上一节我们介绍了随机梯度下降。之前我们也讨论过验证集。到目前为止,我们尚未讨论如何将验证与我们的优化算法结合起来。但在实践中,我们经常通过一种称为“早停法”的技术来结合这两者。

其核心思想是,我们希望在优化过程中运行验证。如果我们希望最大化网络的泛化能力,这与我们的优化目标实际上是不匹配的。我们的优化目标是希望在训练数据集上表现得尽可能好。

但在实践中,我们并非试图最大化训练数据集的性能,而是试图最大化模型在真实世界中的表现。这就产生了一个问题,因为随机梯度下降正在优化的数学目标,与我们实际想做的事情并不一致。

因此,这里存在一个问题:我们能否在运行优化循环的过程中验证模型,以解决这个问题?


早停法的核心思想

早停法的想法是,我们可以在训练过程中检查验证损失。具体做法是,我们将运行训练循环,即运行随机梯度下降,并估计我们在训练数据集上的平均损失。每隔一段时间,我们也会估计在验证数据集上的性能。

我们不会使用验证数据集来进行优化或计算梯度,但我们会使用验证数据集来估计我们的真实世界性能。其理念是:我们不要优化到训练目标完全收敛,而是优化到验证损失不再改善为止。


早停法的两大优势

以下是早停法带来的两个主要好处:

  1. 节省计算成本:这些算法在计算机上训练可能需要很长时间,我们希望使用尽可能少的计算量。
  2. 提升泛化性能:更重要的是,它实际上能让模型在真实世界中表现得更好。

训练损失与验证损失的变化趋势

右侧的图表展示了这一过程。如果你运行这个优化算法(随机梯度下降),随着我们运行越来越多轮的随机梯度下降,我们的训练损失会持续改善,我们会随着时间的推移而变得更好。

但是,随着我们过度拟合的程度越来越深,我们的验证数据集性能实际上会逐渐变差。因此,我们希望在我们的验证损失最小时停止,而不是在训练损失最小时停止。

最佳的验证和泛化性能大约会出现在这张图的中间位置。这是该领域广泛使用的一种技术,它既能帮助我们节省计算,也能帮助我们获得性能尽可能好的网络。


总结

本节课中,我们一起学习了早停法。我们了解到,优化训练集损失与追求最佳泛化性能之间存在目标错位。通过定期在验证集上评估模型,并在验证损失不再改善时提前停止训练,我们不仅能够节省宝贵的计算资源,还能有效防止过拟合,从而获得在未知数据上表现更佳的模型。这是一种简单而强大的正则化技术。

029:使用PyTorch进行模型学习

在本节课中,我们将学习如何将之前介绍的机器学习核心概念——损失函数和随机梯度下降——应用于实践。我们将使用PyTorch框架,编写一个逻辑回归模型来对MNIST数据集中的手写数字进行分类。完成训练后,我们将评估模型性能,并可视化其学习到的内容。课程将从基础的PyTorch操作开始,最后介绍如何使用更高级的API以面向对象的方式高效构建模型。

回顾核心概念

在模块2中,我们学习了神经网络如何从数据中学习。其核心是定义一个损失函数,该函数能将模型的表现不佳程度量化为一个单一数值。

损失函数的公式可以表示为:
L(θ) = 1/N * Σ L_i(f(x_i; θ), y_i)
其中,θ代表模型参数,f是模型,x_iy_i是样本数据和真实标签。

我们可以使用随机梯度下降算法来调整网络中的每个参数,从而提升模型性能。其参数更新公式为:
θ = θ - η * ∇L(θ)
其中,η是学习率,∇L(θ)是损失函数关于参数的梯度。

实践:用逻辑回归分类MNIST

在模块2中,逻辑回归被用作贯穿始终的示例来阐述这些概念。在本节中,我们将把这些概念付诸实践,实际编写一个可工作的模型,使用逻辑回归对MNIST数据集中的数字进行分类。

以下是实现逻辑回归模型的主要步骤:

  1. 数据准备:加载MNIST数据集,并进行必要的预处理,如归一化。
  2. 模型定义:定义逻辑回归模型的结构,即一个线性层后接一个Sigmoid激活函数(对于二分类)或Softmax函数(对于多分类)。
  3. 损失函数与优化器:选择交叉熵损失函数和随机梯度下降优化器。
  4. 训练循环:在多个周期内,让模型遍历训练数据,计算损失,反向传播梯度,并更新参数。
  5. 模型评估:在测试集上评估模型的准确率等性能指标。
  6. 结果可视化:可以可视化模型学习到的权重,观察其识别数字的模式。

一旦模型训练完成,我们就可以评估其性能。作为一个额外的收获,我们还可以可视化它实际学习到了什么。

从基础代码到高级API

我们将首先使用基础的、低层次的PyTorch操作来编写代码。这有助于我们理解底层机制。

但是,我们将以看到如何通过使用更高级的API,以更面向对象的方式重构我们的代码作为结束,从而更高效地构建我们的模型。

作业延伸:构建多层感知机

作为一项作业,你将把我们的逻辑回归模型扩展为一个多层感知机。这是在模块1中介绍过的模型。

你应该会发现,它的性能优于我们简单的逻辑回归模型。

总结

本节课中,我们一起学习了如何将理论概念转化为实际代码。我们使用PyTorch实现了一个逻辑回归模型,用于MNIST数字分类,并理解了从数据加载、模型定义、训练到评估的完整流程。我们还对比了基础操作与高级API在构建模型方式上的不同。最后,我们为下一步学习——构建更复杂的多层感知机模型——做好了准备。

030:糖尿病视网膜病变的动机 🩺

在本节课中,我们将深入探讨深度卷积神经网络。这些网络是进行图像分析的强大工具,在现实世界应用中取得了巨大成功,尤其是在医学图像分析领域。我们将重点介绍卷积神经网络在糖尿病视网膜病变分类中的一个非常成功的应用。

糖尿病视网膜病变简介

上一节我们介绍了卷积神经网络在图像分析中的强大能力,本节中我们来看看一个具体的医学应用实例。

糖尿病视网膜病变是一种影响糖尿病患者视网膜的疾病。其特点是血管会随着时间的推移而恶化。如果不加以治疗,将导致失明。但如果训练有素的眼科医生能在不健康的视网膜中发现特定结构,就可以及早发现该疾病。这种结构能将不健康的视网膜与健康的视网膜区分开来。

在左侧,您可以看到一个健康的视网膜。在右侧,您看到的是一位糖尿病视网膜病变患者的不健康视网膜。希望您能看到这两个视网膜之间的差异。在右侧不健康的视网膜中,您可以看到视网膜左侧有小的出血点。在图像右侧靠近视神经(图像中那个亮点)的地方,您可以看到新生血管。这些共同构成了视网膜不健康的迹象,如果不加以治疗,最终可能导致失明。

眼科医生经过培训,能够区分这种视网膜与另一种。他们在医学院和住院医师期间经过多年的经验积累,从同事那里获得监督信号,帮助他们正式区分不健康的视网膜和健康的视网膜,以及健康与不健康的患者。但由于卷积神经网络非常擅长进行图像分类,它们可以学习区分不健康视网膜与健康视网膜的特征。

机器辅助诊断的优势

因此,可以让机器以这种方式执行分类,从而绕开对训练有素的眼科医生的需求。有一个应用于此问题的卷积网络,它效果非常好,并于2016年发表在《美国医学会杂志》的一项研究中。这里展示的是他们论文中的关键结果图,显示了一个训练好的神经网络进行糖尿病视网膜病变分类的结果,即尝试区分健康视网膜与不健康视网膜。

为了解释结果,需要先理解这里的坐标轴。左侧的y轴是灵敏度,底部的x轴是1减去特异性。这些指标的含义是什么?它们是医学界常用的指标。

灵敏度是一个有助于定义医生或机器在数据集中发现阳性样本方面表现如何的量。如果我们称不健康的视网膜为阳性,那么目标就是尝试从包含阳性(不健康视网膜)和阴性(健康视网膜)样本的大型数据集中找出尽可能多的阳性样本。如果一位医生对大量图像进行标记(健康或不健康),我们通过计算医生能够找到的真正阳性(数据中真正不健康的视网膜)数量,除以数据集中真正的阳性总数,来计算灵敏度。我们希望这个值尽可能高。

然而,您应该能看到如何可能“作弊”这个指标。如果您只是将数据集中的所有样本都标记为阳性,您将获得非常高的灵敏度分数,但这显然会导致大量假阳性,因为医生将所有健康的视网膜都归类为不健康。因此,我们需要一个补充指标来帮助区分假阳性率和假阴性率,这就是特异性。

特异性是灵敏度的补充指标。在标记的数据集中,当您将视网膜标记为健康或不健康时,真正的阳性计入灵敏度指标,而真正的阴性则计入特异性指标。因此,您计算医生能够正确识别的真正阴性(健康视网膜)数量,除以数据集中真正的阴性总数。理论上,您希望特异性也尽可能高,与灵敏度一起。

在此图中,我们绘制的是1减去特异性。因为我们希望特异性高,所以1减去特异性我们希望它低或接近0。这意味着,这些图像分类器的最佳值位于此图的左上角。

结果解读:机器与医生的对比

现在让我们重新审视这个图。图中的彩色圆点代表8位独立眼科医生,他们在一个包含大量健康和不健康视网膜的数据集上执行了此分类任务。您可以看到这是他们执行此分类能力的分布。左上角的紫色医生点可能是该组中最好的眼科医生。但在灵敏度和特异性之间的权衡能力上似乎存在一些差异,这反映了这些医生在处理分类问题上的表现。

这些彩色圆点是医生。如果您训练一个卷积神经网络(我们稍后会详细介绍如何做到这一点),在一个带有标签的大型训练图像集上执行相同的任务,您可以让机器按照这里的黑线表现。因为我们刚刚说过,越靠近左上角越好,您可以看到,只要黑线比那些彩色圆点更靠近左上角,机器就击败了医生(眼科医生)。在这种情况下,您应该能看到,在此特定任务上,机器击败了80%的眼科医生。这是一个非常有力的结果。

我们认为,对于这个特定任务,机器可能有助于辅助诊断这种疾病。这也为这类卷积网络以及其他类型的医学图像分析任务(包括放射学和病理学)预示了一个非常有前景的未来。

超越分类:图像分割应用

除了图像分类(刚才只是将视网膜分类为不健康或健康的例子),这些卷积神经网络还可用于分割出图像中可能对下游用户很重要的特定特征。

想象一下,您是机场的运输安全管理局筛查员,正在查看乘客行李的X光图像,目标是发现行李中的违禁物品。但您已经在这些监视器前坐了很长时间,非常疲劳。如果有一台机器能自动高亮显示行李中与那些违禁物品对应的感兴趣区域,可能会有所帮助。事实证明,您可以很好地训练卷积神经网络来完成这项任务。

在上方,您可以看到在一个特定行李的多个不同视角中,对枪支位置的预测(以边界框形式)。这些红色框在此案例中高亮显示了某些行李中的玩具手枪。如果您能看到枪支周围那些微小的黄色像素,它们实际上是该物体在行李中的精细轮廓追踪。在下方,您可以看到对口袋刀和其他类型违禁物品进行的类似分析,这些物品不允许通过运输安全管理局的筛查点。

因此,卷积神经网络,因为它非常擅长从图像中提取信息,可以完成这项任务,并有可能被运输安全管理局采用,以帮助增强这些筛查点安检员的工作。这是该工具的另一个强大应用。

高级分割:从2D到3D姿态估计

除了这些应用,这可能是一个将分割任务推向极致的例子。这是一个可以读取视频的网络。在视频的右下角,这只是一个单一摄像头拍摄的场景视频。网络的目标是隔离视频中的所有人物,像前一个例子中的手枪一样将他们分割出来。但不仅仅是勾勒出人物的轮廓,而是生成一个密集的关键点图,这些关键点对应于人体上不同的解剖位置。

以形成一个网格,一个针对视频中每个人的特定3D网格。这是一项非常具有挑战性的任务,尤其是在这些单摄像头视图中。通常,这些网格是使用非常昂贵的动作捕捉技术在非常特殊的场景下开发的。

拥有这样一个网格的具体应用,以及人们使用当前技术(这些动作捕捉服)的原因,是希望开发这些网格,以便在娱乐行业中将纹理应用到这些人物上,从而开发新的视频游戏和电影的新CGI动画。

这些网格也可能有助于未来与新的自动驾驶汽车、机器人等的交互。

总结

本节课中,我们一起学习了卷积神经网络在医学图像分析(特别是糖尿病视网膜病变分类)中的强大应用。我们了解了机器如何通过学习区分特征来辅助甚至超越部分人类专家的诊断。此外,我们还探讨了卷积神经网络在图像分割领域的扩展应用,包括安检中的物体检测和视频中的人体3D姿态估计,展示了该技术在分类之外更广泛的潜力。这些实例共同说明了深度卷积神经网络在处理复杂视觉任务方面的有效性和多功能性。

031:一维与二维卷积分解

在本节课中,我们将要学习卷积神经网络(CNN)的核心操作——卷积运算。我们将从一维信号入手,理解卷积的基本概念,然后将其扩展到二维图像处理中,并展示卷积如何用于提取图像特征。

卷积运算概述

卷积神经网络的一般架构是:输入图像经过一系列卷积滤波器处理,通过卷积运算生成特征图。这个过程会重复多次,最终得到图像的高级表示,以供分类器使用。那么,卷积运算具体是什么呢?

一维卷积详解

卷积本质上是两个信号相互滑动的过程,用于在目标信号中搜索特定特征。我们先从一维信号开始介绍。

假设我们有两个一维信号:一个方波信号 F 和一个锯齿波信号 G。卷积的数学定义如下:

公式: (F * G)[n] = Σ_{m=-∞}^{∞} F[m] * G[n - m]

这个公式的含义是:对于每个位置 n,将信号 G 翻转并平移后,与信号 F 逐点相乘,然后将所有乘积结果求和。这个求和值就是卷积在位置 n 的输出值。这个操作会针对不同的 n 值(即 G 相对于 F 的不同平移量)重复进行。

以下是几个计算示例:

  • 当 n = -5 时:信号 G 先向左平移5个单位,然后进行翻转(沿中线反射)。接着,将翻转平移后的红色信号与蓝色信号 F 逐点相乘并求和。此时,两个信号重叠区域的面积(积分)为15,因此卷积结果为15。
  • 当 n = 0 时:信号 G 不进行平移,只进行翻转。然后与 F 相乘求和,重叠面积更大,结果为20。
  • 当 n = 10 时:信号 G 向右平移10个单位并翻转。此时重叠区域变小,卷积结果也变小。
  • 当平移量很大时:如果两个信号完全没有重叠,相乘结果处处为零,求和后卷积值即为0。

这个过程可以通过动画直观展示:一个红色方波信号在蓝色方波信号上滑动。随着红色信号的移动,当它与蓝色信号重叠时,相乘后会产生一个面积值。图中黑线描绘的正是这个面积值随平移量变化的结果,即整个卷积输出。

一维卷积的意义在于:卷积滤波器 G 可以用来从信号 F 中提取与自身匹配的特征。如果特征匹配良好,卷积输出值就会很高。

例如,假设滤波器 G 与信号 F 在零平移时完美匹配,卷积结果会在多个区域累积较大的正值面积。但如果使用一个不匹配的长方波滤波器,在中间区域,正负值相乘会产生很大的负面积,从而从总和中减去,导致最终的卷积值低于匹配滤波器的情况。

从一维到二维卷积

在卷积神经网络中,我们需要对二维图像应用二维滤波器。其原理与一维完全相同,只是滤波器具有二维空间范围。

在上图中,一个3x3的滤波器被应用到下方图像的某个区域。与一维情况类似,进行逐元素相乘然后求和,这个和值就是该特定平移位置下的卷积结果。然后,这个滤波器在图像上滑动,直到与图像的每一个位置都进行卷积运算。

为了更直观地理解,假设滤波器是一个“十字形”图案,而图像中也存在一个十字形特征。当滤波器与图像特征部分重叠时,卷积输出一个正值;当完全重合时,输出值最高(图中显示为深紫色);随着滤波器滑离该特征,输出值逐渐降低。最终,得到的卷积特征图(或称热图)会在图像中存在对应特征的位置呈现高亮区域。

二维卷积的数字示例

让我们用具体数字演示二维卷积。这里有一个滤波器 W,我们将其应用到输入图像上。

以下是单次卷积操作的步骤:

  1. 将滤波器 W 放置在输入图像的左上角。
  2. 进行逐元素乘法。
  3. 对重叠区域所有元素的乘积结果求和。
  4. 将求和结果填入输出特征图的对应位置。在本例中,这个值为4。

图中左侧展示的滤波器是一个实际用于图像处理的真实滤波器,它是一个边缘检测器。为了展示运行此滤波器如何生成有意义的特征图,这里使用了一张黑白照片。将此滤波器滑动遍历整个图像后,卷积运算的结果生成了一幅新图像,其中清晰地检测出了该滤波器设计要寻找的特征——即图像的边缘。


核心要点总结

最后,我们再次强调二维卷积在特征提取中的作用。在卷积神经网络中,一个滤波器(本例中是一个圆形)在图像上从左到右、从上到下移动。

当滤波器与图像中与之对应的特征(如蓝色圆形)重叠时,会产生一个高幅值的“热点”,在右侧的热图中表现为高卷积值。而当滤波器与不匹配的形状重叠时,卷积运算的输出值则较低。

由此可见,这个圆形滤波器在扫过图像的过程中,能够突出显示特定特征,并在右侧形成特征图。这些特征图可以被网络的上游层利用,以理解输入图像内部的层次化属性和特征。

本节课总结:我们一起学习了卷积运算的核心原理。我们从一维信号的卷积定义和计算过程开始,理解了其通过滑动匹配来提取特征的机制。然后,我们将这一概念扩展到二维空间,详细讲解了滤波器如何在图像上滑动并进行乘加运算以生成特征图。通过边缘检测器的实例,我们看到了卷积操作如何从原始图像中提取出有意义的特征(如边缘),这些特征图构成了卷积神经网络理解视觉信息的基础。

032:卷积层的核心组件 🧩

在本节课中,我们将深入探讨卷积神经网络(CNN)中卷积层的核心组件。这些组件是系统从图像中提取有意义特征的基础。我们将逐一介绍卷积层、激活函数、池化层和全连接层。首先,让我们从卷积层开始。

卷积层详解

上一节我们介绍了卷积神经网络的基本概念,本节中我们来看看卷积层的具体构成。卷积操作是核心,但在设计系统时,用户可以选择卷积的多个特征,包括卷积核大小、卷积步长和卷积核数量。

卷积核大小

卷积核大小如其字面意思所示。之前展示的卷积操作通常使用 3x3 的配置,即卷积核为 3x3。这个卷积核在图像上滑动,生成特征图。

你也可以改变卷积核的大小。例如,右侧展示了一个 5x5 的卷积核。更大的卷积核可能包含更多关于其搜索特征的信息,从而生成不同的特征图。

通常,卷积核大小在 3x3 到 7x7 之间。经验法则是,卷积核应足够大以捕捉小的局部特征(例如空间中的边缘),但不应过大以至于同时寻找多个复杂特征(例如一个圆形和一个三角形)。这种对应关系应让网络更高层来处理。

卷积步长

卷积步长定义了卷积核每次移动的距离。之前展示的是步长为 1 的情况,这意味着卷积核每次移动一个像素,从而生成特征图。

如果增加步长,卷积核在图像上滑动时会跳过更多像素。例如,右侧展示了步长为 2 的情况,卷积核每次移动两个像素。这会导致生成的特征图尺寸变小。

步长有助于通过下采样输入来减少计算负载。

在神经网络中,常见的步长范围是 1 到 2,有时会稍高,但 1 到 2 非常普遍。

卷积核数量

卷积核数量决定了网络在每一层中寻找的独特特征或过滤器的数量。

在这个特定示例中,展示了六个基本构建块(如六边形、矩形、圆形等)。为了在各自的特征图中隔离出所有这些特征,你需要为每一个配备一个卷积核。你可以拥有比这更多的卷积核。

核心思想是,卷积核数量决定了在输入上运行的独特特征检测器的数量。

这些就是卷积层的核心组件。我想换个角度展示一下:对于我们使用的每个卷积核,我们都会生成一个特征体积,并传递给网络的更高层。

如果我们这里有一个单独的卷积核(例如提取红色特征图),同时有另一个卷积核(例如紫色)在输入上运行并生成自己独特的特征图,那么对于你拥有的所有不同卷积核,这个过程会持续进行。这样,你就构建了一个特征图堆叠而成的体积,作为输入馈送到网络的下一层。

处理输入体积

回想之前的玩具示例,我们有第二层卷积核在特征图上运行。因此,需要在特征图堆叠上运行的卷积核,也必须具有一定的深度,以覆盖馈送到该层作为输入的所有特征图。

这一点在第一层也同样成立。尽管我们一直将输入图像视为单通道(例如灰度)图像,但彩色图像实际上有三个通道:红色、绿色和蓝色通道。这些通道共同定义了每个像素的颜色。

第一层的卷积核在处理输入图像时,需要具有对应于每个颜色通道的权重。因此,你可以将这些卷积核视为在每个输入通道中都具有二维范围,这样每个卷积核都对应一个深度为 3(对应三个通道)的堆叠。

所以,在任何情况下,这些卷积核主要都是在输入体积上运行,尤其是在进行卷积并构建了特征图堆叠之后。

卷积操作总结

为了将这一切放回我们原始动画的上下文中,当我们滑动这个卷积核时,我们实际上是在操作一个小立方体。例如,一个 3x3x3 的卷积核,其权重对应于图像输入的每个切片(通道)。图像输入可能是 9x9x3,其中 3 对应三个颜色通道。

这个操作的结果是,我们仍然进行逐元素相乘然后求和,从而为该特定卷积核得到一个单一的二维特征图。

这个动画总结了我所讨论的卷积层操作。左侧是一个输入体积,在本例中有三个切片。你可以将其视为具有红、绿、蓝通道的输入图像,我们称之为输入 I

我们使用类似 Python 的数组表示法来索引所有这些切片。顶部是 I[:, :, 0],这表示输入的第 0 个索引(即第一个)切片的所有行和所有列,可能是红色通道。下面是 I[:, :, 1](绿色通道)和 I[:, :, 2](蓝色通道)。

我想让你理解的是,卷积核 W0 具有对应于输入所有相应通道中空间位置的权重。因此,卷积核实际上是三维的,它具有二维空间范围和深度范围。

你仍然是在进行卷积核中所有值与输入中相应值的逐元素相乘,求和,然后将结果存入对应于卷积核 0 的特征图中的单个值。

对于第二个卷积核 W1,你执行完全相同的操作。但该卷积求和的结果被存入第二个特征图 feature map 1 中的相应位置。


本节课中我们一起学习了卷积神经网络中卷积层的核心组件。我们详细探讨了卷积核大小、步长和数量的选择及其影响,理解了卷积核如何在多通道输入体积上操作以生成特征图堆叠。这些组件是构建有效 CNN 以从图像中提取特征的基础。

033:激活函数

在本节课中,我们将要学习神经网络中的第二个核心组件——激活函数。我们将了解它的作用、常见的类型,以及它们如何影响网络的学习能力。


上一节我们介绍了卷积操作,它负责从输入数据中提取特征。本节中我们来看看,卷积运算得到的数值如何通过激活函数进行转换,从而赋予神经网络强大的非线性表达能力。

回想一下将滤波器应用于图像输入的示例。我们进行逐元素相乘,然后求和,这就是卷积操作。求和的结果被放置在输出特征图的一个像素位置上。实际上,特征图中每个位置都代表一个人工神经元。它接收输入,并可能将其转换为不同的值,传递给网络中的后续层。

如果我们放大其中一个红色圆圈,这就是一个单独的人工神经元。它接收一些输入,这里我们展示三个输入值 X1X2X3。对于每个输入,都有一个对应的权重 W1W2W3。用这些权重与输入进行卷积的结果是一个和 A,它同样是逐元素相乘后的总和。

但通常我们不会直接将 A 传递给网络的后续层,而是会应用一个函数来处理这个输入,以产生不同类型的输出。

这是什么意思呢?一种最简单的形式是线性激活。到目前为止,我在展示卷积操作时,一直默认使用的就是这种形式:将卷积求和得到的值 A 直接输出。因此,线性激活函数对值 A 应用后的结果就是 A 本身,输入到输出没有发生任何变换。

然而,在设计神经网络时,我们实际使用的是非线性激活函数。你可能在逻辑回归或多层感知机中见过它们。这些非线性激活函数意味着,对于输入到人工神经元的 A,我们不是原样输出,而是以非线性的方式转换这个值。这极大地增强了神经网络的功能容量,因为它允许网络表示输入特征之间的非线性关系。这对于分类、分割等实际应用中的特征提取非常强大。

以下是两种经典的非线性激活函数:

  • Sigmoid函数:对于给定的输入值 A,它将结果压缩在 0 和 1 之间。在逻辑回归中,可以将其视为产生一个介于 0 和 1 之间的概率输出。
    • 公式σ(A) = 1 / (1 + e^(-A))
  • 双曲正切函数:它接收某个值 A,并进行类似的压缩,但将值压缩在 -1 和 1 之间。
    • 公式tanh(A) = (e^A - e^(-A)) / (e^A + e^(-A))

虽然这些非线性激活函数在神经网络中曾非常强大,但它们也带来了一些问题。如果你注意到这些图的顶部或底部,会看到非常平坦的区域。在这些区域,即使输入值 A 变化很大,输出结果的变化也非常小。这意味着当数值以截然不同的方式变化时,神经网络能获得的信号非常微弱。这有时会导致网络训练停滞,不利于学习进行分类所需的特征表示。

因此,人们开始使用另一种类型的非线性激活函数。

修正线性单元 是一种非常简单的函数:对于输入 A 的任何负值,函数应用的结果是 0;如果输入值 A 大于 0,则返回 A 本身。其非线性特性非常简单,就是取输入值 A 和 0 之间的最大值。

  • 公式/代码ReLU(A) = max(0, A)

当这种非线性被引入到网络每一层的所有神经元时,网络表示输入信息的能力会显著提高。


本节课中我们一起学习了激活函数。我们了解到,激活函数是人工神经元中对卷积结果进行非线性变换的关键组件。我们介绍了线性激活、Sigmoid函数、双曲正切函数以及目前更常用的ReLU函数。理解不同激活函数的特性,对于设计和优化神经网络至关重要。

034:池化层与全连接层

在本节课中,我们将学习卷积神经网络(CNN)的另外两个核心组件:池化层和全连接层。我们将了解池化层如何通过下采样来降低计算复杂度、防止过拟合并增强平移不变性。随后,我们将探讨如何通过全连接层将提取到的高级特征映射到最终的分类结果。

池化层

上一节我们介绍了卷积层和激活函数,本节中我们来看看池化层。池化层通常应用在卷积和激活操作之后,其作用是减小传递给网络后续层的输入尺寸。

池化操作降低了整个网络的计算复杂度,使其更易于训练。它还能对抗过拟合,并通过提供一定程度的平移不变性来提升模型鲁棒性。平移不变性是指,无论某个特定特征出现在图像的左上角、中间还是右下角,神经网络都能正确识别它。这意味着,无论该特征在图像中如何平移,神经网络都能判断其身份。

那么这是如何实现的呢?池化层也有一个类似卷积核的“过滤器”,但它不进行卷积运算,而是将过滤器窗口内的所有值聚合为一个单一值。

以下是池化操作的两种常见方式:

  • 最大池化:取窗口内的最大值。
  • 平均池化:取窗口内所有值的平均值。通常更常用的是最大池化。

以一个2x2的窗口、步长为2的最大池化为例。这个2x2的窗口从左上角开始,依次移动到右上角、左下角和右下角。在每个窗口中,只取最大值,并将该值赋给输出中对应的位置。

例如,在左上角窗口中,最大值是6,那么输出对应位置就是6。右上角窗口最大值是8,输出就是8。左下角和右下角则分别是3和4。

关于平移不变性,可以这样理解:假设左上角窗口内有一个6,无论这个6具体位于该窗口的左上角还是右下角,最大池化操作都会将这个6传递到输出中。这样,神经网络就不必过分关心特征在局部区域内的精确位置,只要该信息对最终分类不是必需的,模型就能忽略它。因此,最大池化能在一定程度上提取强烈的激活信号,同时忽略其精确位置信息。

全连接层

在一个典型的卷积神经网络中,我们堆叠了之前介绍过的组件:首先通过卷积层构建特征图,接着是激活函数(图中未显示),然后进行最大池化来下采样特征图。这些操作(卷积、激活、池化)会反复堆叠多次,从而构建出图像特征的高级表示。

那么,这些高级特征是如何被处理并最终得出分类结果的呢?答案就是使用类似于之前学过的多层感知机。在CNN中,我们称这些层为全连接层

最简单的形式是一个全连接读出层。例如,在一个手写数字分类任务中,你会有10个神经元,分别对应0到9这10个输出类别。

将这些神经元连接到网络中最后一个池化层的方法,是首先将池化层的输出展平向量化。假设经过一系列卷积、激活和池化操作后,最终得到一个4x4x20的特征体积。你需要将这个三维体积转换成一个一维向量。

然后,读出层中的每个神经元都与这个向量化后的高级特征表示中的所有上游元素全连接。这意味着每个神经元都有一组权重,连接到向量中的每一个元素。图中仅展示了对应数字“0”类别的单个读出神经元的连接,但实际上,对应“1”、“2”等其他类别的神经元也同样会连接到该向量的所有元素。

与多层感知机类似,你也可以在CNN中使用多层全连接神经元。例如,可以在池化层和最终的分类读出层之间,加入一个或多个中间隐含层。这些隐含层的神经元与上游池化层展平后的向量全连接,而最终的分类读出神经元则与这个隐含层全连接。这种结构能够学习更复杂的元特征表示,从而有助于解决分类问题。

总结

本节课中,我们一起学习了卷积神经网络的两个关键部分。我们了解了池化层(特别是最大池化)如何通过下采样来减少数据维度、控制过拟合并提供平移不变性。随后,我们探讨了全连接层如何将卷积和池化后得到的高级特征图展平,并通过类似于传统神经网络的结构,最终映射到具体的分类输出。池化层和全连接层的结合,使得卷积神经网络能够高效地从图像中提取并理解复杂的模式。

035:网络训练 🧠

在本节课中,我们将学习如何训练一个卷积神经网络。我们将回顾网络的前向传播过程,并详细介绍如何使用梯度下降法来优化网络参数,使其能够准确预测输入图像的标签。


上一节我们介绍了卷积层和池化层的基本操作。本节中,我们来看看如何通过梯度下降来训练整个网络。

我们假设有一组输入图像。每张输入图像都有一个对应的真实标签。对于一个二元分类任务,例如糖尿病视网膜病变检测,标签可以是+1(表示不健康的视网膜)或-1(表示健康的视网膜)。

对于每一张输入图像 ( I_n )(第n张图像),我们将其输入卷积神经网络进行处理。以下是处理步骤:

以下是网络前向传播的核心步骤:

  1. 第一层卷积:使用第一层的滤波器(表示为 ( \phi_1, \phi_2, ..., \phi_K ),共K个)对输入图像 ( I_n ) 进行卷积操作。该操作由函数 ( F ) 表示,其输出是第一层特征图 ( M_n )。公式表示为:
    [
    M_n = F(I_n; \phi_1, \phi_2, ..., \phi_K)
    ]

  2. 第二层卷积:使用第二层的滤波器(表示为 ( \psi_1, \psi_2, ..., \psi_K ))对第一层特征图 ( M_n ) 进行卷积操作。输出是第二层特征图 ( L_n )。公式表示为:
    [
    L_n = F(M_n; \psi_1, \psi_2, ..., \psi_K)
    ]

  3. 第三层卷积:使用第三层的滤波器(表示为 ( \omega_1, \omega_2, ..., \omega_K ))对第二层特征图 ( L_n ) 进行卷积操作。输出是第三层特征图 ( G_n )。公式表示为:
    [
    G_n = F(L_n; \omega_1, \omega_2, ..., \omega_K)
    ]

  4. 全连接层与分类:最终的特征图 ( G_n ) 被送入一个或多个全连接层(表示为函数 ( \mathcal{L} )),该层具有权重矩阵 ( W )。全连接层将特征图转换为该输入图像的预测标签 ( \hat{l}_n )。公式表示为:
    [
    \hat{l}_n = \mathcal{L}(G_n; W)
    ]

整个网络的目标是找到一组参数(所有卷积层的滤波器和全连接层的权重),使得网络的预测标签 ( \hat{l}_n ) 尽可能接近真实标签 ( l_n )。

我们通过设置一个损失函数来衡量预测与真实标签之间的差异。对于二元分类任务,通常使用二元交叉熵函数。我们的目标是最小化所有输入图像上的平均损失,这个平均损失被称为经验风险函数 ( E )。

该风险函数是所有层滤波器参数 ( \phi, \psi, \omega ) 和全连接层权重 ( W ) 的函数。为简化表示,我们将所有这些参数统称为 ( \theta )。训练的目标就是找到能够最小化 ( E(\theta) ) 的参数 ( \theta )。一旦找到,我们就得到了一个可以输入图像并正确预测其是否患有糖尿病视网膜病变的系统。


由于经验风险函数 ( E(\theta) ) 通常非常复杂且存在于高维空间,我们使用梯度下降法来寻找最优参数。

梯度下降的核心思想是:在当前的参数估计点,计算风险函数的梯度(即多维斜率),然后沿着梯度的反方向更新参数,从而逐步降低损失值。

梯度下降的更新公式如下:
[
\theta_{\text{new}} = \theta_{\text{old}} - \alpha \cdot \nabla E(\theta_{\text{old}})
]
其中:

  • ( \alpha ) 是学习率,决定了每次更新的步长。
  • ( \nabla E(\theta_{\text{old}}) ) 是在当前参数 ( \theta_{\text{old}} ) 处计算的风险函数梯度。

这个过程可以形象地理解为“下山”:我们根据当前位置的坡度(梯度)方向,决定下一步往哪里走才能更快到达山谷(损失最小值)。


在实际操作中,计算整个数据集上的真实梯度(称为“批量梯度下降”)计算量巨大。因此,我们通常使用随机梯度下降或其变种。

随机梯度下降的核心是:在每次参数更新时,我们不使用全部数据来计算梯度,而是随机抽取一个数据子集(称为“小批量”或“mini-batch”),仅计算该子集上的梯度,并用这个估计的梯度来更新参数。

这种方法在实践中非常有效,因为它能以更快的速度引导我们找到接近最优的解,同时避免了巨大的计算开销。


本节课中我们一起学习了卷积神经网络的训练流程。我们回顾了从输入图像到输出预测的前向传播步骤,明确了训练的目标是最小化经验风险。接着,我们介绍了使用梯度下降法来优化网络参数的原理,并解释了在实际中更高效的随机梯度下降方法。通过这个过程,网络能够自动学习到从图像中提取有效特征并做出准确预测的能力。

036:迁移学习与微调 🧠

在本节课中,我们将要学习迁移学习(Transfer Learning)的概念及其在卷积神经网络(CNN)中的应用。迁移学习是一种强大的技术,它允许我们利用在一个大型数据集上预训练的模型,来加速和提高另一个相关任务的学习效果。


图像特征分层表示的优势

上一节我们介绍了卷积神经网络如何分层提取图像特征。本节中我们来看看这种分层表示的主要优势。

卷积神经网络按顺序提取图像特征。这种分层表示的一大优势在于,通过学习和共享图像高层部分(即这些高层图案)中的统计相似性,我们能更好地利用所有训练数据。

这意味着,假设你正在构建一个手写数字分类系统,需要区分数字9和7。由于数字9和7共享一些低层元素,你可以通过观察数字7来学习数字9的基本构建模块。因此,在整个训练集中,你可以从其他样本中学到很多知识,以帮助你分类感兴趣的样本。这非常强大。

一个相关的要点是,如果你每次都试图独立学习某个高层过滤器,无异于重复造轮子。例如,一个高层“7”特征和一个高层“9”特征。当你引入一个新类别进行分类时,你将无法利用已学到的低层特征知识来帮助你构建表示以识别和分类这个新类别。这正是卷积神经网络的一个特别强大的特性。

因此,能够利用网络在低层学到的知识,并将这些信息应用到网络的新特定任务中,这个过程就称为迁移学习


什么是迁移学习?

在迁移学习中,你需要一个已经在先前大型数据库分类任务(例如ImageNet图像分类竞赛)上训练好的网络。然后,你在感兴趣的领域进行额外的训练。

以糖尿病视网膜病变诊断为例。在训练神经网络时,你输入一张视网膜图像。这张图像被网络的所有层消化并提取特征,然后在网络顶部做出分类决策,判断视网膜是健康还是有病变。

事实证明,在这篇论文以及大多数同类研究中,他们使用了在ImageNet数据上预训练网络的权重进行初始化,这极大地提高和改善了模型性能。

原因在于,顶层的特征(有时仅指分类器中的全连接层)是高度专门化于特定任务或特定领域的。而低层的特征,即这些包含基本构建模块的层,对所有图像来说是通用的。

一旦你从一个大数据集中学到了这些低层特征,就不一定需要重新学习它们,因为视网膜图像中的低层构建模块同样出现在猫、汽车等其他图像中。因此,你可以通过重用网络、将另一个网络在不同图像分类任务中学到的知识迁移到当前感兴趣的分类任务上,来加速整个训练过程。这就是所谓的迁移学习。


低层特征的通用性

为了更清晰地阐明这一点,低层特征对所有图像是通用的。

在左侧,我想向你展示卷积神经网络第一层的过滤器。这些是小型边缘检测器,用于提取不同方向的边缘。你可以看到非常相似的感受野,或者说能激活右侧真实猴子视觉皮层中单个神经元的图像特征。

一个真实的哺乳动物视觉系统同样提取这些低层模式来构建其自身的表示,进而在生物大脑中构建对真实世界的感知。由此可见,这些特定的低层特征提取器具有某种非常基础和根本的特性。这正是迁移学习过程所利用的原理。


总结

本节课中我们一起学习了迁移学习。我们了解到,卷积神经网络的分层结构使得低层特征(如边缘、纹理)具有通用性。通过利用在大型数据集(如ImageNet)上预训练的网络权重,我们可以将这些通用的低层知识迁移到新的、数据可能较少的特定任务(如医学图像诊断)中。这不仅能显著加快训练速度,还能提高模型在新任务上的性能,是一种非常高效且强大的机器学习技术。

037:使用PyTorch实现CNN 🧠

在本节课中,我们将学习如何使用PyTorch实现卷积神经网络(CNN)。CNN是计算机视觉领域取得重大突破的核心技术,几乎在所有先进的视觉模型中都有应用。我们将介绍CNN的主要构建模块,并简要了解PyTorch的视觉库TorchVision,它提供了许多预训练的CNN模型和权重,方便我们在自己的应用中使用。

计算机视觉与CNN 🖼️

计算机视觉是深度学习取得最大成功的领域之一。卷积神经网络(通常缩写为CNN)构成了几乎所有先进视觉模型的主要部分。

上一节我们介绍了深度学习的基本概念,本节中我们来看看如何在PyTorch中构建CNN。

CNN的主要构建模块 🧱

以下是CNN在PyTorch中的主要构建模块:

  1. 卷积层:用于提取图像特征。
  2. 池化层:用于降低特征图的空间维度。
  3. 激活函数:如ReLU,用于引入非线性。
  4. 全连接层:用于最终的分类或回归任务。

使用TorchVision加载预训练模型 📚

TorchVision是PyTorch的视觉库。通过TorchVision,我们可以轻松加载许多先进的CNN及其预训练权重,用于我们自己的应用程序。

作业任务:构建自己的CNN 🛠️

在作业中,你将构建自己的CNN。与多层感知机相比,CNN的性能应该会略有提升。

# 示例:一个简单的CNN模型结构
import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.fc = nn.Linear(32 * 14 * 14, 10)
    
    def forward(self, x):
        x = self.pool(nn.functional.relu(self.conv1(x)))
        x = x.view(-1, 32 * 14 * 14)
        x = self.fc(x)
        return x

调整架构以提升性能 ⚙️

尝试调整我们的架构,看看你能达到什么样的性能。

# 尝试调整层数、滤波器数量等参数
class ImprovedCNN(nn.Module):
    def __init__(self):
        super(ImprovedCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 64, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(128 * 7 * 7, 256)
        self.fc2 = nn.Linear(256, 10)
    
    def forward(self, x):
        x = self.pool(nn.functional.relu(self.conv1(x)))
        x = self.pool(nn.functional.relu(self.conv2(x)))
        x = x.view(-1, 128 * 7 * 7)
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        return x

总结 📝

本节课中我们一起学习了如何使用PyTorch实现卷积神经网络(CNN)。我们介绍了CNN的主要构建模块,包括卷积层、池化层、激活函数和全连接层。我们还了解了如何使用TorchVision加载预训练的CNN模型和权重。最后,我们通过作业任务和架构调整,探讨了如何构建和优化自己的CNN模型,以提升性能。

038:词向量概念介绍 📖

在本节课中,我们将要学习自然语言处理中的一个核心概念——词向量。词向量是将词汇映射到向量空间的技术,使得语义相近的词汇在向量空间中的位置也相近。这一概念是后续使用神经网络模型处理自然语言的基础。


从地图到词向量 🌍

上一节我们介绍了自然语言处理的基本背景,本节中我们来看看词向量这一核心概念是如何通过类比来理解的。

想象一张世界地图,上面有不同符号标记的点,例如正方形和三角形。如果地图上的两个点物理位置接近,那么它们所代表的地区特征(如文化、地理、历史)也可能相似。反之,相距较远的点则代表特征迥异的地区。地图上的每个位置可以用两个数字(经度和纬度)来表示,这构成了一个二维空间。在这个空间中,位置的接近程度反映了地区的相似性。

我们将类似的概念应用于词汇。每个词汇将被映射到一个多维空间中的一个点(向量)。在这个向量空间中,两个词的距离越近,它们的语义就越相似或相关;距离越远,则语义差异越大。

以下是这一概念的核心表述:

  • 核心概念:每个词被映射为一个向量。语义相似的词,其向量在空间中的距离较近;语义不同的词,其向量距离较远。

词向量的基本思想 💡

上一节我们通过地图类比理解了词向量的空间相似性概念,本节中我们来具体看看其形式化定义。

我们有一个包含 V 个词的词汇表:word1, word2, ..., wordV。目标是为每个词学习一个向量表示。最初为了便于理解,我们设想将其映射到二维空间(类似经纬度),但实际应用中,词向量的维度通常远高于二维。

学习的目标是:让语义相近的词(如“猫”和“狗”)的向量在空间中彼此靠近;让语义无关的词(如“猫”和“宇宙”)的向量彼此远离。这种将词映射为向量的技术常被称为 Word2Vec

下图展示了词向量空间的一个示例(尽管文字较小,但可以看出位置邻近的词确实语义相关):


为什么需要词向量? 🔢

上一节我们了解了词向量的目标,本节中我们探讨为什么需要将词表示为向量。

词汇本身不是数字,而是符号。然而,我们用于建模的机器学习算法通常需要数值输入。因此,我们需要一种方法将每个词转换为数值形式。

词向量正是提供了这种映射。通过将每个词表示为一个数值向量(空间中的一个点),我们就能对语言进行数学上的分析和建模。关键在于,这种表示方法捕捉了词汇间的语义关系,相似的词具有相似的向量表示。

以下是词向量价值的总结:

  • 核心需求:算法处理需要数值输入,而词是符号。词向量实现了从符号到数值向量的映射。
  • 关键特性:该映射保留了语义信息,语义相似性体现为向量空间的邻近性。

学习词向量 🧠

上一节我们明确了词向量的作用,本节中我们简要说明如何获得这些向量。

词向量的映射不是预先定义的,而是通过机器学习模型从大量文本数据中学习得到的。在后续的自然语言处理模型讨论中,学习每个词到其向量的映射将是一个核心组成部分。

有多种方法可以实现这种学习(例如,我们之后会介绍的特定神经网络架构)。重要的是,我们通常学习的是高维向量(维度 > 2),以捕捉更丰富、更复杂的语义关系。


总结 📝

本节课中我们一起学习了词向量的基本概念。

  • 我们通过地图的类比引入了概念:将词映射到向量空间,用空间距离表示语义相似度。
  • 我们理解了词向量是将非数值的词汇转化为算法可处理的数值向量的关键步骤。
  • 我们知道了这种映射是通过数据驱动的方式学习得到的,并且通常是高维的。

在接下来的课程中,我们将具体介绍如何实现这种词向量的学习,并如何将其应用于自然语言处理任务中。

039:从词到向量 📖➡️🔢

在本节课中,我们将学习一个自然语言处理中的核心概念:如何将文本中的单词转换为计算机可以处理的数字形式,即“词向量”或“词嵌入”。

上一节我们介绍了将单词映射到向量的基本想法。本节中,我们将更深入地探讨这一概念,并提供更多细节。

什么是词向量(Word to Vector)?

将单词建模或映射为向量的想法被称为 Word to V(词向量)。这是一个非常自然且广泛使用的术语。与每个单词相关联的向量,有时也被称为一个 嵌入。这主要是为了引入一些你在阅读相关文献时可能会遇到的术语。

嵌入的概念,是指将单词“嵌入”到某个特征空间中。回想我们之前看过的地球地图图片,那是一个二维空间。在那个例子中,我们将每个单词嵌入到一个二维空间中。因此,词向量这个概念有时也被称为词嵌入。

核心概念与符号表示

让我们用 Wᵢ 来对应一个单词,它只是一个代表特定单词的符号。用 Wᵢ 表示我们词汇表中的第 i 个单词。

词嵌入的核心思想是,我们将取第 i 个单词,并将其映射到一个 M 维向量。这个向量由 M 个数字组成。在我们之前看过的二维地图例子中,M 等于 2。但我们不必局限于二维,通常 M 可能是 100 或 200,这取决于我们要解决的问题。

以下是词向量概念的关键点:

  • 映射关系:将词汇表中的每个单词映射到一个 M 维向量。
  • 维度 M:向量维度 M 的值取决于我们选择的具体问题,我们可以选择不同的 M 值。

词汇表与码本

从概念上理解,假设我们有一个由 V 个单词组成的词汇表。那么 W₁ 代表单词 1,W₂ 代表单词 2,一直到 Wᵥ 代表第 V 个单词。这就是我们的词汇表。

当我们实现词向量映射后,我们将得到一个从词汇表中每个单词(W₁ 到 Wᵥ)到向量的映射。我们将这个向量称为 C₁(对应单词 1),C₂(对应单词 2),以此类推。每个向量 Cᵢ 都是 M 维的。

在完成学习之后,我们会得到一个被称为 码本 的集合,它是一组与词汇表中 V 个单词相关联的 V 个向量。每个向量 Cᵢ 都与单词 Wᵢ 相关联。

我们希望实现的目标是:如果两个单词彼此相似(同义词或相关词),我们希望这两个单词的向量在这个 M 维空间中是相似或彼此接近的。我们将基于一个大型文本语料库来学习这些向量 C₁Cᵥ。通过学习过程,我们的目标是实现:在这个 M 维向量空间中的“邻近性”概念,与相关单词的“关联性”概念联系起来。

一个简单的例子

考虑一个包含六个单词的文本示例。通常,我们会考虑一个代表 句子开始 的标记(BOS),以及一个代表 句子结束 的标记(EOS),这样自然语言模型就知道句子何时开始和结束。

在这个例子中,词汇表中的六个单词被映射为六个“代码”。C_{W₁} 对应第一个单词的代码,C_{W₆} 对应第六个单词的代码。

一旦我们实现了这种映射,即我们可以将词汇表中的实际单词映射为数字(在这个例子中由六个 M 维向量表示,这些向量当然由数字组成),我们就为在计算机上进行分析做好了准备,因为现在它已经可以进行数学运算了。

如何学习词向量?

现在我们需要思考的问题是:我们如何实际学习这些词向量?我们如何学习这些词向量,以便它们能让我们实现自然语言处理的目标?

随着课程的深入,我们将开始开发多种不同的方法来实现这一点。事实上,学习单词与向量之间关系的方法不止一种,而是有多种。这些不同的方法通常会产生非常相似的结果。这一点很重要,因为它意味着这个概念非常稳健,并不那么依赖于你使用的特定方法。有多种方法都能产生非常有效的结果。

接下来,我们将开始深入探讨学习词嵌入的技术。


本节课总结:在本节课中,我们一起学习了自然语言处理的基础——词向量(Word to Vector)或词嵌入(Word Embedding)的概念。我们了解了将单词映射为多维向量的必要性,介绍了相关的术语(如码本),并明确了学习词向量的目标:让语义相近的单词在向量空间中也彼此接近。最后,我们指出了存在多种学习词向量的有效方法,为后续课程奠定了基础。

040:词嵌入应用示例

在本节课中,我们将学习如何利用词嵌入(Word Embeddings)或词向量(Word Vectors)进行自然语言处理分析。我们将探讨如何将文本映射为向量,并应用卷积神经网络(CNN)的概念来处理这些向量数据。


概述

词嵌入的核心思想是将每个单词映射到一个向量。一旦我们获得了这些词向量,就可以将任何由N个单词组成的文档转换为N个M维向量。这个转换过程使我们能够将自然语言转化为数值形式,从而应用各种分析方法,例如情感分析、问答系统和语言翻译。

上一节我们介绍了词嵌入的基本概念,本节中我们来看看如何具体应用这些词向量,特别是如何结合卷积神经网络来处理文本数据。


从文本到向量

首先,我们假设已经学习到了一个“码本”(Codebook),它建立了从每个单词到其对应向量的映射关系。虽然我们尚未讨论如何学习这种映射,但理解其应用场景有助于我们后续理解学习过程。

  • 文档表示:一个包含N个单词的文档(W1, W2, ..., WN)可以通过词嵌入映射为N个M维向量。
  • 分析基础:将文本转化为向量后,我们就能够对其执行多种分析任务。

应用卷积神经网络(CNN)于文本

在图像处理中,我们介绍了卷积神经网络(CNN)的概念。现在,我们将探讨如何在文本处理的语境下应用CNN。

回忆一下,CNN通过一个滤波器在数据上滑动来进行操作。在图像中,这是在二维空间上的滑动。对于文本,我们将使用一维卷积。

文本卷积滤波器

以下是文本CNN中滤波器的关键特性:

  • 滤波器尺寸:每个滤波器的尺寸为 M × D
    • M 是词向量的维度(高度)。
    • D 是滤波器覆盖的单词数量(长度或“时间”步长)。
  • 操作方式:假设我们有一个长度为3(D=3)的滤波器。这个滤波器对应一个与三个连续单词相关的概念。我们将这个滤波器沿着文本序列滑动。当滤波器所代表的概念与文本中当前位置的三个单词高度相关时,滤波器和该处文本会产生活跃的响应(高相关值)。

卷积与池化过程

通过卷积操作,我们将原始文本(N个M维向量)转换为一个新的表示。

  1. 卷积输出:对于每一个滤波器,我们在文本的每一个可能位置进行卷积操作,会得到一个包含N个数值的序列。这个序列反映了该滤波器与文本在不同位置上的匹配程度。如果我们有K个不同的滤波器,最终会得到一个 N × K 的矩阵。
  2. 最大池化:为了从整个文本中提取最显著的特征,我们通常会对卷积输出进行池化操作。一种常见的方法是最大池化(Max Pooling)
    • 对于上述 N × K 矩阵的每一列(对应一个滤波器),我们取该列所有N个位置中的最大值。
    • 这个最大值代表了该滤波器与整个文本最强烈的关联程度。
  3. 最终特征向量:经过最大池化后,我们得到一个 K维向量。这个向量概括了整个文档相对于K个不同“概念”滤波器的特征。

进行分类决策

一旦我们将文本压缩为这个K维的特征向量,就可以利用已有的工具进行分类预测。

  • 下游模型:这个K维向量可以作为特征,输入到逻辑回归(Logistic Regression)或多层感知机(Multilayer Perceptron)等模型中。
  • 决策流程:模型将基于这个向量表示来做出最终的分类决策(例如,判断文档的情感是正面还是负面)。

关于监督学习的挑战

上述流程有一个重要前提:需要带标签的数据进行学习

  • 标签需求:为了训练CNN(包括其中的词向量和滤波器参数),我们需要大量已知标签的文档(例如,明确标注了情感的影评)。
  • 成本问题:人工为海量文档标注标签是非常昂贵和耗时的。这限制了完全基于监督学习方法来学习词嵌入的可行性。

因此,在自然语言处理中,我们特别关注能够从无标签数据中学习的方法。这意味着我们可以直接利用原始文本(无需人工标注)来学习词向量表示。接下来,我们将探讨这类强大的无监督或自监督学习方法。


总结

本节课中我们一起学习了词向量的应用方法。我们了解到,通过词嵌入将文本转化为向量后,可以借助卷积神经网络(CNN)提取文本特征。具体过程包括:使用一维卷积滤波器在词向量序列上滑动,然后通过最大池化得到固定长度的文档特征向量,最后利用该向量进行分类预测。同时,我们也认识到完全依赖带标签数据学习词向量成本高昂,从而引出了对无监督学习方法的兴趣。在下一节,我们将探讨如何直接从无标签文本中学习这些词向量。

041:文本的神经网络模型 🧠

在本节课中,我们将学习如何利用神经网络模型来学习词向量(Word Vectors)。我们将探讨如何将词汇表中的每个单词映射到一个向量,并利用这些向量进行文本分析。核心在于,我们希望通过无监督的方式,从大量未标注的文档中学习这些词向量,使得每个单词的向量能够预测其周围可能出现的单词。

词向量学习的基本概念

上一节我们介绍了词向量的概念,即将单词映射为向量以便于计算机分析。本节中,我们来看看如何实际学习这些词向量。

我们的目标是学习一个码本(Codebook),即一组向量,其中词汇表中的每个单词都对应一个向量。我们希望在不依赖人工标注数据的情况下完成学习,仅使用大量未标注的原始文档。

学习词向量的核心思想是:每个单词的向量应能预测其周围单词的出现。例如,如果你理解语言,给定一个单词,你就能说出与之相关的、可能在文档中邻近出现的单词。因此,我们将构建模型,使其能够根据给定单词的向量,预测其周围的单词。好的词向量应能有效支持这种预测。

神经网络模型架构

为了学习词向量,我们将使用我们已经掌握的工具——多层感知机(Multilayer Perceptron)

考虑文档中的第 N 个单词 ( W_n )。其对应的词向量记为 ( C(W_n) ),这是一个 M 维向量,其分量是 ( C_1, C_2, ..., C_M )。这个向量将作为多层感知机的输入。

以下是模型的基本架构:

  1. 输入层:输入是单词 ( W_n ) 的 M 维词向量 ( C(W_n) )。
  2. 隐藏层:输入向量通过权重矩阵 ( W ) 和偏置向量 ( b ) 的线性变换,再经过一个非线性激活函数 ( g )(如双曲正切函数 tanh),得到一个 D 维的隐藏向量 ( H )。这个过程可以简洁地表示为:
    [
    H = g(W \cdot C(W_n) + b)
    ]
    其中,函数 ( g ) 对向量的每个分量独立操作。
  3. 输出层:隐藏向量 ( H ) 再通过另一个权重矩阵 ( U ) 和偏置向量,映射到输出层。输出层有 ( V-1 ) 个节点,其中 ( V ) 是词汇表的大小。

预测概率:Softmax 函数

模型的最终目标是量化词汇表中任意单词 ( W_i ) 出现在目标单词 ( W_n ) 周围的概率。

我们将输出层的 ( V-1 ) 个值记为 ( y_1, y_2, ..., y_{V-1} ),并始终将第 ( V ) 个输出 ( y_V ) 设为 0。然后,我们使用 Softmax 函数 来计算概率。这是一个对逻辑回归的推广。

单词 ( W_i ) 出现在单词 ( W_n ) 周围的概率由以下公式给出:
[
P(W_i | C(W_n)) = \frac{e{y_i}}{\sum_{j=1} e^{y_j}}
]
其中,我们定义 ( y_V = 0 )。这个函数的特性是,对所有可能的单词 ( W_i ) 的概率求和等于 1,符合概率的定义。

因此,这个神经文本模型的输入是一个单词的词向量,输出则是词汇表中每个单词出现在该输入单词周围的概率分布。

模型的意义与学习目标

这个模型将词向量的学习与上下文预测联系了起来。如果两个单词在语义上相关,那么它们在文本中邻近出现的概率就高。通过学习使模型能够准确预测上下文单词,我们同时也在优化词向量本身(即码本 ( C ))以及神经网络的所有参数(权重 ( W, U ) 和偏置 ( b ))。

总结:本节课我们一起学习了用于学习词向量的基本神经网络模型。我们了解了如何将单词表示为向量输入多层感知机,并通过 Softmax 函数输出其上下文单词的概率分布。这个模型为我们提供了无监督学习词向量的基础框架,通过让词向量能够预测上下文,我们使语义相近的单词在向量空间中彼此靠近。在接下来的学习中,我们将探讨如何训练这个模型并应用这些词向量。

042:Softmax函数详解 📚

在本节课中,我们将深入探讨一个在文本神经网络模型中引入的新工具——Softmax函数。我们将了解它的作用、它与之前学过的逻辑函数的联系,以及它如何将二元分类问题推广到多类别场景。


概述

上一节我们介绍了文本的神经网络模型,该模型利用了之前学习过的多层感知机。然而,在这个文本模型中,我们引入了一个新函数——Softmax,这是我们在之前讨论多层感知机时未曾见过的。

这是一个新的工具,值得花些时间来讨论它,并将其与我们之前的工作联系起来。


从二元到多元:为什么需要Softmax? 🔄

你或许还记得,当我们介绍逻辑回归和最初的多层感知机时,我们处理的是二元或二维的输出结果。

但在处理文本时,我们必须将其推广,因为我们不仅仅有两个单词。我们有一个包含 V 个单词的词汇表。因此,我们必须回答一个问题:如何计算所有可能结果的概率,而不仅仅是二元结果的概率?Softmax函数允许我们做到这一点。


Softmax:逻辑函数的推广 🧮

然而,我想强调的是,从概念上讲,这个Softmax函数与我们之前用于二元结果的逻辑函数并没有太大不同。事实上,它是逻辑函数的一个推广

为了帮助你回忆,这里再次展示了我们的文本神经网络模型。我们有一个单词,它由一个M维向量 C₁Cₘ 表示。我们通过权重矩阵 W 将该输入向量映射到隐藏单元 H,再通过权重矩阵 U 将隐藏单元映射到神经网络顶部的 V-1 个输出(y₁yᵥ₋₁)。然后,这些输出值被送入底部的函数,即 Softmax

这看起来可能很复杂,不像我们以前见过的东西。但我们将看到,它实际上并不像看起来那么陌生。

通过这个Softmax函数,我们可以量化词汇表中每个单词(单词1、单词2……单词V)出现在输入单词附近的概率。我们将通过观察真实文本来进行学习,因为我们知道一个单词及其周围的单词,即我们知道“真相”。我们的目标是学习这个由权重参数 WU 以及词向量 C 共同构成的文本神经网络模型。


深入Softmax方程

让我们花点时间讨论一下底部的Softmax方程。为了简单起见,我把它再次写在这里。

我们设定 yᵥ(对应词汇表中的第V个单词)等于0。Softmax就是底部的方程。

现在,让我们考虑一个只有两个单词的简单词汇表的情况。

在这种情况下,顶部那个看似复杂的方程会大大简化。我们只有两个输出单词,W₁ 和 W₂。

  • 单词 W₁ 的概率,给定编码 C,是逻辑函数(或Sigmoid函数)σ(y₁)。
  • 单词 W₂ 的概率是 1 - σ(y₁),即 1 / (exp(y₁) + 1)。

因此,我们的文本神经网络模型在很多方面只是逻辑模型的推广。当只有两个单词时,它就是逻辑模型的一个特例。

需要注意的是,Softmax操作本质上是逻辑函数(Sigmoid函数)的推广,适用于我们拥有 V 个单词(而非仅两个)的词汇表的情况。在只有两个单词的情况下,它直接简化为我们熟悉的Sigmoid函数。

所以,我们可以认为,在文本神经网络建模中新引入的Softmax,与我们更熟悉的逻辑回归实际上是近亲,它们密切相关。Softmax操作只是逻辑连接函数的一个推广。


总结与展望 🎯

本节课我们一起学习了Softmax函数。它虽然看起来有些新,但本质上并不是一个与已有逻辑回归概念截然不同的概念。它只是一个将二元逻辑扩展到多元分类的强大工具。

现在,我们掌握了带有Softmax(逻辑函数的推广)的文本神经网络模型工具。我们已经准备好提出下一个问题:如何利用这个模型来学习词向量,并同时学习与文本多层感知机模型相关的参数W和U?

在接下来的课程中,我们将使用文本语料库来同时学习所有这些参数

043:模型参数学习方法

概述

在本节课中,我们将要学习如何为词汇表中的每个单词学习一个向量表示,这个过程被称为学习词嵌入或词向量。我们将探讨两种核心的学习方法:连续词袋模型和跳字模型。理解这些方法是如何从大量文本数据中自动学习到单词的语义表示,是应用词向量进行后续分析的基础。

词向量学习的基本思想

上一节我们介绍了将词汇映射为向量的概念。但一个开放的问题是:这些词向量本身是如何学习的?

事实证明,学习这些词向量有多种不同的方法,这是一个非常活跃的研究领域。我们将介绍几种目前被广泛使用的方法。

其核心思想是:通过单词在上下文中的出现模式来学习其向量表示。具体来说,我们可以构建一个预测模型。

连续词袋模型

一种方法是利用目标单词周围的上下文单词来预测目标单词本身。

假设我们有一个文档,其中包含一系列单词。我们关注第 n 个单词。我们的目标是,基于它周围的单词(例如,前两个词和后两个词)来预测这个第 n 个单词是什么。

以下是构建此预测模型的步骤:

  1. 获取上下文向量:假设我们已经有了上下文单词(例如,word_{n-2}, word_{n-1}, word_{n+1}, word_{n+2})的词向量。
  2. 计算平均向量:将这些上下文词向量进行平均,得到一个 M 维的向量。我们将其表示为 c = [c1, c2, ..., cM]
  3. 通过多层感知机:将这个平均向量 c 输入到一个多层感知机中。该网络由参数 W, U 以及偏置 b, β 定义。
  4. 使用Softmax输出概率:在多层感知机的末端,使用一个Softmax函数。Softmax将网络的输出转换为一个概率分布,表示词汇表中 V 个单词中的每一个是目标单词 word_n 的概率。

公式表示
给定上下文单词集合 Context,模型预测目标单词 w_t 的概率为:
P(w_t | Context) = Softmax( U * f( W * avg(v(Context)) + b ) + β )
其中 v(word) 表示单词的词向量,f 是激活函数。

因此,我们得到了一个可以预测第 n 个单词概率的模型。如果这个模型预测得很准确,那就意味着我们为每个单词学习的向量表示(即词嵌入)能够很好地捕捉其语义,因为上下文信息被有效地编码到了向量中。

为了更清晰地说明,我们来看一个海明威文本的例子。假设绿色高亮部分是上下文单词(“there”, “was”, “much”, “hanging”, “outside”, “the”),我们的模型需要预测中间缺失的单词“game”。通过上述步骤,模型利用上下文单词的向量来预测“game”出现的概率。训练的目标是让模型参数(包括多层感知机的参数和所有单词的词向量)能够使这个预测概率最大化。

跳字模型

另一种互补的方法是,给定中心单词,来预测其周围的上下文单词

假设我们已知第 n 个单词是“game”,并且它由一个向量 c = [c1, c2, ..., cM] 表示。

以下是构建此预测模型的步骤:

  1. 输入中心词向量:将中心单词“game”的词向量 c 作为输入。
  2. 通过多层感知机:将向量 c 输入到一个多层感知机中。
  3. 使用Softmax输出概率:在网络的末端,Softmax函数会输出一个概率分布。但在这里,这个分布表示的是词汇表中每个单词出现在中心词周围特定位置(例如,前两个或后两个位置)的概率。在实践中,模型通常会为每个上下文位置输出一个独立的概率分布。

公式表示(简化)
给定中心单词 w_t,模型预测其某个上下文单词 w_c 的概率为:
P(w_c | w_t) = Softmax( U * f( W * v(w_t) + b ) + β )

因此,我们希望模型能够理解,当出现单词“game”时,其周围很可能出现“there”, “was”, “much”, “hanging”, “outside”, “the”这些词。通过这种方式,我们同样可以有效地学习到每个单词的语义向量表示。

模型对比与参数学习

我们来总结一下这两种模型:

  • 连续词袋模型:通过上下文预测中心词。因为它对上下文单词进行平均,所以单词的顺序无关紧要,这就像把单词扔进一个袋子(Bag),故得名。
  • 跳字模型:通过中心词预测上下文。它试图“跳过”中心词去捕捉周围的语法(gram),故得名。

在这两种情况下,我们想要学习的参数包括:

  1. 所有单词的词向量矩阵 C(可以看作一个编码本)。
  2. 多层感知机的参数 W, U 以及偏置 b, β

关键点:所有这些参数都可以基于一个大型的文本语料库进行学习。我们不需要任何人工标注的文本含义标签,模型可以直接从文本数据本身学习到有意义的词向量表示。学习过程通常通过最大化在训练数据上预测的似然概率(或最小化损失函数)来完成。

总结

本节课中,我们一起学习了两种主流的词向量学习方法:连续词袋模型和跳字模型。它们的核心思想都是利用单词与其上下文之间的共现关系,通过构建一个神经网络预测任务,来无监督地学习每个单词的向量表示。学习到的词向量能够捕捉单词的语义信息,为后续的文本分析任务(如分类、情感分析等)提供了强大的基础特征。

044:模型参数学习细节 🧠

在本节课中,我们将深入探讨机器学习模型参数学习的具体细节。我们将了解如何通过大量文本数据,以无监督的方式学习词向量和模型参数,从而构建一个能够预测上下文中单词的模型。


模型与学习目标

上一节我们介绍了Skip-gram和Bag of Words两种简单的模型形式。本节中,我们来看看“学习”这个概念的具体含义。

这里的“机器”指的是我们为文本开发的算法或模型,其核心概念是将每个单词映射到一个向量。

学习意味着我们将采用一个大型文档数据集(语料库),并基于这些文档尝试学习模型的参数。这被称为无监督学习,因为我们不需要人工标注文档的含义,仅从文档本身就能学习这个预测模型。

模型参数详解

我想强调,多层感知机(也称为神经网络)是一个非常基础的概念,在本课程及其他领域会反复出现。

我们试图学习的参数就是这个模型的参数。

模型参数主要包括两部分:

  1. 代表每个单词的向量集合,用 C 表示。
  2. 多层感知机的参数,用 WU 表示。

基于softmax模型,我们可以根据输入单词 C(由向量C表示)来预测最可能出现的V个单词中的哪一个。

模型的输入与输出

在这个模型中,我们有一个输入和一个输出。我们的目标是构建一个模型,使得当我们给定输入时,能够预测输出。

  • 输入:由上下文单词的向量表示。例如,对于第n个单词,我们取其周围六个单词的向量平均值作为输入。
  • 输出:预测第n个单词本身的存在。

无论是使用Skip-gram模型还是Bag of Words模型,我们学习的目标本质上是相同的:学习多层感知机的参数和词向量。这两种模型只是实现这一目标的两种不同方式,学习词向量的方法还有很多。

学习的基本框架

无论采用哪种方式,我们的目标都是进行模型学习。让我们更深入地思考一下。

本质上,我们试图做的是预测输出单词的概率。回想一下softmax模型,我们基于输入单词C(由向量C表示)来计算V个单词中每一个的概率。

这是一个基本概念。模型的参数由 θ 表示。

以下是模型的核心组成部分:

  • 输出单词的概率:由我们的神经网络通过softmax函数体现。
  • 输入单词:代表定义神经网络输入的上下文单词。
  • 输入单词的向量表示。
  • 参数 θ:包括词向量和多层感知机的参数。

训练与优化

当我们进行学习时,我们假设有M个示例对。

具体来说,我们假设语料库中有M个示例。对于每个示例(第i个示例),我们有一个输入向量 W_in^(i) 和一个输出向量 W_out^(i)。这M个示例构成了我们的训练集

在Skip-gram和CBoW的概念中,这M个输入输出示例可以通过扫描大型文档语料库自动生成,因此M的数量可以非常庞大。

接下来,我们建立一个称为成本函数的东西,用 F 表示。F 是参数 θ 和数据的函数。

我们表示成本函数的方式很简单,就是对训练集中所有M个示例的预测概率取对数后求和。

最后一个公式即为我们模型对所有训练集中输入输出对的预测之和。我们希望学习参数 θ,以最大化这个函数 F

如果我们能很好地做到这一点,就意味着我们拥有一个能够根据输入单词有效预测输出单词的模型。这一切都基于我们从语料库中获得的M个示例。


本节课总结:我们一起深入学习了机器学习中模型参数学习的细节。我们明确了学习的目标是最大化模型在训练数据上的预测概率,这通过优化成本函数来实现。核心在于,我们利用大量无标注文本,以无监督的方式自动学习词向量和神经网络参数,从而让模型掌握单词在上下文中的关系。

045:循环神经网络

在本节课中,我们将学习循环神经网络(RNN)的基本概念。这是一种用于处理序列数据(如文本)的强大工具。我们将了解RNN如何利用前文信息来预测序列中的下一个元素,并理解其核心工作原理。

概述

上一节我们介绍了用于自然语言处理的词向量模型,如Skip-gram和词袋模型。这些模型非常适合学习词向量(或称词嵌入)。然而,有些任务无法用这些工具完成,这促使我们引入循环神经网络。RNN是表示序列数据的基本框架,其“循环”意味着网络结构会重复使用。虽然RNN概念通用,但自然语言建模是其非常重要的应用场景。

文本合成与RNN的动机

假设我们已经学习了词向量,现在的目标可能是使用它们来执行文本合成,即自动生成文本。这在许多场景下非常有用,例如为图像自动生成描述,或者进行语言翻译。从语言A翻译到语言B,就需要能够合成语言B的文本。目前我们尚不具备这种工具,因此现在我们将深入探讨如何实现文本合成,这需要使用循环神经网络

RNN不仅是处理文本的强大工具,也是处理任何序列数据的重要工具,因此理解它至关重要。

RNN的基本工作方式

以下是我们思考循环网络使用方式的基本思路。请记住,W_n 代表文档中的第n个单词。我们可以将文档视为一个单词序列:W_{n-1}, W_n, W_{n+1} 等等。根据之前讨论的概念,每个单词都将通过一个向量来表示。

我们的目标是建立一个模型,该模型可以接收第n-1个单词及其对应的向量,同时利用前一个单词的隐藏向量 H_{n-1} 的知识,然后能够预测第n个单词。随着讲解深入,这个概念会变得更清晰。

我们的核心思想是:给定序列中的一个单词,我们希望模型能预测下一个单词。例如,给定单词 W_{n-1},预测单词 W_n;给定单词 W_n,预测单词 W_{n+1}。我们希望能够一个接一个地预测单词序列。这是通过一个重复使用的神经网络来实现的。目前这个图示可能看起来有些令人困惑,但随着深入讲解,它会变得更清晰。

这里最重要的一点是注意这个设置的循环特性。请注意,神经网络和Softmax函数被重复使用,这就是为什么它被称为循环神经网络。

深入理解RNN结构

让我们更深入地理解这个神经网络。该神经网络在这里由两个输入来表征:

  1. W_{n-1}:文档中的第n-1个单词,我们将通过一个向量或嵌入来表示它。
  2. H_{n-1}:来自前一个单词(同样是第n-1个单词)的多层感知机隐藏向量。

我们将把这两个向量拼接在一起。这意味着我们将获取第n-1个单词的向量,以及与前一个单词相关的隐藏单元向量,然后将它们首尾相连组合成一个更长的向量。

接着,我们将这个组合后的向量送入一个由参数 W 表征的神经网络。从这个模型中,我们将预测第n个隐藏单元,它同样由一个向量表示。

这里的关键点是:我们将一个单词向量和前一个单词的隐藏单元送入一个神经网络(由参数 W 表征),然后预测与下一个单词(第n个单词)相关的隐藏单元。在此过程中,我们得到了一个新的隐藏向量 H_n

然后,隐藏向量 H_n 会像我们之前所做的那样,被送入多层感知机,再经过Softmax层,最终预测第n个单词 W_n

接下来,H_n 会被传递给序列中的下一个单词。这样,我们就可以以循环的方式预测文档中的每个单词。

请注意,来自前一个单词的隐藏向量 H_{n-1} 会馈入用于预测第n个单词的神经网络模型。在此过程中,我们得到一个新的隐藏向量 H_n,它随后被送入下一个神经网络。同时,相关的下一个单词 W_n 也被送入那个神经网络,然后它们预测下一个隐藏单元 H_{n+1},接着再预测下一个单词。这个过程不断重复或循环发生,因此被称为循环神经网络。

不过,关键要注意的是,这个架构看起来与我们之前见过的非常相似。我希望随着我们反复观察这些神经网络,有一点变得越来越明显:这个循环网络的基本结构是一个带有某些输入并预测输出的多层感知机。我们之前讨论的Skip-gram和词袋模型也具有相同的基本多层感知机架构。因此,尽管这些是不同的模型,做着不同的事情,但它们的核心、每个案例的底层核心,都是多层感知机。

模型公式化表示

为了便于后续讨论,我们引入一些符号表示。

我们将第n-1个单词的向量,以及与第n-1个单词相关的隐藏向量 H_{n-1} 拼接在一起,并将这个拼接结果称为 X_{n-1}。所以,X_{n-1} 仅仅是第n-1个单词向量和隐藏向量 H_{n-1} 拼接在一起的符号表示。

然后,X_{n-1} 被送入一个模型来生成隐藏向量 H_n。该模型是一组权重 W 乘以输入 X_{n-1}(即对每个输入进行加权然后求和),再加上一个偏置项 b,最后通过一个非线性函数。这里使用的非线性函数是双曲正切函数,这不是唯一可用的非线性函数,但它非常流行,我们稍后会详细讨论。

因此,我们的隐藏单元 H_n 的模型是:
H_n = tanh(W * X_{n-1} + b)

接着,隐藏单元 H_n 被送入另一组权重 U(即乘以权重然后求和),再加上一个偏置项 c。最后一步是Softmax函数。通过这个两步过程——将输入映射到隐藏向量,然后隐藏向量通过Softmax映射为概率——我们得到了我们的模型。

用公式表示,预测单词 W_n 的概率为:
P(W_n | W_{n-1}, H_{n-1}) = softmax(U * H_n + c)

所以,这个模型在做什么?最后一个方程是在给定前一个单词 W_{n-1} 和前一个隐藏向量的情况下,预测第n个单词 W_n 是什么。这正是多层感知机所做的事情。

RNN的核心思想

思考这个模型在做什么的关键在于:它基于两个输入来预测下一个单词(第n个单词)。

  1. 它使用了来自前一个单词的隐藏向量 H_{n-1}。如果你思考一下,这基本上是在告诉我们关于前一步中哪些单词可能出现的上下文信息。因为如果你看这个模型,隐藏向量 H_n 预测了下一个单词是什么。所以,H_{n-1} 的作用是告诉我们前一步中哪些单词是可能的,它提供了上下文信息。
  2. W_{n-1} 告诉我们前一个单词具体是什么

因此,基于 H_{n-1} 提供的上下文,以及前一个单词 W_{n-1},我们预测下一个单词 W_n。这就是所谓的循环神经网络。

它被称为循环神经网络的原因是:这个由图示表示的过程会以循环的方式一遍又一遍地重复。这是一种我们可以合成或生成数据序列(这里指单词或文本序列)的方法。

总结

本节课中,我们一起学习了循环神经网络的基本原理。我们了解到RNN通过重复使用相同的网络结构来处理序列数据,利用前一个单词的向量 W_{n-1} 和隐藏状态 H_{n-1} 来预测下一个单词 W_n。其核心公式包括隐藏层的计算 H_n = tanh(W * X_{n-1} + b) 和输出的预测 P(W_n | ...) = softmax(U * H_n + c)。RNN的强大之处在于其循环结构能够捕捉序列中的上下文信息,使其成为文本合成、翻译等序列生成任务的理想工具。

046:长短期记忆网络 (LSTM) 🧠

概述

在本节课中,我们将要学习一种更复杂的循环神经网络变体——长短期记忆网络。上一节我们介绍了基础的循环神经网络,本节中我们来看看如何通过引入“记忆单元”和控制门机制,来解决基础RNN在处理长序列文本时可能遇到的困难。LSTM是当前自然语言处理领域最先进的技术之一,理解其工作原理至关重要。


从基础RNN到LSTM的演进

我们引入了循环神经网络的概念。循环神经网络是多层感知机的一种非常自然的扩展。实际上,它只是对基础多层感知机的重复或循环使用。这是一个非常简单的概念,也是一个非常强大的概念。

然而,人们发现,在我们试图分析的文本、文档和自然语言语境中,上一课中讨论的最简单形式的循环神经网络,其效果并不如我们所愿。

因此,我们现在要引入一种新的、更复杂形式的循环神经网络。它同样建立在多层感知机的概念之上,但方式要复杂得多。本节课的内容比我们其他一些课程要复杂得多,这可能是最复杂的一课。之所以要花时间讨论这个被称为LSTM或长短期记忆网络的技术,是因为它代表了当今自然语言处理领域的最先进水平。虽然方法有些复杂,但值得研究和理解,因为这项技术正在推动基于神经模型的自然语言处理领域最近的革命。这项技术确实非常出色,我们将在后续内容中进一步讨论。

虽然这个模型更复杂,但我希望展示它是可以理解的,或许理解起来并不那么困难。


LSTM的基本架构

我们再次看到循环神经网络。我们看到一个单词序列 W_{n-1}, W_n, W_{n+1},这对应于我们文档序列中的第 n-1nn+1 个单词。我们再次看到神经网络的重复使用和重复的Softmax层。

然而,这个模型现在引入了一些我们在之前更简单的循环神经网络中没有的新东西,其中最重要的是我们称之为记忆单元的东西。

请注意,在我们相对简单的循环网络中,我们所做的是将隐藏单元 H 从前一个单词传播到下一个单词。所以我们有 H_{n-1},它被输入到对 H_n 的预测中,然后 H_n 预测第 n 个单词。

我们引入了一个新东西,叫做记忆单元。我们将在后续详细描述它。它由 C(单元)表示:C_{n-1}, C_n, C_{n+1}, C_{n+2}。我们将对此进行更深入的探讨。

和之前一样,在更简单的循环神经网络中,我们仍然有这些隐藏单元。所以我们保留了它们。我们引入的新关键点是这些记忆单元,我们将在后续深入探讨。但需要注意的关键是,这个循环神经网络的基本设置是相同的。我们再次看到Softmax层,它允许我们预测下一个单词。

这里将要改变的是黄色部分的内容。循环网络的形式将发生变化。


回顾基础概念与符号

为了理解这一点,我们需要稍微退一步,回顾一些符号,因为在后续内容中我们需要使用这些符号。这是一个复习。

我们之前有一个词向量,代表第 n-1 个单词的词向量,我们还有一个隐藏向量,代表第 n-1 个单词。我们将它们连接起来,这意味着我们只是将它们拼接在一起。这两个向量在连接过程之后被拼接在一起。我们称这个累积向量为 X_{n-1}

该向量随后进入一个由参数 W 表征的神经网络。基本上,我们取向量 X_{n-1} 的分量,用权重乘以它们,将它们求和,得到输出。我们加上一个偏置 b,然后该过程通过一个非线性函数 f 发送,我们将对此进行更多讨论。然后我们从那里得到我们的隐藏单元 H_n。这是我们之前看过的基本结构。


非线性激活函数

现在我想花点时间讨论一下那个非线性函数 f 的形式。

之前当我们介绍循环神经网络时,我们使用了双曲正切函数 tanh。它是神经网络中广泛使用的函数,其函数关系如图所示。从该图中要理解的关键点是,双曲正切函数的输出 y 始终在 -11 之间。当输入 x 为正且很大时,双曲正切趋向于 1;当输入 x 为负且很大时,输出趋向于 -1。双曲正切是非线性函数 f 的一个例子。

我们将使用该函数 f 的多种形式。因此,值得花一些时间讨论它们。

一种是双曲正切函数。另一种是我们在课程其他地方讨论过的函数,即 Sigmoid函数。这里,Sigmoid函数用希腊符号 σ 表示。Sigmoid函数如图所示。

现在请注意,重要的是,Sigmoid函数的输出始终在 01 之间。当输入为正且很大时,Sigmoid函数的输出趋向于 1。当Sigmoid函数的输入为负且很大时,其输出趋向于 0

因此,重要的是要注意,双曲正切函数的输出在 -11 之间,而Sigmoid函数的输出在 01 之间。这些差异在我们后续的讨论中很重要。


LSTM的核心:三个控制网络

让我们回到这个模型。这是我们的循环神经网络,我想花点时间慢慢地、仔细地讲解这个神经网络,因为这有些复杂。但它是可以理解的,我们需要慢慢来并思考它。我还想重申,这是自然语言处理领域最先进的模型,因此绝对值得尝试理解。

我们再次引入符号,其中 X_{n-1} 将是第 n-1 个单词的向量与前一步的隐藏单元 H_{n-1} 的连接或组合。这和之前做的一样。所以 X_{n-1} 将是我们模型的输入,它来自前一个单词的词向量和前一个单词的隐藏向量。

现在我们要做的,不是引入一个神经网络,而是实际上引入三个神经网络。这就是事情开始变得复杂的地方。以前在我们的循环神经网络中,我们有一个神经网络处理过程。这里我们引入了三个。其中一个用 I 表示,另一个用 F 表示,另一个用 O 表示。我们稍后会解释 IFO 的含义。

但如果我们看看这里发生了什么,这与我们之前所做的并非天差地别。我们取输入 X_{n-1},并分别将其通过三个不同的神经网络发送。

与输出 I 相关的神经网络的参数是 W_ib_i,其中 b_i 是偏置,W_i 是权重参数。我们取输入 X_{n-1}(我们的连接向量),用权重乘以它,将它们求和,然后得到一个输出,该输出随后通过一个Sigmoid函数发送。

我们取输入 X_{n-1},用与 W_f 相关的权重乘以它,将它们相加,加上偏置 b_f,将它们通过Sigmoid函数发送,然后得到输出 F_n

对于与输出 O 相关的神经网络,我们做同样的事情,参数是 W_ob_o,非线性函数同样是Sigmoid函数 σ

需要注意的关键点是,我们现在引入了三个神经网络。每个神经网络的基本函数形式是相同的。这三个神经网络的具体参数各不相同。

我想再次强调,非线性函数是Sigmoid函数,这意味着向量 I、向量 F 和向量 O 的每个分量都是一个介于 01 之间的数字。这将在后面很重要。

这三个输出为 IFO 的神经网络,就是我们所说的控制网络。它们由参数集 W_oW_fW_i(权重)和偏置集 b_ob_fb_i 来表征。基本上,这三个控制神经网络中的每一个看起来都非常像我们在多层感知机中见过的样子。我们在这里表示的这三个控制神经网络将用于控制我们神经网络的输出,或者控制我们循环神经网络的输出,我们将在后续看到。


引入第四个网络与记忆单元更新

现在我们要引入第四个神经网络。在LSTM或长短期记忆中,我们将有四个神经网络。

其中三个神经网络由之前的方程表示。这些是我们之前见过的基本多层感知机。

现在我们将引入第四个,它将为我们提供记忆单元的新估计值,我将其表示为 \tilde{C}_n。这个 C 是我们的记忆单元,下标 n 表示它是第 n 个,C 上面的波浪线 ~ 只是一个符号,称为 \tilde{C}_n

我们在这里将使用双曲正切 tanh 作为我们网络中的输出或非线性函数。在这种情况下,我们知道向量 \tilde{C}_n 的每个分量都将在 -11 之间,这由双曲正切的性质决定。

现在我们要做的最后一步,我们将慢慢进行并尝试真正理解,是更新记忆单元。请记住,在这个循环网络中,我们有一个隐藏向量 H_n 和一个记忆单元 C_n

让我们尝试理解这个符号 (圆圈中间有一个点)。我们在这里说的是,C_n(记忆单元的第 n 次实现)是 C_{n-1}(前一次的记忆单元)和 \tilde{C}_n(我们对记忆单元的新估计)的组合。

C_n 是前一个记忆单元 C_{n-1} 和一个新估计 \tilde{C}_n 的组合,然后 C_{n-1}\tilde{C}_n 由来自我们控制网络的输出 F_nI_n 进行操作。

符号 意味着我们将取 F_n 的每个分量,并将其乘以 C_{n-1} 的相应分量。完成此操作后,我们将生成一个新向量,它是 F_nC_{n-1} 的组合。我们取向量 F_n(一组数字,每个数字都在 01 之间),将其乘以记忆单元 C_{n-1} 的相应分量。这给了我们一个新向量。该过程、该操作由 F_n ⊙ C_{n-1} 表示。这只是取 F_n 的每个分量并将其乘以 C_{n-1} 的相应分量。

现在你可以开始看到这个控制过程是如何体现的。F_n 所做的是控制前一个记忆单元 C_{n-1} 在我们更新新记忆单元 C_n 时的贡献。

然后 I_n\tilde{C}_n 进行类似的操作,我们将这两个向量相加,就得到了 C_n

基本上,发生的情况是,记忆单元 C_n 是前一个记忆单元 C_{n-1} 和记忆单元的新估计 \tilde{C}_n 的组合,然后向量 F_nI_n(它们本身都是神经网络的输出)控制着 C_{n-1}\tilde{C}_n 对新更新单元的贡献程度。

我们需要思考的最后一件事是如何生成隐藏单元或输出 H_n,然后它进入Softmax层。这是第三个控制网络,其输出为 O_n。这与之前相同的方式 与记忆单元的双曲正切相乘。

因此,如果你思考这里发生了什么:我们有三个控制网络,生成了输出向量 O_nF_nI_n。我们有一个记忆单元的更新估计 \tilde{C}_n,它也由神经网络表示。然后,三个控制网络对记忆单元进行操作,接着输出控制向量 O_ntanh(C_n) 进行操作,给我们隐藏单元 H_n

这就是长短期记忆网络的基本结构。正如我所说,这是自然语言处理和许多类型序列建模的最先进方法。它肯定比我们之前看过的任何东西都复杂。


总结

本节课中我们一起学习了长短期记忆网络的核心架构。我们了解到,LSTM通过引入记忆单元和三个控制门,有效地解决了基础RNN在长序列依赖上的不足。具体来说:

  • 输入门控制新信息 \tilde{C}_n 的流入。
  • 遗忘门控制旧记忆 C_{n-1} 的保留程度。
  • 输出门控制当前记忆 C_n 对当前输出 H_n 的影响。

这些门机制均由Sigmoid函数实现,输出值在0到1之间,起到了“开关”或“调节器”的作用。记忆单元的更新则结合了经过门控筛选的旧记忆和新信息。虽然结构复杂,但LSTM通过这种精巧的设计,成为了处理序列数据的强大工具。在下一课中,我们将逐步剖析这个模型,以更全面地理解其工作原理。

047:长短期记忆网络回顾 🧠

在本节课中,我们将回顾长短期记忆网络。这是一种用于建模序列数据的循环神经网络。在自然语言处理领域,由单词序列构成的语言是LSTM一个非常自然的应用场景。

上一节我们介绍了LSTM的基本概念,本节中我们将更深入地剖析其内部组件和工作原理。

LSTM的结构与组件 🔧

LSTM是一种循环神经网络,用于对数据序列进行建模。在文档处理中,文档的每个单词由一个向量表示,因此LSTM操作的是与文档中单词相关联的向量序列。

LSTM是当前自然语言处理领域最先进的方法,在许多场景中取得了显著成果。然而,它比我们课程中讨论过的其他大多数模型都要复杂。因此,有必要退一步回顾LSTM,以便更深入地理解模型中各个组件的作用。

让我们回顾一下长短期记忆网络。它由三个控制神经网络组成,在我们的序列时间点 n 处,它们输出向量 O_nF_nI_n

这三个神经网络本质上都具有多层感知机的基本形式。我们注意到,每个控制单元的非线性函数都是Sigmoid函数 σ。这意味着向量 O_nF_nI_n 的每个分量都是介于0和1之间的数字。

在长短期记忆网络中,除了隐藏向量 H,我们还引入了一个新的向量,即由 C 表示的记忆单元。

记忆单元由第四个神经网络更新,该网络使用双曲正切作为非线性函数。它同样是一个多层感知机,但其非线性函数是双曲正切,这意味着向量 C̃_n 中的每个元素都是一个介于-1和1之间的数字。

顶部的这四个神经网络随后被用来更新记忆单元 C_n 和隐藏变量 H_n

具体做法是:利用 F 网络和 I 网络的控制输出来操作先前的记忆单元 C_{n-1} 和我们的新估计值 C̃_n。然后,其输出 C_n(即我们更新后的记忆单元)经过双曲正切函数处理,再与 O 网络的输出 O_n 进行运算,从而得到隐藏单元 H_n

这里涉及的内容很多,让我们尝试更深入地理解一下。

理解控制机制 🎛️

观察记忆单元的更新输出,我们注意到向量 F_n 的作用是控制我们遗忘旧记忆单元分量的程度。

请记住,向量 F_n 的每个分量都在0和1之间。因此,如果 F_n 的某个特定分量接近0,那么记忆单元 C_{n-1} 的对应分量就会乘以一个接近0的数,这意味着它基本上会遗忘该记忆单元的输出。所以,F_n 控制或允许模型遗忘或擦除先前的记忆单元输出。我们使用符号 F_n 的原因在于,这是一种允许模型遗忘或擦除旧记忆单元的方法。

相比之下,I_n 控制着我们新估计值 C̃_n 的输入。我们所做的是:取先前的记忆单元(一个数字向量 C_{n-1}),将其与向量 F_n 逐分量相乘。F_n 告诉我们(记住 F_n 的每个输出都在0和1之间),如果 F_n 的某个分量接近0,那就意味着我们试图擦除或遗忘记忆单元的对应分量。因此,F 被称为我们的遗忘控制

I 被称为输入控制,因为它控制着我们的新估计值 C̃_nC_n 新估计值的贡献程度。同样,I_n 的每个分量都在0和1之间。如果 I_n 的对应分量接近0,那么 C̃_n 的对应分量就不会对我们的记忆单元新表示有显著贡献。相反,如果 I_n 的某个分量接近1,那就意味着我们新估计值 C̃_n 的对应分量将对新的记忆单元 C_n 有显著贡献。

因此,遗忘控制 F 和输入控制 I 共同控制着先前记忆单元和我们记忆单元的新表示对下一时间戳更新记忆单元 C_n 的贡献程度。

然后,O_n输出控制。它的作用是:取记忆单元 C_n,将其通过非线性函数双曲正切(输出介于-1和1之间)。O_n 也是一个数字向量,每个分量都在0和1之间。O_n 的每个分量与双曲正切输出的相应分量相乘,这个乘积控制着这些分量对下一个隐藏向量 H_n 的贡献程度。

我们还引入了第四个神经网络,即记忆单元的更新网络,由 C̃_n 表示。

总结与优势 📈

在原始的循环神经网络中,单一的循环网络在LSTM中被四个神经网络所控制。这些网络允许模型通过 F 控制来遗忘数据序列中的先前数据;通过 I 控制来输入新数据的能力;然后 O 控制控制着记忆单元对输出(即隐藏向量)的贡献程度。

我们引入了循环模型相同的基本概念,因为示意图中看到的基本结构是循环重复的,这就是为什么它被称为循环神经网络。

然而,它有两个输出:隐藏向量 H_n 和记忆单元的更新 C_n

所有LSTM参数都可以使用未标记数据进行学习,因为这基本上是一个允许我们根据前一个单词预测下一个单词的模型。我们可以对文档或语料库中的单词序列进行此操作,并且不需要对文档进行人工标记。因此,我们可以将此模型应用于未标记数据。

词向量可以被视为模型中的附加参数,也可以被学习。因此,这个LSTM模型是一个允许我们学习词嵌入向量,同时也允许我们学习能够合成文本的模型。我们稍后将更多地讨论这种合成文本的能力,这对于文本翻译等应用至关重要。例如,输入文本可能是一个英语单词序列,输出可能是一个法语单词序列。如果我们要从英语翻译成法语,我们必须能够合成语言,而这个允许我们合成单词序列的LSTM,正是我们执行文本合成任务的一种方式。

LSTM模型无疑很复杂,但它是由我们之前见过的基本构件(多层感知机)构建而成的。它是一个复杂的模型,但现实是它在实践中效果非常好,为包括翻译在内的许多应用提供了最先进的结果。在下一课中,我们将展示LSTM在文本合成方面被证明非常有效的另一个应用。

本节课中,我们一起回顾了长短期记忆网络的核心结构、三个关键控制门(遗忘门、输入门、输出门)的作用机制,以及它如何通过记忆单元管理长期依赖关系。LSTM通过其精巧的设计,有效地解决了传统RNN在长序列训练中遇到的梯度消失或爆炸问题,使其成为处理序列数据(尤其是自然语言)的强大工具。

048:LSTM用于文本生成 🧠📝

在本节课中,我们将学习长短期记忆网络在文本生成任务中的应用。我们将了解其基本工作原理,并探讨一个结合了图像分析与文本生成的端到端应用实例——自动图像描述。


上一节我们介绍了长短期记忆网络的基本概念。本节中,我们来看看如何将LSTM模型应用于文本合成。这种基本框架已在多个应用中取得了显著成果,例如语言翻译和图像自动描述。

文本生成的基本流程

假设我们已经基于一个大型文档语料库学习了LSTM的参数。那么,如何使用LSTM来合成文本呢?

LSTM的基本结构是一个神经网络。其输入包括:

  • 来自前一步的隐藏单元 H 和记忆细胞 C
  • 前一个单词。

其输出是:

  • 下一个隐藏单元,用于预测下一个单词。
  • 更新后的记忆细胞。

更新后的记忆细胞和隐藏单元将传递到下一个神经网络单元。我们将以循环的方式反复应用这个基本结构,因此它被称为循环神经网络。

以下是文本生成的具体步骤:

  1. 初始化:我们使用一个“句子开始”符号 BOS 来初始化文本生成过程。同时,我们初始化隐藏单元 H0 和记忆细胞 C0
  2. 预测第一个单词:将 BOSH0C0 输入LSTM单元。输出的隐藏单元 H1 会通过一个 softmax 层,该层会给出词汇表中每个单词作为下一个单词(即第一个单词 W1)的概率。我们通常选择概率最高的单词作为 W1
  3. 循环生成:将预测出的单词 W1 的向量表示,连同更新后的 H1C1,一起作为输入送入下一个LSTM单元。该单元输出 H2,再经过 softmax 得到第二个单词 W2 的概率分布,并选择最可能的单词。此过程不断重复。
  4. 结束生成:当模型输出“句子结束”符号 EOS 时,生成过程终止。

通过这种循环神经网络,我们可以顺序地合成文本。接下来,我们将看到一个结合了图像分析的强大应用。

应用实例:自动图像描述 🖼️

在真实应用中,我们通常需要根据特定任务来初始化 H0C0。自动为图片生成描述就是一个很好的例子。

观察这张鸟的图片及其描述文本:“这只鸟有着红色的喉咙和胸部,头部和翅膀是深棕色的”。重要的是,这个句子是由机器自动生成的,而非人类撰写。

这是如何实现的呢?它结合了我们课程中讨论过的两个关键概念:

  1. 深度卷积神经网络:用于分析图像。图片首先通过一个DCNN,网络顶层的输出是一组能表征图像的特征。
  2. 长短期记忆网络:用于合成文本。上一步提取的图像特征被用来初始化LSTM的记忆细胞 C0

这个端到端的方法,通过将用于图像分析的DCNN和用于文本合成的LSTM结合在一起,训练出一个能够同时分析图像并生成描述文字的模型。模型的输入是图像,输出是文本。

为了学习这样一个组合模型,我们需要为模型提供大量由人类标注的“图像-文本”配对示例。利用这些数据,我们可以同时学习卷积神经网络和LSTM的参数。

以下是机器生成的一些描述示例。可以看到,这些句子语法正确,并且对图像内容的描述相当准确和真实,其质量令人印象深刻。

  • 一只棕白相间的小狗躺在沙发上。
  • 一个穿着黑色西装的男人正在弹吉他。
  • 一群长颈鹿站在一棵树旁边。
  • 一盘食物放在桌子上。
  • 一辆公共汽车行驶在城市的街道上。
  • 一个小孩在公园里玩飞盘。

这个例子展示了机器学习领域的巨大潜力:我们将用于图像分析的先进技术(深度卷积神经网络)与用于文本合成的先进技术(LSTM)相结合,实现了对图像的自动描述,其准确性和真实感已接近人类水平。


本节课中,我们一起学习了LSTM用于文本生成的基本流程,并深入探讨了其在自动图像描述任务中的端到端应用。我们看到了如何将图像特征作为LSTM的初始状态,从而引导模型生成与图像内容相关的连贯文本。这体现了现代机器学习系统整合多种技术以解决复杂任务的能力。

049:神经NLP的简单有效替代方法 🧠➡️📄

在本节课中,我们将要学习一种用于自然语言处理任务的、极其简单却非常有效的模型。我们将以情感分析任务为例,探讨如何通过简单的词向量平均或最大化操作,结合逻辑回归分类器,达到与复杂模型(如LSTM和CNN)相媲美的性能。


概述

我们已经介绍了几种不同的文本分析方法,包括用于学习词嵌入向量的Skip-gram和词袋模型,以及特别擅长文本生成的长短期记忆网络模型。然而,近年来人们认识到,对于许多任务,非常简单的模型往往也能取得出色的效果。本节我们将通过情感分析任务来演示这一点。


问题定义:情感分析

上一节我们介绍了复杂的序列模型,本节中我们来看看一个更简单的替代方案。首先,我们明确要解决的问题:情感分析。

情感分析任务通常定义为:给定一个文本文档(用 ( T_i ) 表示第 (i) 个文档的单词集合),以及一个标签(例如,-1 表示负面情感,+1 表示正面情感),目标是构建一个模型来预测文本的情感倾向。


构建简单模型:词向量平均

以下是构建简单模型的核心步骤。我们将采用一种忽略词序的直观方法。

  1. 获取词向量:对于文档中的每个单词 ( W_j ),我们有其对应的词向量(或嵌入向量) ( C_{W_j} )。
  2. 计算平均向量:我们简单地计算文档中所有 ( N ) 个词向量的平均值:
    [
    \text{平均向量} = \frac{1}{N} \sum_{j=1}^{N} C_{W_j}
    ]
  3. 输入分类器:将这个平均向量输入一个简单的逻辑回归分类器。逻辑回归由参数 ( W ) 定义,并使用Sigmoid函数(( \sigma ))来预测标签为+1的概率:
    [
    P(\text{标签} = +1) = \sigma(W^T \cdot (\text{平均向量}))
    ]
    [
    P(\text{标签} = -1) = 1 - P(\text{标签} = +1)
    ]

这个模型需要学习的参数仅仅是所有词汇的词向量和逻辑回归的权重 ( W )。它比LSTM或CNN要简单得多。


模型为何有效?

你可能会问:这个模型完全忽略了单词的顺序,它怎么可能有效呢?关键在于模型的学习过程。

在训练过程中,模型会自动学习将那些对情感分析任务不重要的单词的词向量调整到接近零值。因此,在计算平均值时,这些“不重要”的单词贡献几乎为零。最终,模型的预测主要依赖于少数对情感有显著贡献的关键词的词向量。这相当于模型自动进行了特征选择。


扩展:分量最大化方法

除了取平均值,我们还可以采用另一种简单的聚合方法:分量最大化。

以下是分量最大化方法的操作流程:

  1. 对于一个包含 ( N ) 个单词的文档,我们拥有 ( N ) 个词向量。
  2. 对于词向量的每一个维度(分量),我们找出该维度在所有 ( N ) 个词向量中的最大值。
  3. 用这些最大值组成一个新的向量,作为文档的表示。
  4. 同样,将这个新向量输入逻辑回归分类器进行预测。

我们甚至可以将“平均向量”和“最大化向量”连接起来,形成一个更丰富的文档表示,再送入分类器。这类模型统称为简单词嵌入模型


实证结果与模型对比

为了直观展示简单模型的效果,我们将其与复杂模型进行对比。

  • 参数数量与速度

    • 卷积神经网络:约54万个参数。
    • 长短期记忆网络:约180万个参数。
    • 简单词嵌入模型:仅约6.1万个参数。
    • 参数量的巨大差异直接体现在计算速度上,简单模型要快得多。
  • 性能表现:在多个不同的自然语言处理数据集和任务(如SNLI、MultiNLI等)上,简单的SWM模型在情感分析等任务上的准确率常常与复杂的CNN和LSTM模型相当,有时甚至更好

  • 词向量分布:通过SWM方法学习到的词向量有一个显著特点:绝大多数单词的向量值都集中在0附近,只有少数重要单词拥有非零值。这与GloVe等其他方法学习到的、值分布更广泛的词向量形成鲜明对比。这印证了模型“聚焦关键信息”的工作原理。


总结

本节课中我们一起学习了自然语言处理中一种强大而简单的范式。我们了解到,学习单词的嵌入向量是一个核心且强大的概念,它可以应用于从极其简单的模型到非常复杂的模型。

关键在于,对于许多实际任务(如情感分析),我们应仔细评估问题所需的模型复杂度。事实证明,匹配任务复杂度的简单模型往往能提供最佳的性能与效率平衡。因此,在着手解决NLP问题时,不妨先从像SWM这样的简单模型开始尝试。

050:使用PyTorch进行自然语言处理 🧠📚

在本节课中,我们将学习如何使用PyTorch进行自然语言处理。我们将介绍词嵌入的概念,探索预训练的词嵌入模型,并构建一个简单的神经网络来预测电影评论的情感。最后,我们会简要概述PyTorch中的循环神经网络。


与计算机视觉领域类似,自然语言处理领域也因深度学习的引入而经历了重大变革。

词嵌入简介

在模块4中,我们介绍了词嵌入的概念。词嵌入是单词的向量化表示,它能够承载单词的语义信息。

其核心思想是,语义相近的单词在向量空间中的位置也相近。这可以用一个简单的公式来描述:如果单词A和单词B语义相似,那么它们的词嵌入向量 embedding(A)embedding(B) 之间的余弦相似度会很高。

# 示例:计算两个词向量的余弦相似度
import torch.nn.functional as F
similarity = F.cosine_similarity(embedding_A, embedding_B, dim=0)

接下来,我们将探索如何使用预训练的词嵌入模型。

探索预训练词嵌入

我们将使用一些预训练的词嵌入模型,并观察如何利用它们来寻找相似词和解决词语类比问题。

以下是使用预训练词嵌入的几个关键步骤:

  1. 加载预训练模型:例如,使用torchtext库加载GloVe或Word2Vec模型。
  2. 查找词向量:通过单词索引直接获取其对应的向量表示。
  3. 计算相似度:通过计算向量间的距离(如余弦相似度)来找到语义上最接近的单词。
  4. 解决类比问题:例如,通过向量运算解决“国王 - 男人 + 女人 = 女王”这类问题。
# 伪代码示例:解决词语类比
vector = embedding(“king”) - embedding(“man”) + embedding(“woman”)
# 然后在所有词向量中寻找与 `vector` 最接近的向量,其结果很可能就是 “queen”

在了解了词嵌入的基本用法后,我们将尝试构建一个实际的应用模型。

构建情感分析模型

现在,我们将训练一个非常简单的神经网络模型。该模型学习如何使用词嵌入来预测电影评论的情感(正面或负面)。

以下是构建和训练情感分析模型的主要步骤:

  1. 数据预处理:将文本评论转换为词索引序列,并进行填充以保证输入长度一致。
  2. 嵌入层:使用预训练或随机初始化的词嵌入层将词索引映射为稠密向量。
  3. 模型结构:构建一个简单的网络,例如嵌入层后接一个全局池化层(如平均池化),然后连接全连接层进行二分类。
  4. 训练与评估:使用交叉熵损失和优化器进行训练,并在验证集上评估模型性能。
import torch.nn as nn

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-ml/img/bfda3d9568c87f1f22c2142ec5f45dc9_5.png)

class SentimentClassifier(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_classes):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.fc = nn.Linear(embed_dim, num_classes)

    def forward(self, text):
        # text shape: (batch_size, sequence_length)
        embedded = self.embedding(text) # shape: (batch_size, seq_len, embed_dim)
        # 对序列维度进行平均池化
        pooled = embedded.mean(dim=1) # shape: (batch_size, embed_dim)
        output = self.fc(pooled)
        return output

掌握了基于词嵌入的简单模型后,我们来了解一种更适合处理序列数据的神经网络结构。

循环神经网络概述

我们将以PyTorch中的循环神经网络作为本节结尾。RNN是一类专门用于处理序列数据的神经网络,它能够捕捉文本中的时序依赖关系。

在PyTorch中,可以使用 nn.RNNnn.LSTMnn.GRUCell 等模块轻松构建RNN模型。它们能够接收一个序列输入,并输出每个时间步的隐藏状态或最终状态。

对于作业部分,你将在一个文本分类数据集上训练几种不同类型的模型,并比较它们的性能。


本节课中,我们一起学习了自然语言处理的基础知识。我们从词嵌入的概念出发,探索了预训练模型的应用,并动手构建了一个用于情感分析的简单神经网络。最后,我们简要了解了PyTorch中的循环神经网络。这些工具和方法为处理和理解文本数据提供了强大的基础。

051:词向量及其解读 🧠

在本节课中,我们将要学习自然语言处理中的一个核心概念——词向量。我们将探讨词向量的基本思想、其数学表示,并尝试理解这些向量所蕴含的语义信息。这为后续学习更复杂的模型(如Transformer)奠定了基础。


在课程的前面部分,我们已经在自然语言处理的背景下讨论过词向量(Word to Vector)的概念。

核心思想是,词汇表中的每个单词都将被映射到一个向量,这些向量有时也被称为嵌入。如果 w_i 表示词汇表中的第 i 个单词,我们要做的就是将其映射到一个 D 维向量。

我们将对词汇表中的每个单词都进行这种映射。

我们曾在长短期记忆网络的背景下讨论过这个概念。现在,我们将把这个概念扩展到所谓的Transformer网络或基于注意力的网络。这样做,是希望我们能进一步理解这些词嵌入或词向量所代表的意义。


词向量映射的核心思想

词向量映射(Word to Vector Mapping)的关键思想是:我们将由 V 个单词组成的词汇表,映射为一组对应的向量或编码。

我们使用符号 C 表示编码。因此,如果我们的词汇表有 V 个单词,我们现在就有 V 个编码,每个编码都是一个 D 维向量。

完成此映射后,我们通过一个“码本”来表示我们的词汇表。码本就是词汇表中每个单词对应的 D 维向量的集合。


如何学习词向量

学习这些向量(编码向量)的方法有很多种。事实上,我们在课程的其他部分已经讨论过这些不同的学习方法,包括长短期记忆网络。正如之前所说,我们将把这个概念扩展到一种新模型——Transformer。

所有这些方法的关键思想是:对于给定文档中的每个单词,我们应该能够预测其下一个或周围的单词。其理念是,单词具有意义,这种意义意味着一个给定的单词应该能以高概率暗示另一个特定单词的存在。我们要学习的这些词向量,就是为了保留或实现这个概念。


理解词向量的含义

我们现在要做的是,尝试进一步理解这些向量意味着什么。这将有助于激发我们接下来要讨论的模型。

为了简化讨论,我们假设每个词向量都是10维的。在这个图示中,每个方框代表一个数字,10个数字对应这个向量的10个分量。

我们想要思考的理念是,这10个数字中的每一个都关联着一个潜在的主题。这个10维词向量中的每个主题都代表了单词的特征,或者人们试图用单词表达的东西。

因此,如果一个给定的单词与第 i 个主题对齐,那么我们期望向量中对应的分量将是正数,因为它与该单词对齐。如果第 i 个主题与单词无关或不对齐,那么我们期望该分量的值为负数。随着我们继续深入,会进一步看到这一点。


示例:解读“Paris”的词向量

让我们概念性地看一个特定的单词,例如“Paris”。我在这里做的是,为这个10维向量的每个分量分配主题或主题。这些主题或主题将在我们的机器学习过程中被学习。

为这些主题分配特定的名称(如体育、政治、历史)是概念性的,我们并不明确这样做。但这是为了帮助理解与这个词向量相关的底层概念。

如果我们看“Paris”这个词:

  • 从历史上看,巴黎扮演了重要角色,它是法国的首都。
  • 它在政治上也扮演了重要角色。因此,我们概念性地看到该向量的第二个分量(对应政治)是正的,这意味着巴黎与政治正相关。
  • 同样,由于巴黎是一个重要国家(法国)的首都,它在历史上具有非常重要的作用。因此,我们看到第三个分量(对应历史)是正的。
  • 第四个分量概念上对应动作或动词。巴黎是一个专有名词,与动作没有太多明确关系。因此,我们看到动作分量为负。
  • 巴黎是一个城市的名字。因此,下一个对应名称的分量是正的。

我们试图在这里反映的理念是:词向量的底层分量具有某种主题或语义上的意义。我们不需要明确知道这种意义是什么,但它会通过机器学习被揭示出来。

因此,我们想从中得出的结论是:词向量所做的是,按分量表示该单词是否与某个主题对齐。如果对齐,则分量为正;如果不对齐,则分量为负。这提供了单词的底层语义含义。这就是词向量概念所要反映的。


迈向新模型

接下来,我们将利用词向量所代表的这种意义或关联性的理念,来构建一种用于自然语言处理的新形式的机器学习模型。


总结

本节课中,我们一起学习了词向量的核心概念。我们了解到,词向量是将词汇映射到高维空间向量的技术,其目标是捕捉单词的语义信息。每个向量分量可以概念性地理解为与某个潜在主题的对齐程度(正值为对齐,负值为不对齐)。这种表示方法为理解单词的深层含义和构建更强大的自然语言处理模型(如Transformer)提供了基础。

052:词向量间的关系 🔍

在本节课中,我们将深入探讨词向量的含义,理解其各个维度如何捕捉词语的潜在语义和关系。我们将通过具体的例子,展示词向量如何编码诸如性别、单复数等概念,并揭示这些向量在几何空间中的规律性。


词向量的语义维度

上一节我们介绍了词向量的基本概念。本节中,我们来看看词向量的各个维度具体代表什么含义。

每个词向量的分量都对应一个潜在的主题或语义特征。以下是几组含义相似但存在关键差异的词语对。

以下是“king”(国王)与“queen”(女王/王后)的对比:

  • kingqueen 都是王室职位,含义非常相似。
  • 关键区别在于,king 通常为男性,而 queen 通常为女性。
  • 因此,kingqueen 的词向量在几乎所有分量上都相同,除了一个分量
  • 在这个特定的分量上,king 的值为正,queen 的值为负。
  • 我们可以推断,这个分量代表“性别”

以下是“uncle”(叔叔/舅舅)与“aunt”(阿姨/舅妈)的对比:

  • uncleaunt 对于年轻人来说含义基本相同。
  • 关键区别在于,uncle 是男性,aunt 是女性。
  • 同样,uncleaunt 的词向量在几乎所有分量上都相同,除了一个分量
  • 在这个分量上,uncle 的值为正,aunt 的值为负。
  • 我们再次推断,这个分量也代表“性别”,并且它在“king/queen”和“uncle/aunt”这两组词对中表现一致。

通过这个简单的例子,我们理解了词向量如何编码语义。这揭示了词向量所捕捉的底层机制。


单复数关系的编码

理解了性别维度后,我们再来看看词向量如何编码“单复数”关系。

以下是“king”(国王)与“kings”(国王们)的对比:

  • kingkings 是同一个词,区别在于一个是单数,一个是复数。
  • kingkings 的词向量在几乎所有分量上都相同,除了一个分量
  • 在这个分量上,king(单数)的值为正,kings(复数)的值为负。
  • 因此,这个分量代表词语的“单数性”。对于单数词(king)它是正的,对于复数词(kings)它是负的。

这种关系同样适用于“queen”和“queens”。此外,请注意代表“性别”的分量在“king/kings”之间保持一致,在“queen/queens”之间也保持一致,但在“king”和“queen”之间是不同的。

核心思想是:如果我们能够通过学习得到这些词向量,并通过观察已知的、仅在某一方面有区别的词语对,我们就可以分析它们的词向量,找出相似和不同之处,从而揭示这些词向量背后关联的底层语义。


词向量关系的几何直观

之前课程的另一部分曾展示过这种关系。这里我们要表达的是,每个词语都对应一个嵌入向量或词向量(图中为二维空间表示)。

概念上存在这样的关系:man(男人)之于 woman(女人),如同 uncle(叔叔)之于 aunt(阿姨),也如同 king(国王)之于 queen(女王)

如果我们讨论的关系成立,即 king 之于 kings 如同 queen 之于 queens,那么即使“king”和“queen”是不同的词、不同类型的词,我们也会期望在它们所表示的 D 维空间中的词嵌入或词向量之间,存在一致性的几何关系。

在右侧我们看到,“king 到 kings”的向量关系与“queen 到 queens”的向量关系是平行的。这是一种基于词语底层语义,我们期望在词向量中发现的几何概念。这种关系为我们理解这些词向量的实际含义提供了直观的底层逻辑。


总结

本节课中我们一起学习了词向量间的关系。我们通过“king/queen”、“uncle/aunt”的例子,看到词向量的特定维度可以编码“性别”语义;通过“king/kings”、“queen/queens”的例子,看到另一个维度可以编码“单复数”语义。最后,我们认识到这些语义关系会表现为词向量空间中的一致性几何变换(如平移),这为我们理解和解释词向量提供了强大的直观工具。

053:词向量的内积

在本节课中,我们将学习如何将单词映射为向量,并引入一个核心概念——内积(也称为点积)。我们将探讨如何使用内积来量化两个词向量之间的相似性,这是后续构建更复杂自然语言处理模型的基础。

从单词到向量

上一节我们介绍了将单词映射为向量的概念。现在,我们进一步理解这种映射所代表的含义,并开始向前推进,着手对单词序列、句子或文档进行建模。

考虑一个包含 N 个单词的序列,表示为 W1, W2, ..., WN。这可以是一个句子或文档中的单词。基于我们目前的理解,每个单词都将被映射到一个 D 维的向量或编码。例如,单词 W1 对应编码 C1,W2 对应 C2,以此类推,WN 对应 CN。

单一向量映射的局限性

此时,你可能会意识到一个潜在问题:将每个单词映射到单一向量的概念存在限制。因为字典中的一个单词通常有多个定义,具体使用哪个定义取决于该词所处的上下文环境。因此,为每个单词分配一个固定向量(意味着该词只有一种我们之前讨论过的“含义”),显得过于局限,因为它没有考虑周围单词提供的语境信息。

因此,我们现在希望建立一个框架,能够根据周围单词所暗示的含义来调整这些词向量。

引入内积概念

为了实现上述目标,我们需要引入两个词向量之间的内积这一新概念。我们将以一种相对简单的方式来介绍它。

再次强调,我们有 N 个单词 W1 到 WN,它们被映射到 N 个编码 C1, C2, ..., CN。每个编码 C 都是一个 D 维向量。例如,C1 有 D 个分量,可以表示为 C11(第一个分量),C12(第二个分量),...,C1D(第 D 个分量)。

现在,我们引入两个编码之间的内积概念。以单词 W1 和 W2 对应的编码 C1 和 C2 为例,我们希望通过一种方式量化这两个编码之间的关系。这种方式就是内积,也称为点积。记作 C1 · C2

以下是计算内积的具体步骤:

  1. 取 C1 的第一个分量和 C2 的第一个分量,将它们相乘。
  2. 取 C1 的第二个分量和 C2 的第二个分量,将它们相乘。
  3. 以此类推,对 D 个分量中的每一个都执行此操作。
  4. 最后,将所有 D 个乘积结果相加。

用公式表示如下:
C1 · C2 = Σ (C1_i * C2_i),其中 i 从 1 到 D。

这个相乘然后求和的过程,就是内积运算。内积的作用是量化 C1 与 C2 的相似程度。

我们可以对词汇表中的任意两个编码进行此操作。如果单词 W1 和 W2 含义相似,那么根据我们之前的讨论,代表其含义的编码 C1 和 C2 也应该相似。如果 C1 和 C2 相似,那么它们的点积 C1 · C2 将会是一个较大的正数。反之,如果单词 W1 和 W2 不相似,对应的编码也不同,那么它们的内积往往会较小甚至是负数。

核心要点:使用内积来通过词向量量化单词之间的相似性,是后续神经网络处理自然语言任务的基础。

内积的简洁表示法

内积是我们后续讨论中会反复使用的工具。为了书写方便,我们将引入一个简洁的表示法。

从今往后,编码 C1 和 C2 之间的内积将用以下简洁形式表示:
<C1, C2>

这个符号 < , > 就代表我们之前定义的内积运算:将两个向量的对应分量相乘,然后求和。

总结

本节课中,我们一起学习了:

  1. 回顾了将单词映射为向量的模型。
  2. 指出了为每个单词分配单一固定向量的局限性,因为它忽略了上下文信息。
  3. 引入了内积(点积) 这一核心概念,其公式为 <C1, C2> = Σ (C1_i * C2_i)
  4. 理解了内积可以量化两个词向量的相似性:相似单词的向量内积倾向于为正且较大,不相似单词的向量内积则较小或为负。
  5. 掌握了内积的简洁表示法 < , >

内积是连接词向量与语义相似度的桥梁,为接下来构建能够理解上下文的神经网络语言模型奠定了重要的数学基础。

054:词向量内积意义的直观理解 🔍

在本节课中,我们将深入探讨词向量内积的概念,理解其含义以及如何应用。我们将从一个高度简化的10维词向量表示开始,逐步分析内积如何揭示词语之间的相似性与差异性,并解释为何在机器学习中常使用指数函数来处理内积值。


词向量的简化表示

上一节我们介绍了词向量的基本概念,本节中我们来看看一个具体的简化示例。我们使用一个10维向量来表示词语,这纯粹是为了可视化方便。在实际的自然语言处理机器学习任务中,词向量的维度通常更高,例如256或512维。

我们回到之前讨论过的“巴黎”一词的例子。每个维度都代表某种潜在的含义,例如性别、复数形式等。如果词语与某个维度代表的概念正相关,则该维度的值为正;如果负相关或不相关,则为负。

内积与词语相似性

现在,让我们利用这个概念来进一步理解内积的作用。假设我们从词汇表中任意选取两个词:词 i 和词 j

以下是这两个词向量在10个维度上的示意情况:

  • 在几乎所有维度上,词 i 和词 j 的符号(正或负)都是一致的。
  • 例如,在第10个维度上,两者都为正;在第一个维度上,两者都为负。

由于每个维度都代表某种潜在含义,这种符号的一致性意味着这两个词向量是相似的,进而可以推断这两个词的含义也相似。

内积的计算与意义

内积的计算是逐分量相乘后求和。记住这个公式:内积 = sum(向量_i的每个分量 * 向量_j的对应分量)

基于上述观察,我们可以推导:

  • 当两个分量符号相同时(正正或负负),它们的乘积为正数。
  • 如果两个词向量在大多数维度上符号一致,那么大多数乘积项为正数,求和得到的内积结果也将是一个较大的正数。
  • 因此,词语越相似,其对应词向量的内积值就越大、越正

相反,考虑另一种情况:

  • 如果词 i 和词 j 在大多数维度上的符号相反。
  • 例如,词 i 在第10个维度为负,而词 j 为正;在第一个维度上,词 i 为正,而词 j 为负。
  • 符号相反的分量相乘会得到负数。当大多数乘积项为负数时,求和得到的内积结果将是一个负数。
  • 因此,负的内积值意味着两个词语不相似,含义不同

核心概念:词向量的每个维度编码了潜在语义。两个词语越相似,其向量在各维度上的符号越一致,内积值越正;越不相似,符号越相反,内积值越负。因此,内积值的正负和大小揭示了词汇表中任意两个词语之间的语义关系。

引入指数函数

然而,在机器学习实践中,处理有时为正、有时为负的内积值并不方便。我们希望所有数值都是正的,但同时要保留“正代表相似,负代表不相似”的序关系。

这时,指数函数 exp(x) 就派上了用场。以下是其关键特性:

  1. 输出恒为正:对于任何输入 xexp(x) 的输出总是正数。
  2. 单调递增:如果 x1 > x2,那么 exp(x1) > exp(x2)。它完美地保留了输入值的大小顺序。

在词向量的上下文中,我们将内积值作为指数函数的输入 x

  • 如果两个词相似,内积 C1·C2 是一个较大的正数,那么 exp(C1·C2) 会是一个更大的正数。
  • 如果两个词不相似,内积 C1·C2 是负数或很小的正数,那么 exp(C1·C2) 会是一个接近0的正数。
  • 无论内积是正是负,exp(C1·C2) 的输出永远是正数。

因此,通过对内积取指数,我们既将所有值转换为了正数(便于后续模型计算),又通过函数的单调性完整保留了词语相似度的比较信息。这为接下来要构建的机器学习模型提供了极大的便利。


本节课中我们一起学习了词向量内积的直观意义。我们了解到,内积的正负和大小直接反映了两个词语在语义上的相似程度。同时,为了适应机器学习模型的需求,我们引入了指数函数 exp(x) 来处理内积值,使其恒为正的同时,保留了关键的序关系,为后续的建模工作奠定了基础。

055:注意力机制介绍 🧠

在本节课中,我们将学习注意力机制的核心概念。注意力机制是现代自然语言处理中的关键组成部分,它通过计算词向量之间的相似度,来量化一个词与序列中其他词的关系强度。我们将从基本概念入手,逐步构建出完整的注意力计算过程。


上一节我们介绍了词向量的概念,本节中我们来看看如何量化词与词之间的关系。我们假设有一个包含 N 个词的句子或文档,这些词表示为 C1, C2, ..., Ck, ..., CN。

我们知道,两个词向量的内积是衡量它们相似度的一个指标。如果内积为正,则两个词向量相似;如果内积为负,则它们不相似。

基于此,我们将量化序列中每个词与第 K 个词的相似度。以下是计算相对相似度的三个步骤:

  1. 计算内积:首先,取第 K 个词向量 Ck,分别与序列中所有 N 个词向量(C1 到 CN)计算内积。这量化了 Ck 与每个词的原始相似度。

    • 相似度原始值_i = Ck · Ci
  2. 指数化:由于内积结果可能为正或负,我们使用指数函数 exp() 对其进行处理。指数函数输出始终为正,并且它是一个单调递增函数,因此能保持内积大小的相对顺序。

    • 指数化相似度_i = exp(Ck · Ci)

  1. 归一化:最后,为了得到第 K 个词与第 I 个词的相对相似度,我们将 Ck 与 Ci 的指数化内积,除以 Ck 与序列中所有词(C1 到 CN)的指数化内积之和。这样得到的结果称为关系权重 R_{k→i}。
    • R_{k→i} = exp(Ck · Ci) / Σ_{j=1 to N} [ exp(Ck · Cj) ]

这个过程——内积、指数化、归一化——是注意力机制的核心构造块。为了简化表示,我们通常用右边的符号来概括左边的整个计算流程。


现在,让我们总结一下关系权重 R_{k→i} 的特性。首先,由于经过了指数运算,R_{k→i} 的值总是介于 0 和 1 之间的正数。其次,对于固定的 K,所有 R_{k→i}(i 从 1 到 N)之和等于 1。

这意味着 R_{k→i} 量化了词 K 与词 I 的相对关联强度。R 值越大,表示两个词在语义或语法上的关联越强;R 值越小(趋近于 0),则表示关联越弱。语言本身存在内在的词汇关系,而 R 正是对这种关系的数学量化。

在机器学习的背景下,我们将通过梯度下降(对于大数据集则使用随机梯度下降)来学习这些词向量。模型的目标是让学习到的词向量能够通过上述计算过程,准确地反映出词汇之间的真实关系。


最后,需要指出这个框架的一个重要计算优势:并行性。计算第 K 个词与序列中所有其他 N 个词的内积,这些操作是彼此独立的,可以同时进行。

这与我们课程中介绍过的长短期记忆循环神经网络不同。循环神经网络的计算是顺序的,一步接一步,因此不适合并行计算。而注意力机制中的内积计算可以高度并行化,这恰好契合了现代图形处理器强大的并行计算能力,能显著提升模型的计算效率。


本节课中我们一起学习了注意力机制的基本原理。我们了解到,通过内积衡量词向量相似度,再经过指数化归一化,可以得到一个词相对于序列中所有其他词的注意力权重。这个权重不仅量化了词汇间的关系,其可并行计算的特性也为高效处理自然语言任务奠定了基础。

056:注意力网络的查询、键与值 🧠

在本节课中,我们将学习注意力机制的核心概念,特别是如何通过查询、键和值来构建一个能够理解上下文的新词向量表示。我们将从回顾之前的内容开始,逐步引入这些新概念。


上一节我们讨论了如何通过内积和归一化来计算词与词之间的相对关系。本节中,我们来看看如何利用这种关系来“精炼”一个词的向量表示,使其包含上下文信息。

我们有一个由 N 个词组成的序列,每个词 Wi 都映射到一个对应的编码 Ci。对于序列中的第 K 个词(其编码为 CK),我们想量化它与序列中其他每个词的相似度。我们通过计算内积来实现这一点。如果两个词相似,内积倾向于为正;如果不相似,则倾向于为负。

接着,我们通过指数化和归一化来量化词 K 与每个词 I 之间的相对关系,得到一组 R 值。R_{K->I} 代表了词 K 与词 I 之间的相对关系。

现在,我们的目标是修订或精炼词 K 的向量 CK。需要记住的是,从词 K 到编码 CK 的映射是独立于该词的使用语境的。因此,我们希望修改词 K 的向量或编码,以考虑其周围词语构成的上下文。

我们已知 R_{K->1} 代表词 K 与词 1 的相对关系,R_{K->2} 代表与词 2 的关系,依此类推。每个 R 值都是正数,且它们的总和为 1。我们将利用这个想法,为词 K 生成一个考虑了其所在上下文(即 N 个词 C1CN)的精炼编码。

以下是具体步骤:

  1. 我们将 R_{K->1} 乘以编码 C1
  2. R_{K->2} 乘以编码 C2
  3. 以此类推,直到将 R_{K->N} 乘以编码 CN
  4. 最后,将所有乘积相加。

这样,我们就得到了词 K 的一个新表示 \tilde{C}_K(波浪线符号称为“tilde”)。

这个过程的关键在于:如果词 K 与序列中的某个特定词高度相关,那么对应的 R 值就会很大。这个大的 R 值会乘以相关的编码,从而使这个高度相关的词对精炼后的编码 \tilde{C}_K 做出显著贡献。通过这种方式,我们根据词 K 与序列中其他 N 个词的上下文相对关系,修订了它的编码向量。


这些关系数 R_{K->I} 告诉我们,在进行到 \tilde{C}_K 的映射时,我们应该对编码 CI 给予多少注意力。如果关系度高(R 值大),我们就应该高度关注那个词;如果关系度低(R 值小),则意味着词 K 与该词关联不大,我们应该给予较少关注。

因此,这个概念被称为注意力。在自然语言处理的神经网络中,它量化了在构建词 K 的新表示时,应该给予词 I 多少关注(通过内积隐含地量化)。这样,我们通过注意力机制,将原始的、独立于上下文的编码向量 CK,转换成了考虑了所有其他词语上下文的新向量 \tilde{C}_K


现在,我想引入一些标准符号,因为这种注意力网络将成为我们后续构建基于注意力的自然语言处理网络的基础。

  • 查询:我们正在考察的编码 CK 被称为查询。我们用这个查询来探究它与序列中其他 N 个词的关系。
  • :序列中其他 N 个词对应的向量被称为。查询 CK 与每个键通过内积计算出的相关度,量化了在构建更新版编码 \tilde{C}_K 时,应对对应向量给予多少注意力。
  • :关系权重 R_{K->I} 所乘的对象被称为。在这里,值就是原始序列中的 N 个编码向量本身。

因此,整个过程可以概括为:我们有一个查询,它通过与每个计算内积来获得相对权重,这些权重再与对应的相乘,最终为查询生成一个考虑了上下文(由 N 个编码 C1CN 构成)的新表示 \tilde{C}_K


本节课中,我们一起学习了注意力机制的核心运作原理。我们了解到,通过将目标词作为查询,序列中其他词作为,可以计算出一组注意力权重。这些权重决定了在生成目标词的新上下文相关表示时,应如何加权组合其他词的信息。这为理解更复杂的 Transformer 等模型奠定了重要基础。

057:自注意力与位置编码

在本节课中,我们将学习自注意力机制如何为序列中的每个单词生成包含上下文信息的向量表示,并探讨如何通过位置编码来解决自注意力机制忽略单词顺序的问题。

概述

我们从一个由N个单词组成的序列开始:W1, W2, ..., WN。首先,我们将每个单词映射为一个独立的向量,称为编码(Code),记作 C1, C2, ..., CN。然而,这些初始编码存在一个问题:它们没有考虑单词在句子中的上下文关系。例如,“bank”一词在“river bank”和“bank account”中含义不同,但初始编码无法体现这种差异。

为了解决这个问题,我们引入了自注意力机制。该机制能够将每个单词的初始编码 Ck,转换成一个新的编码 C̃k。这个新编码不仅保留了单词本身的含义,还融合了它与序列中所有其他单词的关系信息。

上一节我们介绍了自注意力的基本概念,本节中我们来看看其具体工作原理以及一个关键的改进——位置编码。

自注意力机制的工作原理

自注意力机制的核心思想是:为序列中的每个单词计算一个新的表示,该表示是序列中所有单词原始表示的加权和。权重由单词之间的“相关性”决定。

具体步骤如下:

  1. 对于目标单词 k,我们将其编码 Ck 作为查询(Query)。
  2. 将序列中所有单词的编码 C1, C2, ..., CN 既作为(Key),也作为(Value)。
  3. 计算查询 Ck 与每个键 Cj点积(Dot Product),得到一个相关性分数。这个分数衡量了单词 k 与单词 j 的关联程度。
    • 公式:score(k, j) = Ck · Cj
  4. 对所有相关性分数应用 Softmax 函数,将其转换为和为1的正数权重 Rk1, Rk2, ..., RkN
    • 公式:Rkj = softmax(score(k, j))
  5. 新的编码 C̃k 是所有权重 Rkj 与对应值 Cj 的加权和。
    • 公式:C̃k = Σ (Rkj * Cj), 其中 j 从1到 N

这个过程确保了 C̃k 是原始编码 C1CN 的一个凸组合。我们可以对序列中的每一个单词(k=1, 2, ..., N)重复此过程,从而得到一组全新的、包含上下文信息的编码序列:C̃1, C̃2, ..., C̃N

自注意力机制的局限性:忽略词序

然而,上述自注意力机制存在一个显著缺陷:它对单词的顺序不敏感

这意味着,如果我们打乱输入序列 W1, W2, ..., WN 的顺序(例如进行排列置换),经过自注意力机制处理后,输出的新编码序列 C̃1, C̃2, ..., C̃N 在内容上将是相同的,只是顺序相应地被打乱。单词的向量表示不会因为它在句子中的位置不同而改变。

这显然不符合语言的实际规律。单词的顺序至关重要。例如,“猫追老鼠”和“老鼠追猫”表达了完全不同的意思。因此,我们需要对模型进行改进,使其能够感知单词的位置信息

引入位置编码

为了解决词序问题,我们引入位置编码(Positional Embedding)。其核心思想是:为序列中的每个位置(第1个词,第2个词...)生成一个独特的、固定维度的向量,然后将这个向量加到该位置单词的初始编码上。

这样,模型在计算注意力时,使用的输入就变成了“单词含义 + 位置信息”。

以下是构建位置编码 P 的一种常用方法(使用正弦和余弦函数):

对于位置为 pos 的单词,其位置编码向量的第 i 个维度(i 为偶数或奇数)的值由以下公式给出:

  • P(pos, 2i) = sin(pos / 10000^(2i/d))
  • P(pos, 2i+1) = cos(pos / 10000^(2i/d))

其中,d 是编码向量的总维度。

这种设计具有以下特点:

  • 每个位置有唯一编码:不同 pos 值会产生不同的正弦/余弦波形组合,从而生成独特的向量。
  • 模型能感知相对位置:由于正弦函数的性质,对于固定的偏移量 kP(pos + k) 可以表示为 P(pos) 的线性函数,这有助于模型学习单词间的相对距离。
  • 能处理任意长度序列:公式是确定性的,可以计算训练时未见过的序列位置。

完整的序列编码器架构

结合自注意力、位置编码和其他优化技术,我们得到了一个强大的序列编码器(Sequence Encoder)模块。以下是其核心组件和数据流:

  1. 输入与词嵌入:输入是一个单词序列。首先通过词嵌入层将每个单词映射为一个 d 维向量。
  2. 添加位置编码:为序列中的每个位置生成一个 d 维的位置编码向量 P。将词嵌入向量与对应的位置编码向量相加,得到融合了语义和位置信息的输入表示。
  3. 自注意力层:将上一步的结果同时作为查询,输入到自注意力网络中。该层输出包含全局上下文信息的新向量序列。
  4. 残差连接与层归一化:将自注意力层的输出与它的输入(即步骤2的结果)进行相加(这就是残差连接跳跃连接),然后进行层归一化。这有助于缓解梯度消失问题,稳定训练过程。
  5. 前馈神经网络:将归一化后的每个向量独立地通过一个简单的前馈神经网络(通常是两层线性变换加一个激活函数,如ReLU或tanh)。这为模型增加了非线性变换能力。
  6. 再次残差连接与层归一化:将前馈网络的输出与它的输入(即步骤4的结果)再次进行相加层归一化,得到该编码器模块的最终输出。

这个编码器模块是Transformer等现代自然语言处理模型的基础构件。通过堆叠多个这样的模块,模型能够学习到非常复杂和深层的语言表示。

总结

本节课中我们一起学习了:

  1. 自注意力机制:它通过计算序列内部单词间的相关性,为每个单词生成包含上下文信息的向量表示。其核心公式是 C̃k = Σ (softmax(Ck · Cj) * Cj)
  2. 自注意力的局限性:该机制本身是排列等变的,无法区分单词的顺序,而词序在语言中至关重要。
  3. 位置编码的解决方案:我们通过为每个位置生成一个独特的向量(例如使用正弦/余弦函数),并将其加到单词的初始嵌入上,从而将位置信息注入模型。公式为 P(pos, 2i)=sin(pos/10000^(2i/d))P(pos, 2i+1)=cos(pos/10000^(2i/d))
  4. 完整的序列编码器:结合词嵌入、位置编码、自注意力层、残差连接、层归一化和前馈网络,构成了一个强大的序列编码基础模块。这个模块能够同时处理单词的语义、位置及其在全局上下文中的关系。

在下一节课中,我们将逐一深入剖析这个序列编码器的各个组件,从概念上理解它们的作用,并探讨为何这种架构能如此有效地处理自然语言任务。

058:基于注意力的序列编码器 🧠

在本节课中,我们将学习一种用于建模词序列的新框架。这个框架是现代基于神经网络的序列建模方法——Transformer网络的核心。理解其每个组成部分至关重要,因为它们会反复出现。

概述

我们将从底部开始,逐步向上解析这个序列编码器的各个组件。该框架结合了词义、位置信息和上下文理解,是构建强大自然语言处理模型的基础。


词嵌入与位置嵌入

上一节我们介绍了建模词序列的新框架。本节中,我们来看看其第一个核心步骤:将词序列转换为向量表示。

我们首先有一个由N个词组成的序列:W1, W2, ..., WN。每个词会被映射到一个D维向量,这称为词嵌入。这些向量反映了词的含义,其D个分量编码了对应词的意义。这是一个非常重要的概念。

然而,最简单的词嵌入形式没有考虑周围词的上下文信息,也没有考虑词的顺序

因此,下一步是引入位置嵌入的概念。

现在,我们将为每个词引入一个新的D维向量。这些向量与词的含义无关,而是与词的位置相关。根据词在序列中的位置,每个词会有一个不同的、依赖于位置的D维向量。

接着,我们将这N个位置向量与N个词嵌入向量相加。公式表示为:
最终向量 = 词嵌入向量 + 位置嵌入向量

此时,经过“词嵌入 + 位置嵌入”后,我们得到的向量既表征了词的含义,也考虑了词的位置。

这个简单的相加操作可能看起来有违直觉,但在实践中发现它非常有效。我们应尽可能选择简单的模型,而这个简单的想法在实践中被证明是可行的。

注意力机制与上下文

在考虑了词义和位置之后,我们还需要纳入上下文信息。

经过加和后的每个词向量,现在将扮演三个角色:键(K)值(V)查询(Q)。这些向量随后被送入我们之前讨论过的注意力网络中。

注意力网络能够考虑词的上下文。至此,我们通过词嵌入获得了词义,通过位置嵌入获得了位置信息,现在又通过注意力网络获得了上下文信息。

跳跃连接与前馈神经网络

为了避免丢失原始的嵌入向量信息,我们引入了跳跃连接。这意味着原始向量会绕过注意力网络,直接加到注意力网络的输出上。跳跃连接被证明能有效提升模型性能。

最后,我们引入一个前馈神经网络来处理这些向量。这样做有两个主要原因:

  1. 提供正则化或结构:从数学角度,它将神经网络的输出限制在与网络相关的向量子空间内,这有助于提升性能。
  2. 约束输出范围:通过使用双曲正切(tanh)等激活函数,神经网络的输出值被限制在-1到1之间。这种约束也被发现能改善序列编码器的性能。

构建深度序列编码器

上述“注意力网络 + 前馈神经网络 + 跳跃连接”的过程可以重复多次(K次)。在实践中,K通常等于6。

这种深度堆叠的结构构成了我们的最终深度序列编码器。它是Transformer网络中用于建模词序列的关键模块。


序列编码器的应用

一旦我们拥有了这个序列编码器,就可以用它做很多事情。以下是两个简单的应用示例:

1. 情感分析

我们可能想分析一个由N个词组成的序列所表达的情感是积极还是消极(例如,对电影或餐厅的评论)。

一种简单的使用方法是:

  1. 将输入序列通过编码器(词嵌入 -> 位置嵌入 -> K层注意力/前馈网络)处理。
  2. 在顶部得到N个编码向量。
  3. 计算这些向量的平均值,得到一个代表整个序列的向量 V。公式为:
    V = (1/N) * Σ(编码向量_i)
  4. 引入一个需要学习的参数向量 E
  5. 通过计算 VE 的点积,并经过Sigmoid函数,来量化情感倾向。公式为:
    情感概率 = σ(V · E)
    其中,σ 是Sigmoid函数。

2. 预测下一个词

另一个常见任务是给定前N个词,预测第N+1个词是什么。

处理流程如下:

  1. 同样将前N个词的序列通过编码器处理,得到N个编码向量。
  2. 计算这些向量的平均值,得到向量 V
  3. 我们有一个词汇表,大小为V。对于词汇表中的第k个词,都有一个对应的需要学习的参数向量 E_k
  4. 通过Softmax函数计算下一个词是词汇表中第k个词的概率。公式为:
    P(下一个词 = k) = exp(V · E_k) / Σ_j(exp(V · E_j))

总结

本节课我们一起学习了基于注意力的序列编码器,它是Transformer网络的核心。我们逐步拆解了其构成:

  1. 通过词嵌入捕获词义。
  2. 通过位置嵌入捕获词序。
  3. 通过注意力机制捕获上下文信息。
  4. 通过跳跃连接保留原始信息。
  5. 通过前馈神经网络进行正则化和约束。
  6. 通过堆叠多层(K次) 构建深度模型,以增强表示能力。

我们还看到了该编码器在两个简单任务(情感分析和下一个词预测)中的应用。然而,这个Transformer编码框架的能力远不止于此,它将引领我们进入下一部分的学习:如何利用这些网络预测整个词序列,而不仅仅是单个词。

059:序列编码器与解码器的耦合 🔄

在本节课中,我们将学习如何将序列编码器与解码器耦合,以完成更复杂的任务,如机器翻译或文本摘要。我们将深入探讨编码器-解码器架构的工作原理,特别是“交叉注意力”机制。


概述

上一节我们介绍了如何使用序列编码器(如Transformer)来编码一个词序列并预测下一个词。然而,许多任务的目标不仅仅是预测下一个词,而是预测下一个完整的词序列。例如,将一句英语翻译成法语,或者为一长段文本生成简洁的摘要。本节我们将探讨如何通过耦合编码器和解码器来实现这一目标。

编码器回顾

首先,让我们回顾一下左侧的输入序列编码器。这是我们之前讨论过的核心结构。

我们有一个词序列 W1WN(例如,一个英语句子)。处理流程如下:

  1. 词嵌入:将每个词映射为一个 d 维向量,捕捉其语义。
  2. 位置嵌入:为每个位置生成一个 d 维向量,与词义无关,仅表示词在序列中的顺序。
  3. 相加:将词嵌入向量与对应的位置嵌入向量相加,得到同时包含语义和位置信息的向量。
  4. 注意力网络:通过自注意力机制,让每个词的表示能考虑到其上下文(周围所有词)的信息。
  5. 深度编码:上述注意力过程会重复 K 次,构成一个深度编码网络。

最终,在编码器顶部,我们得到了一组向量。这组向量综合了每个词的语义位置上下文信息。

解码器架构

现在,假设我们已经用编码器处理了一个长度为 N 的英语序列。我们的目标是将它转换成一个法语词序列。这需要右侧的解码器来完成。

解码器的结构与编码器非常相似,但有几个关键区别。其输入是已预测出的输出序列

以下是解码器的逐步工作流程:

  1. 输入序列:解码器底部的输入是截至目前已预测出的 M 个法语词。最重要的一点是:最左边的词是最近预测的词,越往右的词预测得越早。每次预测一个新词后,整个输入序列会向右移动一位,新词插入最左端。
  2. 词嵌入与位置嵌入:与编码器相同,我们将已预测的法语词通过法语词表映射为词嵌入,并加上对应的位置嵌入。
  3. 自注意力:同样,通过注意力机制让每个已预测词的表示能考虑到其他已预测词的上下文。这个过程也会重复 J 次,构成解码器的深度网络。
  4. 交叉注意力:这是解码器的核心不同之处。解码器需要利用编码器输出的信息。具体做法是:
    • 查询:来自解码器当前步骤处理后的向量。
    • 键与值:来自编码器最终输出的那组向量。
    • 我们将这三者输入到一个注意力网络中。这个网络让解码器在生成下一个词时,能够“关注”输入序列(英语)中最相关的部分。
  5. 前馈神经网络与Softmax:经过交叉注意力后,向量会通过一个前馈神经网络进行进一步变换。最后,通过一个Softmax层,预测出下一个最可能的词。这个词随后被添加到解码器输入序列的最左端,过程重复,直到生成完整的输出序列。

核心概念:交叉注意力

交叉注意力是连接编码器和解码器的桥梁。它的公式与标准注意力机制相同:

Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V

其中:

  • Q 来自解码器(已预测序列的表示)。
  • KV 来自编码器(输入序列的编码表示)。

通过计算 QK 的相似度,模型可以决定在生成当前输出词时,应该对输入序列的哪些部分赋予更高的权重。

总结

本节课中,我们一起学习了序列到序列模型的核心——编码器-解码器架构。

  • 我们回顾了编码器如何将输入序列(如英语句子)编码为富含语义、位置和上下文信息的向量表示。
  • 我们详细探讨了解码器如何逐步生成输出序列(如法语句子)。它利用已生成的部分序列,通过自注意力整合自身上下文,并通过交叉注意力机制聚焦于编码器提供的输入信息,从而预测下一个词。
  • 我们明确了交叉注意力是实现编码与解码信息流耦合的关键,它使得解码器在生成每一个词时都能动态地参考输入序列的相关内容。

这种编码器-解码器架构,特别是结合了注意力机制的Transformer模型,已成为机器翻译、文本摘要、对话生成等序列生成任务的基石。

060:序列到序列模型中的交叉注意力

在本节课中,我们将要学习序列到序列模型,特别是其中的一个核心组件——交叉注意力机制。我们将了解它如何连接编码器和解码器,并理解其在机器翻译等任务中的关键作用。

概述

我们之前已经构建了一个名为Transformer的序列到序列模型。该模型左侧是编码器,负责处理输入序列;右侧是解码器,负责生成输出序列。本节课,我们将深入探讨连接这两部分的关键机制:交叉注意力。

编码器输出:键与值

上一节我们介绍了Transformer的整体架构,本节中我们来看看编码器的输出如何为注意力机制提供信息。

在编码器的顶部,我们得到了输入序列的编码表示。如果输入序列由M个词组成,那么编码网络的输出就是M个向量,每个向量的维度为D。

以下是这些向量的作用:

  • 这些M个向量构成了注意力机制中的

解码器状态:查询

理解了编码器的输出后,我们接下来看看解码器如何利用这些信息。

在解码网络的底部,是当前已生成输出序列的表示。如果我们到目前为止已经解码了N个词,那么就会有N个对应的向量,每个向量维度也是D。

以下是这些向量的作用:

  • 这N个对应于已解码词的向量,构成了注意力机制中的查询

交叉注意力机制

现在,我们已经有了查询、键和值,本节中我们将看看它们如何共同工作,形成交叉注意力。

编码器顶部输出的M个向量是注意力网络的键和值。解码器已生成的N个词对应的向量是注意力网络的查询。之所以称为“交叉”注意力,是因为查询来自解码器已生成的N个词,而键和值来自编码器编码的输入M个词。

当我们将这N个查询与M个键和值进行注意力计算时,会得到一个新的序列,包含N个新的D维向量。这个过程意味着,通过注意力机制,当前已解码的N个词被根据输入序列的编码信息(键和值)进行了重新表示。

Transformer模型与应用

这种左侧编码输入序列、右侧解码输出序列的复合模型,被称为Transformer网络。

Transformer网络有许多应用。正如之前提到的,一个关键应用是序列到序列模型,例如机器翻译。你可以输入一个英语句子序列,然后解码器输出一个德语句子序列。此外,Transformer也可用于情感分析,或预测接下来可能输入的一两个词等任务。

总结

本节课中我们一起学习了序列到序列模型中的交叉注意力机制。我们了解到,编码器将输入序列编码为键和值,解码器将已生成序列作为查询,通过注意力机制,解码器能够动态地聚焦于输入序列的不同部分,从而生成更准确的输出。这种机制是Transformer模型实现高效翻译和理解任务的核心。

061:多头注意力机制

在本节课中,我们将学习Transformer网络中的一个核心概念——多头注意力。我们将从回顾已学过的注意力机制开始,然后深入探讨其如何被扩展为更强大的多头注意力形式。

注意力机制回顾

上一节我们介绍了注意力机制的基本原理。在Transformer网络中,注意力机制是我们已构建模型的基础,它主要通过两种方式体现。

首先,是自注意力。我们有一个由n个单词组成的序列,每个单词由一个向量表示。通过注意力机制,我们根据周围单词的特征来修改每个单词的向量表示。

其次,是交叉注意力。在序列到序列模型中,我们评估编码器输出和解码器输出之间的注意力关系。我们有一个输入序列和一个输出序列,交叉注意力帮助解码器在生成输出时关注输入序列的相关部分。

多头注意力概述

在原始的Transformer网络中,注意力机制被推广为所谓的多头注意力。接下来,我们将花一些时间理解这个概念,它是实际应用中Transformer网络的核心。

在深入之前,让我们先回忆一下注意力机制的各个组成部分。

注意力机制组件

在注意力机制中,我们有一个由n个单词组成的序列,它们由向量 C1, C2, ..., Cn 表示。我们还有一个查询向量 Qk,用于相对于这n个单词进行查询。

回忆查询机制,我们还有:输入序列对应的n个向量 C1, C2, ..., Cn 就是我们的键。最后,我们还有,这里的值同样是 C1, ..., Cn

通过结合查询、键和值,我们实现了注意力机制。该机制将查询 Qk 转换为一个新的向量 C’k,这个新向量将查询置于 C1Cn 这n个单词向量的上下文中。

从单头到多头

我们目前讨论的原始注意力机制如下图所示。我们有一个输入单词序列,每个单词被映射到一个词嵌入(即一个词向量)。这些向量随后被用作键、值和查询,从而实现了自注意力机制,最终产生一个输出序列。回忆一下,这个输出序列将每个词向量置于其周围所有词向量的上下文中。

为了使后续讨论更具体,我们将引入一个符号或函数形式来表示注意力机制。它是一个关于键、值和查询的函数,其输出称为输出本身。在将其推广到多头注意力时,我们将使用这个符号。

多头注意力的数学形式

认识到我们刚才讨论的内容,我们可以将查询视为一组n个向量 Q,键视为一组n个向量 K,值 V 视为一组n个向量。每个向量都是d维的。查询、键和值是我们整个课程中讨论的注意力网络的基础。

现在,如果我们考虑第i个查询(即这n个向量中的第i个),我们将对其进行一个称为投影的操作。

Qi 是一个d维向量,对应于n个向量中的第i个(i从1到N)。我们将把这个向量 Qi 乘以一个矩阵 M^Q。这个矩阵由k行组成,每一行也是d维的。

我们做的是取矩阵 M^Q 的每一行(用蓝色表示)与查询 Qi 做内积。这可以看作是将查询 Qi 映射到一个由矩阵 M^Q 的k行所张成的线性子空间上。

投影的直观理解

让我们尝试理解这里发生了什么。回忆一下,与每个单词相关联的嵌入向量具有潜在的主题含义。例如,单词“Paris”被映射到一个10维的嵌入向量,该向量的每个分量代表一个主题。如果单词“Paris”与该主题一致,则相关分量为正。

例如,巴黎是法国的首都,具有政治意义,因此与政治相关的第二个分量(概念上)是正的。另一方面,巴黎与体育关系不大,因此与体育相关的第一个分量略为负。

这就是词向量背后的直觉。现在,请记住,在这种情况下,每个查询都对应于与特定单词相关联的向量,并且该向量的每个分量都代表主题。

我们可以这样思考:我们取查询 Qi,然后将其与矩阵 M^Q 的第1行、第2行...第k行(我们将其表示为 R1, R2, ..., Rk)进行内积。我们所做的是将原始查询向量 Qi 投影到这个矩阵 M^Q 的k行上。

你可以这样理解:矩阵 M^Q 的每一行代表一个 overarching 的元主题。因此,该矩阵的每一行都在选择或强调向量 Qi 的某些分量。本质上,通过使用这个矩阵,我们正在突出某些重要的主题或元主题。

这对此进行了总结。因此,这个由k行组成的矩阵 M^Q(此处用蓝色表示),每一行都是d维,它将原始的d维查询向量 Qi 映射到一个新的k维向量。这个新向量的k个维度代表了原始向量的元主题。

这是一个通用概念:将查询乘以一个矩阵,从而突出与该向量相关的k个元主题。

总结

本节课中,我们一起学习了多头注意力机制。我们从回顾基础的注意力机制(包括自注意力和交叉注意力)开始,理解了其核心组件:查询、键和值。接着,我们探讨了如何通过投影操作将单头注意力扩展为多头注意力,即使用不同的投影矩阵为查询、键和值生成多个子空间(或称“头”),使模型能够同时关注来自不同表示子空间的信息。这种设计极大地增强了模型捕捉复杂依赖关系的能力,是Transformer架构成功的关键之一。

062:完整的Transformer网络 🧠

在本节课中,我们将学习Transformer网络的完整架构,特别是其核心组件——多头注意力机制。我们将从回顾投影矩阵开始,逐步构建出完整的Transformer模型,并解释其为何在自然语言处理任务中如此高效。

概述

上一节我们介绍了如何通过投影矩阵将查询向量映射到新的线性子空间。本节中,我们将看看如何将这一概念扩展到键和值,并最终构建出完整的、包含多头注意力机制的Transformer网络。

从单头到多头注意力

我们之前介绍过,可以将原始的维度为 D 的查询向量 Q_i,通过乘以一个 KD 列的矩阵 M_i,映射到一个新的 K 维向量。

公式Q_i' = Q_i * M_i

这个过程本质上是将原始的、对应 D 个主题的词嵌入向量 Q_i,映射到由矩阵 M_i 的每一行所定义的“元主题”上。每个矩阵行的权重突出了与词嵌入因子相关的特定主题。

如果我们可以用一组特定的矩阵 M_i 做一次这样的映射,那么我们也可以做 H 次。因此,我们可以取原始查询向量 Q_i,并分别用 H 个不同的投影矩阵 M_1, M_2, ..., M_H 与之相乘。

公式Q_i^{(h)} = Q_i * M_h,其中 h = 1, 2, ..., H

这样,我们就是将原始向量 Q_i 映射到了 H 个不同的线性子空间上,每个子空间由对应的蓝色矩阵定义。通过这些矩阵 M_1M_H,我们分别突出了原始词向量 Q_i 的不同子空间或元主题集合。通过这种方式,我们利用这些矩阵强调了特定词的特定方面或主题特征。

到目前为止的讨论中,我们为查询引入了这些投影矩阵,但我们完全可以对键和值做完全相同的事情。

  • M^Q 对应查询的投影矩阵。
  • M^K 对应键的投影矩阵。
  • M^V 对应值的投影矩阵。

我们可以多次进行这个操作。换句话说,我们可以有 H 个不同的查询矩阵、H 个不同的键矩阵和 H 个不同的值矩阵。这里的下标 i 表示第 i 个实例。

通过每次投影,对于查询、键和值,我们取原始的 ND 维向量序列。经过投影后,我们将这 N 个向量映射到一个新的、由 NK 维向量组成的序列。

整合到注意力模型中

现在,让我们回到注意力模型。我们再次在底部有一个输入序列。输入序列中的每个词都被映射为一个向量(词嵌入),这些词嵌入就是键、值和查询。然后,我们将这些向量分别乘以矩阵 M^KM^VM^Q。也就是说,我们将原始的键、值和查询投影到由这些各自矩阵定义的线性子空间上。

完成这一步后,我们再次进行注意力计算,得到一个输出序列。这里我想要传达的关键点是,通过投影到这些矩阵(第 i 组矩阵)的过程,我们正在突出由这些矩阵行特征所定义的词的特定方面。

回顾我们开始讨论注意力网络时,注意力机制的输入是键、值和查询。现在的修改是,注意力网络的输入是原始的键、值和查询,但它们现在分别乘以了相应的矩阵 M^KM^VM^Q。这里我们在每个矩阵上都有下标 i,因为这是这些投影矩阵的第 i 个实例。

因此,我们称这个输出为 output_ioutput_i 关注的是由相应矩阵 M^KM^VM^Q 突出的词嵌入向量的特定方面。这就是第 i 个序列的输出。

我们可以重复这个过程 H 次,对应 H 组不同的矩阵。因此,我们得到 output_1, output_2, ..., output_H,这些是不同的注意力机制的输出。

多头注意力的形成

然后,我们取这些输出向量,将它们一个接一个地堆叠起来。这被称为拼接

概念:拼接(Concatenation)意味着将 output_1output_2 直到 output_H 全部堆叠在一起。

接着,我们通过一个称为输出矩阵 W^O 进行线性变换,得到多头注意力的最终输出。

公式MultiHeadOutput = Concat(output_1, output_2, ..., output_H) * W^O

现在来总结一下:在原始的注意力机制中,我们有对应于查询、键和值的输入向量,并通过内积机制进行“注意力”计算。多头注意力意味着我们进行多次注意力计算,这里是 H 次。

我们称之为“多头”的原因是,矩阵 M_i^KM_i^VM_i^Q 对应于这个投影或这个“头”的第 i 个实例。因此,这被称为多头注意力

完整的Transformer网络

在Transformer网络中,人们发现这种多头注意力对量化性能很有价值。它运行良好的原因是,每个头(第 i 个头 M_i)都专注于词的特定方面或特征。因此,当施加注意力时,注意力机制关注的是词的特定特征。

如果我们有 H 个头,通过 H 个不同版本的矩阵 M_i(即 M_1, M_2, ..., M_H),这允许注意力机制关注词或语言的 H 个不同方面、成分或特征。

这就是最终的Transformer网络。

  • 左侧,我们有一个输入词序列。
  • 右侧,我们有一个输出词序列。
  • 在左侧编码器中,我们重复这个过程 K 次以形成一个深度网络。
  • 在右侧解码器中,我们重复 J 次以形成另一个深度网络。

编码器和解码器的关键都是注意力这个概念。我们现在所做的、并且已被证明有效的是,将这种注意力推广到所谓的多头注意力。这就是最终的Transformer网络,它用于自然语言处理的序列到序列编码。一个非常重要的应用是翻译,即输入一种语言的序列,输出另一种语言的序列。

Transformer的优势与总结

以下是Transformer网络的关键组成部分总结:

  1. 编码器-解码器结构:由编码器和解码器组成,用于序列到序列建模。
  2. 注意力机制核心:编码器和解码器的关键组件都是注意力机制。编码器基于自注意力,解码器基于自注意力和交叉注意力
  3. 多头注意力:在注意力机制中,多头注意力的概念已被证明非常有效并在实践中使用。
  4. 训练并行性:由于Transformer网络的设计方式,在训练时存在显著的并行化机会。在注意力机制内部,许多计算可以并行进行。利用现代图形处理器来开发这种并行性,人们发现Transformer网络在实践中训练效率非常高。

这与我们讨论过的另一种自然语言处理工具——长短期记忆网络形成了对比。LSTM是一种循环神经网络模型,数据通过RNN按顺序一个接一个地建模。因此,与Transformer相比,RNN的缺点是在训练时无法充分利用并行性。


本节课中我们一起学习了Transformer网络的完整架构,深入理解了多头注意力机制如何通过多个“头”来捕捉输入序列的不同特征,以及这种设计如何赋予Transformer强大的表达能力和高效的训练并行性。这使得Transformer成为当今自然语言处理领域最主流的模型架构之一。

063:强化学习介绍 🎮

在本节课中,我们将要学习一个名为“强化学习”的机器学习领域。强化学习近年来引发了巨大关注,尤其是在开发能够精通围棋的机器学习解决方案中起到了核心作用。围棋是一种源自亚洲的古老棋类游戏,其棋盘复杂,对弈策略深奥。过去人们认为机器不可能达到人类的下棋水平,但通过结合强化学习与深度学习技术,研究人员成功开发出了超越人类顶尖棋手的程序。这一突破是机器学习领域的里程碑,也极大地推动了当前对机器学习的热情。有趣的是,这一成就主要基于我们即将讨论的强化学习技术。希望这能为我们理解强化学习提供一些动力。

从直观例子理解强化学习

我们很快会发现,如果直接研究强化学习,它是一个相当数学化的领域,涉及一些复杂的数学方程。展示这些方程的目的并非为了吓退大家,而是想说明,如果我们直接试图从数学层面理解强化学习,可能会错失理解其背后更简单、更基础原理的机会。这些原理实际上远比方程本身更直观。

因此,我想通过一个对大多数人来说都易于理解的例子,来让大家感受强化学习在做什么。让我们考虑一位医生治疗病人的情境。

这位医生的目标是制定一个策略或框架,以便能够最优地治疗病人。这里“最优”意味着从改善病人健康的角度最有效,同时也要考虑成本效益。我们假设医生有一系列可以采取的行动,例如开具处方药、执行特定医疗程序等。

强化学习的基本要素

上一节我们介绍了医生治疗的场景,本节中我们来看看如何用强化学习的术语来形式化描述这个问题。

以下是描述此问题的核心要素:

  • 状态 (State):医生观察病人,特别是观察病人的“状态”。这个状态用一个向量 S 表示,它包含了表征病人健康的所有变量,例如体温、血压、实验室检测结果等。S 就是我们所掌握的、描述病人健康的所有数据。

  • 行动 (Action):我们假设医生有一系列可以采取的行动,用大写字母 A 表示这个集合。具体行动可以是 A₁, A₂, ..., Aₘ,例如开具某种特定药物、建议某项检查等。

  • 状态转移概率 (Transition Probability):当病人处于状态 S 时,对于医生选择的行动 A,病人如何反应存在不确定性或随机性。这种随机性可能源于疾病本身,也可能因为状态向量 S 并未捕捉到病人健康状况的所有方面,那些未被捕捉的方面在不同病人间存在差异,从而表现为随机性。我们用概率分布 P 来表示这种不确定性,具体地,P(S‘ | S, A) 表示当病人处于状态 S 且医生采取行动 A 时,病人转移到新状态 S‘ 的概率。

  • 奖励函数 (Reward Function):为了定义什么是“最优”行动,我们需要一个“奖励函数” R(S, A, S‘)。它表示当病人初始状态为 S,医生采取行动 A,然后病人转移到状态 S‘ 时所获得的即时奖励。例如,如果病人的健康状况改善(即 S‘ 优于 S),奖励应该较高;如果健康状况恶化,奖励应该较低。这个奖励函数应同时考虑病人的健康收益和提供该医疗行动的成本。

需要注意,奖励函数 R(S, A, S‘) 反映的是采取行动 A 后对病人产生的即时影响。

总结

本节课中我们一起学习了强化学习的基本介绍。我们首先通过围棋AI的突破性成果了解了强化学习的重要性。然后,为了避开复杂的数学公式,我们通过一个医生治疗病人的直观例子,逐步引入了强化学习的核心概念:状态(S)行动(A)状态转移概率(P)奖励函数(R)。这个框架描述了智能体(医生)如何通过与环境(病人)的交互(采取行动),根据获得的奖励来学习最优策略,以达到长期目标(最优治疗)。这为我们后续深入探讨强化学习算法奠定了坚实的基础。

064:强化学习问题设置 🎯

在本节课中,我们将学习强化学习问题的基本设置方式。我们将通过一个医生与病人互动的例子,来理解强化学习中的核心概念,包括状态、动作、奖励和策略。


上一节我们介绍了强化学习的基本概念,本节中我们来看看如何具体地设置一个强化学习问题。

我们以医生与病人的互动为例,来引入强化学习的概念。医生通过一系列动作、奖励和观察与病人互动。具体来说,在时间 t-1,病人的健康状况是状态 s_{t-1}。医生采取一个动作 a_{t-1},例如开药或考虑某个治疗方案。随后,由于健康状况改变为新的状态 s_t,一个奖励 r_t 随之产生。接着,医生再次采取动作,获得奖励 r_t,状态变为 s_{t+1},如此循环往复。

强化学习中的交互(例如医生与病人)的特点在于,它是由一个状态、动作、奖励的序列构成的。这个序列按“状态 -> 动作 -> 奖励 -> 新状态 -> 新动作 -> 新奖励”的顺序不断推进。


上一节描述了交互的序列,本节中我们来看看强化学习的目标。

医生以及强化学习的目标,是制定一个策略。这个策略定义了当面对处于状态 S 的病人时,医生应该采取的最优动作。因此,强化学习的目标就是学习这个策略。这个策略将有效地定义护理标准,即医生应如何照护病人。

最优策略应当最大化长期的平均奖励,并综合考虑病人的治疗结果和医疗成本。策略应该是非短视的,这意味着它不仅要考虑对病人最直接的影响,还要着眼于长期的后果。具体来说,在这种非短视的特性下,我们通常会更重视近期的影响,而非远期的影响。但无论如何,一个非短视的策略会同时考虑当前和未来的奖励。


了解了目标后,我们来看看解决强化学习问题时所面临的挑战。

我们面临的挑战在于,通常我们并不知道底层的状态转移概率分布 P(s' | s, a)。这个概率表示,当病人在状态 s 时,我们采取动作 a 后,病人转移到状态 s' 的可能性。这个底层概率通常是未知的。

那么问题就来了:在无法获知底层概率 P(s' | s, a) 的情况下,我们如何学习一个最优策略?


既然无法直接获知模型,概念上我们可以采取的方法是:通过体验世界来学习

我们可以去体验世界,尝试各种行动,并记录下发生的结果。其核心思想是,随着时间的推移,我们调整策略,以强化那些带来良好结果的动作,并弱化那些导致不良结果的动作。

这实际上正是“强化学习”这一术语的核心。在强化学习中,我们将通过反复体验世界来学习:观察世界状态,采取动作,观察新状态和获得的奖励。

通过反复经历状态、动作、奖励和新状态,我们希望学习到一个最优策略。这里的“最优”是指,从长远来看,该策略能为病人带来良好的平均结果(奖励),同时从医疗系统的角度,也能很好地控制成本。


因此,强化学习就是对这个基本挑战的公式化表述。

基本挑战在于:我们将通过一系列“状态 -> 动作 -> 奖励 -> 新状态 -> 新动作 -> 新奖励”的序列来体验世界,并反复进行这个过程。然后,我们希望基于这些经验,学习到一个最优策略。

这是一个非常根本的问题,也正是强化学习要解决的问题。我们将要讨论的强化学习方法,就是为了应对这一挑战。

需要认识到的重要一点是,虽然我们使用医疗健康作为主题示例(因为它对大多数人来说直观易懂),但这种试图制定长期最优策略的框架也体现在许多其他场景中。

以下是几个其他领域的例子:

  • 工厂设备维护:考虑运营工厂车间的情况。你需要监控机器的健康状况,并决定维护计划。例如,何时应将特定机器下线进行维修或调整。等待机器完全故障可能不是好主意。因此,监控机器健康的最佳方式以及维护健康的最佳策略,也是一个强化学习问题。
  • 投资:观察公司股价随时间的变化,你希望做出好的投资。理解股票市场的底层统计规律非常困难。因此,你可能会尝试制定一个策略,来指导你买卖哪些股票。你希望这个策略能长期带来平均意义上的正向投资结果。

我想通过这张幻灯片强调的是,虽然我们在课程中将使用医学作为主题,但强化学习这个框架是非常通用的。我们之前也曾在围棋游戏的背景下讨论过它,让机器与人类对弈。这些都是序列决策类型的问题。而强化学习,正是解决这类问题的一个基本机器学习框架。


本节课中我们一起学习了强化学习问题的基本设置。我们通过医生与病人的例子,理解了状态 s、动作 a、奖励 r 和策略 π 等核心概念,明确了学习最优策略的目标,并认识到在未知环境模型 P(s'|s,a) 的情况下,需要通过与环境交互的体验来学习。最后,我们了解到强化学习框架具有通用性,可广泛应用于医疗、工业、金融和游戏等多个领域的序列决策问题。

065:强化学习实践示例 🧠

在本节课中,我们将通过一个具体的例子来学习强化学习的基本框架。我们将以糖尿病医生制定治疗方案为例,详细解释强化学习中的核心概念,包括状态、动作、奖励、Q函数以及如何通过经验学习一个非短视的策略。

概述

强化学习的核心目标是学习一个策略,该策略能指导我们在特定状态下采取何种行动,以最大化长期的平均奖励。这个过程涉及状态、动作、奖励和策略等关键概念。为了让大家更好地理解这些抽象概念,我们将通过一个糖尿病医生管理患者血糖的实例来具体说明。

状态、动作与奖励的定义

上一节我们介绍了强化学习的抽象框架,本节中我们来看看如何将其应用于具体场景。

我们以糖尿病医生为例。医生的目标是制定一个治疗方案,以控制糖尿病患者的健康状况。我们将此问题构建为一个强化学习问题,目标是让医生通过学习,为患者的任何健康状况指定最优的治疗行动。

以下是该问题的具体设定:

  • 状态 (S):代表患者的健康状况。我们用一个向量 S 表示。在本例中,我们用患者前一天的最低和最高血糖浓度这两个数值来表征其健康状况。即 S = [最低血糖浓度, 最高血糖浓度]
  • 动作 (A):代表医生可以采取的治疗措施。我们假设医生可以控制两种药物参数:连续胰岛素输注速率大剂量胰岛素剂量。因此,动作 A 可以表示为 A = [输注速率, 大剂量]
  • 奖励 (R):代表采取行动后患者获得的“好处”。当患者从状态 S 采取动作 A 并转移到新状态 S‘ 时,会获得一个奖励 R。我们的目标是设计奖励函数,使得如果新状态 S‘(由新的血糖浓度范围表征)比旧状态 S 更健康,则奖励 R 较高;反之,如果健康状况恶化,则奖励 R 较低。这个奖励规则由我们(或医生)来定义。

离散化与Q函数

为了简化问题求解,我们需要对连续的状态和动作空间进行离散化处理。

状态(血糖浓度)和动作(胰岛素剂量)在现实中是连续值。我们将这些连续范围划分为若干个“区间”或“箱子”。例如,将血糖浓度范围分成N个区间,将胰岛素剂量范围分成M个区间。这样,任何具体的血糖读数或医嘱剂量都会被归类到某个特定的离散区间中。

经过离散化,我们定义了核心的Q函数

Q函数 Q(S, A) 是一个 N × M 的矩阵(表格),其中N是状态区间的数量,M是动作区间的数量。这个表格中的每个值 Q(S, A) 代表了当患者处于状态S时,采取动作A所能获得的价值

因此,强化学习的关键目标就变成了:通过与环境(患者)的交互,学习出这个Q函数表格。一旦我们学到了一个准确的Q表格,那么对于任何呈现给我们的患者状态 S,我们只需查找表格,选择能使 Q(S, A) 值最大的那个动作 A 即可,这理论上就能为患者带来最大奖励。

Q学习算法:基于经验更新

那么,如何通过经验来学习这个Q表格呢?我们采用一种称为时序差分学习的方法。

首先,我们初始化Q表格,可以基于先验知识,也可以随机初始化。
接着,医生开始与患者互动:

  1. 观察患者当前状态 S
  2. 根据某种规则(例如,结合当前Q表格和探索)选择一个动作 A
  3. 执行动作后,患者转移到新状态 S‘,并观察到即时奖励 R

获得这些经验数据 (S, A, S‘, R) 后,我们如何更新Q表格以改进我们的策略呢?以下是更新公式:

Q_new(S, A) = Q_old(S, A) + α * [ R + γ * max(Q_old(S‘, A‘)) - Q_old(S, A) ]

让我们分解这个核心公式:

  • Q_old(S, A):更新前,对在状态S下采取动作A的价值的旧估计。
  • R:观察到的即时奖励。
  • max(Q_old(S‘, A‘)):在新状态 S‘ 下,所有可能动作 A‘ 中能获得的最大Q值。这代表了对未来潜在奖励的最佳估计
  • γ:折扣因子,是一个介于0和1之间的数。它决定了我们对未来奖励的重视程度。γ越接近1,策略越有远见;越接近0,策略越短视。
  • α:学习率,也是一个介于0和1之间的数。它控制着新经验对旧估计的更新幅度。

这个更新公式的本质是:将旧估计值向一个更全面的“目标值”调整。这个目标值不仅包含了即时奖励 R,还加上了对未来可能获得的最佳奖励的折现估计 γ * max(Q_old(S‘, A‘))。如果这个目标值高于旧估计,我们就提高 Q(S, A);反之则降低。

从短视到远见:折扣因子的作用

最初的简单更新公式 Q_new = Q_old + α * (R - Q_old) 有一个明显缺陷:它只考虑了即时奖励R,是短视的。在医疗等场景中,一个行动可能带来立竿见影的好处(高即时奖励),但却可能导致严重的长期副作用(未来负奖励)。

因此,我们引入了折扣因子γ未来状态价值估计 max(Q(S‘, A‘))。通过公式 R + γ * max(Q(S‘, A‘)),我们将即时奖励与未来可能获得的奖励总和(经折现)结合起来,作为评估动作A在状态S下总价值的更佳指标。这样学习到的策略就能兼顾眼前和长远的利益,成为一个非短视的策略

医生通过反复经历“状态-动作-新状态-奖励”的循环,并应用上述Q学习更新公式,可以逐步完善Q表格。最终,这个学习好的Q表格就构成了医生的最优治疗策略:对于任何给定的患者血糖状态,查找表格并选择Q值最高的那个胰岛素治疗方案。

总结

本节课中,我们一起学习了强化学习在一个具体医学示例中的应用。我们定义了糖尿病管理中的状态(血糖)、动作(胰岛素方案)和奖励(健康改善)。通过离散化,我们将问题转化为学习一个Q函数表格。我们深入探讨了Q学习的核心更新算法,该算法通过结合即时奖励和折现后的未来奖励估计,使智能体(医生)能够学习到一个既考虑当下又着眼长远的非短视最优策略。这个框架是许多现代强化学习算法的基础。

066:使用PyTorch进行强化学习 🎮

在本节课中,我们将学习强化学习的基本概念,了解它与监督学习的区别,并探索如何使用OpenAI Gym环境和PyTorch来构建一个简单的强化学习智能体。


到目前为止,在本课程中,我们主要关注的是监督学习。这意味着我们从一个包含输入和输出对的数据集中进行学习。

虽然监督学习是一个强大的框架,但它并不适用于所有场景。例如,当我们的目标是让一个智能体在与环境的交互中学习行为时,通常不存在关于最优行为的数据集。

相反,我们希望智能体能够通过经验试错来学习。强化学习领域正是为了解决这个问题而存在的。

与在自然语言处理领域一样,深度学习对强化学习也产生了巨大影响。在这些笔记中,我们将结合OpenAI Gym介绍一些基本的强化学习概念。我们将看到Gym中实现的几个环境,并探讨如何尝试学习解决它们。你的作业将是调整其中一个智能体,使其能够使用一种新算法进行学习。


强化学习基础概念

上一节我们介绍了强化学习的目标。本节中,我们来看看强化学习中的几个核心组成部分。

强化学习问题通常被建模为一个马尔可夫决策过程。它包含以下几个关键元素:

  • 智能体:进行学习和决策的主体。
  • 环境:智能体与之交互的外部世界。
  • 状态:环境在某一时刻的状况,记为 s
  • 动作:智能体在某个状态下可以执行的操作,记为 a
  • 奖励:智能体执行动作后,环境给出的即时反馈信号,记为 r
  • 策略:智能体根据当前状态选择动作的规则,可以表示为函数 π(a|s)

智能体的目标是学习一个最优策略 π*,以最大化从环境中获得的累计奖励(通常考虑折扣因子 γ)。

OpenAI Gym 环境介绍

了解了基本概念后,我们来看看实践工具。OpenAI Gym 是一个用于开发和比较强化学习算法的工具包,它提供了多种标准化的测试环境。

以下是Gym中一些经典环境的示例:

  • CartPole:控制一个小车,使其顶部的杆子保持直立不倒。
  • MountainCar:控制一辆动力不足的小车,使其驶上山坡。
  • Atari 游戏:如 PongBreakout 等,提供像素级别的观察输入。

使用PyTorch构建一个简单智能体

现在,让我们动手使用PyTorch构建一个解决CartPole问题的简单智能体。我们将采用基于策略梯度的方法。

首先,我们需要定义神经网络策略。这个网络将环境状态作为输入,并输出每个动作的概率。

import torch
import torch.nn as nn
import torch.optim as optim
import gym

class PolicyNetwork(nn.Module):
    def __init__(self, state_size, action_size):
        super(PolicyNetwork, self).__init__()
        self.fc1 = nn.Linear(state_size, 128)
        self.fc2 = nn.Linear(128, action_size)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return torch.softmax(x, dim=-1)  # 输出动作概率分布

接下来是智能体的核心学习循环。智能体将与环境交互,收集轨迹(状态、动作、奖励序列),然后使用这些数据来更新策略网络,目标是增加带来高奖励的动作的概率。

def train_agent(env_name='CartPole-v1', episodes=1000):
    env = gym.make(env_name)
    policy_net = PolicyNetwork(env.observation_space.shape[0], env.action_space.n)
    optimizer = optim.Adam(policy_net.parameters(), lr=0.01)

    for episode in range(episodes):
        state = env.reset()
        log_probs = []
        rewards = []
        done = False

        # 1. 收集轨迹数据
        while not done:
            state_tensor = torch.FloatTensor(state).unsqueeze(0)
            action_probs = policy_net(state_tensor)
            action = torch.multinomial(action_probs, 1).item()

            next_state, reward, done, _ = env.step(action)

            log_probs.append(torch.log(action_probs.squeeze(0)[action]))
            rewards.append(reward)
            state = next_state

        # 2. 计算折扣回报
        returns = []
        R = 0
        for r in reversed(rewards):
            R = r + 0.99 * R  # 折扣因子 gamma=0.99
            returns.insert(0, R)
        returns = torch.FloatTensor(returns)

        # 3. 策略梯度更新
        policy_loss = []
        for log_prob, R in zip(log_probs, returns):
            policy_loss.append(-log_prob * R)  # 损失 = -log(概率) * 回报
        policy_loss = torch.stack(policy_loss).sum()

        optimizer.zero_grad()
        policy_loss.backward()
        optimizer.step()

        if episode % 50 == 0:
            print(f'Episode {episode}, Total Reward: {sum(rewards)}')

    env.close()

总结与展望

本节课中,我们一起学习了强化学习的基础。我们了解了它与监督学习的区别,认识了MDP的核心要素,并实际使用PyTorch和OpenAI Gym实现了一个简单的策略梯度智能体来解决CartPole环境。

这只是强化学习的入门。要构建更强大、更稳定的智能体,你还需要探索更多内容,例如:

  • 价值函数:评估状态或状态-动作对的好坏。
  • Actor-Critic方法:结合策略和价值函数。
  • 深度Q网络:使用深度神经网络来近似Q值函数。
  • 更复杂的探索策略:如噪声注入或内在好奇心驱动。

希望本教程为你打开了强化学习的大门,并激发你继续探索这个令人兴奋的领域。

067:转向非短视策略 👁️

在本节课中,我们将学习如何将之前介绍的短视策略扩展为非短视策略。我们将探讨如何让智能体在决策时不仅考虑即时奖励,也考虑未来的潜在回报,从而做出更优的长期决策。

上一节我们介绍了基于即时奖励的短视策略更新方法。本节中我们来看看如何改进它,使其能够考虑未来的奖励。

短视策略的局限性

我们之前建立的框架虽然直观,但其解决方案是“短视”的。它只考虑了患者(在我们的例子中)获得的即时奖励。因此,我们希望将其扩展,发展出一种非短视的策略。

所谓非短视,是指我们评估的策略或Q函数,在评估在状态S下采取动作A的价值时,不仅考虑即时奖励,也考虑后续到来的奖励。

我们回顾一下之前的例子和方程。以下是之前展示的相同方程:

如果 R > Q_old(S, A):
    Q_new(S, A) = Q_old(S, A) + α * (R - Q_old(S, A))
否则:
    Q_new(S, A) = Q_old(S, A) + α * (R - Q_old(S, A))

这个方程的问题是,我们用它学习的Q函数只预测了患者的即时奖励,因此没有考虑后续可能发生的情况。

引入未来奖励

我们希望以一种相对直接的方式扩展这个框架。观察第一个方程,这是我们之前更新Q函数的方式:如果即时奖励R大于我们对Q函数的旧估计,就增大Q函数;如果R小于旧的Q值,就减小Q函数。但问题在于,它只基于即时奖励R。

现在,我们将对第一个方程做一个虽小但非常重要的修改。第二个方程与第一个方程完全相同,只进行了一项更改。

在第一个方程的括号里是即时奖励R。在第二个方程中,我们将用“即时奖励R”加上“γ乘以后续状态的最佳估计价值”来替换这个单独的R。

具体来说,过程是这样的:患者处于状态S,采取了动作A,然后转移到了新状态S‘。患者的新健康状态是S‘。我们需要评估处于状态S‘对患者的价值。

让我们回想一下早先的例子。假设你是一名医生,你的患者是一位年轻女性。你可以采取一个可能改善患者即时健康的行动(比如用药)。因此,S‘代表了患者改善后的健康状态,即时奖励R(S‘)很高。

但现在假设,服用这种药物会显著增加这位年轻女性未来无法生育的可能性。那么,患者现在处于一个新状态S‘,我们必须评估这个新状态对患者的好坏。对于这位年轻女性来说,如果她进入了一个无法生育的新状态,这对她可能是一个非常糟糕的状态。

非短视的Q学习更新规则

观察这个修改:在第二个方程中,我们用两项之和替换了单独的即时奖励R。第一项是即时奖励R,第二项是对患者处于状态S‘的价值的估计。

患者采取动作A后处于状态S‘,这对患者有何价值?我们将使用我们对Q函数的旧估计,并假设随后我们将采取在状态S‘下可能采取的最佳动作A‘。

需要注意的是,我们现在考虑的是即时奖励,加上一个打了折扣的后续奖励。后续奖励是患者在状态S‘下能获得的最大价值,即对所有可能动作A‘取最大值,由旧的Q函数参数化。γ是一个折扣因子。

γ是一种让我们能够权衡患者后续健康状态和行动的重要性相对于当前情况的方法。回到年轻女性的例子,我们想采取一个能增加即时奖励R的行动,同时我们也关心后续发生的事。但生育是未来的事,可能不如当下生存那么重要。参数γ就是这个折扣因子。

现在,我们来看每一项:

  • R:给患者的即时奖励。
  • max_{A‘} Q_old(S‘, A‘):这是患者处于状态S‘时的预期未来奖励。
  • γ:折扣因子,是一个介于0和1之间的数,用于权衡我们如何看待即时奖励R相对于未来可能获得的后续奖励的重要性。

这个方程也是一个时间差分,但它是一个非短视的时间差分。新的Q函数通过旧Q函数与“非短视奖励”(即时奖励加上折扣后的后续奖励)之间的时间差来更新。

如果这个复合奖励大于我们对Q函数的旧估计,就意味着在状态S下采取动作A比我们原先认为的更有价值,因此我们增加Q函数的值。如果这个复合奖励小于我们的旧估计,那么我们可能高估了在状态S下采取动作A的价值,因此通过这个方程和时间差,我们在Q函数的估计中减小其值。

这个学习规则与之前的几乎完全相同,只是在奖励项中增加了第二项(即γ * max_{A‘} Q_old(S‘, A‘))。这个复合奖励现在取代了我们原始设置中的部分,这就是强化学习的基础。

标准形式与总结

如果我们对上面的方程进行一些操作,可以将其重写为另一种形式。下面的方程只是另一种写法,对某些人来说更常见,但两个方程是等价的。

Q_new(S, A) = Q_old(S, A) + α * [ R + γ * max_{A‘} Q_old(S‘, A‘) - Q_old(S, A) ]

我们推导出的这个框架,希望相对直观易懂。虽然最终得到了一些看起来相当复杂的方程,但我们是通过相对简单的直觉到达这些方程的。这些方程是强化学习的核心,特别是被称为Q学习的方法。它之所以叫Q学习,是因为我们试图学习这个Q函数或Q表。

本节课中我们一起学习了如何从短视策略转向非短视策略。我们引入了考虑未来奖励的Q学习更新规则,其中通过折扣因子γ来平衡即时与未来的回报,并使用下一状态的最佳估计价值来更新当前状态-动作对的价值。这是强化学习中Q学习算法的基础。

068:Q学习详解 🧠

在本节课中,我们将深入探讨强化学习的核心算法——Q学习。我们将学习Q函数的概念、其更新机制,以及如何通过Q学习来制定最优策略。


Q学习概述

我们目前所建立的这个框架被称为Q学习。之所以称为Q学习,是因为我们的目标是学习一个称为Q函数的表格。这个表格描述了在状态S下采取动作A的价值。强化学习的核心,在许多应用中,就是通过一系列状态、动作、新状态和奖励来学习这个Q函数。

上一节我们介绍了强化学习的基本框架,本节中我们来看看其核心算法——Q学习。理解Q学习的细节至关重要,因为它正是强化学习的心脏。回想我们在强化学习讨论开始时提到的AlphaGo,其解决方案的核心正是基于Q学习。因此,Q学习是一个非常基础的构建模块。

Q学习的核心方程 🔢

Q学习的特性由以下方程定义:

Q_new(S_T, A_T) = (1 - α) * Q_old(S_T, A_T) + α * [R_T + γ * max_a Q_old(S_{T+1}, a)]

我们再次通过观察状态、采取动作、观察新状态、获得奖励,并重复这一过程,来顺序更新Q函数。

学习Q函数与制定策略

在我们通过长时间的一系列“状态-动作-状态-奖励”交互学习到这个Q函数之后,我们就得到了一个估计的Q函数。以医疗应用为例,这正是医学实践的本质:医生与患者互动,根据患者的健康状况(状态)采取行动(动作),观察结果,并不断重复。随着时间的推移,医学界就对在状态S下采取动作A的价值有了深刻的理解。

在通过与患者(在医学案例中)的长期交互学习到Q函数之后,我们现在可以制定一个策略。

这个策略由一个函数π表示,它告诉我们当患者处于状态S时应该采取哪个动作。

以下是策略制定的过程:

  1. 我们拥有Q表格Q(S, A),它反映了在状态S下采取动作A的价值。
  2. 作为医生,我们会判断患者的健康状况,即状态S是什么。
  3. 然后,我们选择能为患者带来最大价值的动作。

因此,最优策略π(S)就是对于每个状态S,选择那个能最大化患者价值的动作A。请记住,我们这里使用的基础奖励综合考虑了从健康改善角度对患者的价值,以及提供该护理的成本。

深入理解Q学习方程

让我们花点时间详细讨论一下这个方程。这个方程是Q学习的基础。

  • γ(Gamma): 这被称为折扣因子R_T是在状态S_T下采取动作a_T所获得的即时奖励
  • 第二项max_a Q_old(...) 这部分代表了在患者转移到新状态S_{T+1}后,采取最优动作所能获得的预期未来奖励

因此,方括号内的项 [R_T + γ * max_a Q_old(S_{T+1}, a)] 代表了即时奖励加上未来奖励的折现值

我们进行折现的原因是,通常即时情况下的奖励R_T比后续的奖励对我们更重要。参数γ(折扣因子)是一个介于0和1之间的数,它告诉我们相对于当前情况,我们有多关心未来。γ是可以选择的参数。

以我们的年轻女性患者为例,我们可以询问她:“未来拥有孩子对你有多重要?”如果这对患者非常重要,那么γ值会较大(接近1),因为未来奖励对她很重要。如果这位年轻女性说:“我不太关心未来是否有孩子,对我来说最重要的是现在恢复健康。”那么折扣因子γ可能会较小,这意味着患者的即时奖励远比后续奖励重要。

需要注意的是,对于每一个γ的选择,我们都会得到一个不同的策略。因此,从某种意义上说,医生有能力制定一个根据患者对即时奖励与后续奖励的重视程度而定制的策略。这个折扣因子非常重要,它根据个人偏好或即时奖励与后续奖励的情况来选择。

  • α(Alpha): 这是我们的学习率。它基本上指导着Q函数随时间变化的速度。

请记住,我们通过“状态-动作-新状态-奖励”来观察世界。当我们体验世界时,我们获取旧的Q函数表示Q_old,并将其映射到新的表示Q_new。问题是,我们应该以多快的速度改变它?我们应该让每个新的测量值以多快的速度改变Q函数的值?

如果α很大(即学习率高),那么可能会出现Q函数随着新情况而剧烈变化的情况,这可能不是一个好主意。因此,在这种情况下,你可能希望学习率较小(α接近0),这意味着Q函数随时间变化的速率是平滑的。同样,学习率也是一个可以设定的参数。

  • Q_old: 这是我们对在状态S下采取动作A的价值的先前表示
  • R + γ * max Q_old: 这是我们观察到的、在状态S_T下采取动作A_T所获奖励的非短视表示

这就是我们所说的Q学习,它是强化学习的核心。正如我之前所说,并且我们随后将展示的,这正是我们在开头讨论的突破性技术(AlphaGo以及机器以世界最佳人类水平玩围棋游戏的能力)的核心。这也是强化学习应用于许多其他应用(包括我们讨论过的设备监控等)的核心。

Q学习的实施步骤 📝

如果我们看这个用于Q学习的表达式(方程),虽然乍一看可能很复杂,但希望通过我们的推导方式,它变得相对直观。

在评估这个方程时,我们实际上不必将下一个动作A_{T+1}设置为最大化Q_old的那个动作。

以下是实施步骤:

  1. 我们可以直接评估它,因为我们有旧的Q表格,所以我们只需选择能最大化Q_old的动作a。
  2. 然后,我们可以将我们的Q表格更新为Q_new
  3. 接着,我们可以选择下一个动作A_{T+1}来优化或最大化新的Q函数。

因此,在实际实施时,当我们观察到“状态-动作-奖励”序列时,我们在每一步都通过观察即时奖励和我们估计的折现未来奖励来更新Q函数。在我们更新Q函数之后,我们就可以根据该Q函数选择最优的下一个动作。


总结

本节课中我们一起学习了强化学习的核心算法——Q学习。我们了解到Q学习的目标是学习一个评估状态-动作价值的Q函数表格。其核心更新方程结合了即时奖励和折现后的未来奖励。通过调整折扣因子γ,我们可以定制策略以反映对即时与未来收益的不同重视程度;通过调整学习率α,我们可以控制学习速度。最终,学习到的Q函数可以直接用于制定最优策略,即在每个状态下选择价值最大的动作。Q学习是许多突破性强化学习应用(如AlphaGo)的基础。

069:Q学习的扩展 🚀

在本节课中,我们将学习Q学习算法的核心概念及其重要扩展。我们将探讨Q函数的基本更新公式,介绍SARSA算法,并深入讨论强化学习中至关重要的“探索与利用”权衡问题,以及如何通过ε-贪婪策略来平衡两者。


Q学习回顾

上一节我们介绍了Q学习的基本思想。Q学习的目标是学习一个称为Q函数的近似函数。Q函数反映了智能体(在我们的例子中是患者)在状态S下采取动作A的价值。这是强化学习的核心。

Q函数的基本更新公式如下:

Q_new(S_t, A_t) = Q_old(S_t, A_t) + α * [ R_t + γ * max_a Q_old(S_{t+1}, a) - Q_old(S_t, A_t) ]

其中:

  • α 是学习率,控制Q函数更新的速度。实践中,通常将其设置为0.1。
  • γ 是折扣因子,用于衡量未来奖励的当前价值。
  • max_a Q_old(S_{t+1}, a) 代表基于旧Q函数对新状态S_{t+1}下所有可能动作的最大价值估计。

强化学习是一个被研究了几十年的领域,因此存在许多基于这个基本框架的扩展和改进方法。


SARSA算法

接下来,我们看看Q学习的一个简单而有效的扩展——SARSA算法。SARSA与Q学习非常相似,但有一个关键区别。

Q学习的更新基于一个“状态-动作-奖励-新状态”的序列。而SARSA则基于一个“状态-动作-奖励-新状态-新动作”的序列。SARSA的更新公式如下:

Q_new(S_t, A_t) = Q_old(S_t, A_t) + α * [ R_t + γ * Q_old(S_{t+1}, A_{t+1}) - Q_old(S_t, A_t) ]

请注意,与Q学习使用max_a Q_old(S_{t+1}, a)不同,SARSA直接使用在状态S_{t+1}下实际采取的动作A_{t+1}对应的Q值。Q学习估计的是最优未来价值,而SARSA遵循的是实际执行的策略。这两种方法展示了强化学习算法的多样性。


探索与利用的权衡

现在,让我们更深入地思考学习过程本身。在强化学习中,我们通过一系列“状态-动作-奖励-新状态”的序列来更新Q函数。这就引出了一个关键问题:在每一步,我们应该采取什么动作?

一种直观的想法是,总是根据当前对Q函数的最佳估计来选择动作。也就是说,在任何状态S下,都选择能使Q函数最大化的动作。这种方法被称为“利用”。

然而,这种方法的问题是,我们永远没有机会去“探索”。探索是指尝试不同的、可能并非当前最优的动作。这样做可能会带来意想不到的、有益的结果。如果我们只利用已知的最佳动作,Q函数可能会陷入局部最优,而无法发现真正全局最优的策略。

因此,在强化学习中存在一个根本性的权衡:探索与利用。我们需要在利用现有知识获取即时奖励,和探索未知领域以发现可能更好的长期策略之间取得平衡。


ε-贪婪策略

为了解决探索与利用的权衡问题,实践中一种非常有效的方法是ε-贪婪策略

以下是该策略的工作原理:

  1. 我们设定一个小的概率值 ε(例如0.1)。
  2. 每次需要选择下一个动作时,我们进行一次“抛硬币”:
    • 以概率 ε,我们进行探索:完全随机地选择一个动作,不考虑当前的Q函数。
    • 以概率 1-ε,我们进行利用:选择当前Q函数认为在给定状态下能带来最大预期价值的动作。

这种框架允许我们以可控的概率(ε)进行探索,从而有机会发现新的、有价值的动作,同时大部分时间(1-ε)仍在利用现有知识做出高效决策。ε-贪婪策略已被证明是提升强化学习性能的有效工具。


总结

本节课中我们一起学习了Q学习的几个重要扩展。我们回顾了Q函数的核心更新公式,了解了与之相关的SARSA算法。更重要的是,我们深入探讨了强化学习中的核心挑战——探索与利用的权衡,并学习了如何使用ε-贪婪策略来巧妙地平衡两者,从而更有效地学习最优策略。

070:Q学习的局限性与深度Q学习介绍 🧠

在本节课中,我们将要学习Q学习的基本概念及其局限性,并由此引出一种更强大的技术——深度Q学习。深度Q学习结合了深度神经网络,能够处理更复杂、状态空间更大的问题,正是这项技术支撑了像AlphaGo这样的突破性成就。

Q学习回顾 📚

上一节我们介绍了Q学习,它是强化学习的核心技术之一。Q学习的核心思想是通过一个Q函数来评估在特定状态下采取某个动作的长期价值。其更新过程遵循一个特定的公式。

Q学习的核心更新公式如下:
Q(s, a) = Q(s, a) + α [ R + γ * max_a' Q(s', a') - Q(s, a) ]

这个公式的含义是:我们根据即时奖励R和未来折扣奖励γ * max_a' Q(s', a')的估计值,来调整当前状态-动作对的价值Q(s, a)。参数α是学习率,γ是折扣因子。

Q学习的局限性 ⚠️

尽管Q学习是一个强大的概念,但它存在一些重要的局限性,这些局限性促使我们寻找更先进的解决方案。

以下是Q学习的主要局限性:

  1. 表格表示法的限制:Q学习通常假设所有状态和动作都可以存储在一个表格(矩阵)中。我们通过离散化状态和动作来构建这个表格。
  2. 可扩展性问题:当状态和动作的数量变得非常庞大时(这在现实问题中很常见),这种表格表示法将变得不切实际,因为存储和计算成本会急剧上升。
  3. 泛化能力不足:基于表格的Q学习方法无法对不同但相似的环境状态进行泛化。它必须为每一个独立的状态-动作对单独学习价值,缺乏从经验中提取通用模式的能力。

深度Q学习介绍 🚀

为了解决Q学习的局限性,我们引入了深度Q学习。深度Q学习不再假设状态和动作可以用表格表示,而是使用一个深度神经网络来近似Q函数。这种方法能够处理近乎无限的状态和动作空间。

深度Q网络架构

在深度Q学习中,我们用一个深度神经网络来表示Q函数。

  • 输入:神经网络的输入是状态s。状态可以由n个数值特征构成,例如一张图像的像素值。
  • 输出:神经网络的输出层对应所有可能动作的价值估计。例如,如果有三个可选动作,输出层就有三个节点,分别代表Q(s, a1)Q(s, a2)Q(s, a3)
  • 参数:这个神经网络由一组参数θ(Theta)定义。因此,Q函数现在表示为Q(s, a; θ),意为“在参数为θ的神经网络下,状态s下动作a的价值”。

我们的目标从学习一个Q表格,转变为学习神经网络的最优参数θ

学习目标与优化

深度Q学习的学习目标与Q学习在精神上是一致的:让我们的Q函数估计值尽可能接近“非短视”的奖励。

我们定义一个成本函数U(θ),它衡量当前神经网络预测值与目标值之间的差距:

U(θ) = [ R + γ * max_a' Q(s', a'; θ_old) - Q(s, a; θ) ]^2

  • 目标值R + γ * max_a' Q(s', a'; θ_old)。这部分与Q学习相同,是即时奖励加上用旧参数θ_old的网络估计的未来折扣奖励最大值。
  • 当前预测值Q(s, a; θ),即当前参数θ下网络的预测。

我们的目标是找到参数θ,使得成本函数U(θ)最小化。这意味着让神经网络的预测尽可能接近理想的目标奖励值。

通过梯度下降进行优化

为了最小化成本函数,我们使用机器学习中一种常见的方法——梯度下降。

以下是梯度下降的更新步骤:

  1. 计算梯度:计算成本函数U(θ)关于参数θ的梯度(即多维空间中的斜率)。梯度指向函数值增长最快的方向。
  2. 反向更新:我们沿着梯度的反方向(即函数值下降最快的方向)更新参数。更新公式为:
    θ_new = θ_old - α * ∇U(θ_old)
    其中,α是学习率,是梯度算子。
  3. 迭代:重复上述过程,逐步将参数θ调整到使成本函数最小的值。

通过数学推导,我们可以得到深度Q网络参数的具体更新公式。有趣的是,这个公式的结构与传统的Q学习更新公式非常相似,都包含一个“时序差分误差”项,只是额外乘以了一个与神经网络梯度相关的项。这揭示了深度Q学习本质上是Q学习思想在函数近似框架下的自然延伸。

总结 ✨

本节课中我们一起学习了:

  1. Q学习的局限性:主要在于其表格表示法难以扩展至大规模状态/动作空间,且缺乏泛化能力。
  2. 深度Q学习的核心思想:使用深度神经网络作为函数近似器来代表Q函数,从而克服表格法的限制。
  3. 深度Q网络的学习过程:通过定义成本函数来衡量网络预测与目标奖励的差距,并采用梯度下降法来优化网络参数θ,使网络能准确估计长期奖励。

深度Q学习将深度学习的表示能力与强化学习的决策框架相结合,为处理复杂的序列决策问题(如游戏、机器人控制)提供了强大的工具。在下一课中,我们将进一步深入探讨深度Q学习的实现细节。

071:基于图像的深度Q学习 🖼️🤖

在本节课中,我们将学习深度Q学习的一个特殊应用场景:基于图像进行强化学习。我们将探讨如何将深度卷积神经网络与Q学习结合,使机器能够通过分析图像(例如围棋棋盘或医学影像)来做出最优决策。


上一节我们介绍了深度Q学习的基本概念。本节中,我们来看看当强化学习的状态输入是图像时,深度Q学习是如何工作的。正如我们在AlphaGo案例中谈到的,机器通过分析围棋棋盘的图像,利用深度Q学习算法来决定下一步的最优落子位置。

这个概念非常基础且重要。你甚至可以想象它在医学中的应用:例如,放射科医生获得患者的影像后,目标就是基于该图像确定对患者最佳的后续治疗方案。因此,基于图像的强化学习分析是深度Q学习的核心,值得我们深入探讨。


基于图像的Q函数优化

我们试图优化的函数仍然是Q函数,它由一个参数为 θ 的深度神经网络表示。这个网络的输入是状态 s,在这里状态就是一张图像(例如围棋棋盘的图片)。而输出则对应不同行动 a 的Q值。

我们的目标是让这个Q函数能够准确估计即时奖励 Rt 加上未来奖励的折现值。因此,代价函数 J(θ) 试图让 Q(s, a; θ) 匹配这个非短视的总体奖励。

从形式上看,这可以视为一个监督学习问题。原因在于,在强化学习与环境交互的过程中,我们能够观察到即时奖励 R_t,也能看到转移后的新状态 s_{t+1}。利用旧的模型参数 θ_old,我们可以评估新状态的价值。因此,公式中括号内的“目标值”在训练过程中是可观测的,我们可以用它来监督训练深度Q网络。


深度卷积Q网络 🧠

在图像处理的背景下,Q函数将通过一个深度卷积神经网络来表示。我们在本课程的其他部分已经介绍过CNN,这里它出现在了Q学习的上下文中。

观察这个架构图,Q神经网络从左到右依次为:

  • 输入层:接收图像状态。
  • 一系列卷积层:用于提取图像的层次化特征。
  • 一系列全连接层:最终输出每个可能动作的Q值。

这是一个对深度卷积神经网络的绝佳应用。我们的学习目标,就是调整网络参数 θ,使得网络的输出值尽可能接近前面公式中括号内计算出的非短视奖励目标值


意义与应用 🎮➡️🌍

有趣的是,这个基于我们已掌握工具(深度CNN和Q学习)的基本架构相对容易理解,而最初的AlphaGo技术正是基于此深度Q网络构建的(后续已有显著改进)。这意味着,即使在本入门课程中,我们也已经触及了促成近几十年来机器学习最重大突破之一的底层技术。

除了围棋,同样的技术已被用于自动玩许多不同的电子游戏(例如各种Atari游戏)。基于此深度Q学习框架的机器,在这些游戏上达到了超越世界顶尖人类玩家的水平。

当然,围棋或Atari游戏本身并非现实世界中非常实际的应用。但是,如果机器能玩好这类游戏,本质上意味着它拥有了一套根据当前状态选择最佳后续行动的自适应算法。这些游戏是我们开发技术的试验场。

这项技术最终将对人们生活产生影响的领域,是诸如辅助临床医生等。我们在课程开始时提到,强化学习可用于糖尿病患者药物的自动控制,以协助医生完成这项任务。因此,这项通过游戏展示的技术,拥有非常深远且潜力巨大的应用前景,很可能在全球范围内影响人们的生活。


总结 📝

本节课我们一起学习了基于图像的深度Q学习。我们了解到:

  1. 当状态以图像形式呈现时,可以使用深度卷积神经网络来近似Q函数。
  2. 其训练目标是最小化Q网络输出与可观测的非短视奖励目标值之间的差异,这类似于一个监督学习过程。
  3. 这项技术是AlphaGo等突破性成果的基础,并在游戏AI中得到了验证。
  4. 其核心价值在于能够学习复杂的序贯决策策略,未来有望在医疗、自动驾驶等需要根据视觉信息做出决策的领域发挥重要作用。

072:深度Q学习与传统Q学习的联系 🔗

在本节课中,我们将深入探讨深度Q学习与传统Q学习之间的数学联系。这是强化学习系列中最具技术性的一课,旨在为有数学背景的学习者提供更深层次的理解。我们将看到,在特定条件下,深度Q网络的行为本质上与传统Q学习是一致的。

课程回顾

上一节我们介绍了Q学习和深度Q网络的基本概念。简单来说,我们做了两件事:

  1. 传统Q学习:我们假设状态和动作是离散且有限的,因此Q函数 Q(s, a) 可以表示为一个表格或矩阵。
  2. 深度Q学习:为了解决状态空间巨大(如围棋棋盘)导致表格法不可行的问题,我们引入深度神经网络来近似表示Q函数,并学习其参数 θ

以下是两种方法的直观对比:

深度Q学习的更新公式

深度Q网络(DQN)的核心是更新其参数 θ。其参数更新规则(通过梯度下降得到)和更新后的Q函数表示如下:

参数更新规则:
θ_new = θ_old + α * [r + γ * max_a‘ Q(s‘, a‘; θ_old) - Q(s, a; θ_old)] * ∇_θ Q(s, a; θ_old)

更新后的Q函数:
Q(s, a; θ_new)

其中,α 是学习率,r 是即时奖励,γ 是折扣因子。这个公式看起来复杂,但它与传统Q学习有着深刻的联系。

建立数学联系

为了揭示这种联系,我们首先定义参数的变化量 Δθ
Δθ = θ_new - θ_old

那么,更新后的Q函数可以写为:
Q(s, a; θ_new) = Q(s, a; θ_old + Δθ)

现在,我们应用一个关键的数学工具——一阶泰勒级数展开。当参数变化 Δθ 很小时,我们可以对上述函数进行近似:

Q(s, a; θ_old + Δθ) ≈ Q(s, a; θ_old) + Δθ^T * ∇_θ Q(s, a; θ_old)

这个近似是微积分中的基本结论。接下来,我们将参数更新规则中的 Δθ 代入这个近似公式。

代入并整理后,我们得到:

Q(s, a; θ_new) ≈ Q(s, a; θ_old) + α‘ * [r + γ * max_a‘ Q(s‘, a‘; θ_old) - Q(s, a; θ_old)]

其中,我们定义了一个新的有效学习率 α‘
α‘ = α * ||∇_θ Q(s, a; θ_old)||²

观察最终的近似公式,你会发现一个熟悉的结构。

与传统Q学习的对比

我们得到的近似公式,正是传统Q学习的更新形式!传统Q学习的表格更新规则为:

Q(s, a) ← Q(s, a) + α * [r + γ * max_a‘ Q(s‘, a‘) - Q(s, a)]

比较两者:

  • 深度Q学习(近似后)Q_new ≈ Q_old + α‘ * (目标 - Q_old)
  • 传统Q学习Q_new = Q_old + α * (目标 - Q_old)

它们的结构完全一致,都是将当前的Q值向“目标值”(即时奖励加折扣后的未来最大收益)调整。唯一的区别在于学习率:深度Q学习中是一个由梯度范数调整后的 α‘,而传统Q学习中是一个固定的 α

核心结论与总结

本节课中我们一起学习了深度Q学习与传统Q学习之间的数学联系。

  1. 关键前提:当深度Q网络的参数更新步长 Δθ 较小时,一阶泰勒展开是良好的近似。
  2. 核心发现:在此前提下,深度Q网络的参数更新过程,在效果上等价于对Q函数本身进行传统Q学习式的更新。
  3. 意义:这证明了我们为处理复杂问题而引入的深度神经网络方法,并没有脱离强化学习的基础理论框架。深度Q网络可以视为传统Q学习在连续、高维状态空间中的一种自然且强大的泛化。

因此,深度Q学习并非一个全新的、完全不同的算法,而是建立在经典Q学习思想之上,利用函数近似(深度学习)来突破其局限性的一种扩展。这统一了我们在本系列课程中学到的强化学习核心概念。

posted @ 2026-03-26 12:26  布客飞龙III  阅读(34)  评论(0)    收藏  举报