如何在不影响梯度的情况下更改神经网络权重?

假设我有一个简单的NN:

import torchimport torch.nn as nnimport torch.optim as optimfrom torch.nn.utils import parameters_to_vectorclass Model(nn.Module):    def __init__(self):        super(Model, self).__init__()        self.fc1 = nn.Linear(1, 2)        self.fc2 = nn.Linear(2, 3)        self.fc3 = nn.Linear(3, 1)    def forward(self, x):        x = self.fc1(x)        x = torch.relu(x)                x = torch.relu(self.fc2(x))        x = self.fc3(x)        return xnet = Model()opt = optim.Adam(net.parameters())

还有几个特征

features = torch.rand((3,1))

我可以正常训练它,使用:

for i in range(10):    opt.zero_grad()    out = net(features)    loss = torch.mean(torch.square(torch.tensor(5) - torch.sum(out)))    loss.backward()    opt.step()

然而,我对在批次中的每个示例之后更新每一层的权重感兴趣。也就是说,通过某些对于每一层不同的量来更新实际的权重值。

我可以用以下代码打印每一层的参数:

for i in range(1):    opt.zero_grad()    out = net(features)    print(parameters_to_vector(net.fc1.parameters()))    print(parameters_to_vector(net.fc2.parameters()))    print(parameters_to_vector(net.fc3.parameters()))    loss = torch.mean(torch.square(torch.tensor(5) - torch.sum(out)))    loss.backward()    opt.step()

如何在反向传播之前更改权重值而不影响梯度?

假设我想根据以下函数更新各层的权重:

def first_layer_update(weight):    return weight + 1e-3*weightdef second_layer_update(weight):    return 1e-2*weightdef third_layer_update(weight):    return weight - 1e-1*weight

回答:

– 使用torch.no_grad上下文管理器。

这允许你在你的张量上执行(就地或非就地)操作,而Autograd不会跟踪这些变化。正如@***解释的那样:

def first_layer_update(weight):    with torch.no_grad():        return weight + 1e-3*weightdef second_layer_update(weight):    with torch_no_grad():        return 1e-2*weightdef third_layer_update(weight):    with torch.no_grad():        return weight - 1e-1*weight

或者在调用它们时使用上下文管理器而不改变你的函数:

with torch.no_grad():    first_layer_update(net.fc1.weight)    second_layer_update(net.fc2.weight)    third_layer_update(net.fc3.weight)

– 使用@torch.no_grad装饰器。

一种变体是使用@torch.no_grad装饰器:

@torch.no_grad()def first_layer_update(weight):    return weight + 1e-3*weight@torch.no_grad():def second_layer_update(weight):    return 1e-2*weight@torch.no_grad():def third_layer_update(weight):    return weight - 1e-1*weight

并以first_layer_update(net.fc1.weight)second_layer_update(net.fc2.weight)等方式调用这些函数…


– 变更torch.Tensor.data

替代使用torch.no_grad上下文包装你的操作的方法是,使用权重的data属性来变更权重。这意味着以以下方式调用你的函数:

>>> first_layer_update(net.fc1.weight.data)>>> second_layer_update(net.fc2.weight.data)>>> third_layer_update(net.fc3.weight.data)

这将使用各自的更新策略变更三层的权重(不是偏置)。


简而言之,如果你想变更nn.Module的所有参数,你可以:

>>> with torch.no_grad():...     update_policy(parameters_to_vector(net.layer.parameters()))

或者

>>> update_policy(parameters_to_vector(net.layer.parameters().data))

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注