Seq-embedding

用BERT生成句子向量

一开始我用的是Linux虚拟机环境,后来发现内存不够,因此改为Windows10. 接下来是调用别人完成的一个接口。

  1. tensorflow版本要大于等于1.10, numpy也要更新

  2. 1
    2
    pip install bert-serving-server  # server
    pip install bert-serving-client # client, independent of `bert-serving-server`
  3. 下载中文预训练模型,https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip, 直接解压,得到对应的文件夹。

  4. 得到上面文件夹的绝对路径,输入命令(我用相对路径出错了):

    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服务,此时的命令窗口不可关闭,否则相当于关闭服务。

  1. python运行
    1
    2
    3
    4
    # 本地运行
    from bert_serving.client import BertClient
    bc = BertClient()
    bc.encode(['开心的一天','今天真开心','开心!']) # 文档建议一次性将需要的句子作为列表输入,而不是用for循环,这样效率较高

结果:
image.png

用ERNIE生成句子向量

要用到PaddlePaddle,在Linux下似乎比较好,所以又转向了虚拟机…

  1. 下载预训练模型: https://ernie.bj.bcebos.com/ERNIE_stable.tgz 解压得到params文件夹
  2. Linux安装PaddlePaddle: http://www.paddlepaddle.org/ 老师可以在此网站查看自己的电脑合适的安装方式,我是用pip装的。
  3. 下载需要的ERNIE源文件,需要的话我可以发给老师
  4. 完成脚本文件
    注意:因为我没有cuda,所以use_cuda那里改为了false;${MODEL_PATH}我填的是模型的绝对路径;${TASK_DATA_PATH}我填的是数据的绝对路径,注意数据有特定的格式,而且必须是tsv文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    export 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
  5. 建立文件夹test,执行上述bash文件,可以分别得到cls_emb.npy(存储句子embeddings)和top_layer_emb.npy(存储句子的token embeddings)。

  6. 读取npy文件内容:
    image.png

相似度比较

测试的句子:

- 我可以给您介绍一下免费拿手机的活动吗? 您可以给我介绍一下免费拿手机的活动吗?
- 我可以给您介绍一下不要钱就能拿手机的活动吗? 我来给您介绍一下免费就能得到好手机的活动
- 我该叫你妈妈什么? 我应该怎么称呼你妈妈?
- 爸爸的儿子我应该叫什么? 儿子的爸爸我该怎么叫?

三种方法的比对结果:

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

给我的感觉是,三种模型都是基于词来进行句子向量的实现的,而没有考虑到句子的含义,比如最后那一句,爸爸的儿子,儿子的爸爸,这两句三个模型的相似度都很高。感觉不太妥当。