使用qa_match开源工具完成58同城AI算法大赛
背景
以人工智能技术为核心的智能客服近年来被广泛应用,它不仅能给用户提供高效和个性化的客户服务体验,还可以为企业节省大量客服人力成本。智能客服的本质是充分理解用户的意图,在知识库中精确查找与之相匹配的内容,自动回答用户的问题。文本匹配、分类是智能客服里最核心的技术,同时也是自然语言理解领域中的核心问题之一。
58同城举办了首届AI算法大赛,具体参见文章《58同城AI算法大赛最新动态,欢迎关注》,当前已经有159支团队报名,欢迎大家参赛。
本文将介绍如何使用我们的开源工具qa_match中的SPTM (Simple Pre-trained Model,轻量级预训练模型) 来开展比赛,qa_match是一款基于深度学习的问答匹配工具,支持一层和两层结构知识库问答。具体参见文章:
《开源|qa_match:一款基于深度学习的层级问答匹配工具》
《开源|qa_match更新啦——支持轻量级预训练、提高问答通用性》
模型和数据准备
1. 下载SPTM源码
确保所用系统装有tensorflow(tf版本在1.8以上2.0以下)和python3,我们是在linux系统gpu环境下进行的实践,具体操作如下:
1) 下载SPTM源码
git clone https://github.com/wuba/qa_match.git
2) 进入qa_match文件夹
cd qa_match
2. 下载竞赛数据
从大赛首页下载竞赛数据并解压,可以将下载的数据解压到qa_match的data_demo文件夹下,解压后生成data文件夹,具体文件结构如下:
SPTM模型训练
1. 预训练语言模型
大家在用SPTM参赛时可以选择用竞赛提供的预训练数据预训练SPTM模型,预训练语言模型的目的是为了更好的服务下游任务,让下游任务得到更好的泛化能力。具体操作如下:
1) 进入sptm文件夹
cd sptm
2) 创建保存预训练模型的文件夹
mkdir -p model/pretrain
3) 预训练SPTM模型
nohup python run_pretraining.py --train_file="../data_demo/data/pre_train_data" \
--vocab_file="../data_demo/data/vocab"\
--model_save_dir="./model/pretrain"\
--batch_size=512 \
--print_step=100 \
--weight_decay=0 \
--embedding_dim=1000 \
--lstm_dim=500 \
--layer_num=1 \
--train_step=100000 \
--warmup_step=10000 \
--learning_rate=5e-5 \
--dropout_rate=0.1 \
--max_predictions_per_seq=10 \
--clip_norm=1.0 \
--max_seq_len=100 \
--use_queue=0 > pretrain.log2>&1&
具体参数含义如下:
参数 | 说明 |
vocab | 词典文件(竞赛提供的vocab文件) |
train_file/valid_data | 训练/验证集 |
lstm_dim | lstm的门控单元数 |
embedding_dim | 词嵌入维度 |
dropout_rate | 节点被dropout的比例 |
layer_num | LSTM的层数 |
weight_decay | adam的衰减系数 |
max_predictions_per_seq | 每个句子中,最多会mask的词数 |
clip_norm | 梯度裁剪阈值 |
use_queue | 是否使用队列生成预训练数据 |
模型成功运行后信息显示如下:
2. 训练分类模型
本次竞赛题目要求利用用户输入的文本,从知识库中找出与之语义最相近的问题。在这里我们利用SPTM源码给出的训练分类模型代码训练文本分类模型,将用户输入文本分类到某个标准问题。
基于SPTM的文本分类模型训练时需要验证集,由此需要先将train_data切分训练集和验证集,然后再进行模型训练。注意:这里参赛选手可以根据自己的实际需要灵活划分训练集和验证集,我们下面的操作仅供参考。
1) 随机打乱train_data
shuf ../data_demo/data/train_data| tr -d "\r" > ../data_demo/data/train_data_shuf
2) 取出头部1000行数据作为验证集
head -n1000../data_demo/data/train_data_shuf > ../data_demo/data/valid_data_final
3) 将余下的数据作为训练集
tail -n+1001../data_demo/data/train_data_shuf > ../data_demo/data/train_data_final
4) 训练文本分类模型
python run_classifier.py --output_id2label_file="model/id2label.has_init" \
--vocab_file="../data_demo/data/vocab"\
--train_file="../data_demo/data/train_data_final"\
--dev_file="../data_demo/data/valid_data_final"\
--model_save_dir="model/finetune"\
--lstm_dim=500 \
--embedding_dim=1000 \
--opt_type=adam \
--batch_size=256 \
--epoch=20 \
--learning_rate=1e-4 \
--seed=1 \
--max_len=100 \
--print_step=10 \
--dropout_rate=0.1 \
--layer_num=1 \
--init_checkpoint="model/pretrain/lm_pretrain.ckpt-500000"
具体参数含义如下表所示:
参数 | 说明 |
output_id2label_file | (id,标签)映射文件,最后预测的时候使用 |
opt_type | 优化器类型,有sgd/adagrad/adam几种可选 |
seed | 随机种子的值,使用相同的随机种子保证微调模型结果一致 |
init_checkpoint | 预训练模型保存的checkpoint,即前面预训练的结果文件 |
注意:这里如果不想用预训练模型,不需要填写”init_checkpoint”参数。
本文的实验我们不使用预训练语言模型,在单卡k40 gpu机器上使用比赛数据训练模型,耗时大约2小时。模型成功运行后信息显示如下:
SPTM模型预测
1. 用训练好的分类模型进行打分
我们用SPTM训练好文本分类模型后,就可以对竞赛提供评测集test_data进行打分了,具体操作如下:
python run_prediction.py --input_file="../data_demo/data/test_data" \
--vocab_file="../data_demo/data/vocab"\
--id2label_file="model/id2label.has_init"\
--model_dir="model/finetune"> "../data_demo/data/result_test_raw"
具体参数含义同上,打分结果如下图所示,其中每行行首的”__label__xx”中的xx对应的数字为预测打分最高的标准问题id,即竞赛给出的sample.csv文件中第二列预测出的标准问题id。
2. 生成竞赛最终预测文件并上传
由于用SPTM源码生成的打分文件格式不符合竞赛要求上传的文件格式,我们需要对打分文件进行处理生成符合竞赛要求的预测文件。具体操作如下:
1) 从竞赛提供的验证集test_data取出扩展问题id
awk '{print $2}' test_data >ext_id
2) 从SPTM打分文件result_test_raw中取出预测的标准问题id
awk -F',' '{print $1}'result_test_raw | awk -F'|' '{print $1}'| awk -F'__' '{print $3}' > std_id
3) 往最终要上传的预测文件添加”ext_id,std_id”首行
echo ext_id,std_id > 58cop.csv
4) 往最终要上传的预测文件添加扩展问题id,预测的标准问题id
paste -d","ext_id std_id >> 58cop.csv
3. 上传竞赛预测文件
上传完预测文件后,竞赛得分0.6424,欢迎大家使用qa_match,可以在此基础上开展各种调优。
作者简介王勇,58同城AI Lab算法架构师,硕士毕业于北京理工大学,曾就职于优酷,从事视频推荐算法研发相关工作,目前就职58从事NLP相关算法研发。
AI Lab 招聘信息欢迎关注部门微信公众号:58AILab
欢迎在欣秀(https://app.ic3i.com)平台上加入"58同城AILab技术沙龙"圈子,一起交流技术,可以扫描以下二维码加入该圈子。