🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
文章目录
在第 9 章,新兴的神经网络设计中,我们介绍了新的神经网络( NN ) 架构来解决现有深度学习( DL ) 算法的一些限制。我们讨论了用于处理结构化数据的图形神经网络,以图形表示。我们还介绍了记忆增强神经网络,它允许网络使用外部记忆。在本章中,我们将研究如何通过使 DL 算法能够使用更少的训练样本来学习更多信息来改进 DL 算法。
让我们用一个例子来说明这个问题。想象一个人从未见过某种类型的物体,比如汽车(我知道——极不可能)。他们只需要看到一辆车就可以识别其他汽车。但 DL 算法并非如此。DNN 需要大量训练样本(有时还需要数据增强),才能识别特定类别的对象。即使是相对较小的 CIFAR-10 ( CIFAR-10 and CIFAR-100 datasets ) 数据集也仅包含 10 类对象的 50,000 张训练图像,相当于每类 5,000 张图像。
元学习,也称为学习学习,允许机器学习( ML ) 算法利用和引导从多个训练任务中获得的知识,以提高其对新任务的训练效率。希望通过这种方式,该算法将需要更少的训练样本来学习新任务。用更少的样本进行训练的能力有两个优点:减少训练时间和在没有足够训练数据时获得良好的性能。在这方面,元学习的目标类似于我们在第 2 章“理解卷积网络”中介绍的迁移学习机制 . 实际上,我们可以将迁移学习视为一种元学习算法。但是元学习有多种方法。在本章中,我们将讨论其中的一些。
本章将涵盖以下主题:
- 元学习简介
- 基于度量的元学习
- 基于优化的元学习
元学习简介
正如我们在介绍中提到的,元学习的目标是允许 ML 算法(在我们的例子中,NN)与标准监督训练相比从相对较少的训练样本中学习。一些元学习算法试图通过在已知任务领域的现有知识与新任务领域之间的映射来实现这一目标。其他算法只是从头开始设计,以从更少的训练样本中学习。另一类算法引入了新的优化训练技术,专为元学习而设计。但在我们讨论这些主题之前,让我们介绍一些基本的元学习范式。在标准的 ML 监督学习任务中,我们的目标是在训练数据集D中最小化成本函数J(θ) 通过更新模型参数θ (网络权重,在 NN 的情况下)。正如我们在介绍中提到的,在元学习中,我们通常使用多个数据集。因此,在元学习场景中,我们可以通过说我们的目标是在这些数据集P(D)的分布上最小化J(θ)来扩展这个定义:
这里,是最优模型参数,
是成本函数,它现在取决于当前数据集以及模型参数。换句话说,目标是找到模型参数,以使所有数据集的成本
的期望值(如第 1 章,神经网络的基本要素中所述,在随机变量和概率分布
部分中所述)最小化。我们可以将这种情况视为对单个数据集的训练,其训练样本本身就是数据集。
接下来,让我们继续扩展我们在介绍中使用的更少训练样本的表达式。 在监督训练中,我们可以将这种训练数据稀缺的场景称为k -shot learning,其中k可以是 0、1、2 等。假设我们的训练数据集由分布在n 个类别中的标记样本组成。在k次学习中,我们为n 个类中的每个类都有k个标记的训练样本(标记样本的总数为n × k)。我们将此数据集称为支持集,并用S表示。我们还有一个查询集 Q,其中包含属于n 个类之一的未标记样本。我们的目标是正确分类查询集的样本。存在三种类型的k -shot 学习:zero-shot、one-shot 和few-shot。让我们从零样本学习开始。
零样本学习
我们将从零样本学习(k = 0)开始,我们知道存在一个特定的类,但我们没有该类的任何标记样本(也就是说,没有支持集)。起初,这听起来不可能——我们如何对从未见过的事物进行分类?但在元学习中,情况并非如此。回想一下,我们利用先前学习的任务的知识(让我们用a表示它们)而不是手头的任务(b)。在这方面,零样本学习是迁移学习的一种形式。为了理解这是如何工作的,让我们假设一个人从未见过大象(另一个极不可能的例子),但是当他们看到它的图片时必须认出它(新任务b)。然而,这个人在一本书中读到大象很大,灰色,有四只腿,大耳朵和一个躯干(之前的任务a)。有了这个描述,当他们看到大象时,他们会很容易认出它。在这个例子中,这个人将他们以前学习的任务(读书)领域的知识应用到新任务(图像分类)的领域。
在 ML 的上下文中,这些特征可以编码为非人类可读的嵌入向量。我们可以通过使用语言建模技术(例如 word2vec 或变换器)来编码 NN 领域的大象识别示例,以编码一个基于上下文的单词嵌入向量。我们还可以使用卷积网络 (CNN) 来生成大象图像的嵌入向量h b。让我们一步一步来看看如何实现这一点:
- 在标记和未标记的样本a和b上应用编码器f和 g (NN),分别生成嵌入h a和h b。
- 使用映射函数将h b转换为已知样本的嵌入h a*的向量空间。映射函数也可以是 NN。此外,编码器和映射可以组合在一个模型中并联合学习。
- 一旦我们有了查询样本的变换表示,我们就可以使用相似度度量(例如,余弦相似度)将其与所有表示h a * 进行比较。然后我们假设查询样本的类与与查询最密切相关的支持样本的类相同。下图说明了这种情况:
让我们形式化零样本学习场景。在具有单个数据集的传统分类任务中,NN 表示条件概率,其中y是输入样本x的标签,θ是模型参数。在元学习中,x和y 属于传统数据集,但我们引入了一个随机变量T来描述我们感兴趣的新任务。在我们的示例中,x将是单词的上下文(周围的单词),并且标签y是大象类的 one-hot 编码。另一方面,T将是我们感兴趣的图像;因此,元学习模型代表了一种新的条件概率
。我们刚刚描述的零样本场景是所谓的基于度量的元学习的一部分(我们将在本章后面看到更多这样的例子)。现在,让我们继续进行一次性学习。
一键学习
在本节中,我们将研究one-shot learning ( k = 1 ) 及其泛化的few-shot learning ( k > 1 )。在这种情况下,支持集不为空,并且每个类别都有一个或多个标记样本。这是相对于零样本场景的一个优势,因为我们可以依赖来自同一域的标记样本,而不是使用来自另一个域的标记样本的映射。因此,我们只有一个编码器f,不需要额外的映射。
一次性学习任务的一个例子是公司的面部识别系统。该系统应该能够根据单张照片识别员工的身份。也应该可以用一张照片添加新员工。让我们注意,在这种情况下,添加一个新员工相当于添加一个已经看过(照片本身)但在其他方面未知的新类。这与零样本学习形成对比,零样本学习是我们看不见但已知的类。解决此任务的一种简单方法是使用分类前馈网络(FFN),它将照片作为输入并以 softmax 输出结束,其中每个类代表一个员工。该系统将有两个主要缺点。首先,每次添加新员工时,我们都必须使用员工的完整数据集重新训练整个模型。其次,我们需要每个员工多张图像来训练模型。
我们也可以在一次性学习框架内解决这个任务。我们需要的第一件事是一个预训练的网络,它可以生成员工图像的嵌入向量。我们假设预训练允许网络产生足够独特的嵌入h对于每张照片。我们还将所有员工照片存储在某个外部数据库中。出于性能原因,我们可以将网络应用于所有照片,然后也存储每个图像的嵌入。让我们关注一个用例,在该用例中,系统必须在现有员工尝试使用新照片进行身份验证时对其进行识别。我们将使用网络生成该照片的嵌入,然后将其与数据库中的嵌入进行比较。我们将通过获取与当前照片的嵌入最匹配的数据库嵌入来识别员工。
接下来,让我们看一下将新员工添加到系统时的用例。在这里,我们将简单地拍摄该员工的照片并将其存储在数据库中。这样,每次员工尝试进行身份验证时,他们当前的照片都会与最初的照片(以及所有其他照片)进行比较。通过这种方式,我们添加了一个新类(员工),而无需对网络进行任何更改。我们可以将员工照片/身份数据库视为一个支持集。该任务的目标是将此支持集映射到一个分类器
,该分类器在给定以前未见过的查询样本
的情况下输出标签
上的概率分布。在我们的例子中,
对表示以前不属于系统的新员工(即新的查询样本和新的类)。
换句话说,我们希望能够在现有支持集的帮助下预测从未见过的类。我们将映射定义 为条件概率
,由权重为θ的神经网络实现。此外,我们还可以将新的支持集插入同一网络,这将导致新的概率分布
。通过这种方式,我们可以在不改变网络权重θ的情况下,根据新的训练数据调整输出。
现在我们已经熟悉了k -shot 学习,让我们看看如何用少样本数据集训练算法。
元训练和元测试
我们在零样本学习和一次性学习 部分中描述的场景称为 元测试 阶段。在这个阶段,我们利用预训练网络的知识,仅借助一个小的支持集(或根本没有支持集)将其应用于预测以前看不见的标签。我们还有一个元训练阶段,在这个阶段,我们在几个场景中从头开始训练一个网络。Matching Networks for One Shot Learning的作者引入与元测试密切匹配的元训练算法。这是必要的,这样我们就可以在我们期望它在测试阶段工作的相同条件下训练模型。由于我们从头开始训练网络,因此训练集(用 D表示)不是少数样本数据集,而是包含足够数量的每个类的标记示例。然而,训练过程模拟了几个样本数据集。
以下是它的工作原理:
- 对一组标签进行采样
,其中T是D中所有标签的集合。为了澄清,L仅包含所有标签T的一部分。这样,当模型只看到几个样本时,训练就会模仿测试。例如,将新员工添加到面部识别系统需要一个图像和一个标签。
- 采样一个支持集
,其中所有样本的标签
只是 L 的一部分。支持集包含每个标签的k个样本。
- 对训练批次进行采样
,其中
(与支持集相同)。
和
的组合代表一个训练集。我们可以将情节视为具有相应数据集的单独学习任务。或者,在监督学习中,一个情节只是一个单一的训练样本。
- 优化情节的网络权重。网络表示概率
并使用
和
作为输入。为了澄清,该集合
由元组
组成,以支持集
为条件。这是训练过程的“元”部分,因为模型学习从支持集中学习以最小化整个批次的损失。该模型使用以下交叉熵目标:
在这里,和
分别反映标签和示例的采样。让我们将其与相同的任务进行比较,但在经典的监督学习场景中。在这种情况下,我们从数据集D中采样小批量B ,并且没有支持集。抽样是随机的,不依赖于标签。然后,前面的公式将转换为以下公式:
元学习算法可以分为三大类:基于度量的、基于模型的和基于优化的。在本章中,我们将关注基于度量和优化的方法(不包括基于模型的方法)。基于模型的元学习算法不对实现概率的 ML 算法的类型施加任何限制。也就是说,不需要编码器和映射功能。相反,它们依赖于专门适用于少量标记样本的网络架构。您可能还记得在第 9 章,新兴的神经网络设计中,我们在查看One-shot Learning with Memory-Augmented Neural Networks论文时介绍了一个这样的模型( https://arxiv.org/abs/1605.06065 )。顾名思义,该论文演示了在一次性学习框架中使用记忆增强神经网络。由于我们已经讨论了网络架构,并且训练过程与我们在本节中描述的类似,因此我们不会在本章中包含另一个基于模型的示例。
现在我们已经介绍了元学习的基础知识,在下一节中,我们将重点关注基于度量的学习算法。
基于度量的元学习
当我们在元学习简介部分讨论一次性场景时,我们提到了一种基于度量的方法,但这种方法通常适用于 k -shot 学习。这个想法是测量未标记的查询样本与支持集的所有其他样本X之间的相似性。 使用这些相似度分数,我们可以计算概率分布 y^。以下公式反映了这种机制:
这里,α是查询样本之间的相似性度量,是具有n 个类和每个类的k个样本的支持集的大小。为了澄清,查询样本的标签只是支持集的所有样本的线性组合。具有较高相似性的样本类别将对查询样本的标签分布有较高的贡献。我们可以将α实现为聚类算法(例如,k最近邻)或注意力模型(我们将在下一节中看到)。在零样本学习的情况下,这个过程有两个正式的步骤:计算样本嵌入,然后计算嵌入之间的相似性。但是前面的公式是这两个步骤的广义组合,并直接从查询样本中计算相似度(尽管在内部,这些步骤仍然可以分开)。下图说明了两步基于度量的学习(包括编码器f和g):
在接下来的几节中,我们将讨论一些更流行的度量元学习算法。
用于一次性学习的匹配网络
我们已经在元学习简介 部分讨论了与匹配网络一起介绍的训练过程。现在,让我们关注实际模型,从我们在基于度量的元学习部分中概述的相似性度量开始。实现这一点的一种方法是使用余弦相似度(用c表示),然后是 softmax:
这里,f和g分别是新任务和支持集样本的编码器(正如我们所讨论的,f和 g可能是相同的函数)。编码器可以是用于图像输入或词嵌入的 CNN,例如自然语言处理任务中的 word2vec。这个公式与我们在第 8 章“序列到序列模型和注意力”中介绍的注意力机制 非常相似。
在当前定义下,编码器g一次只编码一个支持样本,独立于支持集的其他样本。然而,两个样本i和j的嵌入和
可能在嵌入特征空间中非常接近,但是这两个样本具有不同的标签。该论文的作者建议修改g以将整个支持集S作为附加输入:
通过这种方式,编码器可以调节S上的嵌入向量Xi 并避免这个问题。我们也可以对编码器f应用类似的逻辑。该论文将新的嵌入函数称为完整的上下文嵌入。
让我们看看如何在f上实现完整的上下文嵌入。首先,我们将介绍一个新函数,它类似于旧的编码器(在包含S作为输入之前)——也就是说,f'可以是 CNN 或词嵌入模型,它创建样本嵌入,独立于支持集.
的结果将作为完整嵌入函数
的输入。我们将支持集视为一个序列,这允许我们使用长短期记忆 (LSTM) 嵌入它。因此,计算嵌入向量是多个步骤的顺序过程。
然而,S是一个集合,这意味着序列中样本的顺序是不相关的。为了反映这一点,该算法还对支持集的元素使用了特殊的注意机制。通过这种方式,嵌入函数可以处理序列中所有先前的元素,而不管它们的顺序如何。
让我们看看编码器的一步是如何工作的:
,其中t是输入序列的当前元素,
是中间隐藏状态,
是步骤t-1的隐藏状态,并且
是单元状态。注意机制是用一个连接到隐藏状态
的向量
来实现的。
, 其中
是步骤t的最终隐藏状态。
,其中
是支持集的大小,g是支持集的嵌入函数,α 是相似性度量,定义为乘法注意力,然后是 softmax:
该过程继续进行T步(T是一个参数)。我们可以用下面的公式来概括:
接下来,让我们关注g的完整上下文嵌入。像f一样,我们将引入一个新函数 ,它类似于旧的编码器(在将S作为输入之前)。作者建议使用双向 LSTM 编码器,定义如下:
这里和
是两个方向的单元隐藏状态。我们可以将它们定义如下:
在下一节中,我们将讨论另一种基于度量的学习方法,称为连体网络。
连体网络
在本节中,我们将讨论用于 One-shot Image Recognition 的 Siamese Neural Networks论文 ( https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf )。Siamese 网络是由两个相同的基础网络组成的系统,如下图所示:
这两个网络是相同的,因为它们共享相同的架构和相同的参数(权重)。每个网络都输入一个输入样本,最后一个隐藏层生成该样本的嵌入向量。这两个嵌入被馈送到距离度量。该距离被进一步处理以产生系统的最终输出,该输出是二进制的,表示对两个样本是否来自同一类的验证。距离测量本身是可微的,这使我们能够将网络训练为单个系统。论文作者推荐使用 L1距离:
这里,是基础网络。在一次性学习场景中使用 Siamese 网络遵循我们在元训练和元测试部分中描述的相同一般思想,但在这种情况下,任务被简化了,因为我们总是只有两个类(相同或不同) ,而不管数据集中的实际类数。在元训练阶段,我们使用大型标记数据集训练系统。我们通过生成具有相同或不同类别的图像对和二进制标签的样本来做到这一点。在元测试阶段,我们有一个查询样本和一个支持集。然后我们创建多对图像,其中每对包含查询样本和支持集的单个样本。我们有与支持集大小一样多的图像对。然后,我们将所有对馈送到 Siamese 系统,并选择距离最小的对。查询图像的类别由该对的支持样本的类别决定。
实施连体网络
在本节中,我们将使用 Keras 实现一个简单的连体网络示例,它将验证两个 MNIST 图像是否来自同一类。它部分基于https://github.com/keras-team/keras/blob/master/examples/mnist_siamese.py。
让我们一步一步来看看如何做到这一点:
1.我们将从导入语句开始:
-
import random
-
-
import numpy
as np
-
import tensorflow
as tf
2.接下来,我们将实现create_pairs创建训练/测试数据集(用于训练和测试)的函数:
-
def create_pairs(inputs: np.ndarray, labels: np.ndarray):
-
num_classes
=
10
-
-
digit_indices
= [np.where(labels
=
= i)[
0]
for i
in range(num_classes)]
-
pairs
= list()
-
labels
= list()
-
n
= min([len(digit_indices[d])
for d
in range(num_classes)])
-
1
-
for d
in range(num_classes):
-
for i
in range(n):
-
z
1, z
2
= digit_indices[d][i], digit_indices[d][i
+
1]
-
pairs
+
= [[inputs[z
1], inputs[z
2]]]
-
inc
=
random.randrange(
1, num_classes)
-
dn
= (d
+ inc) % num_classes
-
z
1, z
2
= digit_indices[d][i], digit_indices[dn][i]
-
pairs
+
= [[inputs[z
1], inputs[z
2]]]
-
labels
+
= [
1,
0]
-
-
return np.array(pairs), np.array(labels, dtype
=np.float
32)
每个数据集样本由两个 MNIST 图像的输入对和一个二进制标签组成,该标签指示它们是否来自同一类。该函数创建分布在所有类(数字)上的相等数量的真/假样本。
3.接下来,我们来实现这个create_base_network函数,它定义了 Siamese 网络的一个分支:
-
def create_base_network():
-
return tf.keras.models.
Sequential([
-
tf.keras.layers.Flatten(),
-
tf.keras.layers.Dense(
128, activation
=
'relu'),
-
tf.keras.layers.Dropout(
0.1),
-
tf.keras.layers.Dense(
128, activation
=
'relu'),
-
tf.keras.layers.Dropout(
0.1),
-
tf.keras.layers.Dense(
64, activation
=
'relu'),
-
])
分支表示从输入开始到距离测量之前的最后一个隐藏层的基础网络。我们将使用三个全连接层的简单 NN。
4.接下来,让我们构建整个训练系统,从 MNIST 数据集开始:
-
(x_train, y_train), (x_
test, y_
test)
= tf.keras.datasets.mnist.load_dat
a()
-
x_train
= x_train.astype(np.float
32)
-
x_
test
= x_
test.astype(np.float
32)
-
x_train
/
=
255
-
x_
test
/
=
255
-
input_shape
= x_train.shape[
1:]
5.我们将使用原始数据集来创建实际的训练和测试验证数据集:
-
train_pairs, tr_labels
= create_pairs(x_train, y_train)
-
test_pairs,
test_labels
= create_pairs(x_
test, y_
test)
6.然后,我们将构建连体网络的基础部分:
base_network = create_base_network()
该base_network对象在连体系统的两个分支之间共享。这样,我们确保两个分支中的权重相同。
7.接下来,让我们创建两个分支:
-
# Create
first half
of the siamese system
-
input_a
= tf.keras.layers.
Input(shape
=
input_shape)
-
-
# Note how we reuse the base_network
in both halfs
-
encoder_a
= base_network(
input_a)
-
-
# Create the second half
of the siamese system
-
input_b
= tf.keras.layers.
Input(shape
=
input_shape)
-
encoder_b
= base_network(
input_b)
8.接下来,我们将创建 L1 距离,它使用 和 的encoder_a输出encoder_b。它被实现为一个tf.keras.layers.Lambda层:
-
l
1_dist
= tf.keras.layers.Lambda(
-
lambda embeddings: tf.keras.backend.abs(embeddings[
0]
- embeddings[
1])) \
-
([encoder_a, encoder_b])
9.然后,我们将创建最终的全连接层,它获取距离的输出并将其压缩为单个 sigmoid 输出:
-
flattened_weighted_distance
= tf.keras.layers.Dense(
1, activation
=
'sigmoid') \
-
(l
1_dist)
10.最后,我们可以构建模型并启动 20 个 epoch 的训练:
-
# Build the model
-
model
= tf.keras.models.Model([
input_a,
input_b], flattened_weighted_distance)
-
-
# Train
-
model.compile(loss
=
'binary_crossentropy',
-
optimizer
=tf.keras.optimizers.Adam(),
-
metrics
=[
'accuracy'])
-
-
model.fit([train_pairs[:,
0], train_pairs[:,
1]], tr_labels,
-
batch_
size
=
128,
-
epochs
=
20,
-
validation_
data
=([
test_pairs[:,
0],
test_pairs[:,
1]],
test_labels))
如果一切顺利,该模型将达到 98% 左右的准确率。
接下来,我们将讨论另一种称为原型网络的度量学习方法。
原型网络
在一些简短的学习场景中,大容量模型(具有许多层和参数的 NN)很容易过拟合。原型网络(如Prototypical Networks for Few-shot Learning论文中所述,https://arxiv.org/abs/1703.05175)通过计算每个标签的特殊原型向量来解决这个问题,该向量基于该标签的所有样本. 相同的原型网络也计算查询样本的嵌入。然后,我们测量查询嵌入和原型之间的距离,并相应地分配查询类(本节稍后会详细介绍)。
原型网络适用于零样本和少样本学习,如下图所示:
左:小样本学习;右图:零样本学习。来源:https://arxiv.org/abs/1703.05175
让我们从小样本学习场景开始,其中每个类k的原型向量被计算为该类所有样本的元素平均值:
这里,是k类支持集中的样本数,
是参数为θ的原型网络。在零样本学习场景中,原型计算如下:
这里,是一个元数据向量,它给出了标签的高级描述,并且
是该向量的嵌入函数(编码器)。元数据向量可以预先给出或计算。
在样本嵌入和所有原型之间的距离上,每个新查询样本都被分类为 softmax:
这里,d是距离度量(例如,线性欧几里得距离)。
现在我们对原型网络背后的主要思想有了一个概述,让我们关注如何训练它们(过程类似于我们在元学习简介部分中概述的训练)。
在开始之前,我们将介绍一些符号:
- D是few-shot训练集。
- D k是第k类D的训练样本。
- T是数据集中类的总数。
是标签的子集,为每个训练集选择。
- N S是每集每类的支持样本数。
- N Q 是每集的查询样本数。
该算法从训练集D开始,输出代价函数J的结果。让我们一步一步看它是如何工作的:
1.采样一组标签。
2.对于L中的每个类k,请执行以下操作:
- 样品支撑集
,其中
。
- 样本查询集
,其中
.
- 从支持集中计算类原型:
3.初始化成本函数。
4.对于L中的每个类k,请执行以下操作:
直观地说,第一个组件(在方括号中)最小化了查询与其对应的同一类原型之间的距离。第二项使查询与其他类的原型之间的距离之和最大化。
- 对于每个查询样本
,更新成本函数如下:
该论文的作者展示了他们在 Omniglot 数据集 ( GitHub - brendenlake/omniglot: Omniglot data set for one-shot learning ) 上的工作,该数据集包含从 50 个字母中收集的 1,623 个手写字符图像。每个角色有 20 个示例,每个示例由不同的人类主体绘制。目标是将新角色分类为 1,623 个类别之一。他们使用欧几里得距离、单次和五次场景训练原型网络,并使用 60 个类和每个类 5 个查询点训练集。以下屏幕截图显示了原型网络学习到的相同字母表的相似(但不相同)字符子集的嵌入的t -SNE ( https://lvdmaaten.github.io/tsne/ ) 可视化。
即使可视化的字符彼此之间存在细微的变化,网络也能够将手绘字符紧密地聚集在类原型周围。矩形中突出显示了几个错误分类的字符,以及指向正确原型的箭头:
网络学习的相似字符子集嵌入的t - SNE可视化;来源:https://arxiv.org/abs/1703.05175
这也结束了我们对原型网络和基于度量的元学习的描述。接下来,我们将关注基于模型的方法。
基于优化的学习
到目前为止,我们已经讨论了基于度量的学习,它使用一种特殊的相似性度量(很难过拟合)来适应神经网络的表征能力,并且能够从具有少量训练样本的数据集中学习。或者,基于模型的方法依赖于改进的网络架构(例如,内存增强网络)来解决相同的问题。在本节中,我们将讨论基于优化的方法,这些方法可以调整训练框架以适应少样本学习的要求。更具体地说,我们将专注于一种称为模型无关元学习(MAML; Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks ) 的特定算法,https ://arxiv.org/abs/1703.03400)。顾名思义,MAML 可以应用于任何使用梯度下降训练的学习问题和模型。
引用原始论文:
...
从特征学习的角度来看,训练模型参数的过程使得几个梯度步骤,甚至一个梯度步骤可以在新任务上产生良好的结果,可以看作是构建了一个广泛适用于许多任务的内部表示。如果内部表示适用于许多任务,只需稍微微调参数(例如通过主要修改前馈模型中的顶层权重)即可产生良好的结果。实际上,我们的程序针对易于微调的模型进行了优化,允许在正确的空间进行适应以实现快速学习。从动态系统的角度来看,我们的学习过程可以被视为最大化新任务的损失函数对参数的敏感性:当敏感性高时,
这项工作的主要贡献是一个简单的模型和与任务无关的元学习算法,它训练模型的参数,以便少量的梯度更新将导致对新任务的快速学习。我们在不同的模型类型(包括全连接和卷积网络)以及几个不同的领域(包括小样本回归、图像分类和强化学习)中演示了该算法。我们的评估表明,我们的元学习算法优于专门为监督分类设计的最先进的一次性学习方法,同时使用更少的参数,但它也可以很容易地应用于回归并可以加速强化学习在存在任务可变性的情况下,大大优于作为初始化的直接预训练。
为了理解 MAML,我们将介绍一些特定于论文的符号(其中一些与前面部分中的符号重叠,但我更喜欢保留论文中的原始符号):
- 我们将用 表示模型(神经网络
) ,它将输入x映射到输出a。
- 我们将用
(相当于数据集D)表示完整的训练集。与元训练和元测试部分的元训练类似,我们在训练期间对任务
(相当于情节)进行抽样。这个过程被定义为对任务的分配。
- 我们将用 表示一个任务(一集)
。它由损失函数
(相当于损失J)、初始观测分布
、过渡分布
和长度H定义。
为了理解 MAML 任务定义的一些组成部分,让我们注意除了监督问题之外,MAML 也可以应用于强化学习( RL ) 任务。在 RL 框架中,我们有一个环境和一个代理,它们不断地相互交互。在每一步,代理都会采取一个动作(来自许多可能的动作),环境会为它提供反馈。反馈包括奖励(可能是负面的)和代理行动后的新环境状态。然后代理采取新的行动,依此类推,如下图所示:
强化学习框架
许多现实世界的任务可以表示为 RL 问题,包括游戏,其中代理是玩家,环境是游戏世界。
我们可以在监督和 RL 上下文中查看任务。对于有监督的任务,我们没有按特定顺序标记训练样本
。但是在 RL 上下文中,我们可以将输入x视为环境状态,将输出a视为代理的动作。在这种情况下,任务是顺序的——状态x 1导致动作a 1,这又导致状态x 2,依此类推。环境的初始状态表示为
。这意味着这是一个新环境状态的概率
,给定先前的状态x t和代理的动作a t. 也可以在两种情况下查看损失:监督场景中的错误分类损失
和 RL 场景中的成本函数(提供奖励的函数)。
现在我们已经熟悉了符号,让我们关注 MAML 算法。要了解它是如何工作的,我们将查看原始论文中的另一句话:
![](https://i-blog.csdnimg.cn/blog_migrate/d5995932ffcbc505905408f3e43eaf43.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d5995932ffcbc505905408f3e43eaf43.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d5995932ffcbc505905408f3e43eaf43.png)
有了这些悬念,让我们检查一下 MAML 算法,用下面的伪代码说明:
![](https://i-blog.csdnimg.cn/blog_migrate/bffe88cad43526e0011159b7484af656.png)
该算法有一个外部循环(第 2 行)和一个内部循环(第 4 行)。我们将从内部循环开始,它遍历从任务分布中采样的多个任务。让我们关注一个单循环迭代,它处理带有训练样本
的单个任务
,其中
是任务的支持集。训练样本在以下步骤中作为批次处理(前面屏幕截图中的第 4 到 7 行):
- 通过模型传播样本并计算损失
。
- 计算关于初始参数θ 的误差梯度
。
- 向后传播梯度并计算更新的模型参数
,其中 α 是学习率。请注意,这些参数
是辅助的,并且特定于每个任务。澄清一下,每当内部循环开始新任务
的新迭代时,模型总是以相同的初始参数θ开始。同时,每个任务将其更新后的权重存储为一个附加变量
,而无需实际修改初始参数θ(我们将在外循环中更新原始模型)。
- 我们可以在同一个任务上多次执行这样的梯度更新。将其视为对多个批次的训练,通过内部循环中的附加嵌套循环实现。在这种情况下,算法以最后一次迭代的权重
而不是初始参数θ开始每次迭代i,如以下公式所示:
在多次迭代的情况下,只保留最新的权重。
只有在内循环完成后,我们才能根据所有任务的反馈继续更新原始模型的初始参数θ。为了理解为什么这是必要的,让我们看一下下图:
优化参数θ的MAML可以快速适应新任务:来源:https: //arxiv.org/abs/1703.03400
它显示了三个任务沿全局误差梯度的误差梯度。假设我们不是使用内/外循环机制,而是按顺序迭代每个任务,并在每个小批量之后简单地更新原始模型参数θ 。我们可以看到,不同损失函数的梯度会将模型推向完全不同的方向;例如,任务 2 的误差梯度将与任务 1 的梯度相矛盾。MAML 通过聚合(但不应用)内部循环中每个任务的更新权重(辅助参数
)来解决这个问题。然后,我们可以计算外循环成本函数(称为元目标),同时结合所有任务的更新权重(这是对所有任务的元优化):
我们对主要模型参数的权重更新使用如下公式:
这里,β是学习率。外循环任务(MAML 伪代码程序的第 8 行)与内循环(第 3 行)的任务不同。我们可以将内循环任务视为训练集,将外循环任务视为验证集。请注意,我们使用特定于任务的参数
来计算损失,但我们计算的是相对于初始参数θ的损失梯度。澄清一下,这意味着我们也通过外循环和内循环进行反向传播。这被称为二阶梯度,因为我们计算梯度上的梯度(二阶导数)。这使得即使在多次更新后也可以学习可以泛化任务的参数。
MAML 的一个缺点是通过完整计算图(外循环和内循环)的反向传播在计算上是昂贵的。此外,由于大量的反向传播步骤,它可能会遭受梯度消失或爆炸的影响。为了更好地理解这一点,让我们假设我们有一个任务(我们将在公式中省略它);我们为该任务执行一个梯度步骤(一次内循环迭代),内循环的更新参数为
. 也就是说,我们将损失函数的符号从
更改为
。那么,外循环的参数更新规则变为:
我们可以借助链式法则计算损失相对于初始参数θ的梯度(参见第 1 章,神经网络的基本要素):
我们可以看到公式中包含了二阶导数。MAML 的作者提出了所谓的一阶 MAML ( FOMAML ),它只是忽略了术语
. 有了这个
,我们就有了,FOMAML 梯度变为:
这个简化的公式排除了计算量大的二阶梯度。
到目前为止,我们已经研究了适用于监督和 RL 设置的通用 MAML 算法。接下来,让我们关注监督版本。让我们回想一下,在有监督的情况下,每个任务都是不相关的输入/标签对的列表,并且情节长度H是1。我们可以在下面的伪代码中看到少样本监督学习的 MAML 算法(它类似于通用算法):
在上述代码中,等式 2 和 3 均指分类任务的交叉熵损失或回归任务的均方误差,指的是内循环训练集,
以及外循环的验证集。
最后,让我们讨论一下 RL 场景,如下面的伪代码所示:
每个样本代表一个游戏情节的轨迹,其中环境 在步骤t处向代理呈现其当前状态
。反过来,代理 (NN) 样本使用策略
将状态
映射到动作分布
。该模型使用一种特殊类型的损失函数,旨在训练网络在剧集的所有步骤中最大化奖励。
概括
在本章中,我们研究了元学习领域,可以将其描述为学习学习。我们从介绍元学习开始。更具体地说,我们讨论了零样本和少样本学习,以及元训练和元测试。然后,我们专注于几种基于度量的学习方法。我们研究了匹配网络,实现了一个连体网络的示例,并介绍了原型网络。接下来,我们专注于基于优化的学习,我们介绍了 MAML 算法。