Pytorch 微调模型&x27;使用新标签创建分类器层

Pytorch 微调模型&x27;使用新标签创建分类器层,pytorch,huggingface-transformers,Pytorch,Huggingface Transformers,我想用新的数据集对已经微调过的BertForSequenceClassification模型进行微调,该数据集只包含一个额外的标签,而该标签是模型以前从未见过的 这样,我想向模型当前能够正确分类的标签集添加1个新标签 此外,我不希望随机初始化分类器权重,我希望保持它们不变,并根据数据集示例相应地更新它们,同时将分类器层的大小增加1 用于进一步微调的数据集可能如下所示: sentece,label intent example 1,new_label intent example 2,new_la

我想用新的数据集对已经微调过的BertForSequenceClassification模型进行微调,该数据集只包含一个额外的标签,而该标签是模型以前从未见过的

这样,我想向模型当前能够正确分类的标签集添加1个新标签

此外,我不希望随机初始化分类器权重,我希望保持它们不变,并根据数据集示例相应地更新它们,同时将分类器层的大小增加1

用于进一步微调的数据集可能如下所示:

sentece,label
intent example 1,new_label
intent example 2,new_label
...
intent example 10,new_label
Linear(in_features=768, out_features=135, bias=True)
我的模型的当前分类器层如下所示:

sentece,label
intent example 1,new_label
intent example 2,new_label
...
intent example 10,new_label
Linear(in_features=768, out_features=135, bias=True)
我怎样才能实现它?

这是一个好方法吗?

您可以用新值扩展模型的权重和偏差。请看下面的注释示例:

#这是加载模型的部分
#对于这个例子,我将使用一个预训练的模型
进口火炬
从火炬进口
从transformers导入AutoModelForSequenceClassification、AutoTokenizer
标记器=来自预训练的自动煮沸器(“jpcorb20/有毒检测器蒸馏器”)
模型=自动模型,用于序列分类。来自预训练(“jpcorb20/有毒探测器distilroberta”)
#我们检查一个样本的输出,以便稍后与扩展层进行比较
#验证我们是否保留了之前学到的“知识”
f=标记器.encode_plus(“这是一个示例,返回_tensors='pt'))
打印(型号(**f).登录)
#现在我们需要找出要扩展的线性层的名称
#distilroberta顶部的层包裹在分类器部分内
#此名称可能因您而异,因为它可以随机选择
#使用model.parameters查找分类层
打印(模型分类器)
#输出告诉我们分类层被称为'out_proj'`
#现在,我们可以通过创建一个新的张量来扩展权重,该张量由
#旧权重和新标签的随机初始化张量
model.classifier.out_proj.weight=nn.参数(torch.cat((model.classifier.out_proj.weight,torch.randn(1768)),0))
#对于偏差,我们也会这样做:
model.classifier.out_proj.bias=nn.参数(torch.cat((model.classifier.out_proj.bias,torch.randn(1)),0))
#当我们将产出与预期进行比较时,要感到高兴
打印(型号(**f).登录)
输出:

tensor([[-7.3604, -9.4899, -8.4170, -9.7688, -8.4067, -9.3895]],
       grad_fn=<AddmmBackward>)
RobertaClassificationHead(
  (dense): Linear(in_features=768, out_features=768, bias=True)
  (dropout): Dropout(p=0.1, inplace=False)
  (out_proj): Linear(in_features=768, out_features=6, bias=True)
)
tensor([[-7.3604, -9.4899, -8.4170, -9.7688, -8.4067, -9.3895,  2.2124]],
       grad_fn=<AddmmBackward>)
张量([-7.3604,-9.4899,-8.4170,-9.7688,-8.4067,-9.3895],
grad_fn=)
罗伯塔分类头(
(密集):线性(输入特征=768,输出特征=768,偏差=真)
(辍学):辍学(p=0.1,原地=假)
(输出项目):线性(输入特征=768,输出特征=6,偏差=真)
)
张量([-7.3604,-9.4899,-8.4170,-9.7688,-8.4067,-9.3895,2.2124]],
grad_fn=)

感谢您再次帮助我。我能够扩展分类层并验证权重保持不变。然而,使用随机初始化的新权重偏差对,模型的总体精度显著(随机)下降。在使用如上所示的数据集对模型进行微调的过程中,一般的分类能力似乎受到了微调的高度影响,这是我所不期望的,因为之前使用了数千个示例对模型进行了微调,在这里我们只得到了几个示例。你能给我指出一些我应该更感兴趣的领域吗?@coso我对此并不感到惊讶。当您检查未微调的模型的结果时,您的句子可能都会被标记为新类。线性层应用一个简单的转换
y=xA^T+b
,然后应用类似于
argmax
的东西来选择句子的类别。虽然其他类的权重在您的微调后相当不错,但新引入的类不是,因此与其他类重叠,或者根本不存在。@coso,以防您的主要目标是节省一些时间,您可以尝试冻结除分类头之外的所有层,并对该模型进行微调。有一次讨论是关于冻结基于变压器的微调模型的层,结论似乎是@RameshArvind说这不是一个好主意,而不是sgugger的意思。他说,变形金刚通常都经过充分训练,以获得最佳效果,但这并不意味着冻结某些图层不是一个好主意。例如,在不冻结的情况下为mrpc培训bert需要2:36分钟,达到88%,而仅培训分类头需要0:53分钟,已经达到81%。