有一天,一个出售身世的老板问我:你能解说下“词向量”吗?

经过攀谈得知,老板是做保险业务的。他发现用户会咨询许多手册上的根底问题,这需求业务员一对一进行回复。所以,他想让体系自动回复,从而削减本钱。

老板手里有许多行业材料,但做了几个版别都不如意。上一个版别是经过字符串匹配完成的。这种办法,问不到要害词,体系就答不上。比方,问“高血压”,体系能给出答案。问“三高”,就找不到了。所以,他们只能去后台将“三高”做相关。但是,词海苍茫,此伏彼起。

这个版别,技能人员说采用了词向量,老板想知道这是啥?靠不靠谱?

下面,我就来完成一个问答匹配的例子,然后再详解操作过程、原理。

一、实战作用演示

我在教育行业行走,不懂保险……就拿教育产品来举例吧。

假定咱们有这么一个问答知识库:

  • “找回暗码流程阐明”
  • “怎样检查我的错题记载”
  • “Sorry, an error occurred!”
  • ……

用户要找他的错题本,或许会有以下几种问法:

  • “我的错题从哪里能够检查?”
  • “怎样找到我做错的标题”
  • “我没做对的标题怎样查找”

有些问法,甚至不包含“错题”,仅仅说“没做对的标题”。咱们看看,从知识库里能找到吗?

以下是全部代码,用python完成:

# 加载模型
from text2vec import SentenceModel, semantic_search
model = SentenceModel("text2vec")
# 以下是体系的知识库
corpus = [
    "找回暗码流程阐明",
    "怎样检查我的错题记载",
    "Sorry, an error occurred!"]
corpus_embeddings = model.encode(corpus)
# 以下是用户的问题
queries = [
    "我的错题从哪里能够检查?",
    "怎样找到我做错的标题",
    "我没做对的标题怎样查找"]
for query in queries:
    query_embedding = model.encode(query)
    # 将问题经过模型从知识库匹配,取前3条
    hits = semantic_search(query_embedding, corpus_embeddings, top_k=3)
    print("\n问题:", query, "\n最优前3条:")
    hits = hits[0]  
    for hit in hits:
        print(corpus[hit['corpus_id']], "({:.2f})".format(hit['score']))

运转一下,检查成果:

问题: 我的错题从哪里能够检查? 
最优前3条:
  怎样检查我的错题记载 (0.84)
  Sorry, an error occurred! (0.46)
  找回暗码流程阐明 (0.43)
问题: 怎样找到我做错的标题 
最优前3条:
  怎样检查我的错题记载 (0.80)
  Sorry, an error occurred! (0.48)
  找回暗码流程阐明 (0.46)
问题: 我没做对的标题怎样查找 
最优前3条:
  怎样检查我的错题记载 (0.75)
  Sorry, an error occurred! (0.48)
  找回暗码流程阐明 (0.47)

能够看出,即使发问的要害字不一样,也能够匹配出预期的成果。

咱们能够经过semantic_search这个办法,对文本进行匹配度核算,实验可得:

问题: 怎样检查我的错题记载 
匹配得分:
  我的错题从哪里能够检查? (0.84)
  怎样找到我做错的标题 (0.80)
  我没做对的标题怎样查找 (0.75)
  找回暗码流程阐明 (0.44)
  ……

到这儿,老板们能够回了:词向量比字符串的作用要好,请相信你们的技能

假如你还想实际操作一下,能够继续往下看。

二、操作过程讲解

上面示例用到了一个text2vec(文本转向量)类库。

项目开源地址是:github.com/shibing624/… 。

里边有更多的信息,比方它说:

可免费用做商业用途。请在产品阐明中附加text2vec的链接和授权协议。”

首要,咱们安装它:

pip install torch
pip install -U text2vec

这一步,对应示例代码中的from text2vec import ……,表明导入类库并调用功用。

然后,咱们需求下载它的模型权重。它能这么智能,是由于项目作者做了许多根底工作。咱们是站在巨人膀子上做事情,需求先把巨人搬到家里来

模型下载地址:huggingface.co/shibing624/…

假如你只运用(推理),不练习,下载图中标记的4个文件就够了。

全民AI计划:详解词向量与本地知识库问答匹配

下载之后,新建了一个text2vec(叫啥都行)文件夹,将模型权重仿制进去。

这个文件夹的地址,对应示例代码中,模型文件的加载路径:

