参考代码来源于:https://github.com/brightmart/albert_zh
新的一年刚开始,就碰上了一个基本都是NLP的项目;
一直想找机会学NLP,现在正好遇上了。就是项目是个硬骨头,有点难啃,好在组内有几个NLP大神带着。所以也稍微记录一下我nlp开始学习的历程。(可能有些地方理解错误、说错的,也请各位大佬帮忙指正。)
刚开始遇到的时候想从基础上学起,比如TF-IDF、word2vec这些。但是由于知识量从头来的话,太多太杂了。然后大佬也是说直接上Bert就行。所以我就只是稍微学了下NLP的一些基础知识和任务,就直接去看Bert的源码。
我本身是喜欢搞工程的人,所以一开始学习的时候不会去学细的理论知识,而且直接从工程层面上去学习。可能需要到后期优化的时候,再从项目/数据/模型等方面去学习细节的理论知识。所以我博客里一般不会讲太多理论的东西,一般都是大白话。但是偶尔会直接引用大佬们讲解理论的链接(我也是这样去学理论方面的知识),可以直接跳转去看。
另外分享一个,我在学习的时候找到的网站。里面有关于NLP的很多模型/代码,数据集,API等信息。
https://huggingface.co/
这里有一篇比较简洁的说明NLP是什么,做什么,怎么做的博文。
https://easyai.tech/ai-definition/nlp/
跟CV一样,图像处理有两大任务:目标检测/分类和图像生成。NLP也有两大任务:NLU和NLG,分别是自然语言理解和自然语言生成。
细分的话,NLU有三大类任务,第一种是序列标注,常见的分词,词性标注,命名实体识别都属于这一类问题。第二种是分类任务,常见的文本分类,文本情感分析等都属于这一类。第三种是句子关系判断,比如文本相似匹配、机器阅读理解、自然语言推理等任务。
可以把NLU看作就是分类任务,序列标注其实就是对词或者段的分类,一个文本可能会有多个词分类;第二种是对整个文本进行分类,比如情感分析,对整段话分类消极还是积极情感;句子关系判断是对两段文本之间的关系做分类,比如两段文本相似与不相似,就是一个二分类问题。
这篇博文主要也是写NLU,因为我的项目基本都是一些语言理解方面的任务。
自然语言生成这个实际上我以前玩过,一个叫聊天机器人的项目。用到的模型是GPT。下面是两个机器聊天的项目开源代码,挺好玩的。有时间我也想要不要写篇博文关于聊天机器人的。
https://github.com/thu-coai/CDial-GPT
https://github.com/yangjianxin1/GPT2-chitchat
有关对话生成、机器翻译、文本生成(论文摘要生成/歌词生成/诗词生成)都属于这类。
因为我做的是中文,所以就是最上面这个github的仓库。这里也有英文版的官方仓库。https://github.com/google-research/albert
下面这些来源于https://github.com/CLUEbenchmark/CLUE;也是项目仓库支持的一种数据集CLUE,摘抄了一部分下来。具体可以直接进去看。
我自己的项目主要需要解决文本相似匹配和关键词识别这两个任务,所以本文我就只讲跑LCQMC和CSL这两个数据集的过程。
首先是下载tensorflow,项目需要1.0版本的tensorflow,所以如果同时有多个不同版本tensorflow项目的,建议用虚拟环境弄个专门的环境。tensorflow应该是要1.11版本以上的,我自己环境是tensorflow==1.14.0。
# Run pip install --upgrade pip if tensorflow 1.15 cannot be found
tensorflow==1.15.2 # CPU Version of TensorFlow
tensorflow_hub==0.7
# tensorflow-gpu==1.15 # GPU version of TensorFlow
需要其他环境的话,后面运行报错了再去pip就行了。
数据集可以直接按上面项目 支持的NLP任务 这里写的链接去下载对应任务的数据集就行。
模型的话,在项目仓库内可以直接下载,看你需要下载哪个模型。我自己下载的是albert_tiny_zh,因为项目需要反复调用计算,所以尽量选择小模型。后面精度不够再做优化调整。
数据集和模型下载完成后,会得到对应的.ckpt模型,和训练集、测试集、验证集。
需要注意model.ckpt.data-00000-of-00001、model.ckpt.index和model.ckpt.meta在同一级目录下,然后配置参数的时候"init_checkpoint", 'albert_model/albert_model.ckpt',
只需要给前面一部分即可。
配置数据集路径参数:"data_dir", 'data',
这个data指目录下有train/test/dev三个数据集的目录。
输出路径参数:"output_dir", 'albert_lcqmc_chevkpoints',
其他的参数按具体的任务需求做调整。
做LCQMC这个任务的时候,运行run_classifier.py
文件,按照上面说明修改里面的参数信息、对应的模型配置文件路径等,就可以直接跑通。
做CLUE这些任务的时候,运行run_classifier_clue.py
文件,同样按照上面说明修改参数。
对应的配置"task_name", 'lcqmc_pair'
不同任务如下。
run_classifier.py
文件 task_name
对应参数
“sentence_pair”: SentencePairClassificationProcessor,
“lcqmc_pair”:LCQMCPairClassificationProcessor,
“lcqmc”: LCQMCPairClassificationProcessor
run_classifier_clue.py
文件 task_name
对应参数
“xnli”: XnliProcessor,
“tnews”: TnewsProcessor,
“afqmc”: AFQMCProcessor,
“iflytek”: iFLYTEKDataProcessor,
“copa”: COPAProcessor,
“cmnli”: CMNLIProcessor,
“wsc”: WSCProcessor,
“csl”: CslProcessor,
“copa”: COPAProcessor,
下面的代码是我跑通LCQMC这个任务的时候的参数配置,CLUE同样。
## Required parameters
flags.DEFINE_string(
"data_dir", 'data',
"The input data dir. Should contain the .tsv files (or other data files) "
"for the task.")
flags.DEFINE_string(
"bert_config_file", 'albert_model/albert_config_tiny.json',
"The config json file corresponding to the pre-trained BERT model. "
"This specifies the model architecture.")
flags.DEFINE_string("task_name", 'lcqmc_pair', "The name of the task to train.")
flags.DEFINE_string("vocab_file", 'albert_model/vocab.txt',
"The vocabulary file that the BERT model was trained on.")
flags.DEFINE_string(
"output_dir", 'albert_lcqmc_chevkpoints',
"The output directory where the model checkpoints will be written.")
## Other parameters
flags.DEFINE_string(
"init_checkpoint", 'albert_model/albert_model.ckpt',
"Initial checkpoint (usually from a pre-trained BERT model).")
flags.DEFINE_bool(
"do_lower_case", True,
"Whether to lower case the input text. Should be True for uncased "
"models and False for cased models.")
flags.DEFINE_integer(
"max_seq_length", 128,
"The maximum total input sequence length after WordPiece tokenization. "
"Sequences longer than this will be truncated, and sequences shorter "
"than this will be padded.")
flags.DEFINE_bool("do_train", True, "Whether to run training.")
flags.DEFINE_bool("do_eval", True, "Whether to run eval on the dev set.")
flags.DEFINE_bool(
"do_predict", True,
"Whether to run the model in inference mode on the test set.")
flags.DEFINE_integer("train_batch_size", 32, "Total batch size for training.")
flags.DEFINE_integer("eval_batch_size", 8, "Total batch size for eval.")
flags.DEFINE_integer("predict_batch_size", 8, "Total batch size for predict.")
flags.DEFINE_float("learning_rate", 5e-5, "The initial learning rate for Adam.")
flags.DEFINE_float("num_train_epochs", 1.0,
"Total number of training epochs to perform.")
flags.DEFINE_float(
"warmup_proportion", 0.1,
"Proportion of training to perform linear learning rate warmup for. "
"E.g., 0.1 = 10% of training.")
flags.DEFINE_integer("save_checkpoints_steps", 1000,
"How often to save the model checkpoint.")
flags.DEFINE_integer("iterations_per_loop", 1000,
"How many steps to make in each estimator call.")
项目仓库提供一个相似度计算的推理代码。
首先要修改args.py
配置文件。
这里的模型要训练过的,我试了一下直接用项目内训练的模型运行并不能正常运行。会报错。
#模型目录,存放ckpt文件
model_dir = os.path.join(file_path, 'albert_lcqmc_checkpoints/')
#config文件,存放模型的json文件
config_name = os.path.join(file_path, 'albert_config/albert_config_tiny.json')
#ckpt文件名称
ckpt_name = os.path.join(model_dir, 'model.ckpt')
#输出文件目录,训练时的模型输出目录
output_dir = os.path.join(file_path, 'albert_lcqmc_checkpoints/')
#vocab文件目录
vocab_file = os.path.join(file_path, 'albert_config/vocab.txt')
#数据目录,训练使用的数据集存放目录
data_dir = os.path.join(file_path, 'data/')
其次,修改similarity.py
内的main
:
if __name__ == '__main__':
sim = BertSim()
sim.start_model()
sim.predict_sentences([("小红在喝牛奶",
"小明在喝牛奶")])
输出是个二分类softmax,转换成one-hot编码,就是label:0,代表不匹配。
至于CLUE那边任务的推理,可以参照这份代码自己写一份。我也还没写,目前还在训练阶段,等后面写完再补充。
这个代码很人性化的是提供了许多模型转换的脚本。
包括TFLite模型格式转换和性能测试。
以及转换成TFLite模型后,对于如何在移动端使用该模型。
因为我这边是在服务器端部署,所以就不太需要这些。有需要的可以直接去里面看下。