MetaLearning入门

Meta Learning 入门

Introduction

Machine Learning 让机器能够学习

Meta Learning 让机器学习应该如何学习

在这里插入图片描述

以上图为例,假设现在有一百个识别任务,例如是语音识别,图像识别等等,在这些任务学习完成之后,我们需要给机器一个新的任务,这个新的任务跟之前的一百个任务没有任何的关联,例如是一个文本分类任务。Meta-Learning要做的就是希望能够从前一百个识别任务中让机器在文本分类任务上表现得更加优秀。也就是说,机器在前面的学习中不仅仅学到了如何解决特定任务,并且学习到了学习本身这件事情,从而提高了在新任务上的学习能力。(个人理解是从不同的任务中学到了一些先验知识,然后把它用到新任务里。)

区别

  • Life-long Learning:one model for all the tasks(一个模型–多个任务)

  • Meta-Learning:How to learn a new model(如何学一个新的模型)

刚刚讲的Meta-Learning概念描述可能还是有点抽象,那么我们用一个具体的模型结构来解释一下Meta-Learning实际在做的事情。

在这里插入图片描述

简单地说,机器学习过程是这样的:人为设计一个Learning Algorithm,然后输入一堆训练数据,训练之后得到一个function,然后这个function用来辨认新的数据,如果这个function辨认新数据的结果还不错,我们就认为机器学到了对于该特定任务的实现函数 f ∗ f^* f

So what about Meta Learning?

在这里插入图片描述

在Meta Learning中,也把Learning algorithm当成一个函数 F F F,即输入一堆训练数据,然后根据函数 F F F得到 f ∗ f^* f,最后根据 f ∗ f^* f来测试新的数据。

跟机器学习相比,元学习其实是想让机器从数据中自己学习到Learning Algorithm,而不是人为设计。

在这里插入图片描述

实际上,我们知道Meta Learning的训练资料是一堆训练集和 f ∗ f^* f的组合,训练集的准备是比较容易的,但是 f ∗ f* f的准备就比较复杂了,因为它本身是一个抽象概念。我们需要通过一个实例去介绍:

在这里插入图片描述

上图是gradient descent的算法,它的流程可以简述为:设计一个网络架构–>给参数 θ 0 \theta^0 θ0做初始化–>读入训练数据批次–>计算梯度–>基于梯度更参数–>进入下一轮训练…灰色的部分其实就构成了一个function f ∗ f^* f,而训练的过程中很多参数是自己设计(红色方块)的,例如网络结构,参数,以及怎么基于梯度去更新参数(lr的设置等等),每当我们手动去更新这些模块的时候,其实都在定义一个新的 f ∗ f^* f,所以对于gradient descent方法来说,元学习的最终学习成果是在给定训练资料的条件下,机器能够找到 f b e s t ∗ f^*_{best} fbest

接下来,我们需要做的就是设计评价函数 F F F 好坏的指标,具体来说, F F F可以选择各种不同的训练流程 f ∗ f* f,如何评价 F F F然后找到 f ∗ f^* f,以及如何找到 f ∗ f^* f都是元学习中比较重要的部分。

然后说明一下元学习中函数 F F F的损失函数的定义

在这里插入图片描述

如图所示,在Task1中,函数 F F F的训练算法是 f 1 f^1 f1,而Task1中的测试集在 f 1 f^1 f1上的测试结果被记作在Task1上的损失值 l 1 l^1 l1(这里的测试结果不仅仅是分类任务中的分类损失,也可以是损失下降的速率等,这取决于我们想函数 F F F学习到什么样的算法效果);同理在Task2也是如此。

综上所述,函数 F F F的损失函数就定义在所有Task上的损失总和:

L ( F ) = ∑ n = 1 N l n L(F)=\sum_{n=1}^{N} l^{n} L(F)=n=1Nln

得到损失函数之后我们应该怎样去降低 F F F的损失?由于元学习的求解是非常复杂的过程,接下来以MAML(Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks)算法为例介绍一个Meta Learning的简单情况求解。

MAML算法介绍及其实现

MAML算法介绍

MAML算法要解决的问题是,对于函数 F F F在每个任务中学习到的 f f f,规定 f f f只负责决定参数的赋值方式,而不设计模型结构,也不改变参数更新的方式。也就是说MAML中的 f f f的网络结构和更新方式都是固定的,要解决的其实就是如何针对不同任务为网络赋不同的初值。

在这里插入图片描述

