查看原文
其他

使用qa_match开源工具完成58同城AI算法大赛

王勇 58技术 2022-03-15

导读

以人工智能技术为核心的智能客服近年来被广泛应用,它不仅能给用户提供高效和个性化的客户服务体验,还可以为企业节省大量客服人力成本。智能客服的本质是充分理解用户的意图,在知识库中精确查找与之相匹配的内容,自动回答用户的问题。文本匹配、分类是智能客服里最核心的技术,同时也是自然语言理解领域中的核心问题之一。


背景

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_dimlstm的门控单元数
embedding_dim词嵌入维度
dropout_rate节点被dropout的比例
layer_numLSTM的层数
weight_decayadam的衰减系数
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相关算法研发。


推荐阅读:

58同城AI算法大赛开放报名,欢迎参赛

58同城AI算法大赛最新动态,欢迎关注
人物 | 詹坤林:语音语义技术打开58同城的另一扇门

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存