尝试微调 NER 的 ReformerModelWithLMHead (google/reformer-enwik8) 时出错
Error while trying to fine-tune the ReformerModelWithLMHead (google/reformer-enwik8) for NER
我正在尝试为 NER 微调 ReformerModelWithLMHead (google/reformer-enwik8)。我使用了与编码方法相同的填充序列长度 (max_length = max([len(string) for string in list_of_strings])) 以及 attention_masks。我得到了这个错误:
ValueError:如果进行训练,请确保 config.axial_pos_shape 因子:(128, 512) 乘以序列长度。得到 prod((128, 512)) != sequence_length: 2248。您可能需要考虑将序列长度填充到 65536 或更改 config.axial_pos_shape.
- 当我将序列长度更改为 65536 时,我的 colab 会话因获取所有 65536 长度的输入而崩溃。
- 按照第二个选项(改config.axial_pos_shape),我改不了
我想知道,有没有机会在微调模型的同时改变config.axial_pos_shape?或者我在为 reformer-enwik8 编码输入字符串时遗漏了什么?
谢谢!
问题更新:我试过以下方法:
- 通过在模型实例化时给出参数:
model = transformers.ReformerModelWithLMHead.from_pretrained("google/reformer-enwik8", num_labels=9, max_position_embeddings=1024, axial_pos_shape=[16,64], axial_pos_embds_dim=[32,96],hidden_size=128)
它给我以下错误:
RuntimeError: Error(s) in loading state_dict for ReformerModelWithLMHead:
size mismatch for reformer.embeddings.word_embeddings.weight: copying a param with shape torch.Size([258, 1024]) from checkpoint, the shape in current model is torch.Size([258, 128]).
size mismatch for reformer.embeddings.position_embeddings.weights.0: copying a param with shape torch.Size([128, 1, 256]) from checkpoint, the shape in current model is torch.Size([16, 1, 32]).
这是一个很长的错误。
- 然后我尝试了这个代码来更新配置:
model1 = transformers.ReformerModelWithLMHead.from_pretrained('google/reformer-enwik8', num_labels = 9)
重塑轴向位置嵌入层以匹配所需的最大序列长度
model1.reformer.embeddings.position_embeddings.weights[1] = torch.nn.Parameter(model1.reformer.embeddings.position_embeddings.weights[1][0][:128])
更新配置文件以匹配自定义最大序列长度
model1.config.axial_pos_shape = 16,128
model1.config.max_position_embeddings = 16*128 #2048
model1.config.axial_pos_embds_dim= 32,96
model1.config.hidden_size = 128
output_model_path = "model"
model1.save_pretrained(output_model_path)
通过这个实现,我得到了这个错误:
RuntimeError: The expanded size of the tensor (512) must match the existing size (128) at non-singleton dimension 2. Target sizes: [1, 128, 512, 768]. Tensor sizes: [128, 768]
因为更新后的 size/shape 与预训练模型的原始配置参数不匹配。原参数为: axial_pos_shape = 128512 max_position_embeddings = 128*512 #65536 axial_pos_embds_dim= 256768 hidden_size = 1024
这是我更改配置参数的正确方法还是我必须做其他事情?
有没有微调 ReformerModelWithLMHead('google/reformer-enwik8') 模型的例子。
我的主要代码实现如下:
class REFORMER(torch.nn.Module):
def __init__(self):
super(REFORMER, self).__init__()
self.l1 = transformers.ReformerModelWithLMHead.from_pretrained("google/reformer-enwik8", num_labels=9)
def forward(self, input_ids, attention_masks, labels):
output_1= self.l1(input_ids, attention_masks, labels = labels)
return output_1
model = REFORMER()
def train(epoch):
model.train()
for _, data in enumerate(training_loader,0):
ids = data['input_ids'][0] # input_ids from encode method of the model https://huggingface.co/google/reformer-enwik8#:~:text=import%20torch%0A%0A%23%20Encoding-,def%20encode,-(list_of_strings%2C%20pad_token_id%3D0
input_shape = ids.size()
targets = data['tags']
print("tags: ", targets, targets.size())
least_common_mult_chunk_length = 65536
padding_length = least_common_mult_chunk_length - input_shape[-1] % least_common_mult_chunk_length
#pad input
input_ids, inputs_embeds, attention_mask, position_ids, input_shape = _pad_to_mult_of_chunk_length(self=model.l1,
input_ids=ids,
inputs_embeds=None,
attention_mask=None,
position_ids=None,
input_shape=input_shape,
padding_length=padding_length,
padded_seq_length=None,
device=None,
)
outputs = model(input_ids, attention_mask, labels=targets) # sending inputs to the forward method
print(outputs)
loss = outputs.loss
logits = outputs.logits
if _%500==0:
print(f'Epoch: {epoch}, Loss: {loss}')
for epoch in range(1):
train(epoch)
Reformer 模型是在 Nikita Kitaev、Łukasz Kaiser、Anselm Levskaya 的论文 Reformer: The Efficient Transformer 中提出的。
该论文包含一种分解巨大矩阵的方法,该矩阵是处理非常长的序列的结果!此因式分解依赖于 2 个假设
- 参数
config.axial_pos_embds_dim
设置为一个元组(d1,d2)
,其总和必须等于config.hidden_size
config.axial_pos_shape
设置为元组 (n1s,n2s)
其乘积必须等于 config.max_embedding_size
(更多关于这些 here!)
最后是你的问题 ;)
- 我几乎可以肯定你的会话因 ram 溢出而崩溃
- 您可以在模型实例化期间更改任何配置参数,例如
official documentation!
首先,你应该注意到 google/reformer-enwik8
不是一个经过适当训练的语言模型,你可能不会通过微调得到像样的结果。 enwik8 是一项压缩挑战,the reformer authors 使用此数据集正是为了这个目的:
To verify that the Reformer can indeed fit large models on a single
core and train fast on long sequences, we train up to 20-layer big
Reformers on enwik8 and imagenet64...
这也是他们没有训练分词分词器和字符级别操作的原因。
您还应注意,LMHead
通常用于预测序列的下一个标记 (CLM)。您可能想使用标记分类头(即使用编码器 ReformerModel 并在顶部添加一个线性层,其中 9 类 + 可能是一个 dropout 层)。
无论如何,如果您还想尝试一下,可以执行以下操作来减少 google/reformer-enwik8
改革者的内存占用:
- 减少训练期间的哈希数:
from transformers import ReformerConfig, ReformerModel
conf = ReformerConfig.from_pretrained('google/reformer-enwik8')
conf.num_hashes = 2 # or maybe even to 1
model = transformers.ReformerModel.from_pretrained("google/reformer-enwik8", config =conf)
微调模型后,可以再次增加哈希数以提高性能(比较 Table 改革者论文的 2)。
- 替换轴向位置嵌入:
from transformers import ReformerConfig, ReformerModel
conf = ReformerConfig.from_pretrained('google/reformer-enwik8')
conf.axial_pos_embds = False
model = transformers.ReformerModel.from_pretrained("google/reformer-enwik8", config =conf)
这将用像 Bert 的可学习位置嵌入替换学习的轴向位置嵌入,并且不需要 65536 的完整序列长度。它们未经训练并随机初始化(即考虑更长的训练)。
我正在尝试为 NER 微调 ReformerModelWithLMHead (google/reformer-enwik8)。我使用了与编码方法相同的填充序列长度 (max_length = max([len(string) for string in list_of_strings])) 以及 attention_masks。我得到了这个错误:
ValueError:如果进行训练,请确保 config.axial_pos_shape 因子:(128, 512) 乘以序列长度。得到 prod((128, 512)) != sequence_length: 2248。您可能需要考虑将序列长度填充到 65536 或更改 config.axial_pos_shape.
- 当我将序列长度更改为 65536 时,我的 colab 会话因获取所有 65536 长度的输入而崩溃。
- 按照第二个选项(改config.axial_pos_shape),我改不了
我想知道,有没有机会在微调模型的同时改变config.axial_pos_shape?或者我在为 reformer-enwik8 编码输入字符串时遗漏了什么?
谢谢!
问题更新:我试过以下方法:
- 通过在模型实例化时给出参数:
model = transformers.ReformerModelWithLMHead.from_pretrained("google/reformer-enwik8", num_labels=9, max_position_embeddings=1024, axial_pos_shape=[16,64], axial_pos_embds_dim=[32,96],hidden_size=128)
它给我以下错误:
RuntimeError: Error(s) in loading state_dict for ReformerModelWithLMHead: size mismatch for reformer.embeddings.word_embeddings.weight: copying a param with shape torch.Size([258, 1024]) from checkpoint, the shape in current model is torch.Size([258, 128]). size mismatch for reformer.embeddings.position_embeddings.weights.0: copying a param with shape torch.Size([128, 1, 256]) from checkpoint, the shape in current model is torch.Size([16, 1, 32]).
这是一个很长的错误。
- 然后我尝试了这个代码来更新配置:
model1 = transformers.ReformerModelWithLMHead.from_pretrained('google/reformer-enwik8', num_labels = 9)
重塑轴向位置嵌入层以匹配所需的最大序列长度
model1.reformer.embeddings.position_embeddings.weights[1] = torch.nn.Parameter(model1.reformer.embeddings.position_embeddings.weights[1][0][:128])
更新配置文件以匹配自定义最大序列长度
model1.config.axial_pos_shape = 16,128
model1.config.max_position_embeddings = 16*128 #2048
model1.config.axial_pos_embds_dim= 32,96
model1.config.hidden_size = 128
output_model_path = "model"
model1.save_pretrained(output_model_path)
通过这个实现,我得到了这个错误:
RuntimeError: The expanded size of the tensor (512) must match the existing size (128) at non-singleton dimension 2. Target sizes: [1, 128, 512, 768]. Tensor sizes: [128, 768]
因为更新后的 size/shape 与预训练模型的原始配置参数不匹配。原参数为: axial_pos_shape = 128512 max_position_embeddings = 128*512 #65536 axial_pos_embds_dim= 256768 hidden_size = 1024
这是我更改配置参数的正确方法还是我必须做其他事情?
有没有微调 ReformerModelWithLMHead('google/reformer-enwik8') 模型的例子。
我的主要代码实现如下:
class REFORMER(torch.nn.Module):
def __init__(self):
super(REFORMER, self).__init__()
self.l1 = transformers.ReformerModelWithLMHead.from_pretrained("google/reformer-enwik8", num_labels=9)
def forward(self, input_ids, attention_masks, labels):
output_1= self.l1(input_ids, attention_masks, labels = labels)
return output_1
model = REFORMER()
def train(epoch):
model.train()
for _, data in enumerate(training_loader,0):
ids = data['input_ids'][0] # input_ids from encode method of the model https://huggingface.co/google/reformer-enwik8#:~:text=import%20torch%0A%0A%23%20Encoding-,def%20encode,-(list_of_strings%2C%20pad_token_id%3D0
input_shape = ids.size()
targets = data['tags']
print("tags: ", targets, targets.size())
least_common_mult_chunk_length = 65536
padding_length = least_common_mult_chunk_length - input_shape[-1] % least_common_mult_chunk_length
#pad input
input_ids, inputs_embeds, attention_mask, position_ids, input_shape = _pad_to_mult_of_chunk_length(self=model.l1,
input_ids=ids,
inputs_embeds=None,
attention_mask=None,
position_ids=None,
input_shape=input_shape,
padding_length=padding_length,
padded_seq_length=None,
device=None,
)
outputs = model(input_ids, attention_mask, labels=targets) # sending inputs to the forward method
print(outputs)
loss = outputs.loss
logits = outputs.logits
if _%500==0:
print(f'Epoch: {epoch}, Loss: {loss}')
for epoch in range(1):
train(epoch)
Reformer 模型是在 Nikita Kitaev、Łukasz Kaiser、Anselm Levskaya 的论文 Reformer: The Efficient Transformer 中提出的。 该论文包含一种分解巨大矩阵的方法,该矩阵是处理非常长的序列的结果!此因式分解依赖于 2 个假设
- 参数
config.axial_pos_embds_dim
设置为一个元组(d1,d2)
,其总和必须等于config.hidden_size config.axial_pos_shape
设置为元组(n1s,n2s)
其乘积必须等于 config.max_embedding_size (更多关于这些 here!)
最后是你的问题 ;)
- 我几乎可以肯定你的会话因 ram 溢出而崩溃
- 您可以在模型实例化期间更改任何配置参数,例如 official documentation!
首先,你应该注意到 google/reformer-enwik8
不是一个经过适当训练的语言模型,你可能不会通过微调得到像样的结果。 enwik8 是一项压缩挑战,the reformer authors 使用此数据集正是为了这个目的:
To verify that the Reformer can indeed fit large models on a single core and train fast on long sequences, we train up to 20-layer big Reformers on enwik8 and imagenet64...
这也是他们没有训练分词分词器和字符级别操作的原因。
您还应注意,LMHead
通常用于预测序列的下一个标记 (CLM)。您可能想使用标记分类头(即使用编码器 ReformerModel 并在顶部添加一个线性层,其中 9 类 + 可能是一个 dropout 层)。
无论如何,如果您还想尝试一下,可以执行以下操作来减少 google/reformer-enwik8
改革者的内存占用:
- 减少训练期间的哈希数:
from transformers import ReformerConfig, ReformerModel
conf = ReformerConfig.from_pretrained('google/reformer-enwik8')
conf.num_hashes = 2 # or maybe even to 1
model = transformers.ReformerModel.from_pretrained("google/reformer-enwik8", config =conf)
微调模型后,可以再次增加哈希数以提高性能(比较 Table 改革者论文的 2)。
- 替换轴向位置嵌入:
from transformers import ReformerConfig, ReformerModel
conf = ReformerConfig.from_pretrained('google/reformer-enwik8')
conf.axial_pos_embds = False
model = transformers.ReformerModel.from_pretrained("google/reformer-enwik8", config =conf)
这将用像 Bert 的可学习位置嵌入替换学习的轴向位置嵌入,并且不需要 65536 的完整序列长度。它们未经训练并随机初始化(即考虑更长的训练)。