如上图, f f f只考虑参数的初始化方式。假设当前函数的初始化为 ϕ \phi ϕ,将 ϕ \phi ϕ应用于所有的训练任务中,并将所有任务最终训练结束后的参数作为 θ ^ n \hat{\theta}^{n} θ^n(n表示第n个任务),然后该参数下的测试损失记为 l n ( θ ^ n ) l^{n}\left(\hat{\theta}^{n}\right) ln(θ^n)。那么当前的初始化参数 ϕ \phi ϕ的损失函数就表示为:

L ( ϕ ) = ∑ n = 1 N l n ( θ ^ n ) L(\phi)=\sum_{n=1}^{N} l^{n}\left(\hat{\theta}^{n}\right) L(ϕ)=n=1Nln(θ^n)

接下来我们需要求解 ϕ \phi ϕ使得:

ϕ ∗ = arg ⁡ min ⁡ ϕ L ( ϕ ) \phi^{*}=\arg \min _{\phi} L(\phi) ϕ=argminϕL(ϕ)

怎么求得上式?通过梯度下降方法求解:

ϕ ← ϕ − η ∇ ϕ L ( ϕ ) \phi \leftarrow \phi-\eta \nabla_{\phi} L(\phi) ϕϕηϕL(ϕ)

MAML为了更快地计算出上面的结果,做了两处计算上的调整:

在这里插入图片描述

如上图所示,由于在每一个训练任务上更新多次参数会让训练周期变得很长,因此MAML选择只更新一次的参数结果作为该任务的最终参数 θ ^ n \hat{\theta}^{n} θ^n,也就是只走一次梯度下降:

θ ^ = ϕ − ε ∇ ϕ l ( ϕ ) \hat{\theta}=\phi-\varepsilon \nabla_{\phi} l(\phi) θ^=ϕεϕl(ϕ)

能这样做的原因是,如果模型只训练一次就能达到好的效果,那么这样的训练初始参数基本上能复合好的参数,不过在测试资料上依然需要训练多次才能检验该初始参数的真正效果。

MAML的第二处调整是,对

数学推导比较简单,略。具体见纸质笔记(有空可以黑板推导)。

最终得到 ∂ l ( θ ^ ) ∂ ϕ i = ∑ j ∂ l ( θ ^ ) ∂ θ ^ j ∂ θ ^ j ∂ ϕ i \frac{\partial l(\hat{\theta})}{\partial \phi_{i}}=\sum_{j} \frac{\partial l(\hat{\theta})}{\partial \hat{\theta}_{j}} \frac{\partial \hat{\theta}_{j}}{\partial \phi_{i}} ϕil(θ^)=jθ^jl(θ^)ϕiθ^j

简化后MAML的计算就变得比较简单了,理论分析到此为止。

接下来我们通过一个实际例子来理解上面的计算是怎么执行的。

在这里插入图片描述

首先,最开始有一个初始化的参数 ϕ 0 \phi^0 ϕ0,然后,在Task m上训练一次得到最终参数 θ ^ n \hat{\theta}^{n} θ^n,接着计算 θ ^ n \hat{\theta}^{n} θ^n的梯度(即上图中第二根绿色箭
头),将这一梯度乘以学习率赋给 ϕ 0 \phi^0 ϕ0,得到的 ϕ 0 \phi^0 ϕ0第一次更新结果 ϕ 1 \phi^1 ϕ1

接下来,同样地,在Task n上训练一次 ϕ 1 \phi^1 ϕ1得到最终参数 θ ^ n \hat{\theta}^{n} θ^n,接着计算的 θ ^ n \hat{\theta}^{n} θ^n梯度(即上图中第二根黄色箭头),将这一梯度乘以学习率赋给 ϕ 1 \phi^1 ϕ1,得到第二次训练的更新结果 ϕ 2 \phi^2 ϕ2。这样不断循环往复,直至在所有的训练Task上完成训练,就找到了最终的初始化参数。

算法实现

import numpy as np
import matplotlib.pyplot as plt

pi = np.pi
def sample_points(k):#k为对函数a*sin(x+b)在0到2π的采样点数
    a,b = np.random.uniform(0,2,2)
    x = np.arange(0,2*pi,2*pi/k)
    y = a*np.sin(x+b)
    return x,y,a,b
def draw_sin(a,b):
    x = np.arange(0,2*pi,0.1)
    y = a*np.sin(x+b)
    plt.plot(x,y)

定义一些基本参数

