wangyuxinwhy / uniem

unified embedding model
Apache License 2.0
826 stars 64 forks source link

单机多卡训练 #101

Open kg-nlp opened 1 year ago

kg-nlp commented 1 year ago

🐛 bug 说明

请问微调模型是否支持单机多卡

Python Version

None

wangyuxinwhy commented 1 year ago

支持的,各种单机多卡的策略都可以支持

Bannerli commented 9 months ago

大佬您好,我想问下可以单击多卡进行finetuing吗,我在FineTuner这个类没有找到gpu设置的参数项。

wangyuxinwhy commented 8 months ago

单机多卡的 finetuning 是通过 accelerate 包来支持的,你需要参考 accelerate 的方式来使用

yangxudong commented 4 months ago

单机多卡的 finetuning 是通过 accelerate 包来支持的,你需要参考 accelerate 的方式来使用

你好,请问给出一个单机多卡的 finetuning 的Demo代码吗?谢谢!

zazd commented 4 months ago

@yangxudong 提供一个参考案例给你,希望有帮助, 因为只是简单体验uniem,可能有理解不对的地方。假设你已经跑通单机finetune的情况下,

  1. 通过accelerate启动多卡: a.生成一个config.yaml文件,复制以下配置: (其中num_processes:4 --表示4卡跑任务,其他配置自行查找accelerate配置) compute_environment: LOCAL_MACHINE distributed_type: MULTI_GPU downcast_bf16: 'no' gpu_ids: all machine_rank: 0 main_training_function: main mixed_precision: fp16 num_machines: 1 num_processes: 4 rdzv_backend: static same_network: true tpu_env: [] tpu_use_cluster: false tpu_use_sudo: false use_cpu: false b. 执行命令: accelerate launch --config_file your_dir/config.yaml your_py_file.py 因为我是别人提供gpu集群,我提交任务的方式,所以到此就可以跑起来了,你如果不是,可能需要研究一下gpu多卡启动;

  2. 但是到这里还是无法跑起来,主要原因后面会遇到报错,如: Parameter indices which did not receive grad for rank 2: 197 198 , 类似https://www.cnblogs.com/fireinstone/p/17352130.html 这个。原因是你定义的模型layer没有全部参与到loss计算,在单机下可以跑,但是分布式,涉及多卡更新,所以会catch这个情况并且报错; 简单看了下uniem的代码实现,主要问题是在: embedder = create_uniem_embedder('uer/chinese_roberta_L-12_H-128', pooling_strategy='cls') 这里pooling用的是cls,而bert/roberta的最后一层,可能是BertPooler层,uniem的几个pooling策略,好像都是用的cls的输出(也有其他的),但是最后BertPooler没有用,从而导致分布式更新时候有问题,具体可以看 https://github.com/wangyuxinwhy/uniem/blob/f76acf9287917cbb64ce7e6d36e18afaf4c452fd/uniem/model.py#L106 因此为了可以分布式跑起来,要么把BertPooler去掉,要么计算loss时候用上BertPooler的输出,也就是pooler_output。 我用的是后者,参考代码: a.PoolingStrategy加入新的策略pooler_output class PoolingStrategy(str, Enum): cls = 'cls' last_mean = 'last_mean' first_last_mean = 'first_last_mean' embedding_last_mean = 'embedding_last_mean' last_weighted = 'last_weighted' pooler_output = 'pooler_output' b. 在uniem/model.py添加新的类 class PoolerOutput(UniemEmbedder): pooling_strategy: ClassVar[PoolingStrategy] = PoolingStrategy.pooler_output

    def forward(self, input_ids: torch.Tensor, attention_mask: torch.Tensor | None = None) -> torch.Tensor: if attention_mask is None: attention_mask = create_attention_mask_from_input_ids(input_ids, self.pad_token_id) embeddings = self.encoder(input_ids, attention_mask=attention_mask).pooler_output return embeddings c.embedder = create_uniem_embedder('uer/chinese_roberta_L-12_H-128', pooling_strategy='pooler_output')

到这里应该能跑起来了,当然你可能还会遇上pytorch版本问题,分布式跑也可能有坑,见招拆招吧。