0%

系统架构图

说明

圆角方形代表一个模块。“圆角方形(主)”代表重要的模块,“圆角方形(辅)”代表重要模块中的子模块,“圆角方形(层)”代表多个模块组合成的某一层,例如“业务层”,“应用层”。“圆角方形(数据)”代表各种数据,例如数据库数据,图数据,知识图谱等。

配色1

背景色:#171717

圆角方形背景色(主):#61649f(山梗紫)

圆角方形背景色(辅):#a7a8bd(淡蓝紫)

配色2

背景色:白色

圆角方形背景色(主):#5dbe8a(蔻梢绿),#b9dec9(竹篁绿)

圆角方形背景色(辅):#f4ce69(炒米黄),#f9e9cd(米色),#fbeee2(淡米粉),#5cb3cc(碧青),#93d5dc(清水蓝),#e3b4b8(鼠鼻红)

圆角方形背景色(层):#1ba784(竹绿)

圆角方形背景色(数据):#10aec2(甸子蓝)

阅读全文 »

pytorch zero grad 改变tensor形状 矩阵乘法 loss function pytorch nn 操作张量

本文只记录框架层面的使用。关于深度学习层面的研究记录在 神经网络训练技巧(tricks)

view、reshape和resize_

结论写在前面:张量连续,使用 view()(此为多数情况);张量不连续,则使用 reshape()resize_() 最好不要使用。注意,在张量不连续的情况下,非要使用 view() 也可以,但是要先调用 contiguous() 方法,使得张量连续,但是此方法会返回一个新的张量,浪费时间空间。 共同点:这些方法都可以改变 pytorch 中 tensor 的形状,但是它们略有不同。

  1. view():只能改变连续的(contiguous)张量,且返回的张量与原张量的数据是共享的。在张量不连续的情况下,硬要使用此方法,需要在使用之前使用 tensor.contiguous()
  2. reshape():对张量是否连续无要求,且可能返回的原张量的拷贝(这个“可能”是字面意思,开发者指出,你永远无法预先知道返回的张量是否为拷贝版本。参考 stackoverflow 回答)。
  3. resize_():与上述二者有较大差别,此方法可以无视原张量的形状,进行随意变化。如果元素的数量大于原张量的元素数量,那么底层的存储大小会进行调整,即会进行扩容。小于,则存储空间不做变化。参考《pytorch 文档》。

    这是一个底层的方法,大多数情况可以使用 view() 或者 reshape()。想要使用自定义步长改变张量内置的大小,请使用 set_()。总而言之,就是最好不要用这个方法。

    阅读全文 »

论文地址,作者是 Vinyals et al.,发表于 2015 年。

摘要

提出一个新的神经结构来学习输出序列的条件概率,输出元素是在输入序列中对应位置的离散标记。

由于输出的每一步都与输入的长度有关,但是输入的长度是可变的,所以现有方法 seq2seq 和神经图灵机都无法简单地解决这问题。可变长度序列的排序,各种组合优化的问题都属于此类。我们的模型使用 attention 机制来解决这种输出字典可变大小的问题

阅读全文 »

Mini-batch梯度下降

Q:为什么Mini-batch比普通的梯度下降快?

普通的梯度下降——vanilla gradient descent,是将整个数据集同时做运算,而Mini-batch梯度下降算法是以一组为单位,分别进行梯度下降,所有组执行完毕后再进行下一次迭代。

