目录
问题:tokenizer.basic_tokenizer.tokenize()和tokenizer.wordpiece_tokenizer.tokenize()的区别是什么?
问题:?tokenizer.encode()和tokenizer.convert_tokens_to_ids()的区别是什么?
问题:多GPU加载BERT进行计算时报错:StopIteration: Caught StopIteration in replica 0 on device 0.?extended_attention_mask = extended_attention_mask.to(dtype=next(self.parameters()).dtype) ?# fp16 compatibility?StopIteration
问题:基于Huggingface进行训练时如何控制最大迭代次数Number of Iterations。
问题:tokenizer.basic_tokenizer.tokenize()和tokenizer.wordpiece_tokenizer.tokenize()的区别是什么?
回答:basic_tokenizer是基本的分词,按照character进行分词,会剔除掉空格,而wordpiece_tokenizer认为用户已经分好词,并以空格分开,会对子词进一步拆分并添加“##”前缀符号。从下可以看到,basic_tokenzier会把[CLS]也及进行拆分,而wordpiece_tokenizer则完全以空格进行拆分。如果不想把[CLS]和[SEP]特殊字符拆分的话,可以直接使用tokenizer.tokenize()即可。(transformers==2.8.0)
word_seq = "[CLS] 上海是沿海城市 [SEP]"
basic_tokens = dataloader.tokenizer.basic_tokenizer.tokenize(word_seq)
print(basic_tokens)
>>> ['[', 'cls', ']', '上', '海', '是', '沿', '海', '城', '市', '[', 'sep', ']']
basic_tokens = dataloader.tokenizer.wordpiece_tokenizer.tokenize(word_seq)
print(basic_tokens)
>>> ['[CLS]', '上', '##海', '##是', '##沿', '##海', '##城', '##市', '[SEP]']
问题:?tokenizer.encode()和tokenizer.convert_tokens_to_ids()的区别是什么?
回答:convert_tokens_to_ids是将分词后的token转化为id序列,而encode包含了分词和token转id过程,即encode是一个更全的过程,另外,encode默认使用basic的分词工具,以及会在句子前和尾部添加特殊字符[CLS]和[SEP],无需自己添加。从下可以看到,虽然encode直接使用tokenizer.tokenize()进行词拆分,会保留头尾特殊字符的完整性,但是自己也会额外添加特殊字符,[CLS]->101,[SEQ]->102.(transformers==2.8.0)
word_seq = "[CLS] 上海是沿海城市 [SEP]"
basic_tokens = dataloader.tokenizer.basic_tokenizer.tokenize(word_seq)
print(basic_tokens)
>>> ['[', 'cls', ']', '上', '海', '是', '沿', '海', '城', '市', '[', 'sep', ']']
print(dataloader.tokenizer.convert_tokens_to_ids(basic_tokens))
>>> [138, 100, 140, 677, 3862, 3221, 3784, 3862, 1814, 2356, 138, 9463, 140]
print(dataloader.tokenizer.encode(word_seq))
>>> [101, 101, 677, 3862, 3221, 3784, 3862, 1814, 2356, 102, 102]
问题:多GPU加载BERT进行计算时报错:StopIteration: Caught StopIteration in replica 0 on device 0.?extended_attention_mask = extended_attention_mask.to(dtype=next(self.parameters()).dtype) ?# fp16 compatibility?StopIteration
回答:原因是不能够使用torch.nn.DataParallel(model, device_ids=gpus, dim=0)的方式利用多gpu加载预训练的BERT。应该是torch版本的问题。其中torch1.5以上版本都可能会出现这个问题,据解决方案替换为torch1.4可以解决该问题。临时的解决办法是直接修改Transformer中attention的计算源码,如下(transformers==2.8.0)。另外一种方法使用多GPU的方式是修改Huggingface training_args类型参数“_n_gpu: 8”(8为使用的gpu数目)。(transformers==4.18.0)
# 定位在site-packages/transformers/modeling_bert.py", line 734, in forward
extended_attention_mask = extended_attention_mask.to(dtype=next(self.parameters()).dtype) # fp16 compatibility
# 修改为:
extended_attention_mask = extended_attention_mask.to(dtype=torch.float32)
问题:基于Huggingface进行训练时如何控制最大迭代次数Number of Iterations。
回答:主要通过num_train_epochs,per_device_train_batch_size,gradient_accumulation_steps,和_n_gpu几个参数决定。首先,num_train_epochs设置了最大迭代轮数,per_device_train_batch_size设置了每块GPU上的样本数,gradient_accumulation_steps为进行一次误差反传的累积次数,_n_gpu设置了GPU的使用数目。(transformers==4.18.0)
举例,如果训练样本total_sample=1000,?num_train_epochs=200,?per_device_train_batch_size=5, gradient_accumulation_steps=2,?_n_gpu=4。则最大迭代次数为:num_train_iter=200*(1000/(5*2*4))=5000。
|