【MetaLearning】有关Pytorch的元学习库higher的基本用法

【MetaLearning】有关Pytorch的元学习库higher的基本用法

文章目录

  • 【MetaLearning】有关Pytorch的元学习库higher的基本用法
    • 1. 基本介绍
    • 2. Toy Example
    • Reference

1. 基本介绍

higher.innerloop_ctxhigher库的上下文管理器,用于创建内部循环(inner loop)的上下文,内部循环通常用于元学习场景,其中在模型参数更新的内部循环中进行一些额外的操作。

这个上下文管理器主要有五个参数:(详细请参考官方库说明)

higher.innerloop_ctx(model, opt, device=None, copy_initial_weights=True, override=None, track_higher_grads=True)
  • 第一个参数model是需要进行内部循环的模型,通常是你的元模型
  • 第二个参数opt是优化器,这是你用来更新模型参数的优化器
  • 第三个参数copy_initial_weights是一个布尔值,用于指定是否在每个内部循环之前复制初始权重,如果设置为True则表示在每个内部循环之前都会将模型的初始权重进行复制,以确保每个内部循环都从相同的初始权重开始。如果设置为False,则所有的内部循环共享相同的权重模型。
  • 第四个参数override是一个字典,例如override={'lr':lr_tensor, "momentum': momentum_tensor},用于指定在内部循环期间覆盖优化器的参数,比如在这里示例中,lr_tensormomentum_tensor是张量,用于指定内部循环期间覆盖的学习率和动量。
  • 第五个参数track_higher_grads是一个布尔值,用于跟踪更高阶的梯度,如果是True,则内部循环中计算的梯度将被跟踪以支持高阶的梯度计算,如果设置为False,则不会跟踪高阶梯度。

with语句块中,通过(fmodel, diffopt)获取内部循环的上下文。fmodel表示内部循环中的模型,diffopt表示内部循环中的优化器,在这个上下文中,你可以执行内部循环的计算和参数更新。

下面给出一个基本的使用示例,演示如何使用higher.innerloop_ctx,使用higher库需要习惯下列的转变

从通常使用pytorch的用法

model = MyModel()
opt = torch.optim.Adam(model.parameters())for xs, ys in data:opt.zero_grad()logits = model(xs)loss = loss_function(logits, ys)loss.backward()opt.step()

转变到

model = MyModel()
opt = torch.optim.Adam(model.parameters())with higher.innerloop_ctx(model, opt) as (fmodel, diffopt):for xs, ys in data:logits = fmodel(xs)  # modified `params` can also be passed as a kwargloss = loss_function(logits, ys)  # no need to call loss.backwards()diffopt.step(loss)  # note that `step` must take `loss` as an argument!,这一步相当于使用了loss.backward()和opt.step()# At the end of your inner loop you can obtain these e.g. ...grad_of_grads = torch.autograd.grad(meta_loss_fn(fmodel.parameters()), fmodel.parameters(time=0))

训练模型和执行diffopt.step 来更新fmodel之间的区别在于,fmodel不会像原始部分中的opt.step()那样就地更新参数。 相反,每次调用 diffopt.step时都会以这样的方式创建新版本的参数,即fmodel将在下一步中使用新的参数,但所有以前的参数仍会保留。

运行的原理是什么呢?举个例子,fmodelfmodel.parameters(time=0)开始迭代(这里的time=0表示就是第0次迭代),当我们调用diffopt.stepN次之后,我们可以使用fmodel.parameters(time=i)来访问,其中i可以取到1N,并且我们仍然可以访问fmodel.parameters(time=0),这个结果和迭代之前是一样的,这是为什么呢?

因为fmodel的创建依赖于参数copy_initial_weights,如果copy_initial_weights=True,那么fmodel.parameters(time=0)是从原模型clone’d别且是detach’ed(即是从原模型克隆过来并且进行分离计算图了),如果copy_initial_weights=False,那么只是进行了clone’d并没有detach‘ed。

放一段原文在这里方便大家理解

I.e. fmodel starts with only fmodel.parameters(time=0) available, but after you called diffopt.step N times you can ask fmodel to give you fmodel.parameters(time=i) for any i up to N inclusive. Notice that fmodel.parameters(time=0) doesn’t change in this process at all, just every time fmodel is applied to some input it will use the latest version of parameters it currently has.

Now, what exactly is fmodel.parameters(time=0)? It is created here and depends on copy_initial_weights. If copy_initial_weights==True then fmodel.parameters(time=0) are clone’d and detach’ed parameters of model. Otherwise they are only clone’d, but not detach’ed!

That means that when we do meta-optimization step, the original model’s parameters will actually accumulate gradients if and only if copy_initial_weights==False. And in MAML we want to optimize model’s starting weights so we actually do need to get gradients from meta-optimization step.

2. Toy Example

import torch
import torch.nn as nn
import torch.optim as optim
import higher
import numpy as npnp.random.seed(1)
torch.manual_seed(3)
N = 100
actual_multiplier = 3.5
meta_lr = 0.00001
loops = 5 # how many iterations in the inner loop we want to dox = torch.tensor(np.random.random((N,1)), dtype=torch.float64) # features for inner training loop
y = x * actual_multiplier # target for inner training loop
model = nn.Linear(1, 1, bias=False).double() # simplest possible model - multiple input x by weight w without bias
meta_opt = optim.SGD(model.parameters(), lr=meta_lr, momentum=0.)def run_inner_loop_once(model, verbose, copy_initial_weights):lr_tensor = torch.tensor([0.3], requires_grad=True)momentum_tensor = torch.tensor([0.5], requires_grad=True)opt = optim.SGD(model.parameters(), lr=0.3, momentum=0.5)with higher.innerloop_ctx(model, opt, copy_initial_weights=copy_initial_weights, override={'lr': lr_tensor, 'momentum': momentum_tensor}) as (fmodel, diffopt):for j in range(loops):if verbose:print('Starting inner loop step j=={0}'.format(j))print('    Representation of fmodel.parameters(time={0}): {1}'.format(j, str(list(fmodel.parameters(time=j)))))print('    Notice that fmodel.parameters() is same as fmodel.parameters(time={0}): {1}'.format(j, (list(fmodel.parameters())[0] is list(fmodel.parameters(time=j))[0])))out = fmodel(x)if verbose:print('    Notice how `out` is `x` multiplied by the latest version of weight: {0:.4} * {1:.4} == {2:.4}'.format(x[0,0].item(), list(fmodel.parameters())[0].item(), out[0].item()))loss = ((out - y)**2).mean()diffopt.step(loss)if verbose:# after all inner training let's see all steps' parameter tensorsprint()print("Let's print all intermediate parameters versions after inner loop is done:")for j in range(loops+1):print('    For j=={0} parameter is: {1}'.format(j, str(list(fmodel.parameters(time=j)))))print()# let's imagine now that our meta-learning optimization is trying to check how far we got in the end from the actual_multiplierweight_learned_after_full_inner_loop = list(fmodel.parameters())[0]meta_loss = (weight_learned_after_full_inner_loop - actual_multiplier)**2print('  Final meta-loss: {0}'.format(meta_loss.item()))meta_loss.backward() # will only propagate gradient to original model parameter's `grad` if copy_initial_weight=Falseif verbose:print('  Gradient of final loss we got for lr and momentum: {0} and {1}'.format(lr_tensor.grad, momentum_tensor.grad))print('  If you change number of iterations "loops" to much larger number final loss will be stable and the values above will be smaller')return meta_loss.item()print('=================== Run Inner Loop First Time (copy_initial_weights=True) =================\n')
meta_loss_val1 = run_inner_loop_once(model, verbose=True, copy_initial_weights=True)
print("\nLet's see if we got any gradient for initial model parameters: {0}\n".format(list(model.parameters())[0].grad))print('=================== Run Inner Loop Second Time (copy_initial_weights=False) =================\n')
meta_loss_val2 = run_inner_loop_once(model, verbose=False, copy_initial_weights=False)
print("\nLet's see if we got any gradient for initial model parameters: {0}\n".format(list(model.parameters())[0].grad))print('=================== Run Inner Loop Third Time (copy_initial_weights=False) =================\n')
final_meta_gradient = list(model.parameters())[0].grad.item()
# Now let's double-check `higher` library is actually doing what it promised to do, not just giving us
# a bunch of hand-wavy statements and difficult to read code.
# We will do a simple SGD step using meta_opt changing initial weight for the training and see how meta loss changed
meta_opt.step()
meta_opt.zero_grad()
meta_step = - meta_lr * final_meta_gradient # how much meta_opt actually shifted inital weight value
# before we run inner loop third time, we update the meta parameter firstly.
meta_loss_val3 = run_inner_loop_once(model, verbose=False, copy_initial_weights=False)meta_loss_gradient_approximation = (meta_loss_val3 - meta_loss_val2) / meta_stepprint()
print('Side-by-side meta_loss_gradient_approximation and gradient computed by `higher` lib: {0:.4} VS {1:.4}'.format(meta_loss_gradient_approximation, final_meta_gradient))

结果如下

=================== Run Inner Loop First Time (copy_initial_weights=True) =================Starting inner loop step j==0Representation of fmodel.parameters(time=0): [tensor([[-0.9915]], dtype=torch.float64, requires_grad=True)]Notice that fmodel.parameters() is same as fmodel.parameters(time=0): TrueNotice how `out` is `x` multiplied by the latest version of weight: 0.417 * -0.9915 == -0.4135
Starting inner loop step j==1Representation of fmodel.parameters(time=1): [tensor([[-0.1217]], dtype=torch.float64, grad_fn=<AddBackward0>)]Notice that fmodel.parameters() is same as fmodel.parameters(time=1): TrueNotice how `out` is `x` multiplied by the latest version of weight: 0.417 * -0.1217 == -0.05075
Starting inner loop step j==2Representation of fmodel.parameters(time=2): [tensor([[1.0145]], dtype=torch.float64, grad_fn=<AddBackward0>)]Notice that fmodel.parameters() is same as fmodel.parameters(time=2): TrueNotice how `out` is `x` multiplied by the latest version of weight: 0.417 * 1.015 == 0.4231
Starting inner loop step j==3Representation of fmodel.parameters(time=3): [tensor([[2.0640]], dtype=torch.float64, grad_fn=<AddBackward0>)]Notice that fmodel.parameters() is same as fmodel.parameters(time=3): TrueNotice how `out` is `x` multiplied by the latest version of weight: 0.417 * 2.064 == 0.8607
Starting inner loop step j==4Representation of fmodel.parameters(time=4): [tensor([[2.8668]], dtype=torch.float64, grad_fn=<AddBackward0>)]Notice that fmodel.parameters() is same as fmodel.parameters(time=4): TrueNotice how `out` is `x` multiplied by the latest version of weight: 0.417 * 2.867 == 1.196Let's print all intermediate parameters versions after inner loop is done:For j==0 parameter is: [tensor([[-0.9915]], dtype=torch.float64, requires_grad=True)]For j==1 parameter is: [tensor([[-0.1217]], dtype=torch.float64, grad_fn=<AddBackward0>)]For j==2 parameter is: [tensor([[1.0145]], dtype=torch.float64, grad_fn=<AddBackward0>)]For j==3 parameter is: [tensor([[2.0640]], dtype=torch.float64, grad_fn=<AddBackward0>)]For j==4 parameter is: [tensor([[2.8668]], dtype=torch.float64, grad_fn=<AddBackward0>)]For j==5 parameter is: [tensor([[3.3908]], dtype=torch.float64, grad_fn=<AddBackward0>)]Final meta-loss: 0.011927987982895929Gradient of final loss we got for lr and momentum: tensor([-1.6295]) and tensor([-0.9496])If you change number of iterations "loops" to much larger number final loss will be stable and the values above will be smallerLet's see if we got any gradient for initial model parameters: None=================== Run Inner Loop Second Time (copy_initial_weights=False) =================Final meta-loss: 0.011927987982895929Let's see if we got any gradient for initial model parameters: tensor([[-0.0053]], dtype=torch.float64)=================== Run Inner Loop Third Time (copy_initial_weights=False) =================Final meta-loss: 0.01192798770078706Side-by-side meta_loss_gradient_approximation and gradient computed by `higher` lib: -0.005311 VS -0.005311

Reference

Parper: Generalized Inner Loop Meta-Learning
What does the copy_initial_weights documentation mean in the higher library for Pytorch?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/154867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023亚太杯数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

Prometheus+Grafana环境搭建(window)

PrometheusGrafana环境搭建 1&#xff1a;配置Prometheus 1.1: 下载Prometheus安装包 官方下载地址 找到对应的win版本进行下载并解压 1.2 下载Window数据采集 官方下载地址 下载以管理员运行&#xff0c;安装成功后在服务里会出现一个"windows_exporter"采集…

光伏、储能双层优化配置接入配电网研究(附带Matlab代码)

由于能源的日益匮乏&#xff0c;电力需求的不断增长等&#xff0c;配电网中分布式能源渗透率不断提高&#xff0c;且逐渐向主动配电网方向发展。此外&#xff0c;需求响应(demand response&#xff0c;DR)的加入对配电网的规划运行也带来了新的因素。因此&#xff0c;如何综合考…

【LittleXi】CCPC2023 深圳站 总结

【LittleXi】CCPC2023 深圳站 总结 赛前 1、赛前vp了香港&#xff0c;rank13&#xff0c;还行 2、玩了一把div2&#xff0c;上了75分&#xff0c;感觉不如南京之前CF献祭的100分 3、比赛前一晚打了一把abc&#xff0c;只能说消耗了脑力&#xff0c;下次比赛前不玩了 热身赛…

小趴菜教你如何用Python开发手机App..

Python语言虽然很万能&#xff0c;但用它来开发app还是显得有点不对路&#xff0c;因此用Python开发的app应当是作为编码练习、或者自娱自乐所用&#xff0c;加上目前这方面的模块还不是特别成熟&#xff0c;bug比较多&#xff0c;总而言之&#xff0c;劝君莫轻入。 准备工作 …

白银投资的升值空间及未来趋势

在投资多样化的今天&#xff0c;人们可选择的投资产品也越来越多。白银作为具有较高价值的贵金属&#xff0c;一直以来便是仅次于黄金的贵金属投资品种&#xff0c;今年来也受到更多投资者的关注。那么白银的升值空间及未来趋势如何&#xff1f;是否值得投资&#xff1f;这边将…

做医疗影像心脏方面的看过来:医学图像重建的心脏 MRI 数据集

本文发布了CMRxRecon数据集&#xff0c;包括来自 300 名受试者的多对比度、多视图、多切片和多通道 CMR 成像数据&#xff0c;还由经验丰富的放射科医生提供了所有受试者的心肌和心室的手动分割。单位&#xff1a;复旦, 香港理工大学, 厦大等 心脏磁共振成像&#xff08;CMR&a…

神经网络中BN层简介及位置分析

1. 简介 Batch Normalization是深度学习中常用的技巧&#xff0c;Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift (Ioffe and Szegedy, 2015) 第一次介绍了这个方法。 这个方法的命名&#xff0c;明明是Standardization, 非…

PostgreSQL 入门

文章目录 PostgreSQL介绍PostgreSQL和MySQL的区别PostgreSQL的安装PostgreSQL的配置远程连接配置配置数据库的日志 PostgreSQL基本操作用户操作权限操作 图形化界面安装总结 PostgreSQL介绍 PostgreSQL是一个功能强大的 开源 的关系型数据库&#xff0c;底层基于C实现。其开源…

面向对象程序设计1-类的定义和使用

第1关&#xff1a;数字时钟走字 任务描述 本关任务&#xff1a;本题中已给出一个时钟类的定义&#xff0c;请模拟数字时钟走字过程。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.类和对象。 编程要求 根据提示&#xff0c;在右侧编辑器补充代码&…

模板初阶学习

✨前言✨ &#x1f4d8; 博客主页&#xff1a;to Keep博客主页 &#x1f646;欢迎关注&#xff0c;&#x1f44d;点赞&#xff0c;&#x1f4dd;留言评论 ⏳首发时间&#xff1a;2023年11月21日 &#x1f4e8; 博主码云地址&#xff1a;博主码云地址 &#x1f4d5;参考书籍&…

Scala---WordCount

一、创建Maven项目导入pom.xml文件 安装Maven仓库管理工具&#xff0c;版本要求是3.2版本以上。新建Maven项目&#xff0c;配置pom.xml。导入必要的包。 二、Spark-Scala版本的WordCount 1.val conf new SparkConf() 2.conf.setMaster("local") 3.conf.setAppNam…

4、FFmpeg命令行操作4

ffmpeg命令参数说明 主要参数: -i 设定输入流 -f 设定输出格式(format) -ss 开始时间 -t 时间长度 音频参数: -aframes 设置要输出的音频帧数 -b:a 音频码率 -ar 设定采样率 -ac 设定声音的Channel数 -acodec 设定声音编解码器,如果用copy表示原始编解码数…

【刷题专栏—突破思维】LeetCode 138. 随机链表的复制

前言 随机链表的复制涉及到复制一个链表&#xff0c;该链表不仅包含普通的next指针&#xff0c;还包含random指针&#xff0c;该指针指向链表中的任意节点或空节点。 文章目录 原地修改链表 题目链接&#xff1a; LeetCode 138. 随机链表的复制 原地修改链表 题目介绍&#xf…

拖拽场景遇到 iframe 无法拖拽的问题解决方案

描述一个场景&#xff1a;在网页中&#xff0c;分为上下两部分布局&#xff0c;下半部分显示操作日志&#xff0c;下半部分的区域高度是可拖拽调整的&#xff0c;但是如果下半部分嵌入一个 iframe 的时候&#xff0c;往上拖拽可以&#xff0c;但是往下拖拽&#xff0c;一旦到了…

分类问题的评价指标

一、logistic regression logistic regression也叫做对数几率回归。虽然名字是回归&#xff0c;但是不同于linear regression&#xff0c;logistic regression是一种分类学习方法。 同时在深度神经网络中&#xff0c;有一种线性层的输出也叫做logistic&#xff0c;他是被输入…

【python学习】基础篇-常用模块-shutil文件和目录操作

shutil模块是Python标准库中的一个模块&#xff0c;提供了对文件和目录进行高级操作的函数。 以下是shutil模块的一些常用函数&#xff1a; 1.复制文件&#xff1a; 将源文件src复制到目标文件dst。如果follow_symlinks为True,则会跟随符号链接。 shutil.copy(src, dst, *, f…

以太网_寻址

【架构图】 【ipconfig/all】 MAC地址&#xff1a;作用于本地网络&#xff0c;数据包发送到本地交换机或路由器后经判断目的地址是本地网络地址会转发给当前MAC地址对应的网线端口。 IP地址&#xff1a;供路由器寻址&#xff0c;会跟子网掩码进行运算&#xff0c;属于同一网络…

git问题: git@10.18.*.*: Permission denied (publickey,password)

遇到的问题&#xff1a; openSSH版本太高&#xff0c;openssh高版本默认禁止ssh-rsa加密算法&#xff0c;直接换ed25519 执行以下命令&#xff1a; 在.ssh目录下执行&#xff1a;ssh-keygen -t ed25519 -C “youremail.com” ssh-add ~/.ssh/id_ed25519 将id_ed25519.pub添加…

Java 数据结构、集合框架、ArrayList

一、Java数据结构&#xff1a; Java中的数据结构主要包含以下几种接口和类&#xff1a;枚举、位集合、向量、栈、字典、哈希表、属性。 枚举接口定义一种从数据结构中取回连续元素的方式。 位集合实现了一组可以单独设置和清除的位或标志。 向量类于传统数组相似&#xff0…