假设现在有m个样本。 \[ X = \begin{pmatrix}x^1&x^2&x^3&\cdots&x^m\end{pmatrix}\\ Y = \begin{pmatrix}y^1&y^2&x^3&\cdots&y^m\end{pmatrix}\\ \] 使用Mini-batch,假设每1000个样本为一组: \[ X = \begin{pmatrix}\underbrace{x^1\cdots x^{1000}}_{X^{\{1\}}} & \underbrace{x^{1001}\cdots x^{2000}}_{X^{\{2\}}} & \cdots&\underbrace{\cdots x^m}_{X^{\{t\}}}\end{pmatrix}\\ Y = \begin{pmatrix}\underbrace{y^1\cdots y^{1000}}_{Y^{\{1\}}} & \underbrace{y^{1001}\cdots y^{2000}}_{Y^{\{2\}}} & \cdots&\underbrace{\cdots y^m}_{Y^{\{t\}}}\end{pmatrix}\\ \] 如果使用代码实现就是类似下面这样的伪代码:

1
2
3
4
5
for t = 1, ..., t
forwardprop on X^{t}
compute cost
backprop to compute grads
update weights and bais
for循环完成之后就完成了神经网络的第一次迭代。
阅读全文 »

A Bi-model based RNN Semantic Frame Parsing Model for Intent Detection and Slot Filling

  • 论文笔记
  • 对 ID 和 SF 分别使用了一个模型,但是共享了两个模型的隐藏状态。论文中描述到,以前的研究经常把 ID 和 SF 当做两个任务来看,这次这篇论文将这两个任务交互起来当做一个任务看待。但是我认为 joint model 这种做法已经是将两个任务当做一个看了,毕竟它们共享了一个模型提取的信息,只是在解码时使用不同的模型。
    • 对于解码而言,论文分别使用了 encoder-decoder 结构和纯粹的 encoder 结构,最后是 encoder-decoder 性能略高。
      阅读全文 »

本文记录最初至 2019 年的 DST 论文笔记。本文已更新,移驾DST论文笔记(二)

突然发现有人看这篇文章,这只是本人的论文笔记,对于任务完成型对话系统论文调研的文章,可以移驾:

  1. 任务完成型对话系统论文调研(一)
  2. 任务完成型对话系统论文调研(二)

TripPy: A Triple Copy Strategy for Value Independent Neural Dialog State Tracking

模型的计算方法与 DS-DST 几乎完全一致,只不过补充了几点 slot gate 的类型。

唯一不同的在特征提取这块。DS-DST 将 CLS,一个域槽对和对话上下文拼接起来。由于所有域槽对的词向量是不同的,则可以凭此遍历所有的域槽对,使得每次捕获到的特征都是根据域槽对的变化而变化。所以当使用 CLS 进行 slot gate 分类时,可以确定该 slot gate 是基于某一域槽对的,并且 CLS 表征总是不同的。但是这样的做法计算起来特别麻烦,因为如果想要向量化,必须复制 N 份上下文(N 为域槽对数量)

TripPy 应该是略微地改进了它,它移除了输入中的域槽对,其他基本不变,顶多是改变了一下上下文的输入顺序,这并无大碍。然后,TripPy 为每一个域槽对都设计了一个线性层用于计算 slot gate。这也能使得 CLS 的表征总是不同,因为线性层中的权重矩阵是不同的。但是这样貌似更加无法向量化了?反而,弄巧成拙?

所以,我认为在 dst 模型上,还是 TRADE 模型设计的更合理,它是采用了 attention 的机制。相比于 DS-DST 和 TripPy,参数量大大地减少,并且可以向量化。

图 TripPy
图 TripPy

本文提出三种复制机制:1)从用户语句中直接提取出槽值的跨度预测(span prediction);2)从 system inform memory 中复制出槽值,其为系统回复操作的追踪;3)从对话状态历史中复制槽值。

\(X = \{(U_1, M_1), \cdots, (U_T, M_T)\}\)\(U_t\)\(t\) 轮时的用户语句,\(M_t\)\(t\) 轮时的回复语句。模型的任务是 1)决定每轮是否提到了 \(S = \{S_1, \cdots, S_N\}\) 中的 \(N\) 个域槽对;2)预测每个 \(S_n\) 的槽值;3)追踪整场对话过程中的对话状态。

Context Encoder

使用 BERT 提取上下文特征,公式为:

