写在开始之前
在我之前为 PyTorch 撰写的文章《Active Learning with PyTorch》中,我介绍了主动学习的构建模块。如果你不熟悉主动学习,你可以从这里开始了解,也可以看看我关于两种主动学习——不确定性抽样和多样性抽样的文章,以及相关的主动学习技术来将知识串联起来:
文章网址:https://towardsdatascience.com/uncertainty-sampling-cheatsheet-ec57bc067c0b
文章网址:https://towardsdatascience.com/https-towardsdatascience-com-diversity-sampling-cheatsheet-32619693c304
文章网址:https://towardsdatascience.com/advanced-active-learning-cheatsheet-d6710cba7667
在我的免费 PyTorch 库中,也有所有主动学习算法的相关例子,包括本文中介绍的新算法:
github 网址:https://github.com/rmunro/pytorch_active_learning
理想情况下,你应该在接触本文中更高级的方法之前,亲自尝试实现更简单的主动学习策略。
什么是迁移学习?
迁移学习是将为一个特定任务建立的机器学习模型应用于另一个任务的过程。
「我们要去的地方不需要道路」。机械迁移学习:一辆车可以被改造成一台时间机器,或者一艘船 (图片来源:SF Chronicle)
将技术从一个用例调整到另一个用例是很有趣的。我永远不会忘记,有一天,当我在 San Francisco 附近透过火车车窗看到一辆汽车在 Brisbane Lagoon 的水里与火车相撞时的激动心情。
每当为一个特定目的而构建的机器学习模型适应于一个全新的用例时,你都可以感受到同样的喜悦。如果这个用例碰巧是主动学习,那么我们将把机器学习中最有趣的部分应用到解决机器学习中最重要的问题中:人类和人工智能如何一起解决问题?
在当前的机器学习中,迁移学习通常是指获取一个现有的神经模型,然后对最后一层 (或最后几层) 进行再训练,以完成新的任务,它可以表示为:
迁移学习的一个例子。模型预测标签为「a」、「B」、「C」或「D」,单独的数据集标签为「W」、「X」、「Y」和「Z」。再训练模型的最后一层模型现在能够预测标签「W」、「X」、「Y」和「Z」。
迁移学习的最大优点是,与从头开始训练一个模型相比,你需要更少的人工标记的示例,这意味着你可以用更少的数据获得更高精度的模型。如果你有计算机视觉背景,你可能已经用迁移学习来适应一个来自 ImageNet 分类任务的模型;如果你有自然语言处理背景,你可能已经用迁移学习来适应一个像 BERT 这样的预先训练过的模型。
让你的模型预测它自己的错误
迁移学习的新标签可以是任何你想要的类别,这包括任务本身的信息!这是主动迁移学习三个核心观点中的第一个:
观点 1:你可以使用迁移学习,通过让你的模型预测自己的错误,来发现模型哪里被混淆了。
这篇文章涵盖了三种主动迁移学习的变体,最简单的一种是二进制的「correct/incorrect」任务,用来预测模型可能在哪里出错:
不确定性抽样的主动迁移学习。验证项由模型预测,并根据分类是否正确将其划分为「incorrect」或「incorrect」。然后对模型的最后一层进行重新训练,以预测项目是「correct」还是「incorrect」,从而有效地将两个 bucket 转换为新的标签。
这个过程有三个步骤:
- 将模型应用于验证数据集,并捕获哪些验证项被正确分类了,哪些被错误分类了。这是你的新的训练数据:你的验证项现在有一个附加的「correct」或「incorrect」标签。
- 为模型创建一个新的输出层,并在新的训练数据上训练这个新层,预测新的「correct」/「incorrect」标签。
- 在新模型中运行未标记的数据项,并对预测为「不正确」的数据项进行抽样,这是最可靠的。
PyTorch 使这一过程变得非常简单,它能够将每个神经元的激活传递回其他进程,从而使我们能够在原有模型的基础上构建我们的主动迁移学习模型。假设我们有一个简单的网络,有一个隐含层,使用这个 forward() 函数:
代码语言:javascript复制def forward(self, feature_vec, return_all_layers=False):
hidden1 = self.linear1(feature_vec).clamp(min=0)
output = self.linear2(hidden1)
log_softmax = F.log_softmax(output, dim=1)
if return_all_layers:
return [hidden1, output, log_softmax]
else:
return log_softmax
然后我们可以迭代我们的验证数据,并为每个验证项分配一个值,即它是「correct」还是「incorrect」,并将其隐含层作为输入存储到我们的新模型中:
代码语言:javascript复制correct_predictions = [] # validation items predicted correctly
incorrect_predictions = [] # validation items predicted incorrectly
item_hidden_layers = {} # hidden layer of each item, by id
for item in validation_data:
# assume "item" contains id, label & features of each data point
id = item["id"]
label = item["label"]
feature_vector = item["feature_vector"]
hidden, logits, log_probs = model(feature_vector, True)
item_hidden_layers[id] = hidden # record hidden layer value
if is_correct(label, log_probs):
correct_predictions.append(item)
else:
incorrect_predictions.append(item)
然后我们可以训练一个新的模型来预测「correct」或「incorrect」,使用隐藏层作为新的输入 (特征) 向量。假设我们在代码中调用了新模型 correct_model。
在这个新模型被训练之后,唯一棘手的部分是,我们需要从两个模型中得到未标记数据的预测:第一个预测从第一个模型中得到隐含层,然后第二个预测新的「correct/incorrect」模型:
代码语言:javascript复制active_transfer_preds = []
with torch.no_grad(): #A
v=0
for item in unlabeled_data:
id = item["id"]
label = item["label"]
feature_vector = item["feature_vector"]
# get prediction from initial model
hidden, logits, log_probs = model(feature_vector, True)
# get predictions from correct/incorrect model
correct_log_probs = correct_model(hidden, False)
此时,在代码 correct_log_probs 中有未标记项被正确预测的概率。通过对被正确预测的置信度最低的项进行抽样,就是对那些本应由人类检查的应用标签的项目进行抽样。
这段代码是免费 PyTorch 库中的 advanced_active_learning.py 文件中的代码的一个稍微简化的版本:https://github.com/rmunro/pytorch_active_learning/blob/master/advanced_active_learning.py
你可以使用以下命令立即在用例——识别与灾难相关的消息上运行它:
代码语言:javascript复制python advanced_active_learning.py——transfer_learned_uncertainty = 10
这将运行整个过程,然后给你提供 10 个最不确定的项目,以便你提供正确的标签。
此时,该模型可能并不比简单的不确定性抽样算法更好,因此,首先实现简单的方法作为基线也是一个好主意。但不要放弃:这是构建更强大的算法的第一步。
比起简单的方法,我们从迁移学习中获得的最大优势是,它使我们的主动学习策略更容易适应。主动学习策略的一个常见问题是,它们会对未标记的项目进行抽样,这些项目都来自特征空间的一部分,因此缺乏多样性,因此需要使用像聚类这样的多样性抽样方法来避免这个问题。有一些先进的主动学习技术将不确定性抽样和多样性抽样单独地结合起来,但是本文中的以下方法具有将这两者结合成单一架构的优点。
通常情况下,实时的人类标签很难获得,更实际的做法是采样大量未标记的物品,并将其标记为一批。所以在这些情况下,自适应代表性抽样的主动迁移学习在抽样过程中是合适的,即使我们还不知道标签是什么。
代表性抽样的主动迁移学习
对于许多实际的用例,你的数据会随着时间而变化。例如,在自动驾驶汽车用例中,总是会遇到新类型的对象,并且对象的范围可能会扩大,比如在道路之外的开阔水域驾驶。
代表性抽样是多样性抽样的一种形式,其目的是对与当前机器学习模型的应用领域最相似的未标记项进行抽样。
因为我们采样的项目将获得一个人工标签,我们可以假设它们是训练数据的一部分,而不需要知道标签是什么。
自适应代表性抽样的主动迁移学习
步骤如下:
- 从与训练数据相同的分布中获取验证数据,并给它一个「Training」标签。从我们的目标域获取未标记的数据,并给它一个「Application」标签。
- 训练一个新的输出层来预测训练/应用程序标签,让它访问模型的所有层。
- 将新模型应用于未标记的数据,并对最有可能被预测为「应用程序」的项目进行抽样。
- 假设新抽样的项目稍后将获得标签并成为训练数据的一部分:将这些项目的标签从「Application」更改为「training」,然后重复步骤 2。
这是一个非常强大的算法,因为它避免了只对特征空间的一部分进行采样,在任何人为标记之前对一组不同的项目进行采样。
观点 2:即使你还不知道标签是什么,你也可以假设一个未标记的项目以后会得到一个标签。
自适应采样的主动转迁移学习 (ATLAS)
主动迁移学习最复杂的应用是自适应采样 (ATLAS) 的主动学习。它综合了本文中前面两个模型的原则:在添加任何人工标记之前预测不确定性并适应数据。
我们用时间旅行来对此进行类比。想象一下,你把你的车变成了一台时间机器,但你必须以每小时 88 英里的速度行驶,才能进行时空旅行。即使你还不知道未来的路会是什么样子,你也可以把车开到未来。然后,即使没有充分的知识背景,你也可以考虑汽车将会在哪里,开始制定未来的计划。
我们可以对我们的模型做同样的事情,假设我们有数据知识,我们将在以后标记并使用这些知识来采样更多的数据供人类检查:
用于自适应采样的主动迁移学习
步骤如下:
- 将模型应用于验证数据集,并捕获哪些验证项被正确分类了,哪些被错误分类了。这是你的新训练数据:你的验证项现在有一个附加的「correct」或「incorrect」标签。
- 为模型创建一个新的输出层,并在新的训练数据上训练这个新层,预测新的「correct」/「incorrect」标签。
- 在新模型中运行未标记的数据项,并对预测为「incorrect」的数据项进行抽样,这是最可靠的。
- 假设新抽样的项目稍后将得到标签,并且模型稍后将在对这些项目进行训练后正确预测这些项目:将这些项目的标签从「incorrect」更改为「correct」,然后重复步骤 2。
通过结合不确定性采样和自适应代表性采样的主动迁移学习技术,我们现在有了一个可以预测其未来状态的模型。它不知道最初采样的项目的标签是什么,但它知道它们会得到一个标签,然后它可以根据预期的未来事件做出更明智的抽样决策。
观点 3:你可以假设模型将正确预测未标记项的标签,这些项和稍后将获得标签的项一样,即使你还不知道标签是什么。
此代码与上述文件位于同一个免费 Pythorch 库中的 advanced_active_learning.py 相同:https://github.com/rmunro/Pythorch_active_learning/blob/master/advanced_active_learning.py
你可以使用以下命令行运行它:
代码语言:javascript复制python advanced_active_learning.py --atlas=10
主动迁移学习备忘单
这是一个单页的备忘单,你可以在构建本文中的算法时参考它:
主动迁移学习备忘单
为了快速参考,你可以在这里下载一个 PDF 版本的备忘单:http://www.robertmunro.com/Active_Transfer_Learning_cheatsheet.PDF
本文摘自我的书《Human-in-the-Loop Machine Learning》,网址:https://www.manning.com/books/human-in-the-loop-machine-learning#ref 。
如果你要开始学习这本书,以下有一些注意事项:
- 这本书中的方法在数学上相当于删除最后一层并重新训练一个新层(如上图所示),或者取而代之的是从最后一个隐藏层获取输出并将其用作新模型的输入(如代码示例中所示)。我认为前者在视觉上更直观,但后者不太容易出错,因为它是纯粹的加法,你不必担心更改模型会对代码的其他部分产生什么影响。如果你更喜欢在自己的代码中实现迁移学习,那就没问题了。如果你想用新的数据/标签来调整现有的层,而不是完全移除层,那么这也是正确的。
- 注意,代表性采样的示例使用所有隐藏层,并且还添加了额外的新层,而不确定性采样和 ATLAS 示例是在最终隐藏层之后的简单二进制预测。从设计上来说,这是架构的一个良好起点,但是你可以在所有情况下尝试不同的架构。这背后的原因是,我们模型的最后一层没有将数据中没有很好表示的项与数据中很好表示的项区分开来,但是这些项具有与当前状态下的模型基本无关的特征。因此,代表性抽样应该更好地利用早期层的信息。相比之下,不确定性采样和 ATLAS 示例只使用最后一层,因为模型的最后一层已经最小化不确定性,因此在较早的层中不太可能找到更多的信息,如果包含较早的层,则更容易过度拟合。
- 你可以考虑通过 Monte-Carlo 采样从单个模型进行多个模型变量预测。这些示例依赖于与你的训练域来自同一发行版的验证数据,并且你可以轻松地对该验证集中的特定项进行过拟合。如果要将训练数据 90:10 拆分为 training:validation,就像这里的代码示例一样,那么一个简单的方法是对所有 90:10 组合重复此操作。注意,对于不确定性采样和 ATLAS 示例,你只创建了一个新的二进制预测器,因此不需要太多的数据就可以得到稳健的结果。这是这些模型的一个很好的特性:一个额外的二进制预测很容易用相对较少的数据进行训练,而且通常不需要手动调整。
- 主动迁移学习可以用于更复杂的任务,如目标检测、语义分割、序列标记和文本生成。几乎任何类型的神经模型都可以添加一个新的层来预测「correct/Incorrect」标签或「training/application」标签,因此这是一种非常通用的技术。
via:https://medium.com/pytorch/active-transfer-learning-with-pytorch-71ed889f08c1
封面图来源:https://engineering.fb.com/ai-research/facebook-accelerates-ai-development-with-new-partners-and-production-capabilities-for-pytorch-1-0/