参考代码来源于:https://github.com/brightmart/albert_zh

记录一下nlp开始学习的历程

新的一年刚开始,就碰上了一个基本都是NLP的项目;
一直想找机会学NLP,现在正好遇上了。就是项目是个硬骨头,有点难啃,好在组内有几个NLP大神带着。所以也稍微记录一下我nlp开始学习的历程。(可能有些地方理解错误、说错的,也请各位大佬帮忙指正。😀)

刚开始遇到的时候想从基础上学起,比如TF-IDF、word2vec这些。但是由于知识量从头来的话,太多太杂了。然后大佬也是说直接上Bert就行。所以我就只是稍微学了下NLP的一些基础知识和任务,就直接去看Bert的源码。

我本身是喜欢搞工程的人,所以一开始学习的时候不会去学细的理论知识,而且直接从工程层面上去学习。可能需要到后期优化的时候,再从项目/数据/模型等方面去学习细节的理论知识。所以我博客里一般不会讲太多理论的东西,一般都是大白话。但是偶尔会直接引用大佬们讲解理论的链接(我也是这样去学理论方面的知识),可以直接跳转去看。


另外分享一个,我在学习的时候找到的网站。里面有关于NLP的很多模型/代码,数据集,API等信息。
https://huggingface.co/

1. 初识NLP

这里有一篇比较简洁的说明NLP是什么,做什么,怎么做的博文。
https://easyai.tech/ai-definition/nlp/

跟CV一样,图像处理有两大任务:目标检测/分类和图像生成。NLP也有两大任务:NLU和NLG,分别是自然语言理解和自然语言生成。

(1)NLU

细分的话,NLU有三大类任务,第一种是序列标注,常见的分词,词性标注,命名实体识别都属于这一类问题。第二种是分类任务,常见的文本分类,文本情感分析等都属于这一类。第三种是句子关系判断,比如文本相似匹配、机器阅读理解、自然语言推理等任务。

可以把NLU看作就是分类任务,序列标注其实就是对词或者段的分类,一个文本可能会有多个词分类;第二种是对整个文本进行分类,比如情感分析,对整段话分类消极还是积极情感;句子关系判断是对两段文本之间的关系做分类,比如两段文本相似与不相似,就是一个二分类问题。

这篇博文主要也是写NLU,因为我的项目基本都是一些语言理解方面的任务。

(2)NLG

自然语言生成这个实际上我以前玩过,一个叫聊天机器人的项目。用到的模型是GPT。下面是两个机器聊天的项目开源代码,挺好玩的。有时间我也想要不要写篇博文关于聊天机器人的。
https://github.com/thu-coai/CDial-GPT
https://github.com/yangjianxin1/GPT2-chitchat

有关对话生成、机器翻译、文本生成(论文摘要生成/歌词生成/诗词生成)都属于这类。

2. 自然语言理解 AlBert模型

因为我做的是中文,所以就是最上面这个github的仓库。这里也有英文版的官方仓库。https://github.com/google-research/albert

(1)项目支持的NLP任务
  • 问题匹配语任务:LCQMC(Sentence Pair Matching)
    这个也就是一个文本相似计算的任务,LCQMC任务是在口语化描述的数据集上做文本的相似性预测。仓库里也提供了下载路径LCQMC

下面这些来源于https://github.com/CLUEbenchmark/CLUE;也是项目仓库支持的一种数据集CLUE,摘抄了一部分下来。具体可以直接进去看。

  • AFQMC 蚂蚁金融语义相似度 Ant Financial Question Matching Corpus
  • TNEWS’ 今日头条中文新闻(短文本)分类 Short Text Classificaiton for News
    该数据集来自今日头条的新闻版块,共提取了15个类别的新闻,包括旅游,教育,金融,军事等。
  • IFLYTEK’ 长文本分类 Long Text classification
    该数据集共有1.7万多条关于app应用描述的长文本标注数据,包含和日常生活相关的各类应用主题,共119个类别:“打车”:0,“地图导航”:1,“免费WIFI”:2,“租车”:3,….,“女性”:115,“经营”:116,“收款”:117,“其他”:118(分别用0-118表示)。
  • OCNLI 中文原版自然语言推理 Original Chinese Natural Language Inference
    OCNLI,即原生中文自然语言推理数据集,是第一个非翻译的、使用原生汉语的大型中文自然语言推理数据集。
  • CSL 论文关键词识别 Keyword Recognition
    中文科技文献数据集(CSL)取自中文论文摘要及其关键词,论文选自部分中文社会科学和自然科学核心期刊。 使用tf-idf生成伪造关键词与论文真实关键词混合,构造摘要-关键词对,任务目标是根据摘要判断关键词是否全部为真实关键词。
  • CMRC2018 简体中文阅读理解任务 Reading Comprehension for Simplified Chinese

我自己的项目主要需要解决文本相似匹配和关键词识别这两个任务,所以本文我就只讲跑LCQMCCSL这两个数据集的过程。

(2)环境搭建

首先是下载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就行了。

(3)下载数据集以及模型

数据集可以直接按上面项目 支持的NLP任务 这里写的链接去下载对应任务的数据集就行。
模型的话,在项目仓库内可以直接下载,看你需要下载哪个模型。我自己下载的是albert_tiny_zh,因为项目需要反复调用计算,所以尽量选择小模型。后面精度不够再做优化调整。

(4)训练模型

数据集和模型下载完成后,会得到对应的.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.")
(5)模型推理

项目仓库提供一个相似度计算的推理代码。
首先要修改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那边任务的推理,可以参照这份代码自己写一份。我也还没写,目前还在训练阶段,等后面写完再补充。

(6)部署/测试

这个代码很人性化的是提供了许多模型转换的脚本。
包括TFLite模型格式转换和性能测试。
以及转换成TFLite模型后,对于如何在移动端使用该模型。
因为我这边是在服务器端部署,所以就不太需要这些。有需要的可以直接去里面看下。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