作者:李大雷
原文链接:
https://zhuanlan.zhihu.com/p/94124468
鹅厂 18 年 10 月开源了一份包含 800 万中文词的词向量模型。
官方的介绍中显示其能覆盖一些很低频的词。如喀拉喀什河,一些网络新词如因吹斯汀竟然也可以查到对应的词向量,以及输入马云也可以在最相似词中找到马爸爸等词。
总体来说这个模型在覆盖率、新鲜度、准确性上都有不错的表现。
比较欠缺的是,其训练模型中有一定比例的词并非是词。如马云的 top 相似词结果中有 :马云和、马云说、如马云等词。以及对于未登录词无法增量训练。
本文尝试基于 python 3 + flask + gensim 搭建一个简易的 api 服务,让你可以在实验环境中试玩这个模型。
该模型压缩后 6.4 GB ,解压后 16 GB,在内存中展开 18.5 GB,全量模型加载需要 26 min 左右。
搭建前确保机器资源充足,另外如果只是试玩建议对原始模型做裁剪,如只加载前 10 w 词。
全量模型下载:https://ai.tencent.com/ailab/nlp/embedding.html
精简版下载(全量模型的前 10w 个词):
链接: https://pan.baidu.com/share/init?surl=NidB4Rsy-tqY49QsysUgMw
提取码: tmda
第3、4步骤是虚拟环境搭建以及依赖安装,已经就绪的同学可以直接跳到步骤 5 运行代码。
安装 virtualenv
pip3 install virtualenv
创建 virtualenv(以 /tmp/work 为例)
cd /tmp/work/
virtualenv -p python3 w2v_venv
进入 virtualenv
source w2vAPI/bin/activate
将以下数据,保存为 requirements.txt 。
boto==2.49.0
boto3==1.10.26
botocore==1.13.26
certifi==2019.9.11
chardet==3.0.4
Click==7.0
docutils==0.15.2
Flask==1.1.1
gensim==3.8.1
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.3
jmespath==0.9.4
MarkupSafe==1.1.1
numpy==1.17.4
python-dateutil==2.8.0
requests==2.22.0
s3transfer==0.2.1
scipy==1.3.3
six==1.13.0
smart-open==1.9.0
urllib3==1.25.7
Werkzeug==0.16.0
执行安装
pip3 install -r requirements.txt
将以下数据,保存为 w2v.py 。
import json
from flask import Flask, request
from gensim.models import KeyedVectors
from flask import jsonify
import argparse
import sys
import socket
import time
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s;%(levelname)s: %(message)s",
"%Y-%m-%d %H:%M:%S")
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
console.setFormatter(formatter)
logger.addHandler(console)
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
def isNoneWords(word):
if word is None or len(word)==0 or word not in model.vocab:
return True
else:
return False
@app.route("/", methods=['GET'])
def welcome():
vecAPI="http://"+localIp+":"+str(port)+"/vec?word=淘宝"
simAPI="http://"+localIp+":"+str(port)+"/sim?word1=淘宝&word2=京东"
topSimAPI="http://"+localIp+":"+str(port)+"/top_sim?word=淘宝"
return "Welcome to word2vec api . <br/>\
try this api below:<br/> \
1. vec api: <a href='"+vecAPI+"'>"+vecAPI+"</a> <br/>\
2. sim api: <a href='"+simAPI+"'>"+simAPI+"</a> <br/>\
3. top sim api: <a href='"+topSimAPI+"'>"+topSimAPI+"</a> <br/>\
"
@app.route("/vec", methods=['GET'])
def vec_route():
word = request.args.get("word")
if isNoneWords(word):
return jsonify("word is null or not in model!")
else:
return jsonify({'word':word,'vector': model.word_vec(word).tolist()})
@app.route("/sim", methods=['GET'])
def similarity_route():
word1 = request.args.get("word1")
word2 = request.args.get("word2")
if isNoneWords(word1) or isNoneWords(word2):
return jsonify("word is null or not in model!")
else:
return jsonify({'word1':word1,'word2':word2,'similarity':float(model.similarity(word1, word2))})
@app.route("/top_sim", methods=['GET'])
def top_similarity_route():
word = request.args.get("word")
if isNoneWords(word):
return jsonify("word is null or not in model!")
else:
return jsonify({'word':word,'top_similar_words':model.similar_by_word(word, topn=20, restrict_vocab=None)})
def getLocalIP():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip=s.getsockname()[0]
s.close()
return ip
def main():
global model
global port
global localIp
for arg in sys.argv[1:]:
logger.debug(arg)
p = argparse.ArgumentParser()
p.add_argument("--model", help="Path to the trained model")
p.add_argument("--host", help="Host name (default: localhost)")
p.add_argument("--port", help="Port (default: 8888)")
args = p.parse_args()
host = args.host if args.host else "localhost"
port = int(args.port) if args.port else 8888
localIp = getLocalIP()
if not args.model:
logger.debug("Usage: w2v.py --model model_path [--host host --port 8888]")
sys.exit(1)
logger.debug("start load model:" + str(args.model))
start_time = time.time()
model = KeyedVectors.load_word2vec_format(args.model, binary=False)
logger.debug("end load model:" + str(args.model))
# app.run(host=host, port=port,debug=True)
app.run(host=host, port=port)
if __name__ == "__main__":
main()
启动 api 服务
nohup python3 w2v.py --model /opt/cuiyulei/Tencent_AILab_ChineseEmbedding.txt --host 你的ip 2>&1 &
浏览器中键入
http://你的ip:8888/
提示如下,表示搭建完成
Welcome to word2vec api .
try this api below:
1. vec api: http://ip:8888/vec?word=淘宝
2. sim api: http://ip:8888/sim?word1=淘宝&word2=京东
3. top sim api: http://ip:8888/top_sim?word=淘宝
运行效果
input:
http://ip:8888/top_sim?word=红烧肉
output:
{
"top_similar_words":[
[
"糖醋排骨",
0.8907967209815979
],
[
"红烧排骨",
0.8726683259010315
],
[
"回锅肉",
0.858664333820343
],
[
"红烧鱼",
0.8542774319648743
],
[
"梅菜扣肉",
0.8500987887382507
],
[
"糖醋小排",
0.8475514650344849
],
[
"小炒肉",
0.8435966968536377
],
[
"红烧五花肉",
0.8424086570739746
],
[
"红烧肘子",
0.8400496244430542
],
[
"糖醋里脊",
0.8381932377815247
],
[
"红烧猪蹄",
0.8374584913253784
],
[
"青椒炒肉",
0.8344883918762207
],
[
"粉蒸肉",
0.8337559700012207
],
[
"水煮肉片",
0.8311598300933838
],
[
"青椒肉丝",
0.8294434547424316
],
[
"鱼香茄子",
0.8291393518447876
],
[
"烧茄子",
0.8272593021392822
],
[
"梅干菜扣肉",
0.8267726898193359
],
[
"土豆炖牛肉",
0.8263725638389587
],
[
"红烧茄子",
0.8244959115982056
]
],
"word":"红烧肉"
}
本文由作者授权AINLP原创发布于公众号平台,点击'阅读原文'直达原文链接,欢迎投稿,AI、NLP均可。
推荐阅读
相似词查询:玩转腾讯 AI Lab 中文词向量
玩转腾讯词向量:词语相似度计算和在线查询
腾讯词向量实战:通过Annoy进行索引和快速查询
玩转腾讯词向量:Game of Words(词语的加减游戏)
词向量游戏:梅西-阿根廷+葡萄牙=?
关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLP君微信(id:AINLP2),备注工作/研究方向+加群目的。