model = SentenceModel("text2vec")

小提示:我放在代码的同级目录。你放D盘也行,那代码对应为SentenceModel("D:\text2vec")

最后,新建一个main.py文件,将示例代码仿制进去,就能运转了。

到这儿,功用应急的小伙伴们能够撤了:这个类库确实能够,简略解决文本匹配的问题

假如你想进一步问个为什么,能够再继续往下看。

三、技能原理剖析

词向量是大言语模型的必经之路。一问一答之间,尽显词向量的身影。

下面的流程图,便是一个根据本地文档库问答的开源项目。

项目地址是:github.com/imClumsyPan…

全民AI计划:详解词向量与本地知识库问答匹配

这儿面有15个流程,其中3处涉及到了Vector(词向量)。别的还有两处的Embedding,是将文本转为向量的操作,这也和向量有关。

依托于词向量,咱们能够完成从文档中找答案。我把上一篇博客《怎样告知后端身世的领导,前端需求难完成》导入知识库,然后问它文中的问题。它是能回答出来的。

全民AI计划:详解词向量与本地知识库问答匹配

好了,不卖关子了,开始聊聊词向量。

3.1 词向量

词向量难了解的当地不在于“词”,而在于“向量”

向量,初中数学就开始学。简略来说,便是一个具有“方向”和“巨细”的变量

全民AI计划:详解词向量与本地知识库问答匹配

上图所示,两人拉车。一个向左,一个向右。瘦子力气小,胖子力气大。力是向量,它有方向和巨细。

向量之间是能够核算的

有一个著名的平行四边形法则:向量a和向量b一起使劲,作用等同于向量c。

全民AI计划:详解词向量与本地知识库问答匹配

你能够拿拉车的例子来复原:a和b两个人拉车的作用,等同于c一个人。

3.2 维度

上面说的向量是二维向量,也便是有x、y两个维度。

全民AI计划:详解词向量与本地知识库问答匹配

其实也有三维向量。它具有x、y、z三个维度。

全民AI计划:详解词向量与本地知识库问答匹配

2维向量用(x, y)来表明。3维向量用(x, y, z)来表明。一个向量,有几个维度,就有几个维度的数据来描绘它。

所以,你到底想表达什么?

我想表达,其实咱们的词汇也是能用维度来表达的

3.3 嵌入

来,访问这个地址:projector.tensorflow.org/

全民AI计划:详解词向量与本地知识库问答匹配

上图是10000个词汇,经过200个维度的描绘处理后,投射到3维空间所出现的视觉作用。

下面,咱们随机捕捉一个词man

咱们发现在这个语料的星系中,能和man产生相关的词语有5778个。

全民AI计划:详解词向量与本地知识库问答匹配

其中有“son”、“uncle”、“father”、“king”这些词。这或许是从人物维度来剖析的,看它们都凑一堆儿。

别的也有“girls”、“love”、“woman”、“angry”这些词,这是啥?man的喜好?

总归,他们之间是有相关的。下面我带我们走进和“他”有关的国际。

全民AI计划:详解词向量与本地知识库问答匹配

能做到如上这些的根底,便是由于这些词汇被向量化了

man这个词是一个200维度的向量。假如用数据来表明,它应该是这样的:

[5.82528770e-01, 1.65926769e-01, -8.73286307e-01, 1.16382980e+00
 -8.05581883e-02, -2.68993825e-01, -5.55128217e-01, -7.28500545e-01
 1.19629860e-01, 3.96491200e-01, -5.55124357e-02, ……-2.47849301e-02]

不省掉的话,得有200位数据。

这种将词汇向量化的操作,咱们叫“Embedding”,翻译成中文叫“嵌入”

“嵌入”这个翻译太硬,我只能解说得软一些:便是给词找一个好的归宿,将它嵌入到适宜的方位

正是经过Embedding将文本变成了向量。而向量又能进行数学核算。所以,当咱们用多种办法来发问时,到模型这儿一核算,发现是同一个东西,这才完成了殊途同归。

  • 比方将“单”界说为1,将“双”、“对”界说为2。你问AI模型:“我单身,又找了一个单身。我俩加一起叫啥?”。AI模型说:“成双成对!”
  • 再比方,做如下界说:“男人”(1,0),“权力”(0,1),国王(1,1)。你问AI模型:“我和国王的差异是什么?”。AI模型说:“国王有权力!”

