我尝试使用拥抱脸部变形金刚API。 在导入库时,我有一些问题。如果有人知道答案,请告诉我您的知识。
transformers库具有经过训练的几种模型。转换器不仅提供诸如“ BertModel,RobertaModel”之类的裸模型,而且还提供诸如“ ModelForMultipleChoice”,“ ModelForSequenceClassification”,“ ModelForTokenClassification”,ModelForQuestionAnswering之类的便捷标头。
我想知道裸模型自己添加新的线性变换与模型用于序列分类之间有什么区别。 自定义模型(带有随机初始化线性的预训练模型)和转换器模型的序列分类有什么不同。
是否通过胶水数据训练ModelforSequenceClassification? 我期待有人的回复。
答案 0 :(得分:1)
如果我们看一下实际的实现,我认为这是最容易理解的,这里我随机选择RobertaModel
和RobertaForSequenceClassification
作为示例。但是,该结论对所有其他模型也有效。
您可以找到RobertaForSequenceClassification
here的实现,大致如下所示:
class RobertaForSequenceClassification(RobertaPreTrainedModel):
authorized_missing_keys = [r"position_ids"]
def __init__(self, config):
super().__init__(config)
self.num_labels = config.num_labels
self.roberta = RobertaModel(config, add_pooling_layer=False)
self.classifier = RobertaClassificationHead(config)
self.init_weights()
[...]
def forward([...]):
[...]
我们可以看到,这里没有关于预训练的指示,它只是在顶部添加了另一个线性层(RobertaClassificationHead
的实现可以在更下方找到,即here ):
class RobertaClassificationHead(nn.Module):
"""Head for sentence-level classification tasks."""
def __init__(self, config):
super().__init__()
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
self.dropout = nn.Dropout(config.hidden_dropout_prob)
self.out_proj = nn.Linear(config.hidden_size, config.num_labels)
def forward(self, features, **kwargs):
x = features[:, 0, :] # take <s> token (equiv. to [CLS])
x = self.dropout(x)
x = self.dense(x)
x = torch.tanh(x)
x = self.dropout(x)
x = self.out_proj(x)
return x
因此,要回答您的问题:这些模型在顶部没有任何预先训练的附加层,您可以自己轻松实现它们 *。
现在使用星号:尽管可以很容易地自己包装它,但还要注意它是一个继承的类RobertaPreTrainedModel
。这具有多个优点,最重要的优点是不同实现之间的一致设计(序列分类模型,序列标记模型等)。此外,它们还提供了一些简洁的功能,例如包含大量参数(填充,屏蔽,注意输出等)的前向调用,这将花费相当多的时间来实现。
最后但并非最不重要的是,基于这些特定的实现,已有 个经过训练的模型,您可以在Huggingface Model Hub上进行搜索。在那里,您可能会发现在序列分类任务中经过微调的模型(例如this one),然后直接将其权重加载到RobertaForSequenceClassification
模型中。如果您有自己的序列分类模型实现,那么加载和调整这些预先训练的权重将变得异常复杂。
我希望这能回答您的主要问题,但可以就未解决的任何问题进行详细说明(无论是评论还是新问题)!