\(R_t = BERT([CLS] \oplus U_t \oplus [SEP] \oplus M_t \oplus [SEP] \oplus H_t \oplus [SEP])\)

其中 \(U_t\) 是 t 轮的用户语句,\([CLS], [SEP]\) 都是 BERT 需要的特殊符号,分别为分类特殊符和分隔符,\(H_t\) 为对话历史。那么 \(R_t = [r^{CLS}_t, r^1_t, \cdots, r^{seq_{max}}_t]\)。以上都是比较基础的公式,具体说明略。值得注意得是,TripPy 的输入是逆序的,先输入 t 轮的对话,再输入逆序的历史对话。

Slot Gates

Slot Gate 的思想应该取自 TRADE 模型,简单来说,就是设计一个多分类器,判断接下来的操作应该交给哪个组件执行,一般来说可以选择 \(\{None, dontcare, Ptr, \cdots\}\)

TripPy 为每一个域槽对都配备了一个 slot gate。还是跟以往的做法差不多,将槽值的识别问题转换为一个分类问题。与 TRADE 模型不同的是,TripPy 的 slot gate 在每轮为槽位 \(S_n\) 进行分类,类别包括 \(C = \{none, dontcare, span, inform, refer\}\),其中 inform 代表系统的通知,refer 代表历史对话状态中所提到的,其他都是类似的,就不提了。

由于在 Context Encoder 中已经提取到了上下文特征,而且这步也是 BERT 做的,所以 Slot Gate 实际上就是做几个线性分类而已。BERT 可以得到 \(r^{CLS}_t\),这代表 \(t\)\([CLS]\) 的表征,那么域槽对 \(S_n\) 在类别 \(C\) 上的概率分布为:

\[p^{gate}_{t,s}(r^{CLS}_t) = softmax(W^{gate}_s \cdot r^{CLS}_t + b^{gate}_s) \in \mathbb{R}^5 \]

需要注意的是,上述的分类器是对一个域槽对进行五元分类。但是在系统中我们拥有 \(N\) 个域槽对,所以我们需要 \(N\) 个上述的分类器,这就导致需要一定的参数量。

对于特殊的槽位 Boolean Slot,也使用了类似的方法,但是类别 \(C_{bool} = \{none, dontcare, true, false\}\)

Span-based Value Prediction

使用 Ptr 神经网络预测槽值在用户语句中的位置,包括 start 以及 end 位置。如果 end > start,则简单地将跨度(span)置为空。

System Inform Memory for Value Prediction

系统通知记忆(System Inform Memory) \(I_t = \{I^1_t, \cdots, I^N_t\}\) 追踪系统提到的所有槽值对。简单来说,这就是一个 python 中的 dict,记录每一个槽值对是否被系统提及到。简单来说,如果用户提到了某个系统所通知给用户的槽值,那么槽位应该直接填充这个“通知值”,而不是去使用 Ptr 预测跨度,然后从用户的语句中提取出来。

这听起来可能有点奇怪,因为如果用户提到了某个系统的“通知值”,那么理所当然地我们也可以使用 Ptr 从用于语句中提取出来,为什么要多此一举使用 System Inform Memory 呢?原因在于,用户所提到的“通知值”可能并不是其本身。思考下面的例句,“系统:‘xx酒店有你想要的食物类型。’;用户:‘好的,就是了。’”。可见系统提到的“xx酒店”,用户并没有直接引用它,而是使用了一种共指的语法。

DS Memory for Coreference Resolution

更复杂的对话需要进行共指解析。简单来说,就是某一个槽位的槽值与另一个槽位的槽值相同,所以使用一个 N 元(槽位的数量)分类器,用于计算当前槽位的槽值是否指向另外一个槽位。事实上,这与 System Inform Memory for Value Prediction 类似,都是解决共指解析

Auxiliary Features

辅助特征。个人认为这种特征没什么特别大的意义。