你感觉,哇,好奇特。模型心里想,切,这不便是1+1=2吗?!

上面说到的text2vec这个开源模型,它所做的便是将文本转为向量。这一步是NLP的基石,十分要害。能否给词汇做好Embedding,决定了AI模型的根本了解力。

假如你要想看一个词的向量值,能够这么操作:

from text2vec import SentenceModel
# 从目录加载离线模型
model = SentenceModel("text2vec")
# 将文本向量化
embeddings = model.encode(['男人'])
print(embeddings.shape, embeddings)

输出成果为:

embeddings.shape: (1, 768)
embeddings: [[ 5.82528770e-01  1.65926769e-01  5.58118522e-01
   2.97882259e-02 -3.88074875e-01  7.49602675e-01
  -9.67679083e-01  …… -2.47849301e-02]]

embeddings.shape是数据的形状,这儿表明维度。这框架给每段embedding的文本赋予了768个维度。后边是这768个维度数据的具体值。

前面的那个语料“星云图”,仅仅个学惯用的Demo。下面这个更多、更广,更震慑。

要对这么多数据进行核算,可不是像“1+1=2”这么轻松,其实不简略。

3.4 类似度核算

向量之间的类似度,有许多种核算办法,下面讲一个余弦类似度

它经过核算两个向量间夹角的余弦值,来评价两者的类似度。

全民AI计划:详解词向量与本地知识库问答匹配

余弦!又来一个数学名词。下面发张图,帮我们温习一下。

全民AI计划:详解词向量与本地知识库问答匹配

看上图,可知:

  • 角A变小,c朝向b不断下滑,两者方向共同时,b/c=1。
  • 角A变大,c向上抬,b不断变小,两者笔直时,b为0,b/c=0。
  • 角A继续变大,成为钝角,直到两者方向相反,b/c=-1。

来个动图,生动地表达目的。

全民AI计划:详解词向量与本地知识库问答匹配

为何要选择这个余弦公式来做类似度的评判?

通俗地讲,便是看两个向量是否一条心

  • 方向共同时,函数值为1。
  • 方向相反时,函数值为-1。
  • 当方向越来越偏离时,它的函数值也越来越小。

看!它真的是很适宜。

利用text2vec中的cos_sim办法,就能够轻松完成余弦类似度的核算。

from text2vec import SentenceModel, cos_sim
# 从目录加载模型
model = SentenceModel("text2vec")
# 转为向量
emb1 = model.encode(["我的错题从哪里能够检查"])
emb2 = model.encode(["怎样检查错题记载"])
# 利用cos_sim核算类似度
cosine_scores = cos_sim(emb1, emb2)
print("Score: {:.2f}".format(cosine_scores[0][0]))

试了两个,成果还行。

[我的错题从哪里能够检查] VS [怎样检查错题记载] Score: 0.79
[我的错题从哪里能够检查] VS [Python是编程言语] Score: 0.24

请注意,余弦类似度是有缺点的:它只评判向量的方向,不重视向量的长度

这会导致什么问题呢?答案是:重视性质,忽视数量。

举个例子,假如某网店有甲乙丙三个顾客评分如下:

顾客 物流快递 商品描绘 售后服务
10 8 6
7 8 9
4 2 0

假如用余弦类似度进行核算,算法会以为丙和甲是一类人。

what?为啥?

由于余弦类似度只重视方向,不重视数值。

全民AI计划:详解词向量与本地知识库问答匹配

甲和丙的方向是共同的:物流快递最好,售后服务最差。它重视的是一种趋势。

假如换一种核算办法,比方欧氏距离。那么它会以为顾客甲和顾客乙是一类人,由于他们的评分距离挨近,都是好评。

全民AI计划:详解词向量与本地知识库问答匹配

上图,从视点来看,A和B更近;从距离看,A和C更近。

好了,今日就说这么多。

上面说的一大堆,其实是专业范畴里一笔带过的内容。我是从里边摘芝麻当冬瓜看,小题大做。

全民AI计划:详解词向量与本地知识库问答匹配

我在做AI的科普工作,这篇文章是 全民AI方案 的第3期。

  • 第1期:《尝试你的第一个AI程序》
  • 第2期:《文本摘要的完成原理》

但凡您有一丁点儿听不懂,请反应给我。听不懂,必定是我的问题。

我是@TF男孩,一个遍及AI知识的民科IT男。