在Pytorch类中给定一个简单的神经网络:
import torch.nn as nn
net = nn.Sequential(
nn.Linear(3, 4),
nn.Sigmoid(),
nn.Linear(4, 1),
nn.Sigmoid()
).to(device)
如何将其转换为Huggingface PreTrainedModel对象
目标是将Pytorchnn.Module
对象从nn.Sequential
转换为HuggingfacePreTrainedModel
对象,然后运行以下操作:
import torch.nn as nn
from transformers.modeling_utils import PreTrainedModel
net = nn.Sequential(
nn.Linear(3, 4),
nn.Sigmoid(),
nn.Linear(4, 1),
nn.Sigmoid()
).to(device)
# Do something to convert the Pytorch nn.Module to the PreTrainedModel object.
shiny_model = do_some_magic(net, some_args, some_kwargs)
# Save the shiny model that is a `PreTrainedModel` object.
shiny_model.save_pretrained("shiny-model")
PreTrainedModel.from_pretrained("shiny-model")
而且似乎要将任何本地Pytorch模型构建/转换为Huggingface模型,需要一些配置https://huggingface.co/docs/transformers/main_classes/configuration
有许多如何训练模型的方法;"从头开始";,例如
[使用BertLMHeadModel,而不是那个划痕]https://www.kaggle.com/code/mojammel/train-model-from-scratch-with-huggingface/notebook(这也是从伯特微调,而不是从头开始(
[不是真的刮伤,使用roberta作为模板]https://huggingface.co/blog/how-to-train(这是roberta的微调,不是真正的从头开始训练(
[有点使用一些配置模板]https://www.thepythoncode.com/article/pretraining-bert-huggingface-transformers-in-python(这有点从头开始,但使用BERT中的模板来生成配置,如果我们想改变模型的工作方式,配置应该是什么样子呢?(
[Kinda定义了一个模板,但使用RobertaForMaskedLM]https://skimai.com/roberta-language-model-for-spanish/(这看起来有点定义了一个模板,但将其限制为RobertaForMaskedLM模板(
部分问题:
如果我们有一个像上面代码片段中那样简单得多的Pytorch模型,如何在Huggingface中从头开始创建预训练模型?
如何创建Huggingface从原生Pytorch nn进行转换所需的预训练模型配置。模块工作?
您将需要定义自定义配置和自定义模型类。在这些类中定义属性model_type
和config_class
是很重要的:
import torch.nn as nn
from transformers import PreTrainedModel, PretrainedConfig
from transformers import AutoModel, AutoConfig
class MyConfig(PretrainedConfig):
model_type = 'mymodel'
def __init__(self, important_param=42, **kwargs):
super().__init__(**kwargs)
self.important_param = important_param
class MyModel(PreTrainedModel):
config_class = MyConfig
def __init__(self, config):
super().__init__(config)
self.config = config
self.model = nn.Sequential(
nn.Linear(3, self.config.important_param),
nn.Sigmoid(),
nn.Linear(self.config.important_param, 1),
nn.Sigmoid()
)
def forward(self, input):
return self.model(input)
现在,您可以创建(显然还可以训练一个新模型(,保存并在本地加载您的模型
config = MyConfig(4)
model = MyModel(config)
model.save_pretrained('./my_model_dir')
new_model = MyModel.from_pretrained('./my_model_dir')
new_model
如果你想使用AutoModel
,你必须注册你的课程:
AutoConfig.register("mymodel", MyConfig)
AutoModel.register(MyConfig, MyModel)
new_model = AutoModel.from_pretrained('./my_model_dir')
new_model
一种方法是将模型放在从PreTrainedModel继承的类中,例如,它可以是预训练的resnet34、timm模型或您的"net";模型我建议查看文档以了解有关配置的更多详细信息,我将使用链接中的一个示例。https://huggingface.co/docs/transformers/custom_models#sharing-定制型号
配置(注意:您可以添加不同的配置,例如版本,您可以稍后访问config.json。(
from transformers import PretrainedConfig
from typing import List
class ModelConfig(PretrainedConfig):
model_type = "mymodel"
def __init__(
self,
version = 1,
layers: List[int] = [3, 4, 6, 3],
num_classes: int = 1000,
input_channels: int = 3,
stem_type: str = "",
**kwargs,
):
if stem_type not in ["", "deep", "deep-tiered"]:
raise ValueError(f"`stem_type` must be '', 'deep' or 'deep-tiered', got {block}.")
self.version = version
self.layers = layers
self.num_classes = num_classes
self.input_channels = input_channels
self.stem_type = stem_type
super().__init__(**kwargs)
正如我所说,你的网络模型可能是resnet34。
from transformers import PreTrainedModel
from torch import nn
net = nn.Sequential(
nn.Linear(3, 4),
nn.Sigmoid(),
nn.Linear(4, 1),
nn.Sigmoid()
).to('cuda')
class MyModel(PreTrainedModel):
config_class = ModelConfig
def __init__(self, config):
super().__init__(config)
self.model = net
def forward(self, tensor):
return self.model(tensor)
测试型号
config = ModelConfig()
model = MyModel(config)
dummy_input = torch.randn(1, 3).to('cuda')
with torch.no_grad():
output = model(dummy_input)
print(output.shape)
推送至hugginface hub(注意:您需要使用代币登录,您可以推送多次以更新模型(
model.push_to_hub("mymodel-test")
下载模型(注意:您使用的是MyModel类,如果您想创建像..bert.modeling_bert.BertModel这样的模型,我认为您需要使用lib结构。(
my_model = MyModel.from_pretrained("User/mymodel-test")