Dialog State Update

使用与 Chao and Lane (2019) 同样的规则更新机制。每轮,如果槽值不为 none,则更新槽值;否则不更新。

总结

这模型与 TRADE 之类的 span-based 或者 open-vocabulary 模型有点不同。这个模型需要为每个域槽对都设计一个分类器,即有 \(N\) 个权重矩阵,然后将 \([CLS]\) 的特征输入每个分类器从而判断该域槽对是否被用户提取。而 TRADE 的做法是捕获域槽对的隐藏状态,然后将该隐藏状态 \(h^{dec}\) 输入一个分类器从而判断该域槽对是否被用户提取。粗体就是区别,一个输入的是 \([CLS]\) 特征,其是固定的,只能使用不同的权重矩阵来判断不同的域槽对,另一个输入的是域槽对的隐藏状态 \(h^{dec}\),由于域槽对是不同的,则 \(h^{dec}\) 也是不同的,所只需要一个分类器即可。

阅读全文 »

我按照文章《基于NVIDIA GeForce MX150 的Windows10安装TensorFlow-GPU详解》中的内容进行安装,但是碰到了一些问题。

  1. 首先是安装的选择问题,文中选择的是自定义安装,但是取消了 NVIDIA GeForce Experience... 的安装。我也不知道这个组件是干嘛用的,所以我没取消它,但是我取消了 CUDA 下的 Visual Studio Integration,因为我不使用 VS;
  2. 按照以上操作,我安装失败了。我上网搜了一下,我发现可能是我 NVIDIA 版本的问题,所以建议下载驱动精灵,它会自动升级你的版本,我从 9.1 升级到了 10.0;
  3. 再去 CUDA 官网下载新版本的 NVIDIA 安装;
  4. 但是更新完毕之后,NVIDIA 控制面板不见了!参考这篇文章将服务开启就可以了;
  5. 这次再根据以上的步骤安装,安装成功了。
    阅读全文 »

论文地址,作者为 Wu, Chien-Sheng et al.,发表于 2019 年。

引言

传统的状态跟踪假设本体已经定义好,所有的 slot-value 均已知,这可以将 DST 简化为分类任务。但是这种方法有两种缺陷:1)完整的本体很难提前获得。工业界,数据库通常由 API 支撑,由他人维护,很难枚举所有 slot-value;2)即使完整的本体存在,slot-value 的数量也会极其庞大。例如酒店名称和列车出发时间包含大量可能的值。因此许多先前的工作都基于神经分类模型,其在现实场景下并不适用。

最近 Budzianowski et al. (2018) 介绍了多领域对话数据集 MultiWOZ,由于它的混合领域对话,其在 DST 中引入了新的挑战1)如图一所示,用户先订了酒店,再询问了风景名胜,最后订了一辆出租车。此例中,DST 模型需要探测 (domain, slot, value) 三元组,这在本体中包含了大量的组合,即 30 对 (domian, slot) 以及总计 4500 个可能的值。2)另一挑战是,需要进行多轮映射。单轮映射指的是从单轮对话中推断出 (domain, slot, value) 的场景,但是多轮映射指的是从多轮对话中推断,这些对话发生在多个领域。例如图 1 中,atrraction 领域的 (area, centre) pair 中的 area 信息是在 restaurant 领域中被预测出的,且这是在前几轮被提到的内容。

为了解决这些问题,我们强调 DST 模型应该跨领域共享跟踪知识。不同领域中有许多 slot 可以共享它们的值。例如,area slot 可以存在于 restaurant, attraction, and taxi 中。此外 restaurant 领域的 name slot 可以与 taxi 领域的 departure slot 共享槽值。另外,为了使 DST 在未知领域跟踪 slot,跨领域转移知识势在必行。我们期望 DST 模型可以通过学习跟踪其他领域中的 slot 来学习跟踪 zero-shot 领域中某些相同的 slot。

阅读全文 »