仅冻结torch.nn.Embedding对象的某些行

我是Pytorch的新手,我正在尝试对嵌入实施某种“后期训练”程序。

我的词汇表中包含一组项目,并且我为每个项目学习了一个向量。 我将学习到的向量保存在nn.Embedding对象中。 我现在想做的是在不更新已经学习的向量的情况下向词汇表添加一个新项。新项目的嵌入将被随机初始化,然后在保持所有其他嵌入冻结的同时进行训练。

我知道,为了防止nn.embedding受到训练,我需要将其False变量设置为requires_grad。我还发现了this other question与我的相似。最佳答案建议

  1. 将冻结的向量和要训练的向量存储在不同的nn。嵌入对象中,前者使用requires_grad = False,后者使用requires_grad = True

  2. 或将冻结的向量和新的向量存储在同一nn.Embedding对象中,计算所有向量的梯度,但仅对新项目向量的维度进行降序处理。但是,这会导致性能显着下降(我当然要避免)。

我的问题是,我真的需要将新项目的矢量与旧项目的冻结矢量存储在同一nn.Embedding对象中。出现此约束的原因如下:当使用项(旧项和新项)的嵌入构建损失函数时,我需要根据项的ID查找向量,并且出于性能方面的原因,我需要使用Python切片。换句话说,给定项ID item_ids的列表,我需要执行类似vecs = embedding[item_ids]的操作。如果对旧项目和新项目分别使用两个不同的nn。嵌入项目,则需要使用带有if-else条件的显式for循环,这将导致性能下降。

有什么办法可以做到这一点?

lixb07072014 回答:仅冻结torch.nn.Embedding对象的某些行

如果您查看nn.Embedding的实现,那么它将在向前通过中使用embedding的功能形式。因此,我认为您可以实现这样的自定义模块:

import torch
from torch.nn.parameter import Parameter
import torch.nn.functional as F

weights_freeze = torch.rand(10,5)  # Don't make parameter
weights_train = Parameter(torch.rand(2,5))
weights = torch.cat((weights_freeze,weights_train),0)

idx = torch.tensor([[11,1,3]])
lookup = F.embedding(idx,weights)

# Desired result
print(lookup)
lookup.sum().backward()
# 11 corresponds to idx 1 in weights_train so this has grad
print(weights_train.grad)
本文链接:https://www.f2er.com/2672177.html

大家都在问