我想要做的事情是:利用PaddleNLP在AI Studio上训练好一个基于BERT的实体识别模型,然后将模型导出来放在另一个环境下断网运行。
训练的过程没有什么问题,使用了PaddleNLP项目中的示例代码,在AI Studio上可以很快完成。
训练完成后,我将bert-base-multilingual-uncased
对应的基础模型以及训练结束后生成的参数下载到本地。在默认情况下,bert-base-multilingual-uncased
对应的基础模型会保存在~/.paddlenlp/models
路径下,配套的有两个文件,分别是bert-base-multilingual-uncased.pdparams
和bert-base-multilingual-uncased-vacab.txt
;训练生成的参数文件会保存在训练脚本所在目录下的tmp/msra_ner
目录下,名称为model_4218.pdparams
,后面的数字表示一共训练的步数。
在下载的时候遇到了一个问题,由于基础模型默认保存的路径在一个隐藏的目录下,因此,只能将该隐藏目录重命名后才能在CodeLab左侧的文件浏览器中展示并通过右键菜单下载。
成功导出后,我想要通过预训练模型的from_pretrained()
方法来加载上述导出模型。在这个场景下,用到from_pretrained()
的一共有两处方法,下面我分开来说明:
1、BertTokenizer.from_pretrained()
这里是加载分词器,从这个from_pretrained()
方法的注释中可以看到,第一个形参可以传入一个指向分词器需要数据的本地目录。从代码逻辑可以看出,这个目录下需要有两个文件,一是vocab.txt,一个是tokenizer_config.json,且文件名称必须是这样。追溯源码可以发现,词表名称必须为vocab.txt的约束在paddlenlp/transformers/bert/tokenizer.py/BertTokenizer
类中;配置文件名称必须为tokenizer_config.json的约束在paddlenlp/transformers/tokenizer_utils.py/PretrainedTokenizer
中。
项目示例给出的predict.py
之所以没有这个问题,是因为该示例并没有从本地目录加载模型,而是直接输入的模型名称,只不过在由于在训练前已经下载了基础模型以及词表,因此,在预测时使用的是已下载好的文件。
2、BertForTokenClassification.from_pretrained()
这里加载的基础模型。同样,可以指定一个本地目录进行加载。该目录下也需要有两个名称固定的文件,一个是model_config.json,一个是model_state.pdparams。通过追溯源码,同样可以找到名称被规定成这样的限定所在。
类似地,项目示例给出的predict.py
也是直接加载的模型名称,在下载前检验到已经有下载好的模型从而没有重复下载。
综合上述两点,我目前认为问题主要有两个:一是示例预测代码由于没有使用离线加载模型的方式,因此tokenizer_config.json和model_config.json的信息实际上是从代码中获取的,而且训练是保存的文件中并没有这两个文件,需要阅读源码推理出它们的格式。二是在训练时下载的基础模型以及词表的名称并不能直接满足离线使用时的需要,仍需要阅读源码推理出它们的名称。
以上两点,或许应该有所改进。例如可以改成与加载checkpoint参数相同的方式,即直接定位到文件本身,而非文件所在路径。