- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图使用更高的库进行元学习,但我在理解 copy_initial_weights
的内容时遇到了问题。意思。文档说:
copy_initial_weights – if true, the weights of the patched module are copied to form the initial weights of the patched module, and thus are not part of the gradient tape when unrolling the patched module. If this is set to False, the actual module weights will be the initial weights of the patched module. This is useful when doing MAML, for example.
最佳答案
短版
调用 higher.innerloop_ctx
与 model
作为参数为该模型创建临时修补模型和展开优化器:(fmodel, diffopt)
.预计在内循环中 fmodel 将迭代地接收一些输入,计算输出和损失,然后 diffopt.step(loss)
将被调用。每次diffopt.step
被称为 fmodel
将创建下一个版本的参数 fmodel.parameters(time=T)
这是使用以前的张量计算的新张量(完整的图允许通过该过程计算梯度)。如果用户在任何时候拨打 backward
在任何张量上,常规的 pytorch 梯度计算/累积将以允许梯度传播到例如的方式开始。优化器的参数(例如 lr
、 momentum
- 如果它们作为需要梯度传递到 higher.innerloop_ctx
的张量使用 override
)。fmodel
的创建时版本的参数 fmodel.parameters(time=0)
是原件model
的副本参数。如 copy_initial_weights=True
提供(默认)然后 fmodel.parameters(time=0)
将是 clone
+ detach
'ed 版本 model
的参数(即会保留值,但会严重影响与原始模型的所有连接)。如 copy_initial_weights=False
提供,然后 fmodel.parameters(time=0)
将是 clone
'd 版本 model
的参数,因此将允许梯度传播到原始 model
的参数(参见 pytorch doc 上的 clone
)。
术语说明
fnet.parameters()
,对于 copy_initial_weights=True
是如何完成的),那么原始的 model.parameters()
您的 meta_loss.backward()
将不再处于“梯度磁带”状态计算。 meta_loss.backward()
的部分pytorch 遍历所有时的计算 fnet.parameters(time=T)
从最新开始到最早结束( higher
不控制过程 - 这只是常规的 pytorch 梯度计算,higher
只负责这些新的 time=T
参数是如何从以前的参数中创建的时间 diffopt.step
被调用以及 fnet
如何总是使用最新的进行前向计算)。 higher
的主要功能(只有功能,真的)库以可微分的方式展开模型的参数优化。它可以以直接使用可微优化器的形式出现,例如
higher.get_diff_optim
如
this example或以
higher.innerloop_ctx
的形式如
this example .
higher.innerloop_ctx
的选项正在包装“无状态”模型的创建
fmodel
从现有模型为您提供并为您提供“优化器”
diffopt
为此
fmodel
.因此,正如在更高版本的 README.md 中总结的那样,它允许您从以下位置切换:
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 kwarg
loss = loss_function(logits, ys) # no need to call loss.backwards()
diffopt.step(loss) # note that `step` must take `loss` as an argument!
# 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))
model
和做
diffopt.step
更新
fmodel
是
fmodel
没有将参数就地更新为
opt.step()
在原来的部分会做。而是每次
diffopt.step
被称为参数的新版本是以这种方式创建的,即
fmodel
将在下一步使用新的,但仍保留所有以前的。
fmodel
仅开头
fmodel.parameters(time=0)
可用,但在您调用
diffopt.step
后可以问N次
fmodel
给你
fmodel.parameters(time=i)
对于任何
i
高达
N
包括的。请注意
fmodel.parameters(time=0)
这个过程完全没有变化,只是每次
fmodel
应用于某些输入,它将使用它当前拥有的最新版本的参数。
fmodel.parameters(time=0)
?已创建
here并取决于
copy_initial_weights
.如
copy_initial_weights==True
然后
fmodel.parameters(time=0)
是
clone
'd 和
detach
'ed 参数
model
.否则他们只是
clone
'd,但不是
detach
'ed!
model
的参数实际上会累积梯度当且仅当
copy_initial_weights==False
.在 MAML 中,我们要优化
model
的起始权重,因此我们实际上确实需要从元优化步骤中获得梯度。
higher
缺乏更简单的玩具示例来演示正在发生的事情,而是急于展示更严肃的事情作为示例。因此,让我尝试填补这里的空白,并使用我能想到的最简单的玩具示例(具有 1 个权重的模型将输入乘以该权重)来演示正在发生的事情:
import torch
import torch.nn as nn
import torch.optim as optim
import higher
import numpy as np
np.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 do
x = 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 tensors
print()
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_multiplier
weight_learned_after_full_inner_loop = list(fmodel.parameters())[0]
meta_loss = (weight_learned_after_full_inner_loop - actual_multiplier)**2
print(' 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=False
if 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
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_step
print()
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==0
Representation 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): True
Notice how `out` is `x` multiplied by the latest version of weight: 0.417 * -0.9915 == -0.4135
Starting inner loop step j==1
Representation 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): True
Notice how `out` is `x` multiplied by the latest version of weight: 0.417 * -0.1217 == -0.05075
Starting inner loop step j==2
Representation 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): True
Notice how `out` is `x` multiplied by the latest version of weight: 0.417 * 1.015 == 0.4231
Starting inner loop step j==3
Representation 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): True
Notice how `out` is `x` multiplied by the latest version of weight: 0.417 * 2.064 == 0.8607
Starting inner loop step j==4
Representation 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): True
Notice how `out` is `x` multiplied by the latest version of weight: 0.417 * 2.867 == 1.196
Let'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.011927987982895929
Gradient 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 smaller
Let'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.011927987982895929
Let'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.01192798770078706
Side-by-side meta_loss_gradient_approximation and gradient computed by `higher` lib: -0.005311 VS -0.005311
关于machine-learning - copy_initial_weights 文档在 Pytorch 的更高库中是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60311183/
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
在main()中声明其原型(prototype)的函数的返回数据类型为void。它包含一个指令返回;如 main() { void create(int *p); *some code
我想知道这个 scala 符号是什么:_@。 (搜索引擎无法识别奇怪的字符,因此很难在 google 上找到任何内容...) 这里是上下文: def doNodeParse(json: JValue)
在尝试编译我的项目时,它使用了一些第三方头文件,使用 mingw 4.4,我遇到了以下错误: Assembler messages: Error: junk at end of line, first
我正在解决 picoCTF 上的二进制漏洞利用挑战,并遇到了这段代码: ((void (*)())buf)(); 哪里buf是一个字符数组。 我解决了挑战,但似乎无法理解它到底在做什么。我看了this
我正在浏览 React Navigation docs我在那里遇到了这样的事情: import Ionicons from 'react-native-vector-icons/Ionicons';
selenium 中以下命令的含义是什么? 我尝试创建一个自动测试用例。然后如下://button[@type='submit'] 我在 selenium 工具中看到的语法。 最佳答案 这是一个 XP
我刚开始看书学习 C 语言,对他们讨论指针和数组的部分并没有感到困惑。如果有一个名为 a[NUM_ROW][NUM_COLS] 的多维数组(我只是将此数组讨论为特定的二维数组),那么 a[0] 是什么
这个问题在这里已经有了答案: How does "while(*s++ = *t++)" copy a string? (17 个答案) 关闭 9 年前。 我有一个代码块: int main ()
我没有在我的代码中处理 SIGCHLD。我的进程在终止后仍然立即被删除。我希望它成为僵尸进程。 如果我将 SIGCHLD 设置为 SIG_DFL 那么它会起作用吗?如何将 SIGCHLD 设置为 SI
我已经使用 matplotlib 一段时间了,但我并不真正理解这一行的作用。 fig, ax = plt.subplots() 谁能解释一下? 最佳答案 plt.subplots() 基本上是一个(非
我很难理解以下声明的含义。这个申报标准吗? double* (*p[3]) (void* (*)()); 谁能帮我理解这个声明的意思? 最佳答案 阅读复杂声明的规则:找到最左边的标识符并向外工作,记住
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 8 年前。 Improve t
我正在学习如何并行运行多个进程 ./script1.sh param1 1>/dev/null 2>&1 & pid1=$! ./script1.sh param2 1>/dev/null
我看到这些事件散布在 chaplin 示例代码中,但在文档或源代码中没有任何解释。似乎这意味着它是一个全局事件,触发了一个 Action 。那是对的吗?它们只是一个惯例,还是以某种方式强制执行? #
((void(*)(void))0)(); 所以我们将整数 0 类型转换为这个棘手的类型 (void(*))(void) 然后执行它。消息来源声称这应该有效,但实际上是什么? 我想这一定是像 #def
这个问题在这里已经有了答案: How does this JavaScript/jQuery syntax work: (function( window, undefined ) { })(win
if(a .feq. 5.0_dp) then **** if(a .fne. 5.2_dp) then ***我遇到了一些这样的代码。 .feq 有什么作用?或.fne。意思?是“=”还是“\=”?
所以我在阅读泛型方法时感到很困惑。先说一下这里的问题: 在这个例子中:假设我需要一个适用于任何类型 T 的 selectionSort 版本,方法是使用调用者提供的外部可比较对象。 第一次尝试: pu
我是一名优秀的程序员,十分优秀!