NLP学习—18.Annoy、HNSW、KD tree以及多轮对话

引言

  Annoy、HNSW、KD tree在工业界非常常用

一、Annoy

  Annoy:Approximate Nearest Neighbors Oh Yeah。Annoy 是 Spotify 开源的高维空间求近似最近邻的库,在 Spotify使用它进行音乐推荐。 Annoy通过将海量数据建立成一个二叉树来使得每个数据查找时间复杂度是O(log n)(召回时减少计算)。Annoy解决:如何从海量文本中快速查找出相似的Top N 文本?(高维空间中快速召回最相似的部分)
解决过程如下:

  • 随机选取两点进行切分
    在这里插入图片描述
  • 在子空间中随机选取两个点进行切分
    在这里插入图片描述
    二叉树上的数据代表子空间上有多少个点
    在这里插入图片描述
  • 在划分的子空间内进行不停的递归迭代继续划分,直到每个空间最多只剩下K个数据节点
    在这里插入图片描述
  • 从根节点不停地往叶子节点遍历
    在这里插入图片描述
  • 查询过程最终落在叶子节点的数据节点数小于我们需要的Top N相似节点数目怎么办?
    • trick1:双边遍历,最后得到很多叶子节点,扩充了空间
      在这里插入图片描述
    • trick2:多棵树(Bagging),多次划分空间,得到不同的model,基于不同模型寻找叶子节点构造并集空间,在并集空间计算similarity
      在这里插入图片描述
1.Annoy实战
import random
from annoy import AnnoyIndex

# 向量维度
f = 20
# 构建树
t = AnnoyIndex(f)
# 将索引与向量添加到树中
for i in range(100):
    v = [random.gauss(0, 1) for z in range(f)]
    t.add_item(i, v)

# 对数据建模,10表示每个节点上至少划分10个点
t.build(10)
# 将划分结果进行保存
t.save('test.ann.index')
# 打印与index为0的向量最相近的10个向量的index
print(t.get_nns_by_item(0, 10))
# [0, 14, 89, 4, 61, 79, 1, 92, 77, 26]
from gensim.models import KeyedVectors
from annoy import AnnoyIndex
import json
from collections import OrderedDict
# 加载时间略长
tc_wv_model = KeyedVectors.load_word2vec_format('./Tencent_AILab_Chines/embedding.txt',binary=False)

# 构建一份词汇ID映射表,以json格式保存
word_index = OrderedDict()
for counter,key in enumerate(tc_wv_model.vocab.keys()):
    word_index[key] = counter
# 保存
with open('tc_word_index.json','w') as fp:
    json.dump(word_index,fp)


# 基于腾讯词向量构建Annoy索引,腾讯词向量大概882万条
tc_index = AnnoyIndex(200)
i = 0
for key in tc_wv_model.vocab.keys():
    v = tc_wv_model[key]
    tc_index.add_item(i,v)
    i += 1

# 建模
tc_index.build(10)
# 将index存储到磁盘上,再次单独加载时,内存占用大概2G左右
tc_index.save('tc_index_bulid10.index')

# 准备一个反向id=>word映射词表
reverse_word_index = dict([(value,key) for (key,value) in word_index.items()])

# 测试
for item in tc_index.get_nns_by_item(word_index[u'自然语言处理'],11):
    print(reverse_word_index[item])
# 打印与自然语言处理相似的11个词

# 测试从硬盘加载
u = AnnoyIndex(200)
# 加载
u.load('tc_index_bulid10.index')

二、HNSW

  HNSW解决:如何从海量文本中快速查找出相似的Top N 文本?基于海量数据建图,通过高速通道,可以快速找到最相似节点Top 1,利用该节点的友节点构建Top N。下面将通过近邻图、NSW与Skip-List来详细学习HNSW。
在这里插入图片描述
在这里插入图片描述
   基于上述问题,提出了NSW。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
总结来说,每一个点找到与它最近的n个点(友节点相连),对它周边的点进行状态的更新(要求每一个节点选取最近的n个节点),一般是将原先的最大距离与该点和新加入的点之间距离进行比较,更新为距离短的点。
   NSW解决了近邻图的三个问题,还未解决:如果初始点选择不好(比如很远),将进行多步查找的问题。这里引入了Skip-List。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  HNSW(层次NSW)就是NSW+跳表。
在这里插入图片描述

三、KD tree

  平衡二叉树指的是左子树上的所有节点的值都比根节点的值小,而右子树上的所有节点的值都比根节点的值大,且左子树与右子树的高度差最大为1。要查找一个值,不需要遍历整棵树,可以根据当前遍历到的结点的值来确定搜索方向。
  KD Tree:K指的是K邻近查询中的k;D指的是D维空间;tree指的二叉树。KD tree的建立就是分裂空间的过程。计算每个点的坐标的每一维度上的方差,取方差最大的那一维对应的中间值,作为分裂点,依此类推,直到每个空间中最多有一个点。
在这里插入图片描述在这里插入图片描述
那么KD Tree该如何查找某个点的临近点呢?

  • 首先通过二叉树搜索(比较待查询节点和分裂节点的分裂维的值,小于等于就进入左子树分支,大于就进入右子树分支直到叶子节点)
  • 顺着搜索路径找到最近邻的近似点,也就是与待查询点处于同一个子空间的叶子结点;
  • 回溯搜索路径,并判断搜索路径上的结点的其他子结点空间中是否可能有距离查询点更近的数据点,如果有可能,则需要跳到其他子结点空间中去搜索(也就是将其他子结点加入到搜索路径中
  • 重复这个过程直到搜索路径为空

举个例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.Annoy与KD Tree比较

  Annoy与KD Tree都是将空间划分为很多份,只是划分方式不同。Annoy是随机划分的,KD树会计算每个维度上的方差,取方差最大的那一维对应的中间值作为划分点。

四、Dialog Management(任务型多轮对话)

  多轮对话Pipeline如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
S l o t   F i l l i n g Slot\ Filling Slot Filling
在这里插入图片描述
任 务 型 对 话 场 景 任务型对话场景

在这里插入图片描述
R e i n f o r c e m e n t   L e a r n i n g 在 对 话 策 略 学 习 中 的 应 用 Reinforcement\ Learning在对话策略学习中的应用 Reinforcement Learning
其中, s s s为state, π π π P ( A c t i o n ∣ s t a t e ) P(Action|state) P(Actionstate) a a a为Action, r r r为reward。
a = π ( s ) a=π(s) a=π(s)
  多轮对话的Evaluation,需要在不同的场景选择不同的合适的指标。

  • 内容推荐
    CTR/时长/点击率
  • Task
    是否帮助客户完成任务?用来多少步完成任务?
  • 闲聊
    停留时长
  • 检索

参考:


如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!
在这里插入图片描述


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值