用BERT生成句子向量
一开始我用的是Linux虚拟机环境,后来发现内存不够,因此改为Windows10. 接下来是调用别人完成的一个接口。
tensorflow版本要大于等于1.10, numpy也要更新
1
2pip install bert-serving-server # server
pip install bert-serving-client # client, independent of `bert-serving-server`下载中文预训练模型,https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip, 直接解压,得到对应的文件夹。
得到上面文件夹的绝对路径,输入命令(我用相对路径出错了):
1
bert-serving-start -model_dir=绝对路径 -num_work=2
例如我的:1
bert-serving-start -model_dir=E:\PostGraduate\NLP\chinese_L-12_H-768_A-12\ -num_worker=1
完成后即开启了BERT服务,此时的命令窗口不可关闭,否则相当于关闭服务。
- python运行
1
2
3
4# 本地运行
from bert_serving.client import BertClient
bc = BertClient()
bc.encode(['开心的一天','今天真开心','开心!']) # 文档建议一次性将需要的句子作为列表输入,而不是用for循环,这样效率较高
结果:
用ERNIE生成句子向量
要用到PaddlePaddle,在Linux下似乎比较好,所以又转向了虚拟机…
- 下载预训练模型: https://ernie.bj.bcebos.com/ERNIE_stable.tgz 解压得到params文件夹
- Linux安装PaddlePaddle: http://www.paddlepaddle.org/ 老师可以在此网站查看自己的电脑合适的安装方式,我是用pip装的。
- 下载需要的ERNIE源文件,需要的话我可以发给老师
完成脚本文件
注意:因为我没有cuda,所以use_cuda那里改为了false;${MODEL_PATH}我填的是模型的绝对路径;${TASK_DATA_PATH}我填的是数据的绝对路径,注意数据有特定的格式,而且必须是tsv文件。1
2
3
4
5
6
7
8
9
10
11
12export FLAGS_sync_nccl_allreduce=1
export CUDA_VISIBLE_DEVICES=7
python -u ernir_encoder.py \
--use_cuda true \
--batch_size 32 \
--output_dir "./test" \
--init_pretraining_params ${MODEL_PATH}/params \
--data_set ${TASK_DATA_PATH}/lcqmc/dev.tsv \
--vocab_path config/vocab.txt \
--max_seq_len 128 \
--ernie_config_path config/ernie_config.json建立文件夹test,执行上述bash文件,可以分别得到cls_emb.npy(存储句子embeddings)和top_layer_emb.npy(存储句子的token embeddings)。
- 读取npy文件内容:

相似度比较
测试的句子:
- 我可以给您介绍一下免费拿手机的活动吗? 您可以给我介绍一下免费拿手机的活动吗?
- 我可以给您介绍一下不要钱就能拿手机的活动吗? 我来给您介绍一下免费就能得到好手机的活动
- 我该叫你妈妈什么? 我应该怎么称呼你妈妈?
- 爸爸的儿子我应该叫什么? 儿子的爸爸我该怎么叫?
三种方法的比对结果:
| seq1 | seq2 | LASER | BERT | ERNIE |
|---|---|---|---|---|
| 我可以给您介绍一下免费拿手机的活动吗? | 您可以给我介绍一下免费拿手机的活动吗? | 0.9675291 | 0.9962016 | 0.9903929 |
| 我可以给您介绍一下不要钱就能拿手机的活动吗? | 我来给您介绍一下免费就能得到好手机的活动。 | 0.810219 | 0.94765455 | 0.8651513 |
| 我该叫你妈妈什么? | 我应该怎么称呼你妈妈? | 0.9234945 | 0.9519638 | 0.9113665 |
| 爸爸的儿子我应该叫什么? | 儿子的爸爸我该怎么叫? | 0.9514671 | 0.9730811 | 0.9775459 |
给我的感觉是,三种模型都是基于词来进行句子向量的实现的,而没有考虑到句子的含义,比如最后那一句,爸爸的儿子,儿子的爸爸,这两句三个模型的相似度都很高。感觉不太妥当。