精华内容
下载资源
问答
  • 仅使用Numpy和简单的1层网络的Python实现MAML(模型不可知元学习)。 只是为了更好地了解MAML。 要求 Python 3.x 脾气暴躁的 Matplotlib 记录中 所有这些都包含在Anaconda中。 用法 只需运行maml.py 。 这实现了二...
  • MAML-Pythorch 你可以在我的库中的数据集omn​​iglot: 这些是我最好的回购表现: 杂种 5次1发 MAML:$ 98.7 \ pm 0.4%$ 我们的:$ 97.5%$ 20路1杆 MAML:$ 95.8 \ pm 0.3%$ 我们的:$ 84.8%$ 20路5拍 MAML...
  • MAML

    千次阅读 2020-07-07 17:56:14
    作者根据元学习(meta learning)的表达式提出了MAML算法用来进行元知识的梯度下降,使用一阶近似的方法来避免计算损失函数的二阶导,并在小样本学习任务(few-shot learning)上取得了SOTA的成绩。作者强调MAML算法具有...

    Paper : Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks
    Code : official

    摘要

    作者根据元学习(meta learning)的表达式提出了MAML算法用来进行元知识的梯度下降,使用一阶近似的方法来避免计算损失函数的二阶导,并在小样本学习任务(few-shot learning)上取得了SOTA的成绩。作者强调MAML算法具有模型无关性,可以适用于任何基于梯度下降优化的模型上。并给出了MAML与监督学习的结合和MAML与强化学习结合的算法,强调了算法的通用性。

    Meta-Learning

    在此blog中,Meta-Learning 采用的是 Meta-Learning in Neural Networks: A Survey 一文中的形式化定义方式,之后的话博主会将这篇论文的blog编出来。

    元学习的直观理解是 “Learning to learn”,也就是说通过多个任务的表现来改善学习算法本身。考虑对比常规的机器学习,常规监督学习的形式化表示如下:

    给定训练集 D = { ( x 1 , y 1 ) , . . . ( x N , y N ) } \mathcal D = \{(x_1,y_1),...(x_N,y_N)\} D={(x1,y1),...(xN,yN)},希望找到一个预测模型 y ^ = f θ ( x ) \widehat y = f_{\theta}(x) y =fθ(x) 在训练集上的最优参数解 θ ∗ \theta^* θ,即通过下式求解

    θ ∗ = arg ⁡ min ⁡ θ ( D ; θ , ω ) \theta^* = \arg\min_{\theta} \mathcal(\mathcal D;\theta,\omega) θ=argθmin(D;θ,ω)

    这里使用 ω \omega ω 表示该解对某些因素的依赖性,例如针对 θ \theta θ 的优化器选择或针对 f f f 的模型的选择,常见的 ω \omega ω 包括优化器的初始化(SGD的步长等), f f f 模型的参数初始化方法,正则化强度等等。 ω \omega ω 被称为是元知识(meta-knowledge),对于常规的机器学习任务来说,元知识是被人为设定的。元学习就是对元知识进行学习和优化。

    学习元知识的过程形式化的表示为如下优化问题的求解过程

    min ⁡ ω E T ∼ p ( T ) L ( D , ω ) \min_\omega \mathbb{E}_{\mathcal{T}\sim p(\mathcal T)}\mathcal L(\mathcal D,\omega) ωminETp(T)L(D,ω)

    其中 T = { D , L } \mathcal T = \{\mathcal D,\mathcal L\} T={D,L} 表示一个常规机器学习任务,假定多个常规任务都是从某个任务分布 p ( T ) p(\mathcal T) p(T) 中采样出来的。我们希望学到的是跨任务的元知识 ω \omega ω ,这些知识可以泛化到一个之前没有遇到过的数据集上,有助于模型在小样本数据集上进行学习。形式化的表述meta-training过程:

    给定一个包含 M 个学习任务的数据集 D = { ( D train ( i ) , D val ( i ) ) } \mathbb D = \{(\mathcal D^{(i)}_\text{train},\mathcal D^{(i)}_\text{val})\} D={(Dtrain(i),Dval(i))},求解问题可以表示为

    ω ∗ = arg ⁡ max ⁡ ω log ⁡ p ( ω ∣ D ) \omega^* = \arg \max_{\omega} \log p(\omega|\mathbb D) ω=argωmaxlogp(ωD)

    在meta-testing的过程中,首先需要根据元知识进行学习,然后再进行模型的评估,形式化表述为:

    给定某训练阶段不可知的任务 j \mathcal j j,测试模型的参数定义为

    θ ∗ ( j ) = arg ⁡ max ⁡ θ log ⁡ p ( θ ∣ ω ∗ , D train ( j ) ) {\theta^{*}}^{(j)} = \arg \max_{\theta} \log p(\theta|\omega^*,\mathcal D^{(j)}_\text{train}) θ(j)=argθmaxlogp(θω,Dtrain(j))

    从双层优化问题的角度来理解 meta-learning,meta-training可以形式化的表示为下式

    ω ∗ = arg ⁡ min ⁡ ω ∑ i = 1 M L meta ( θ ∗ ( i ) ( ω ) , ω , D val ( i ) ) s.t.  θ ∗ ( i ) ( ω ) = arg ⁡ min ⁡ θ L task ( θ , ω , D train ( i ) ) \\\omega^* = \arg\min_\omega \sum_{i=1}^M \mathcal L^\text{meta}({\theta^*}^{(i)}(\omega),\omega,\mathcal D_\text{val}^{(i)}) \\\text{s.t. }{\theta^*}^{(i)}(\omega) = \arg\min_{\theta} \mathcal L^\text{task}(\theta,\omega,\mathcal D_\text{train}^{(i)}) ω=argωmini=1MLmeta(θ(i)(ω),ω,Dval(i))s.t. θ(i)(ω)=argθminLtask(θ,ω,Dtrain(i))

    其中 L task \mathcal L^\text{task} Ltask L meta \mathcal L^\text{meta} Lmeta 分别对应内层和外层的优化目标(损失函数)。

    对于few-shot learning来说,一个常见的术语是 N-way K-shot classification,表示对于分类任务,类别总数有 N 个,每个类下面有 K 个样本。

    MAML

    MAML算法的前提是,存在对于模型来说存在某些参数初始化,比其他的初始化方法具有更好的迁移性,更适合做迁移学习。对于MAML算法来说,元知识 ω \omega ω 表示模型的初始化参数,想要解决的问题是小样本学习的问题。小样本集意味着不能在复杂的模型上进行多轮训练,不然会产生overfit问题。MAML通过元学习的方法学到一种对新任务损失函数敏感的初始化方法,使得模型在初始化后经过较少的epoch就可以finetune到一个比较良好的表现上。

    我们的目标是得到一个初始化模型参数可以经过较少的epoch获得一个良好的表现,因此,为了简化起见,假定 θ ∗ ( i ) {\theta^*}^{(i)} θ(i) 表示进行了一步梯度下降的结果,即

    θ ∗ ( i ) = ω − ε ▽ ω L T i ( f ω ) {\theta^*}^{(i)} = \omega - \varepsilon \triangledown_{\omega} \mathcal L_{\mathcal{T}_i}(f_\omega) θ(i)=ωεωLTi(fω)

    而外层的优化目标为

    min ⁡ ω ∑ T i ∼ p ( T ) L T i ( f θ ∗ ( i ) ) \min_\omega \sum_{\mathcal T_i\sim p(\mathcal T)}\mathcal L_{\mathcal T_i}(f_{{\theta^*}^{(i)}}) ωminTip(T)LTi(fθ(i))

    使用SGD算法优化元知识 ω \omega ω ,即

    ω ← ω − ϵ ▽ ω ∑ T i ∼ p ( T ) L T i ( f θ ∗ ( i ) ) \omega\leftarrow \omega -\epsilon \triangledown_{\omega} \sum_{\mathcal T_i\sim p(\mathcal T)}\mathcal L_{\mathcal T_i}(f_{{\theta^*}^{(i)}}) ωωϵωTip(T)LTi(fθ(i))

    考虑将 ω \omega ω θ ∗ ( i ) {\theta^*}^{(i)} θ(i) 都表示为向量,有

    ▽ ω L ( f θ ∗ ) = [ ∂ L ( f θ ∗ ) ∂ ω 1 , . . . , ∂ L ( f θ ∗ ) ∂ ω K ] T    ∂ L ( f θ ∗ ) ∂ ω i = ∑ j ∂ L ( f θ ∗ ) ∂ θ j ∗ ∂ θ j ∗ ∂ ω i \\ \triangledown_{\omega} \mathcal L(f_{\theta^*}) = [\frac{\partial \mathcal L(f_{\theta^*})}{\partial \omega_1},...,\frac{\partial \mathcal L(f_{\theta^*})}{\partial \omega_K}]^\text T \\\; \\ \frac{\partial \mathcal L(f_{\theta^*})}{\partial \omega_i} = \sum_j \frac{\partial \mathcal L(f_{\theta^*})}{\partial \theta^*_j}\frac{\partial \theta^*_j}{\partial \omega_i} ωL(fθ)=[ω1L(fθ),...,ωKL(fθ)]TωiL(fθ)=jθjL(fθ)ωiθj

    根据单步SGD的前提,有

    θ j ∗ = ω j − ε ∂ L ( f ω ) ∂ ω j \theta^*_j = \omega_j-\varepsilon \frac{\partial \mathcal L(f_\omega)}{\partial \omega_j} θj=ωjεωjL(fω)

    上述求导过程涉及到对梯度函数求梯度,结果存在二阶导,如下所示

    ∂ θ j ∗ ∂ ω i = { 1 − ε ∂ 2 L ( f ω ) ∂ ω j ∂ ω i i = j − ε ∂ 2 L ( f ω ) ∂ ω j ∂ ω i i ≠ j \frac{\partial \theta^*_j}{\partial \omega_i} = \left\{\begin{matrix} 1-\varepsilon \frac{\partial^2 \mathcal L(f_\omega)}{\partial \omega_j \partial \omega_i} & i= j\\ -\varepsilon \frac{\partial^2 \mathcal L(f_\omega)}{\partial \omega_j \partial \omega_i} & i\not = j \end{matrix}\right. ωiθj={1εωjωi2L(fω)εωjωi2L(fω)i=ji=j

    对表达式进行一阶近似,假定 ε → 0 + \varepsilon \rightarrow 0^+ ε0+ ,有

    ∂ θ j ∗ ∂ ω i = { 1 i = j 0 i ≠ j \frac{\partial \theta^*_j}{\partial \omega_i} = \left\{\begin{matrix} 1 & i= j\\ 0 & i\not = j \end{matrix}\right. ωiθj={10i=ji=j

    因此,代入结果有

    ▽ ω L ( f θ ∗ ) ≈ ▽ θ ∗ L ( f θ ∗ ) \\ \triangledown_{\omega} \mathcal L(f_{\theta^*}) \approx \triangledown_{\theta^*} \mathcal L(f_{\theta^*}) ωL(fθ)θL(fθ)

    一阶近似的MAML元知识更新式子表示为

    ω ← ω − ϵ ∑ T i ∼ p ( T ) ▽ θ ∗ ( i ) L T i ( f θ ∗ ( i ) ) θ ∗ ( i ) = ω − ε ▽ ω L T i ( f ω ) \omega\leftarrow \omega -\epsilon \sum_{\mathcal T_i\sim p(\mathcal T)} \triangledown_{{\theta^*}^{(i)}} \mathcal L_{\mathcal T_i}(f_{{\theta^*}^{(i)}}) \\ {\theta^*}^{(i)} = \omega - \varepsilon \triangledown_{\omega} \mathcal L_{\mathcal{T}_i}(f_\omega) ωωϵTip(T)θ(i)LTi(fθ(i))θ(i)=ωεωLTi(fω)

    MAML在不同任务上的应用

    Few-Shot Supervised Learning

    在这里插入图片描述

    Reinforcement Learning

    RL任务定义为

    T i = ( q i ( x 1 ) , q i ( x t + 1 ∣ x t , a t ) , L T i , R i ) \mathcal T_i = (q_i(x_1),q_i(x_{t+1}|x_t,a_t),\mathcal L_{\mathcal T_i},R_i) Ti=(qi(x1),qi(xt+1xt,at),LTi,Ri)

    其中 q q q 表示初始状态分布和状态转移分布,损失函数表示为

    L T i ( f ω ) = − E x h , a h ∼ f ω , q T i [ ∑ h = 1 H R i ( x h , a h ) ] \mathcal L_{\mathcal T_i}(f_\omega) = -\mathbb E_{x_h,a_h\sim f_\omega,q_{\mathcal T_i}}[\sum_{h=1}^HR_i(x_h,a_h)] LTi(fω)=Exh,ahfω,qTi[h=1HRi(xh,ah)]

    对于RL任务,通常使用Policy Gradient 方法进行梯度估计。

    在这里插入图片描述

    实验

    作者通过实验观察到,一阶近似的性能与使用二阶导数获得的性能几乎相同,这表明MAML的大部分改进都来自目标在更新后参数值处的一阶梯度,而不是来自更新后参数值的二阶梯度。 过去的工作已经观察到ReLU神经网络在局部几乎是线性的,这表明在大多数情况下二阶导数可能接近于零,部分解释了一阶近似的良好性能。

    在这里插入图片描述

    MAML与Transfer Learning

    在这里插入图片描述

    总结

    作者给出了一种基于梯度下降来学习模型初始化参数的元学习方法,方法简单,不会为元学习引入任何学习的参数。它可以与任何适合基于梯度训练的模型表示以及任何可区分的目标(包括分类,回归和强化学习)相结合。MAML的训练过程中只考虑了内部模型参数的一步更新,但是在测试时可以进行充分的finetune。这项工作是迈向一种简单通用的元学习技术的一步,该技术可应用于任何问题和模型。

    展开全文
  • MAML方法论文

    2018-03-05 09:00:14
    一篇介绍meta-learning方法的论文,发表于2017年,提出一种基于梯度的小样本学习方法
  • MAML::bear:MAML-源码

    2021-03-10 01:11:06
    MAML 关于 发展 平台:Windows 10 32位和64位 编程语言:ISO C ++最新草案标准(> C ++ 17) 编译器:MSVC ++ 16.0.1 IDE :Visual Studio 2019 特征 代数: 复杂的 双 双曲 编译时数学(正在进行中) SIMD...
  • 动手使用Python进行元学习:使用Tensorflow使用一键式学习,MAML,爬行动物,Meta-SGD等进行学习学习
  • PyTorch中的MAML和爬行动物 PyTorch中“用于快速适应深度网络的与模型无关的元学习”的代码。 我重新调制了@AdrienLE IPython Notebook,使其从main.py运行,请查阅参考资料以更好地解释算法。 免责声明 我只是为了...
  • 小米MAML 整理教程

    2016-10-09 17:47:17
    小米主题MAML 整理教程,对官方MAML进行简单归纳与总结,对初学者学习制作小米主题提供基本规范与掌握基础很有帮助
  • 元学习-MAML-资源整合

    2020-12-17 09:57:32
    借鉴其他的博主写的文章,以及自己的理解做的笔记,通过这个word的笔记,可以清楚的掌握MAML的算法理论以及实际使用时的简化,参考链接在文章里面,此文章免费下载。
  • MAML-v1.ipynb

    2020-03-01 19:41:26
    这个文件里时我复现的MAML,也就是模型无关的元学习方法的实验代码的复现,有需要的朋友可以下载下来参考一下。
  • maml-jax 该存储库在Python + JAX中实现了与模型无关的元学习(MAML)算法。 此处的教程: :
  • MAML笔记

    2021-07-13 09:34:22
    最近想康康联邦元学习,涉及MAML,直接看论文有点懵,所以先补一下元学习和MAML的内容。 《Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks》提出一种 meta-learning 算法,即MAML,使模型能...

    最近想康康联邦元学习,涉及MAML,直接看论文有点懵,所以先补一下元学习和MAML的内容。
    《Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks》提出一种 meta-learning 算法,即MAML,使模型能自动进行参数的初始化,省去许多计算步骤。
    该算法是模型无关的,适用于任何利用梯度下降的方法来训练的模型,并且适用于多种任务,如分类,回归,强化学习。meta-learning 的目标是通过多个任务训练一个元模型,该模型可以从少量的新数据中快速学习一个新任务。下面从四个角度来理解MAML。

    通过小样本监督学习理解MAML

    小样本学习在监督学习领域的研究目标是:先在相似的任务中获取一些先验数据,实现可以在少量的“关于某个任务的输入-输出对”来学习一个新的函数。举两个例子:
    在小样本分类问题上,一个模型之前已经见过许多种类的物体了,现在只让这个模型看几个电动车的样本,然后希望模型能学会对电动车图片进行分类。
    在小样本回归问题上,当在许多“具有相似统计特性的函数”上进行训练以后,对于某个新的连续值函数,当给出几个从函数中采样出的数据点以后,模型能够立刻学习出函数的表达式,从而较好的预测函数的输出。
    MAML与此类似,其背后的核心思想通过多个任务训练得到元模型的初始参数,该元模型在少量新数据上通过一次或多次梯度下降更新参数之后,得到的个性化模型在新任务上具有最好的性能。

    通过特征学习理解MAML

    MAML的思想(通过多个任务训练得到元模型的初始参数,该元模型在少量新数据上通过一次或多次梯度下降更新参数之后,得到的个性化模型在新任务上具有最好的性能。)从特征学习的角度来看就相当于构建一个可以适用于许多任务的内部表示。如果一个内部表示是适用于多个任务的,那么微调参数就可以体现出很好的性能。

    从动态系统的角度理解MAML

    从动态角度来看,MAML可以看作是:最大化新任务的损失函数对于参数的敏感度,也就是说当敏感度很高时,参数的微小改变就可以大大改善这个任务的loss。

    MAML和pre-training的区别

    单纯从前面三个角度看的话,貌似MAML和pre-training差不多,都是找到一个初始化模型,该模型的参数在新任务上进行微调便获得新任务的训练模型。
    两者的区别其实就在这个初始化模型上,MAML的目标是找到一个初始化模型,其参数是更具潜力的,怎么理解这个最有潜力呢?简单讲就是这个模型直接应用于新任务上表现一般,但经过一次或若干次梯度下降就能收敛于全局最优解;pre-training的目标也是找到一个初始化模型,其参数具备更好的表现,也就是直接应用于新任务上效果优于MAML应用于新任务上的初始化模型,但训练后可能收敛于局部最优解
    总的来讲就是,MAML目光更长远,pre-training急于求最优。

    MAML的算法框架

    MAML的算法框架如Algorithm 1所示,但有一些点并没有体现出来,例如测试阶段,对各任务采样新的数据等,这个在具体的应用上有体现,可以结合后面的Algorithm 2,Algorithm 3一起理解。
    f θ f_θ fθ是元模型,P(T)是任务分布, q i q_i qi是任务 T i T_i Ti的数据分布, L T i ( f θ ) L_{Ti}(f_θ) LTi(fθ)是任务 T i T_i Ti的损失函数。
    meta-training阶段,首先从任务分布p(T)中采样多个任务 T i T_i Ti,对每个任务,根据该任务的数据分布 q i q_i qi采样K个样本进行训练,根据这k个样本计算梯度▽ L T i ( f θ i ) L_{Ti}(f_{θ_i}) LTi(fθi)并更新模型参数 θ i θ_i θi θ i ′ θ_i^{'} θi
    meta-testing阶段,用任务i已更新的参数 θ i ′ θ_i^{'} θi在testing task上进行测试,计算梯度▽ L T i ( f θ ′ ) L_{Ti}(f_{θ^{'}}) LTi(fθ)。(其实就是把这个任务看作train_set,再找一个任务作为test_set,测试meta-training阶段更新后的模型参数的泛化能力,并作为最后元模型更新的梯度)
    最后执行算法中第8步的计算,也就是将所有task在meta-testing阶段计算的梯度▽ L T i ( f θ ′ ) L_{Ti}(f_{θ^{'}}) LTi(fθ)集中在一起进行梯度下降。
    在这里插入图片描述

    MAML应用于监督回归和分类

    监督回归和分类常用的损失函数分别是交叉熵(3)和均方误差MSE(2),
    在这里插入图片描述
    在这里插入图片描述
    算法框架如Algoritm 2所示
    在这里插入图片描述

    MAML应用于强化学习

    对于任务 T i T_i Ti和模型 f φ f_φ fφ的损失函数如(4)所示
    在这里插入图片描述
    算法框架如Algoritm 3所示
    在这里插入图片描述

    展开全文
  • MAML论文走读

    2020-06-02 18:16:18
    本文提出一种与模型无关的元学习算法,MAML可用于任何利用梯度下降训练的模型和运用到多种学习任务如分类、回归、强化学习。元学习的目标是在多种任务上训练模型,最终使得模型仅需少量样本就能在新任务上有好的表现...

    论文链接:https://arxiv.org/pdf/1703.03400.pdf
    MAML与前人解决meta learning最大的不同在于,MAML参数的更新靠的是梯度下降而不是一个学到的更新策略(如用RNN学一个参数更新策略)。MAML不需要引入新的参数,也不需要特定的模型结构。理论上,用梯度更新算法的训练任务都能用MAML。

    摘要

    本文提出一种与模型无关的元学习算法,MAML可用于任何利用梯度下降训练的模型和运用到多种学习任务如分类、回归、强化学习。元学习的目标是在多种任务上训练模型,最终使得模型仅需少量样本就能在新任务上有好的表现。MAML使得模型参数在新任务的少量训练数据上经过几次梯度下降就能收敛。如此模型在新任务上表现出良好的泛化能力。实际上,MAML训练的模型容易完成微调(fine-tuning)。本文证明了MAML在两种少样本 few-shot 分类问题,少样本回归问题和在梯度更新的强化学习任务中加速微调过程。

    Intro

    简而言之,想让智能体像人类一样仅凭少量样本快速学习。这要求智能体在新任务中能根据少量新信息上总结之前的经验,还要避免过拟合。本文提出的MAML,是一种和模型无关的算法,理论上可以运用在各种利用梯度下降算法训练的任务上。

    本文的重点是深度神经网络模型,但本文说明了MAML如何能够以最少的调整,轻松处理不同的体系结构和不同的问题设置,包括分类,回归和策略梯度强化学习。在元学习中,训练后的模型的目标是从少量新数据中快速学习新任务。MAML的核心在于训练模型的初始化参数,这样,在通过一个或多个梯度步骤更新参数后,该模型就可以在新任务上有好的表现,该梯度更新步骤是使用来自该新任务的少量数据计算得出的。与先前的学习更新功能或学习规则的元学习方法不同,MAML不会新增参数,也不会在模型架构上增加RNN或是Siamese network。MAML可以很容易的和全连接、卷积、递归神经网络结合。MAML可以和各种损失函数一起使用,包括可微分的监督学习损失和不可微分的强化学习目标。(如强化学习在文本生成领域中,通常用的BLEU指标作为奖励。)

    从特征学习的角度来看,训练模型参数以使几个梯度步骤甚至单个梯度步骤可以在新任务上产生良好结果的过程可以看成是模型构建了广泛适用于许多任务的内部表示。如果内部表示适用于许多任务,只需微调参数(如只改变网络的顶层权重)就能有好的结果。实际上,我们的过程针对易于快速调整的模型进行了优化,从而可以在合适的空间进行自适应以进行快速学习。 从动态系统的角度来看,我们的学习过程可以看作是使新任务的损失函数对参数的敏感性最大化:当敏感性高时,参数的更新会导致任务损失的较大改善 。

    本文的贡献在于提出一种与模型无关的元学习算法。本文在不同的模型结构(全连接 & CNN)以及不同的领域(分类,回归,强化学习)上验证MAML算法的可行性。我们的评估表明,MAML与专门为监督分类而设计的最新one-shot学习方法相比具有优势,同时使用的参数更少;但它也可以很容易地应用于回归分析并可以在存在任务可变性的情况下加速强化学习,其性能大大优于直接预训练作为参数初始化。

    MAML

    本文的目标是训练可以实现快速适应新任务的模型,而这种问题通常被形式化为快速学习。 在本节中,我们将定义问题并介绍MAML算法的一般形式。

    定义问题

    meta learning的目标是训练仅需几个样本和迭代就可以快速适应新任务的模型。 为此,在元学习阶段对一组任务训练了模型,以使训练后的模型仅使用少量示例就可以快速适应新任务。 实际上,元学习问题将整个任务集tasks视为训练样本集。

    在本节中,本文以一般的方式将这种meta learning的问题形式化,包括不同学习领域的简短示例。 将在第3节中详细讨论两个不同的学习领域。(有监督的回归和分类问题,强化学习)

    简而言之是 N-ways K-shot 。从任务集中采样N个任务,组成训练tasks,每个task有K个训练样本。模型在N个任务上训练,之后在测试阶段新任务进过K个样本的训练,模型表现作为元学习的评价指标。通常,用于元测试的任务会在元训练期间保留下来。(不可见)

    MAML

    与先前的工作试图训练循环神经网络以吸收可在测试时与非参数方法结合的整个数据集或特征嵌入的工作相反,我们提出了一种方法,该方法可以通过元学习来学习任何标准模型的参数,从而为快速适应做好准备。MAML这个本质是训练模型初始化参数的方法的背后原理是某些内部表示形式比其他内部表示形式更易于传递。例如,神经网络可能会学习广泛适用于任务集中所有任务而不是单个任务的内部特征。由于将在新任务上使用基于梯度的学习方法对模型进行微调,因此我们将旨在找到快速学习的方式学习模型。 从p(T)提取的新任务上取得了进展,而没有过拟合。 实际上,我们的目标是找到对任务的变化敏感的模型参数,以便参数的小的变化将对任务的变化产生较大的改进。

    我们不对模型的形式做任何假设,只是假设它由某个参数向量θ参数化,并且损失函数在θ中足够平滑,因此我们可以使用基于梯度的学习技术。

    为了简化符号表示,在本节的其余部分中,我们将考虑一个梯度更新,但是使用多个梯度更新是一个直接的扩展。
    算法为代码
    在这里插入图片描述具体来说每个task有一套参数θ’,优化过程是用θ’整合更新θ。实际上,MAML旨在优化模型参数,以使在新任务上的一个或少量梯度步骤就能是的模型有好的表现。

    至此MAML需要在梯度上再计算一次梯度。在计算中需要多做一次回传以计算海塞向量积。在本文5.2节,我们也讨论了只用一次梯度近似的。

    特定领域下MAML

    本节将讨论MAML在监督学习和强化学习中的应用。这两个领域在损失函数的形式以及任务如何生成数据并将其呈现给模型的方式有所不同,但是在两种情况下都可以应用相同的基本适应机制。

    有监督的回归和分类

    在少样本分类任务中,我们希望训练出来的模型在看了少量海豹的照片后就能完成海豹照片的分类。同样,在少样本回归问题中,目标是在对许多具有相似统计特性的函数进行训练后,仅从该函数采样的几个数据点中预测连续值函数的输出。例子:正弦波的回归拟合

    回归问题的损失函数MSE
    注意下图是对一个特定任务,K个样本计算的损失。
    在这里插入图片描述
    分类问题的交叉熵cross_entropy
    在这里插入图片描述
    监督学习下MAML伪代码
    关键有两点,在分任务上θ’的计算仍是采用原参数θ;在任务二次采样数据点以便以最后meta-updata
    在这里插入图片描述

    强化学习

    meta learning:在仅有少量样本的新任务上迅速掌握一种策略。新任务的goal可以是new goal或是在新环境下用沿用之前的goal。如用于导航迷宫的智能体,遇到一个新迷宫,只需少量样本就能找到出口。

    强化学习有state,转移概率等概念,损失函数通常是负奖励(- reward)。
    损失函数
    在这里插入图片描述

    伪代码
    在这里插入图片描述

    相关工作

    在少样本分类任务中,一个较为成功的方法是利用孪生神经网络或RNN+attention比较新样本在模型 learned 度量空间中距离。但这类方法不适用于强化学习领域。而MAML可适用于任何模型,任何任务。还有一种方法是训练基于记忆的模型。适用于少样本的图像识别任务和能在强化学习任务中学得更快。具体实验证明,仅通过初始化网络参数和梯度下降的MAML比上述算法都要好。

    本文的方法与之前预训练方法的区别在于,MAML的目标是使得训练后的参数处于损失函数梯度的敏感位置,从而使得在新任务上只需几个样本梯度更新,损失函数就能有显著优化。

    实验

    验证三点,1)MAML能快速学习吗?2)MAML能适用于不同领域的任务吗?3)通过MAML学习的模型在测试新任务时,是否可以持续优化?
    在这里插入图片描述
    解释上述任务3,使用MAML学习的模型,经过了一个梯度下降步骤的最佳性能训练(图中红框),之后的梯度步骤也不断改进(图中黑框)。 MAML优化了参数,使其位于可快速适应且对新任务的损失函数敏感的区域,而不是过度拟合仅在经过1次改善后无法持续优化。

    本文考虑的所有meta learning都需要在测试时适应新任务。 在可能的情况下,我们将结果与一个oracle进行比较,ocacle将任务的identity(作为问题相关的表示)作为附加输入,作为模型性能的上限。

    回归

    拟合一个sin波形。
    baseline1 : 在所有任务上使用标准监督学习进行预训练
    baseline2 : ocacle是the ground truth
    实验表明,1)在测试阶段仅用少量样本训练baseline1结果不理想。2)即便K样本均集中在一个范围内,经MAML训练的模型仍能拟合出整个波形。3)MAML训练的模型能持续优化。

    分类

    少样本数据集:Omniglot、MiniImagenet
    MAML:sota、参数少(不引入除了分类器自身参数以外的参数)
    baseline:Siamese nets, matching nets, the memory module approaches

    强化学习

    跳过

    未来工作

    MAML优势:

    • 不增加新参数
    • 可以与任何基于梯度更新的任务结合,如回归、分类、强化学习
    • MAML最终应用只有一步网络参数初始化,测试阶段适应新任务中对数据量和梯度下降次数没有要求。

    附录

    pretraining on all tasks

    本文论证在所有任务上预训练模型的方法为什么不行?作者认为在本文研究的领域中,相同输入在不同任务下往往有不同的输出。因此 pretraining on all tasks 训练的模型只学到了输出空间的范围,将输出空间取平均再输出,却只学到很少的实际域。(作者认为将一套参数在所有任务上训练得到的结果是在输出空间上取平均。)

    论文据此提出一种在参数空间取平均的做法。在500个任务上分别训练500套参数,将500个最终参数取平均作为初始化参数,在测试阶段,由5个样本进行微调。结果表明参数空间取平均的做法还不如输出空间上取平均。

    QA

    这图对吗?
    在这里插入图片描述

    展开全文
  • MAML代码踩坑

    千次阅读 2020-10-06 22:30:57
    本文是在自己电脑上学习MAML,使用CPU跑的数据 首先已经进行了数据预处理,同时已经形成了.npy文件 加载数据 import torch import numpy as np import os root_dir = 'D:\A_Datasets\omniglot\python' img_...

    参考链接:
    https://www.zhihu.com/question/266497742
    https://zhuanlan.zhihu.com/p/66926599
    https://zhuanlan.zhihu.com/p/57864886

    目录

    加载数据 

     定义一些基本的参数:

     在数据迭代处使用:

    图像类型是[1,28,28]

    迭代数据

    定义了模型结构

    MetaLearner

    步骤4:

    步骤5:

    步骤6:

    更新参数θi:

    步骤8:

    更新参数θ

    微调

    main函数 


    本文是在自己电脑上学习MAML,使用CPU跑的数据

    首先已经进行了数据预处理,同时已经形成了.npy文件 

    加载数据 

    import torch
    import numpy as np
    import os
    root_dir = 'D:\A_Datasets\omniglot\python'
    
    img_list = np.load(os.path.join(root_dir, 'omniglot.npy'))  # (1623, 20, 1, 28, 28)
    x_train = img_list[:1200]
    x_test = img_list[1200:]
    num_classes = img_list.shape[0]
    datasets = {'train': x_train, 'test': x_test}

     定义一些基本的参数:

    N-way K-shot在广义上来讲N代表类别数量,K代表每一类别中样本数量

    这里采用了n_way = 5 ,k-shot 在在support=1,在query=15,8个任务

    ### 准备数据迭代器
    n_way = 5  ## N-way K-shot在广义上来讲N代表类别数量,K代表每一类别中样本数量
    k_spt = 1  ## support data 的个数
    k_query = 15  ## query data 的个数
    imgsz = 28
    resize = imgsz
    task_num = 8
    batch_size = task_num

     在数据迭代处使用:

    indexes = {"train": 0, "test": 0}
    datasets = {"train": x_train, "test": x_test}
    print("DB: train", x_train.shape, "test", x_test.shape)

    图像类型是[1,28,28]

    n_way *shot

    x_spts.shape =  (8, 5, 1, 28, 28) n_way = 5 ,k-shot = 1 

    x_qrys.shape = (8, 75, 1, 28, 28) n_way = 5 ,k-shot = 15

    def load_data_cache(dataset):
        """
        Collects several batches data for N-shot learning
        :param dataset: [cls_num, 20, 84, 84, 1]
        :return: A list with [support_set_x, support_set_y, target_x, target_y] ready to be fed to our networks
        """
        #  take 5 way 1 shot as example: 5 * 1
        setsz = k_spt * n_way
        querysz = k_query * n_way
        data_cache = []
    
        # print('preload next 10 caches of batch_size of batch.')
        for sample in range(10):  # num of epochs
    
            x_spts, y_spts, x_qrys, y_qrys = [], [], [], []
            for i in range(batch_size):  # one batch means one set
    
                x_spt, y_spt, x_qry, y_qry = [], [], [], []
                selected_cls = np.random.choice(dataset.shape[0], n_way, replace=False)
    
                for j, cur_class in enumerate(selected_cls):
                    selected_img = np.random.choice(20, k_spt + k_query, replace=False)
    
                    # 构造support集和query集
                    x_spt.append(dataset[cur_class][selected_img[:k_spt]])
                    x_qry.append(dataset[cur_class][selected_img[k_spt:]])
                    y_spt.append([j for _ in range(k_spt)])
                    y_qry.append([j for _ in range(k_query)])
    
                # shuffle inside a batch
                perm = np.random.permutation(n_way * k_spt)
                x_spt = np.array(x_spt).reshape(n_way * k_spt, 1, resize, resize)[perm]
                y_spt = np.array(y_spt).reshape(n_way * k_spt)[perm]
                perm = np.random.permutation(n_way * k_query)
                x_qry = np.array(x_qry).reshape(n_way * k_query, 1, resize, resize)[perm]
                y_qry = np.array(y_qry).reshape(n_way * k_query)[perm]
    
                # append [sptsz, 1, 84, 84] => [batch_size, setsz, 1, 84, 84]
                x_spts.append(x_spt)
                y_spts.append(y_spt)
                x_qrys.append(x_qry)
                y_qrys.append(y_qry)
    
            #         print(x_spts[0].shape)
            # [b, setsz = n_way * k_spt, 1, 84, 84]
            x_spts = np.array(x_spts).astype(np.float32).reshape(batch_size, setsz, 1, resize, resize)
            y_spts = np.array(y_spts).astype(np.int).reshape(batch_size, setsz)
            # [b, qrysz = n_way * k_query, 1, 84, 84]
    
            print("======>LCF给出的解释 [batch, qrysz = n_way * k_query, 1, imgsz, imgsz]")
            #=>LCF给出的解释 [task, qrysz = n_way * k_query, 1, imgsz, imgsz]
            x_qrys = np.array(x_qrys).astype(np.float32).reshape(batch_size, querysz, 1, resize, resize)
            y_qrys = np.array(y_qrys).astype(np.int).reshape(batch_size, querysz)
            #         print(x_qrys.shape)
            data_cache.append([x_spts, y_spts, x_qrys, y_qrys])
    
        return data_cache

    迭代数据

    从上面的load_data_cache中的epochs,一共迭代epochs次

    datasets_cache = {"train": load_data_cache(x_train),  # current epoch data cached
                      "test": load_data_cache(x_test)}
    
    
    def next(mode='train'):
        """
        Gets next batch from the dataset with name.
        :param mode: The name of the splitting (one of "train", "val", "test")
        :return:
        """
        # update cache if indexes is larger than len(data_cache)
        if indexes[mode] >= len(datasets_cache[mode]):
            indexes[mode] = 0
            datasets_cache[mode] = load_data_cache(datasets[mode])
    
        next_batch = datasets_cache[mode][indexes[mode]]
        indexes[mode] += 1
    
        return next_batch

    定义了模型结构

     Conv2d->BatchNorm2d->ReLU->MaxPool2d

    import torch
    from torch import nn
    from torch.nn import functional as F
    from copy import deepcopy, copy
    
    
    class BaseNet(nn.Module):
        def __init__(self):
            super(BaseNet, self).__init__()
            self.vars = nn.ParameterList()  ## 包含了所有需要被优化的tensor
            self.vars_bn = nn.ParameterList()
    
            # 第1个conv2d
            # in_channels = 1, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2
            weight = nn.Parameter(torch.ones(64, 1, 3, 3))
            nn.init.kaiming_normal_(weight)
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            # 第1个BatchNorm层
            weight = nn.Parameter(torch.ones(64))
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            running_mean = nn.Parameter(torch.zeros(64), requires_grad=False)
            running_var = nn.Parameter(torch.zeros(64), requires_grad=False)
            self.vars_bn.extend([running_mean, running_var])
    
            # 第2个conv2d
            # in_channels = 1, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2
            weight = nn.Parameter(torch.ones(64, 64, 3, 3))
            nn.init.kaiming_normal_(weight)
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            # 第2个BatchNorm层
            weight = nn.Parameter(torch.ones(64))
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            running_mean = nn.Parameter(torch.zeros(64), requires_grad=False)
            running_var = nn.Parameter(torch.zeros(64), requires_grad=False)
            self.vars_bn.extend([running_mean, running_var])
    
            # 第3个conv2d
            # in_channels = 1, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2
            weight = nn.Parameter(torch.ones(64, 64, 3, 3))
            nn.init.kaiming_normal_(weight)
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            # 第3个BatchNorm层
            weight = nn.Parameter(torch.ones(64))
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            running_mean = nn.Parameter(torch.zeros(64), requires_grad=False)
            running_var = nn.Parameter(torch.zeros(64), requires_grad=False)
            self.vars_bn.extend([running_mean, running_var])
    
            # 第4个conv2d
            # in_channels = 1, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2
            weight = nn.Parameter(torch.ones(64, 64, 3, 3))
            nn.init.kaiming_normal_(weight)
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            # 第4个BatchNorm层
            weight = nn.Parameter(torch.ones(64))
            bias = nn.Parameter(torch.zeros(64))
            self.vars.extend([weight, bias])
    
            running_mean = nn.Parameter(torch.zeros(64), requires_grad=False)
            running_var = nn.Parameter(torch.zeros(64), requires_grad=False)
            self.vars_bn.extend([running_mean, running_var])
    
            ##linear
            weight = nn.Parameter(torch.ones([5, 64]))
            bias = nn.Parameter(torch.zeros(5))
            self.vars.extend([weight, bias])
    
        #         self.conv = nn.Sequential(
        #             nn.Conv2d(in_channels = 1, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2),
        #             nn.BatchNorm2d(64),
        #             nn.ReLU(),
        #             nn.MaxPool2d(2),
    
        #             nn.Conv2d(in_channels = 64, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2),
        #             nn.BatchNorm2d(64),
        #             nn.ReLU(),
        #             nn.MaxPool2d(2),
    
        #             nn.Conv2d(in_channels = 64, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2),
        #             nn.BatchNorm2d(64),
        #             nn.ReLU(),
        #             nn.MaxPool2d(2),
    
        #             nn.Conv2d(in_channels = 64, out_channels = 64, kernel_size = (3,3), padding = 2, stride = 2),
        #             nn.BatchNorm2d(64),
        #             nn.ReLU(),
        #             nn.MaxPool2d(2),
    
        #             FlattenLayer(),
        #             nn.Linear(64,5)
        #         )
    
        def forward(self, x, params=None, bn_training=True):
            '''
            :bn_training: set False to not update
            :return: 
            '''
            if params is None:
                params = self.vars
    
            weight, bias = params[0], params[1]  # 第1个CONV层
            x = F.conv2d(x, weight, bias, stride=2, padding=2)
    
            weight, bias = params[2], params[3]  # 第1个BN层
            running_mean, running_var = self.vars_bn[0], self.vars_bn[1]
            x = F.batch_norm(x, running_mean, running_var, weight=weight, bias=bias, training=bn_training)
            x = F.max_pool2d(x, kernel_size=2)  # 第1个MAX_POOL层
            x = F.relu(x, inplace=[True])  # 第1个relu
    
            weight, bias = params[4], params[5]  # 第2个CONV层
            x = F.conv2d(x, weight, bias, stride=2, padding=2)
    
            weight, bias = params[6], params[7]  # 第2个BN层
            running_mean, running_var = self.vars_bn[2], self.vars_bn[3]
            x = F.batch_norm(x, running_mean, running_var, weight=weight, bias=bias, training=bn_training)
            x = F.max_pool2d(x, kernel_size=2)  # 第2个MAX_POOL层
            x = F.relu(x, inplace=[True])  # 第2个relu
    
            weight, bias = params[8], params[9]  # 第3个CONV层
            x = F.conv2d(x, weight, bias, stride=2, padding=2)
    
            weight, bias = params[10], params[11]  # 第3个BN层
            running_mean, running_var = self.vars_bn[4], self.vars_bn[5]
            x = F.batch_norm(x, running_mean, running_var, weight=weight, bias=bias, training=bn_training)
            x = F.max_pool2d(x, kernel_size=2)  # 第3个MAX_POOL层
            x = F.relu(x, inplace=[True])  # 第3个relu
    
            weight, bias = params[12], params[13]  # 第4个CONV层
            x = F.conv2d(x, weight, bias, stride=2, padding=2)
            x = F.relu(x, inplace=[True])  # 第4个relu
            weight, bias = params[14], params[15]  # 第4个BN层
            running_mean, running_var = self.vars_bn[6], self.vars_bn[7]
            x = F.batch_norm(x, running_mean, running_var, weight=weight, bias=bias, training=bn_training)
            x = F.max_pool2d(x, kernel_size=2)  # 第4个MAX_POOL层
    
            x = x.view(x.size(0), -1)  ## flatten
            weight, bias = params[16], params[17]  # linear
            x = F.linear(x, weight, bias)
    
            output = x
    
            return output
    
        def parameters(self):
            return self.vars
    

    MetaLearner

    这里主要是是两层循环,

    步骤4:

    这是一个内循环,利用meta batch中的每一个任务Ti,分别对模型的参数进行更新(比如5个任务更新5次参数)。

    步骤5:

    在N-way K-shot(N-way指训练数据中有N个类别class,K-shot指每个类别下有K个被标记数据)的设置下,利用meta batch中的某个task中的support set(任务中少量中有标签的数据,可以理解为训练集training set)的N*K个样本计算每个参数的梯度。

    步骤6:

    第一次梯度的更新的过程。针对Meta batch的每个任务Ti更新一次参数得到新的模型参数θi,这些新模型参数会被临时保存,用来接下的第二次梯度计算,但其并不是真正用来更来更新模型。

    这里有5个任务,所以这里有5次更新参数θi,这里的θi仅仅是为了更好的完成support set中的任务,并没有对θ进行更新。

    更新参数θi

    第1次更新:

     同时把更新后的参数暂时保存在参数fast_weights中。

    第2-5次更新:

    同时把更新后的参数暂时保存在参数fast_weights中。

    步骤8:

    第二次梯度更新的过程。这个是计算一个query set (另一部分有标签的数据,可以理解为验证集validation set,用来验证模型的泛化能力) 中的5-way*V (V是一个变量,一般等于K,也可以自定义为其他参数比如15)个样本的损失loss,然后更新meta模型的参数,这次模型参数更新是一个真正的更新,更新后的模型参数在该次meta batch结束后回到步骤3用来进行下一次mata batch的计算。

    更新参数θ

    因为k的变化范围从1-4(从0开始),所以第5次更新参数θi之后,获取query set在上面的loss,并保存在loss_list_qry[-1],最后采用了loss_list_qry[-1]/task_num来更新参数θ。

    微调

    以上就是MAML预训练得到Mmeta的全部过程?事实上,MAML正是因为其简单的思想与惊人的表现,在元学习领域迅速流行了起来。接下来,应该是面对新的task,在Mmeta的基础上,精调得到Mfine-tune的方法。

    fine-tune的过程与预训练的过程大致相同,不同的地方主要在于以下几点:

    步骤1:fine-tune不用再随机初始化参数,而是利用训练好的  初始化参数。下图中的deepcopy和fast_weights正是说明了这一点

    步骤3中,fine-tune只需要抽取一个task进行学习,自然也不用形成batch。fine-tune利用这个task的support set训练模型,利用query set测试模型。

    以下代码中说明了抽取一个task进行学习。

     fine-tune利用这个task的support set训练模型(红色的框和箭头),利用query set测试模型(绿色的框和箭头)。

    实际操作中,我们会在 Dmeta-test上随机抽取许多个task(e.g., 500个),分别微调模型Mmeta,并对最后的测试结果进行平均,从而避免极端情况。(在做具体的任务中会出现,这里没有出现这个代码。)

    fine-tune没有步骤8,因为task的query set是用来测试模型的,标签对模型是未知的。因此fine-tune过程没有第二次梯度更新,而是直接利用第一次梯度计算的结果更新参数。

     以上就是MAML的全部算法思路啦。我也是在摸索学习中,如有不足之处,敬请指正。

    class MetaLearner(nn.Module):
        def __init__(self):
            super(MetaLearner, self).__init__()
            self.update_step = 5  ## task-level inner update steps
            self.update_step_test = 5
            self.net = BaseNet()
            self.meta_lr = 2e-4
            self.base_lr = 4 * 1e-2
            self.inner_lr = 0.4
            self.outer_lr = 1e-2
            self.meta_optim = torch.optim.Adam(self.net.parameters(), lr=self.meta_lr)
    
        def forward(self, x_spt, y_spt, x_qry, y_qry):
            # 初始化
            task_num, ways, shots, h, w = x_spt.size()
            query_size = x_qry.size(1)  # 75 = 15 * 5
            loss_list_qry = [0 for _ in range(self.update_step + 1)]
            correct_list = [0 for _ in range(self.update_step + 1)]
    
            for i in range(task_num):
                ## 第0步更新
                y_hat = self.net(x_spt[i], params=None, bn_training=True)  # (ways * shots, ways)
                loss = F.cross_entropy(y_hat, y_spt[i])
                grad = torch.autograd.grad(loss, self.net.parameters())
                tuples = zip(grad, self.net.parameters())  ## 将梯度和参数\theta一一对应起来
                # fast_weights这一步相当于求了一个\theta - \alpha*\nabla(L) θ−α∗∇(L)
                fast_weights = list(map(lambda p: p[1] - self.base_lr * p[0], tuples))
                # 在query集上测试,计算准确率
                # 这一步使用更新前的数据
                with torch.no_grad():
                    y_hat = self.net(x_qry[i], self.net.parameters(), bn_training=True)
                    loss_qry = F.cross_entropy(y_hat, y_qry[i])
                    loss_list_qry[0] += loss_qry
                    pred_qry = F.softmax(y_hat, dim=1).argmax(dim=1)  # size = (75)
                    correct = torch.eq(pred_qry, y_qry[i]).sum().item()
                    correct_list[0] += correct
    
                # 使用更新后的数据在query集上测试。
                with torch.no_grad():
                    y_hat = self.net(x_qry[i], fast_weights, bn_training=True)
                    loss_qry = F.cross_entropy(y_hat, y_qry[i])
                    loss_list_qry[1] += loss_qry
                    pred_qry = F.softmax(y_hat, dim=1).argmax(dim=1)  # size = (75)
                    correct = torch.eq(pred_qry, y_qry[i]).sum().item()
                    correct_list[1] += correct
    
                for k in range(1, self.update_step):
                    y_hat = self.net(x_spt[i], params=fast_weights, bn_training=True)
                    loss = F.cross_entropy(y_hat, y_spt[i])
                    grad = torch.autograd.grad(loss, fast_weights)
                    tuples = zip(grad, fast_weights)
                    fast_weights = list(map(lambda p: p[1] - self.base_lr * p[0], tuples))
    
                    y_hat = self.net(x_qry[i], params=fast_weights, bn_training=True)
                    loss_qry = F.cross_entropy(y_hat, y_qry[i])
                    loss_list_qry[k + 1] += loss_qry
    
                    with torch.no_grad():
                        pred_qry = F.softmax(y_hat, dim=1).argmax(dim=1)
                        correct = torch.eq(pred_qry, y_qry[i]).sum().item()
                        correct_list[k + 1] += correct
            #         print('hello')
    
            loss_qry = loss_list_qry[-1] / task_num
            self.meta_optim.zero_grad()  # 梯度清零
            loss_qry.backward()
            self.meta_optim.step()
    
            accs = np.array(correct_list) / (query_size * task_num)
            loss = np.array(loss_list_qry) / (task_num)
            return accs, loss
    
        def finetunning(self, x_spt, y_spt, x_qry, y_qry):
            assert len(x_spt.shape) == 4
    
            query_size = x_qry.size(0)
            correct_list = [0 for _ in range(self.update_step_test + 1)]
    
            new_net = deepcopy(self.net)
            y_hat = new_net(x_spt)
            loss = F.cross_entropy(y_hat, y_spt)
            grad = torch.autograd.grad(loss, new_net.parameters())
            fast_weights = list(map(lambda p: p[1] - self.base_lr * p[0], zip(grad, new_net.parameters())))
    
            # 在query集上测试,计算准确率
            # 这一步使用更新前的数据
            with torch.no_grad():
                y_hat = new_net(x_qry, params=new_net.parameters(), bn_training=True)
                pred_qry = F.softmax(y_hat, dim=1).argmax(dim=1)  # size = (75)
                correct = torch.eq(pred_qry, y_qry).sum().item()
                correct_list[0] += correct
    
            # 使用更新后的数据在query集上测试。
            with torch.no_grad():
                y_hat = new_net(x_qry, params=fast_weights, bn_training=True)
                pred_qry = F.softmax(y_hat, dim=1).argmax(dim=1)  # size = (75)
                correct = torch.eq(pred_qry, y_qry).sum().item()
                correct_list[1] += correct
    
            for k in range(1, self.update_step_test):
                y_hat = new_net(x_spt, params=fast_weights, bn_training=True)
                loss = F.cross_entropy(y_hat, y_spt)
                grad = torch.autograd.grad(loss, fast_weights)
                fast_weights = list(map(lambda p: p[1] - self.base_lr * p[0], zip(grad, fast_weights)))
    
                y_hat = new_net(x_qry, fast_weights, bn_training=True)
    
                with torch.no_grad():
                    pred_qry = F.softmax(y_hat, dim=1).argmax(dim=1)
                    correct = torch.eq(pred_qry, y_qry).sum().item()
                    correct_list[k + 1] += correct
    
            del new_net
            accs = np.array(correct_list) / query_size
            return accs
    

    main函数 

    import time
    
    device = torch.device('cpu')
    
    meta = MetaLearner().to(device)
    
    epochs = 60000
    for step in range(epochs):
        start = time.time()
        x_spt, y_spt, x_qry, y_qry = next('train')
        x_spt, y_spt, x_qry, y_qry = torch.from_numpy(x_spt).to(device), torch.from_numpy(y_spt).long().to(
            device), torch.from_numpy(x_qry).to(device), torch.from_numpy(y_qry).long().to(device)
        accs, loss = meta(x_spt, y_spt, x_qry, y_qry)
        end = time.time()
        if step % 100 == 0:
            print("epoch:", step)
            print(accs)
            print(loss)
    
        if step % 1000 == 0:
            accs = []
            for _ in range(1000 // task_num):
                # db_train.next('test')
                x_spt, y_spt, x_qry, y_qry = next('test')
                x_spt, y_spt, x_qry, y_qry = torch.from_numpy(x_spt).to(device), torch.from_numpy(y_spt).long().to(
                    device), torch.from_numpy(x_qry).to(device), torch.from_numpy(y_qry).long().to(device)
    
                for x_spt_one, y_spt_one, x_qry_one, y_qry_one in zip(x_spt, y_spt, x_qry, y_qry):
                    test_acc = meta.finetunning(x_spt_one, y_spt_one, x_qry_one, y_qry_one)
                    accs.append(test_acc)
            print('在mean process之前:', np.array(accs).shape)
            accs = np.array(accs).mean(axis=0).astype(np.float16)
            print('测试集准确率:', accs)

    展开全文
  • MAML: meta learning 论文分析

    千次阅读 2019-12-12 18:07:31
    第二个Require中的α和β指的是步长(step size),也可以理解为学习率(learning rate).MAML的模型训练过程是gradient by gradient,即MAML是基于二级梯度的,每次迭代包含两次的参数更新的过程,分别对应两个学习率α...
  • 文章目录1、介绍few-shot learningreinforcement learning概念Meta learning 三个步骤定义一组learning algorithm损失函数寻找最好的FMeta Learning实例:OmniglotN-way K-shotMAML目标函数MAML vs transfer ...
  • MAML原理讲解和代码实现

    千次阅读 多人点赞 2020-11-21 10:44:59
    Model-Agnostic Meta-Learning - MAML 一、相关概念: 1、meta-leaning meta-leaning指的是元学习,元学习是深度学习的一个分支,一个好的元模型(meta-learner)应该具备对新的、少量的数据做出快速而准确的学习。...
  • 深度学习之MAML笔记

    万次阅读 多人点赞 2018-08-15 22:32:17
    接触MAML半年了,在把这个传说中的神奇框架给改得不成样子之后,又回到了原点。从完全没接触过tensorflow和未知深度学习神经网络为何物之时到倒腾实验半年的经历,让我渐渐领会到MAML的一些思想。学习之路坎坷,暂且...
  • 本文介绍我最近学习的两个 Meta Learning 的算法:MAML 和 Reptile。原始论文分别见:Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks 和 Reptile: a Scalable Metalearning Algorithm 。文章...
  • 元学习,大千世界纭纭人生,如何找到海中一粟,当今科技不主张,元学习未来发展帮助我们找到灵感与思想,可能是未来人工智能重要视角,非专业人士路过点评
  • MAML复现全部细节和经验教训(Pytorch)

    千次阅读 多人点赞 2020-04-14 11:17:49
    我将在本文分享我复现maml时的经验和教训。
  • MAML-CNN代码笔记

    2020-07-15 11:39:42
    size,embedding_dim,n_filters,output_dim,dropout,pad_idx) accs = maml(x_spt, y_spt, x_qry, y_qry) 而Meta类的定义如下 class Meta(nn.Module): """ Meta Learner """ def __init__(self, args,vocab_size, ...
  • MAML 源代码解释说明 (一)

    千次阅读 2020-07-30 15:38:59
    此篇是对 MAML 源代码的解释,作者开源了论文代码,但是代码中注释很少,刚开始不容易理清思路,所以对代码中的关键部分进行了解释说明,核心是 construct_model() 函数,里面包含了 MAML 的训练过程,看代码实现...
  • 论文分享:概率MAML

    2020-11-24 17:54:02
    S2.2 神经统计学家方法 S2.3 LLAMA方法 S2.4 贝叶斯神经网络方法 S3 术语 S4 方法 S4.1 用变分推断进行基于梯度的元学习 S4.2 用混合推断进行概率MAML S4.3 加入其它依赖 S5 实验 S6 总结 我的思考 题目与文章脉络 ...
  • MAML在学术界已经是非常重要的模型了,论文Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks自2017年发表至今已经收获了400+的引用。由于当前网上关于MAML的中文介绍少之又少,可能很多小伙伴对...
  • 元学习—模型不可知元学习(MAML

    千次阅读 2020-10-16 17:06:22
    元学习—模型不可知元学习(MAML) 在之前的文章中,我们介绍了神经图灵机和记忆增强网络(MANN),主要介绍了其对于内存中信息的读取与写入。有兴趣的读者可以参考我之前的博客元学习—神经图灵机。在今天的文章中,...
  • 回忆一下我们之所以能很有效的调节参数,而没办法高效的调节超参数,就是因为我们没办法计算超参数的梯度,而MAML则是基于一些假设,使我们可以计算 ϕ\phiϕ 的梯度。 一旦我们可以计算 ϕ\phiϕ 的梯度,就可以...
  • MAML学习笔记

    2020-10-13 14:48:42
    了解到meta learning有一种打开了新世界大门的感觉。记录一下Model-Agnostic Meta Learning这篇论文的学习笔记,以便日后自己温习。 已经有两篇写的非常详细...2.MAML: Model-Agnostic Meta-Learning for Fast Adaptati
  • MAML 源代码解释说明 (二)

    千次阅读 2020-07-30 15:47:09
    此篇是对 MAML 源代码数据生成部分的解释说明,包含了如何构造论文中正弦函数回归任务的数据,以及如何对 omniglot 和 miniImagenet 图像数据进行处理。 原始文件见 data_generator.py """ Code for loading data. ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,158
精华内容 463
关键字:

maml