task_num = 10   #每个batch中含有的task,即一次梯度下降所含的task数目
points_num =10
alpha = 0.01   #子模型的学习率
beta = 0.01    #元学习初始化参数更新的学习率
a_init = np.random.normal()
b_init = np.random.normal()   #要更新的初始化参数的最初数值
epoch = 10000   #元学习模型更新次数

然后开始更新,寻找最优的初始化参数a_init和b_init,采用MSELoss,复合求导略。

for epoch_ in range(epoch):
    x_train = []
    y_train = []
    a_train = []
    b_train = []
    # 生成每个task的数据
    for i in range(task_num):
        x,y,a_,b_ = sample_points(points_num)
        x_train.append(x)
        y_train.append(y)
    a_gradient = 0
    b_gradient = 0   
    # 对每个task进行一次梯度下降,更新a,b,更新之后再计算一次梯度,并把这第二次的梯度累加,用来更新a_init和b_init
    loss = 0
    for i in range(task_num):
        a_0 = a_init
        b_0 = b_init   #梯度下降的初始值为元学习模型要学习的初始化的值
        x = x_train[i]
        y = y_train[i]  #第i个task的x和y
        y_ = a_0*np.sin(x+b_0)  #通过参数a,b对y的预测值
        a_0 = a_0 - sum(2*alpha*(y_-y)*np.sin(x+b_0))/points_num #MSE损失,复合函数求导
        b_0 = b_0 - sum(2*alpha*a_0*(y_-y)*np.cos(x+b_0))/points_num
        #更新完后,再计算一次梯度,累加
        y_ = a_0*np.sin(x+b_0)
        loss += sum(np.square(y_-y))/points_num
        a_gradient += sum(2*alpha*(y_-y)*np.sin(x+b_0))/points_num
        b_gradient += sum(2*alpha*a_0*(y_-y)*np.cos(x+b_0))/points_num
    a_init -= beta*a_gradient
    b_init -= beta*b_gradient
    if epoch_%1000==0:
        print("epoch:%d,loss:%f"%(epoch_,loss))

可能是学习率设置的太大了,收敛到一定程度开始震荡,不过loss至少是下降的

在这里插入图片描述

对MAML学习到的a_init和b_init画出来,进行0次gradient descent,直接画出来和随机生成的a,b做比较。

x,y,a_,b_ = sample_points(points_num)
draw_sin(a_,b_)
draw_sin(a_init,b_init)

在这里插入图片描述

不进行MAML,随机生成a,b,进行0次gradient descent,直接画出。

a = np.random.normal()
b = np.random.normal()
draw_sin(a_,b_)
draw_sin(a,b)

在这里插入图片描述

左边是使用MAML算法的,右边是不使用MAML算法的

image-20201021204455198.png
在这里插入图片描述

100次迭代的时候,MAML学习到的初始化参数以及能够比较贴近函数了,但是随机出来的ab则差得比较多。

元学习的基本问题

元学习的基本问题可以分成三大类:

  • 元知识的表征(meta-representation)。元知识应该如何进行表征,这回答了元学习的最重要问题,即学习什么的问题。
  • 元学习器(meta-optimizer)。即有了元知识的表征后,我们应该如何选择学习算法进行优化,也就回答了元学习中的如何学习的问题。
  • 元目标(meta-objective)。有了元知识的表征和学习方法后,我们应该朝着怎样的目标去进行学习?这回答了元学习中为什么要这样学习的问题。

围绕这三大基本问题,近年来元学习领域出现了诸多研究成果。按照此分类方法,meta-learning的研究框架可以由下图清晰地给出:

在这里插入图片描述

元知识的表征

  1. 初始化参数。由meta-train任务给出模型的初始化参数,然后针对初始化参数进行二次学习,例如MAML等方法。此类方法存在的问题是:一组初始化参数是否具有足够的元知识表征能力,或者这些参数是否会受限于特定任务。
  2. 优化器。深度学习模型通常可以由SGD、Adam等常用的optimizer进行优化,这些优化器是固定不变的。那么,能否从相关的任务中,自动地学习适合于本任务的优化器?有一些工作,例如learning to optimize等,在这方面进行了尝试。
  3. 黑盒模型。这类工作的出发点非常直接:假定待学习模型的参数是由另一个网络所学习而来的,例如CNN、RNN等。比较著名的工作有Memory-augmented neural networks等。
  4. 度量学习(嵌入函数)。这类方法可以看作是上述黑盒模型的一个特例,即通过学习一个特征嵌入函数,使得在这个表征下,仅通过简单的相似度度量就可以进行分类。正因如此,这类方法目前只在few-shot的情景下适用。
  5. 损失。通过自适应地学习损失函数来进行meta-learning。
  6. 网络结构。通过设计额外的学习器来自动生成可用的网络结构,这一部分与AutoML很相关。
  7. 注意力模块
  8. 网络的特定层和模块
  9. 超参数
  10. 数据增强。数据增强已成为深度学习领域的常用方法,如何用meta-learning来帮助进行数据增强,是一个非常有前景的领域。
  11. 样本权重选择与课程学习。如何选择mini-batch大小、如何设定样本权重,这设计到课程学习(curriculum learning)的研究,显然这些都可以通过meta-learning进行学习。
  12. 数据集、标签、环境。回归meta-learning本身的定义,为什么不自适应地学习数据集、标签和环境的切分和构造呢?
  13. 除此之外,激活函数、卷积核、池化等,都可以用meta-learning进行学习。

