加载本地保存的量化BERT模型时报'LinearPackedParams'无'_modules'属性错误
报错原因
- 你直接使用
torch.save()保存整个量化模型对象的方式不符合PyTorch量化模型的序列化规范:PyTorch动态量化会把原始的nn.Linear层替换为带LinearPackedParams的量化线性层,该结构不属于常规nn.Module子类,本身没有_modules属性,全模型序列化时会丢失层结构的关联信息,反序列化后无法正常调用模型方法。 - SentenceTransformer对Transformer模型做了上层封装,全模型直接序列化会额外丢失封装层和量化层的适配关系,进一步导致加载后的模型结构不完整。
解决方案
推荐使用保存/加载state_dict的方式,这也是PyTorch官方推荐的模型序列化方案,操作步骤如下:
第一步:保存量化模型(仅保存权重参数)
# 前面量化逻辑和你原来的一致 model = SentenceTransformer('bert-base-nli-mean-tokens') quantized_model = torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtype=torch.qint8) # 仅保存state_dict,不要保存整个模型对象 torch.save(quantized_model.state_dict(), "/PATH/TO/DESTINATION/Base_bert_quant.pt")
第二步:加载量化模型
先初始化原模型、执行完全相同的量化流程生成结构匹配的空量化模型,再加载已保存的量化参数即可:
# 先初始化原始模型 raw_model = SentenceTransformer('bert-base-nli-mean-tokens') # 执行和保存时完全一致的动态量化操作,得到结构匹配的空量化模型 quantized_model = torch.quantization.quantize_dynamic( raw_model, {torch.nn.Linear}, dtype=torch.qint8) # 加载已保存的量化参数 quantized_model.load_state_dict(torch.load("/PATH/TO/DESTINATION/Base_bert_quant.pt")) # 此时可以正常调用 quantized_model.encode(sentences)
补充注意事项
- 量化和加载所用的PyTorch版本必须完全一致,不同版本的量化层实现存在差异,也会导致加载失败。
- 如果需要用于部署场景,也可以将量化后的模型转为TorchScript格式后保存,加载后不需要重建结构即可直接调用,但是需要注意SentenceTransformer的上层方法是否兼容TorchScript,出现序列化失败时优先使用state_dict方案:
# 保存TorchScript格式 scripted_model = torch.jit.script(quantized_model) torch.jit.save(scripted_model, "/PATH/TO/DESTINATION/Base_bert_quant_scripted.pt") # 加载 loaded_model = torch.jit.load("/PATH/TO/DESTINATION/Base_bert_quant_scripted.pt") loaded_model.encode(sentences)
内容的提问来源于stack exchange,提问作者user3190883
相关产品推荐
相关产品推荐

