多任务学习:多教你的AI,它会变得更好!
嗨,大家好!今天我想分享一个关于机器学习的主题,一方面,注重研究,逐步走向更像人类的推理或机器学习算法,另一方面,我们从基础知识中熟知机器学习,但实际上它很少被解释。因此,今天我会就此进行详细的阐述。它被称为多任务学习,(几乎)与多任务处理无关,如上图所示。在这篇文章中,我将展示什么是人类和算法的多任务学习,今天的研究人员如何应用这个概念,如何使用它来解决你的任何问题,以提高你的模型性能。而且,最重要的是,我将为您提供4个用例的源代码和解释,你可以把它用作您自己项目的模板。
这篇文章的灵感来自Sebastian Ruder和Rich Caruana的资料。
如果你想直接跳转到Keras中的代码,这里是相应的GitHub地址:(https://github.com/rachnog/education/tree/master/multitask_dsua_2018)。
我们的多任务处理
“多任务处理”这个词本身通常意味着一些消极的东西- 一个试图做很多事情并且没有成功的人就是最好的例子。但在这里,我想谈谈有点不同的“多任务处理”。我想,我们的生物大脑所做的所有“功能”都是某种深度神经网络,它也通过反向传播进行训练并给出一些标签作为输出。我们可以考虑一下这样的视觉系统,当我看到某些内容时它会输出什么?我不能只识别物体,分割它们并理解场景。我还可以估计街上人们的情绪,他们如何穿着,基于他们的衣服判断天气,我可以估计它是什么国家甚至城市,从视觉渠道我可以理解到非常丰富的细节内容。
好的,那倾听呢?如果我听到任何人的一个声音,我立刻就会明白一个人的性别、音调、我也会理解单词、整句和它的意思,我知道语言,也理解所有实体,甚至能够答复我所听到的内容。
我可以用我的任何感官系统来做同样的练习,可以从一个单独的“测试”例子中感受到很多东西,可能是图片、声音、文字甚至可能是感觉。
机器的多任务处理
另一方面,现代神经网络(和其他机器学习算法)通常从单个例子中解决单个问题。它可以是分类、回归、结构化预测、异常检测甚至是对象生成,但通常,我们期望在最后得到一个单一的结果。在这篇文章中,我想谈谈并展示如何让我们的模型学习更多东西,我将从多任务学习的例子开始:
用于损失函数的L2正则化
我们都知道这个著名的L2正则化公式。为什么我说这是多任务学习的一个例子?因为我们同时解决了两个优化问题:损失函数的最小化并使我们的参数的范数变小。我们通常不会深入思考,但是在选择这个特定的第二优化函数背后有很多理论:
正则化效应的不同解释
例如,Andrey Tikhonov主要对解决不适定问题感兴趣。波兰数学家Zaremba将其用于统计学习理论,因为模型的复杂性非常希望变小,因此,我们将其最小化。从贝叶斯的观点来看,我们通过这种方式调整权重以获得一定的分布,这些是我们对参数的先验。我们大多数人有时候会在一些我们并不真正担心的课程上研究它,但我们知道它可以防止模型过度拟合。
如您所见,在任何这些解释中,我们只考虑模型本身的参数w。但是从我的直觉观点(以及我脑中的神经网络),我想从推理的角度更具体地解释它。我可以添加一些考虑到“真实”、“类似人”的问题背景的“正则化”吗?如果我想识别照片中的情绪,我是否应该限制权重以“了解”鼻子和嘴唇的动作?很可能是的。如果我想翻译文本,可以帮助我的参数知道给定单词的词性吗?我认为这确实是。
所有这些“知识”、“条件作用”我可以作为一个额外的输入纳入机器学习算法,但是自从我开始在这里谈论多任务学习...你现在应该明白我在往哪里引导了。如果像算法参数正则化这样的额外损失有助于提高性能,为什么我们不应该尝试从人类逻辑的角度来看有助于提高性能的额外损失?然后我们的算法看起来就像上图:单个输入、几个层(在神经网络的情况下)和众多输出,可以发挥一些超参数lambda的正则化器的作用,或者也想要优化和解决一个独立目标。
是的,除了“正则化”之类的多任务学习动机之外,我们只能承认从一个简单的工程角度来看,需要学习用一个神经网络来解决X个问题,而不是拥有X个独立的神经网络。可以看到,更好的性能、正则化和泛化带来了额外的好处。
激励性的用例
在开始深入细节之前,我想展示一些激励性的例子。第一个是计算机视觉方面的惊人研究,他们不仅展示了单个神经网络如何同时解决20多个任务,而且还自动构建了一个层次结构(这就是为什么它被称为Taskonomy)在2D和3D空间中的不同任务与将一项任务转移到另一项任务相比,性能有所提升。而这项工作是如何将单个图像的复杂理解融入单个算法的惊人灵感。
第二个很好的例子来自自然语言处理:为什么我们不使用单个神经网络来解决情绪分析、语义分析、翻译、回答问题、使用单个神经网络从单个句子翻译?Salesforce的研究人员也这么认为,并开发了自己的创意解决方案。
在我负责的机器学习的Mawi解决方案中,我们还应用多任务学习的概念进行实时心电图分析。在测量心电图时,我们需要标记其形态结构以进行进一步分析,估计信号质量并每秒同时解决异常检测任务。我们可以在移动电话上同时运行三种不同的算法(不一定是机器学习算法),但我们成功地使用单个神经网络来解决了所有的问题,与不同方法的组合相比,这种神经网络明显更快、更准确。
在Mawi Solutions中进行实时ECG分析的多任务学习
多任务学习对于强化学习作为“类人”行为的关键概念也非常重要。其中一个很好的例子是DeepMind的工作Distral:我们建议分享一个“提炼”的策略来捕获跨任务的共同行为,而不是在不同的损失之间共享参数。
Distral:强大的多任务强化学习
工作的原因
好吧,这一切都很酷,但仍然不太清楚它为什么会起作用。
- 正则化:额外的损失原则上确实与不同的研究人员想要的正则化相同:它可以平滑损失函数,最大限度地降低模型的复杂性,并为您的模型提供非常丰富的先验。
- 表示偏差:当您在几个任务的交集上训练模型时,您可以推动学习算法在交叉点上的较小区域表示上找到解决方案,而不是在单个任务的大面积上找到一个解决方案。它可以带来更快、更好的收敛。
- 功能选择仔细检查:如果一个功能对于一个以上的任务非常重要,那么很可能这个功能确实非常重要并且代表了您的数据。
- 迁移学习:机器学习已经从学习多个任务中受益,但是依次使用迁移学习:在一个任务上的大型数据集上预先训练模型,并在使用获得的模型训练另一个任务之后。实证结果表明,联合学习这些任务会更有益、也更快。
- 不能作为输入的输出:这一刻对我来说是最有趣的。有些特定类型的数据由于其顺序性质受到过去观察的限制,通常我们需要处理它们:句子中的单词(必须预测下一个单词、帧和视频,必须预测下一个框架等)。我们希望从这些过去时刻的表示能够对未来的模型进行建模。在这里,辅助任务如此自然地产生。过去的帧必须预测下一帧,我们不能用作输入!其他很好的例子是在测试/生产阶段难以长时间计算的特征,但我们可以将它们用作辅助损失函数来规范我们的模型以“了解”它们。
预测视频中的下一帧不能提供非常丰富的信息
每个人的辅助任务
好吧,也许现在的你或多或少觉得多任务学习很酷,适用于研究人员,并且背后有一些理论和经验动机。但你可能会回答我,你在项目中并不真正需要它,因为你不需要同时解决几个任务,或者你根本没有为数据集添加一些额外的标签,或者没有获得它们的可能性。在本节中,我想展示一些辅助损失的例子,你们每个人都可以在任何项目中使用辅助损失作为额外的正则化器,从而提高你的性能。
- 自然语言处理
- 语言建模:NLP的核心是n-gram建模:给出最后n个单词的单词概率。您可以预测句子中的下一个单词作为您希望模型具有的先验知识。
- NLTK:词性、句子树、NER - 你确定你的深度学习不会从中受益吗?尝试从NLTK或spacy作为先验的基本NLP功能。
- DecaNLP:清晰的灵感
- 计算机视觉
- OpenCV:为什么不给你的对象跟踪模型一些先验如HOG特征或一些“基本”阈值分割用于语义分割?它们都在OpenCV、scikit-image或dlib中。
- 任务:明确的灵感
- 信号处理
- 统计/特征建模:好主意是使用给定时间序列中的统计或其他特征,例如,它可以是从标准偏差、偏度和峰度到样本熵、AR或傅立叶系数的任何特征
- 预测建模:尝试预测与给定时间窗口分类,它也可以工作(作为语言建模的类比)
- 一般建议
- 自动编码器/生成建模作为模型推动任何表示尽可能最有用和最具描述性
- 提示(预测重要特征,如计算机视觉中的HOG、NLP中的NER和DSP中的熵)
关于可重复研究的说明
在展示如何实现多任务学习之前,我想展示我必须做些什么来使我在Keras中的代码至少在某些点可以在另一台计算机上重现(但仍然不够)。首先,我必须修复所有随机种子:
修复神经网络层的初始化程序并运行会话:
并在创建数据集时修复随机种子:
甚至在训练模型时设置“shuffle = False”。此外,我修复了模型和训练条件的所有超参数,作为时期,优化器和批量大小的数量。但这还不够,在某些计算机上(我在MacBook Air上运行我的代码)结果与此略有不同。我可以解释它(感谢来自听觉的暗示),只是这样:不同的硬件导致不同的浮点数错误,导致不同CPU上的优化过程略有不同。我想知道是否有办法克服这个问题(我考虑在每次训练过程之前重新初始化随机种子),并且非常感谢任何提示。
练习1:情绪识别
正如我所承诺的那样,本文将有几个代码示例,因此您可以尝试自己进行多任务学习(主要集中在使用其他任务作为正则化器)。第一个例子与计算机视觉有关,特别是与数据集有关(数据集不是免费分发的,但您可以为研究目的请求访问):
我的完整代码在这里:
https://github.com/Rachnog/education/tree/master/multitask_dsua_2018/emotion_detection
此数据集由不同人员的图像和相应的标签组成:
- 他们的脸表达的情绪
- 面部动作单元
- 面部关键点
我们将使用一个非常简单的神经网络(与现有技术相比)的情感识别作为主要任务,并将尝试使FAU和关键点检测适应作为正则化。这是一个神经网络,我们将尝试通过多任务学习来增强。正如您所看到的,在2018年的深度学习时代,我们可以轻松地将其称为“浅层”:
它显示以下结果(当然不满意):
接下来,我为模型添加了第二个输出,该模型必须预测面部动作单元以及情绪:
结果变得稍微好一些!
好吧,如果这种辅助损失有所帮助,也许预测关键点也可能是好的?至少它的表现也比基线好:
好吧,看起来现在我有两个辅助损失,两者都规范我的基线解决方案,所以我想结合它们,得到更好的结果。我将以一种“聪明”的方式做到这一点。当我(作为一个人)分解我自己的情感识别时,我首先看到关键点,然后我将它们组合成动作单元,最后,我才从这个特征层级中理解情绪。就神经网络而言,它可能意味着,我应该将FAU损失附加到第一个卷积层,将关键点损失附加到第二个卷积并最终留下主要损失:
为了避免在较低层上“杀死”来自主要损失函数的梯度,我为第二层和第一层的损失0.1添加了lambdas:
我们训练相同的10个epochs......
我们可以通过智能方式使用额外的损失函数将我们的结果从0.36 F1得分提高到0.60 F1得分。相同的简单卷积网,相同的初始化程序,相同的数据,相同的训练过程。看起来像魔术?让我们看看下一个例子。
练习2:加速度计运动分析
你可以告诉我,通常情况下,你没有面部动作单元这样的好的附加功能,可以与主要损失一起使用。没关系,现在我将向您展示一个任务的示例,您可以自己创造这些损失。该数据集是关于对腕戴式加速度计的活动进行分类:
https://archive.ics.uci.edu/ml/datasets/Dataset+for+ADL+Recognition+with+Wrist-worn+Accelerometer
这是我对这个问题的完整代码:
我的输入是加速度计的三个轴的多变量时间序列,输出是21个活动类别之一。没有额外的损失。我现在应该怎么做?当然,创造一些!我选择了对我来说合乎逻辑的损失:
- 给定时间序列的标准差
- 时间序列的绝对变化之和
- 傅立叶系数
我有一个假设,即如果我的神经网络知道其中一个特征,那么它的表现会好于没有。我首先用一个简单的1D卷积神经网络检查基线解决方案:
并得到以下精确召回-F1:
添加标准偏差损失怎么样?
以及一些变化
可能他们都没有那么多帮助,但傅立叶一定是一个强大的“镜头”。
似乎我们可以将基线提高5%,但这也是一个好结果。我们经常使用不同的棘手方法来争取这五个百分点,所以现在你又多一个。
实践3:促进暹罗网络
暹罗神经网络是一类特殊的模型,旨在比较新嵌入空间中的对象:类似的对象必须彼此靠近(距离小)而不同的对象需要相距较远。计算两个64x64图像的欧几里德距离(在MNIST数据集的情况下)并不是一个明智的想法,但我们可以将这些图像嵌入到某个向量空间中,这将是有意义的。该系列模型的主要特点是具有两个输入和层的权重,这些权重在这些输入之间共享以允许交换(因为我们基本上计算两个对象之间的距离)。在这个例子中,我将展示如何为每个层的“袖子”上添加额外的损失将改善MNIST数据集的性能。完整代码在这里:
首先,每个输入都有一个编码器,如下所示:
正如您所看到的,我们将输入图像嵌入到某个64维空间中,我们可以在其中比较它们,并且损失旨在最小化相同数字的图像之间的距离并最大化不同的图像:
我有一个假设,即在这个64维嵌入空间中,我不仅可以比较图像,还可以对它们进行分类。所以我的第二个损失将是简单分类为10位数的类。训练基线暹罗网络并将其作为分类器进行测试会显示以下结果:
并有辅助损失:
就是这样
实践4:Numerai的财务预测
Numerai是一个关于加密财务数据的数据科学挑战,在加密金融数据中,你已经为自己准备好了所有的东西,剩下的就是——预测5个独立变量的0或1,而不是与训练数据过度匹配。由于这里有几个目标自然而然会产生几个目标(我知道多任务学习可以防止过度拟合)所以,我决定尝试多任务处理。你可以在这里检查整个代码:
在这种情况下,我的额外损失不是辅助的,但它们都很重要。所以,我建立我的神经网络如下:
与lambda相同:
这个模型在15次测试中,有9次超过了实时金融数据的基准,而且仍在计算中。我认为这不是一个糟糕的结果,我很乐意与你们分享。
9月15日在Numerai上进行多任务学习
结论
我知道所有这些材料可能有点压倒性,但不要担心。我所试图展示的所有内容都可以紧凑地压缩成三个主要结论:
- 多任务学习对人类来说是正常的(但也许不是多任务处理)
- 多任务学习对于机器学习来说是正常的,而且,我们已经做了几十年
- 下次当你发现自己过度拟合或者没有从机器学习模型中获得最大收益时,是时候考虑了,也许你不需要更多的数据,但是你需要更多的损失?
此外,我们回顾了一些有关多任务学习的实际用例,并学习了如何在Keras中编写代码,如何使用辅助损失并为它们选择权重(至少在某些情况下)。我希望这篇博文对您有用,您将可以使用多任务学习的概念在您当前的项目中获得更好的结果!