纵观上述元知识的表征,我们可以说meta-learning其实设计到了一个机器学习过程的方方面面。因此,meta-learning也被视为非常有潜力的发展方向之一。

元学习器

有了meta-representation后,下一步便是meta-optimizer的学习,也就是说,如何进行优化的问题。

  1. 梯度优化。这是非常常用的手段,例如MAML等方法都采用了在bi-level优化过程中梯度回传的方式来进行优化。这里的问题包括:如何在一个较长的计算图中实现有效的梯度回传,以及如何避免计算过程中的梯度变差,并且如何base-learner含有不可微分的损失时如何计算。
  2. 强化学习。当base-learner含有不可微分的过程时,RL便是一个强有力的工具。此时涉及到如何将强化学习引入优化过程,使其变得更高效的问题。
  3. 进化算法。另一种非常有效的途径是进化算法,有别于深度学习,进化算法并没有BP的过程,同时也有自身的一些优点和缺点。

元目标

设定好元知识和元学习器后,最后一步便是整个meta-learning的学习目标。

  1. 多样本 还是 小样本。取决于目标任务的设定,meta-objective可以有针对性地被设计为多样本还是小样本的学习模式。
  2. 快速的 还是 渐进式的结果。许多meta-learning方法都要求在meta-test集上快速进行泛化。而一些RL的应用也需要渐进式的学习结果。
  3. 多任务 还是 单任务
  4. 在线 还是 离线
  5. 另外的设计思路:有噪声样本的情况下如何学习,以及有domain-shift的情况下如何学习等。

元学习的应用

元学习在机器学习的诸多场景下都有着广泛的应用。

  • 计算机视觉中的小样本学习(few-shot learning),包括分类、检测、分割、关键点定位、图像生成、密度估计等。可以说小样本的这个任务设定完美契合了meta-learning的学习过程。所以我们看到,绝大多数小样本研究都采用了meta-learning的学习方法。
  • 强化学习。一个很自然的扩展便是强化学习,在RL中的探索(exploration)和利用(exploitation),策略梯度等都有着广泛应用。
  • 仿真(sym2real)。由虚拟环境生成一些样本学习泛化的学习器,然后部属到真实环境中。
  • 神经结构搜索(NAS)
  • 贝叶斯元学习。这个步骤非常有趣,它涉及到用贝叶斯的视角来对元学习进行重新表征,可以发现不一样的研究思维,对解决问题非常有帮助。
  • 无监督元学习
  • 终身学习、在线学习、自适应学习
  • 领域自适应和领域泛化
  • 超参数优化
  • 自然语言处理
  • 元学习系统,等等。

其实我们可以看到,因为元学习是机器学习的一种学习方法,因此,可以说,机器学习的绝大多数问题和研究领域,都可以与meta-learning进行结合,碰撞出不一样的火花。

现存的挑战

  1. 泛化能力。现有的meta-learning方法在一些任务上训练,在新的任务上测试。直接的假设是:训练和测试数据服从同一个分布。所以直接的问题是:如果meta-train和meta-test不是来自一个分布,如何做meta-learning?或者说,meta-train数据本身就包含了来自多个分布的数据,如何做meta-train?
  2. 多模态的任务来源。现有的meta-learning方法假设训练和测试任务来自单一模态的数据,如果是多模态如何进行元学习?
  3. 任务家族。特定任务下只有特定的任务家族可以用元学习,这大大限制了知识的表征和传播。
  4. 计算复杂度。通常来说meta-learning都涉及到一个bi-level的优化,这导致其计算非常复杂。如何提高计算效率是一个难点。
  5. 跨模态迁移和异构的任务
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值