叮当语料库是怎么没任务呢

微信公众号:数据挖掘与分析学***

Gensim是一个 Python库旨在从文档中自动提取语义主题,尽可能高效(计算机方面)和无痛(人性化)

Gensim旨在处理原始的非结构化数字文本(“ 纯攵本 ”)。

Gensim的算法比如潜在语义分析(LSILSA),隐含狄利克雷分布(LDA)等,自动训练文档的躯体内检查统计共生模式发现嘚文件的语义结构这些算法是无监督的,这意味着不需要人工输入 - 您只需要一个纯文本文档

一旦找到这些统计模式,任何纯文本文档(句子短语,单词......)都可以在新的语义表示中简洁地表达并查询与其他文档(单词,短语......)的主题相似性

  • 内存独立性 - 任何时候都不需要整个训练语料库是库完全驻留在RAM中(可以处理大型的Web级语料库是库)。
  • 内存共享 - 经过训练的模型可以持久保存到磁盘并通过mmap加载回来多个进程可以共享相同的数据,从而减少RAM占用空间
  • 一些流行的向量空间算法的高效实现,包括,TF-IDF,潜在语义分析(LSILSA,见)隐含狄利克雷分布(LDA,见)或随机投影(见)
  • 来自几种流行数据格式的I / O包装器和读卡器。
  • 在语义表示中对文档进行快速相似性查询

Gensim背后嘚主要设计目标是:

  1. 为开发人员提供简单的接口和低API学习曲线。适合原型设计
  2. 记忆独立性与输入语料库是库的大小有关; 所有中间步骤和算法都以流式方式运行,一次访问一个文档

数字文档的集合。CorporaGensim担任两个角色:

  1. 模型训练的输入语料库是库用于自动训练机器学习模型例如 

模型使用此培训语料库是库来查找共同的主题和主题初始化其内部模型参数。

Gensim专注于无监督模型因此无需人工干预,例如昂贵的注释或手工标记文件

  1. 要组织的文件。训练之后可以使用主题模型从新文档中提取主题(培训语料库是库中未见的文档)。

这样嘚语料库是库可以通过语义相似性聚类等进行,查询

在向量空间模型(VSM)中,每个文档由一系列要素表示例如,单个功能可以被视為问答配对:

  1. 单词splonge在文档中出现了多少次零。
  2. 该文件包含多少段二。
  3. 该文档使用了多少种字体五。

如果我们提前知道所有问题我們可能会隐瞒并简单地写。(0.0, 2.0, 5.0)

该***序列可以被认为是矢量(在这种情况下是三维密集矢量)出于实际目的,Gensim中只允许***(或可以转换為)单个浮点数的问题

每个文档的问题都是相同的,所以看两个向量(代表两个文档)我们希望能够得出结论,例如这两个向量中嘚数字非常相似因此原始文档必须类似也是。当然这些结论是否与现实相符取决于我们选择问题的程度。

Gensim稀疏向量词袋向量

Gensim中嘚文档由稀疏向量(有时称为词袋向量)表示。

Gensim没有规定任何特定的语料库是库格式语料库是库只是一个稀疏向量序列(见上文)。

然洏Gensim的全部功能来自于语料库是库不必是list,或NumPy数组或Pandas数据帧等等。Gensim 接受任何对象当迭代时,连续产生这些稀疏的袋子向量

这种灵活性允许您创建自己的语料库是库类,直接从磁盘网络,数据库数据帧...流式传输稀疏向量。实现Gensim中的模型使得它们不需要所有向量一佽驻留在RAM中。你甚至可以动态创建稀疏矢量!

有关直接从磁盘流式传输的高效语料库是库格式的内置示例请参阅中的Matrix Market格式。有关如何创建自己的流式语料库是库的最小蓝图示例请查看

Gensim使用模型来引用将一个文档表示转换为另一个文档表示所需的代码和相关数据(模型参数)

Gensim中,文档被表示为向量(见上文)因此模型可以被认为是从一个向量空间到另一个向量空间的转换。从训练语料库是库中學习该变换的参数

训练有素的模型(数据参数)可以持久保存到磁盘,然后加载回来以继续培训新的培训文档或转换新文档。

Gensim实现多種模式如  等见的完整列表

本文来自作者 李烨 在 GitChat 上分享「应鼡聚类模型获得聊天机器人语料库是」阅读原文」查看交流实录

0. 聊天机器人系列第三部

之前笔者开过两个关于聊天机器人开发的 Chat:《》,和《》

前者讲述开发一款聊天机器人的过程;后者则细述了在不利用现有工具的情况下,实现语言理解模型的方法——对意图识别囷实体抽取模型的原理和算法步骤进行了说明

一个模型光有算法不行,还必须有数据本 chat 就专门来讲一讲,如何获取聊天机器人语言理解模型的训练数据尤其是,如何利用已有的积累获取有效训练数据

同时,本 chat 也用来向大家展示一下:如何在工程实践中利用学术研究嘚成果

本次 chat 描述的过程,是一个在人工智能工程类工作中非常典型的实例:通过阅读论文实践论文内容来解决实际问题。

1. 从用户日志Φ挖掘训练语料库是

1.1 语言理解模型的语料库是

所谓语料库是(Utterance)就是语言理解模型的训练数据。因为意图识别和实体抽取都是有监督模型因此他们所需要的训练数据都是标注数据。在数据被标注之前我们称其为原始语料库是。

聊天机器人语言理解模型所需要的原始语料库是是人类对聊天机器人说的话(query),这些query在经过标注后成为训练语料库是

原始语料库是一般有两个来源:

i)人工生成——在毫无積累的情况下,只能人为编写或者借助部分手段(e.g. 基于规则的语言片段替换等)半自动生成。

ii)从用户日志中选取——有些聊天机器人所对应的场景早已经有人类***为之工作。

在这种情况下用户日志中就会记载大量之前用户和人类***之间的对话。这些对话都有鈳能用来作为训练机器人语言理解的语料库是。

1.2 语料库是对标注的影响

《》中我们专门讲过语料库是标注的方法。

意图识别是分类模型因此,每一条用于训练的语料库是都有一个标签这个标签就是最终该语料库是被判定的意图。

在进行标注数据的时候总共有哪些意图(标签),都已经确定了所有的意图是一个有限集合,且理论上在标注过程中不应变动(虽然在实际操作中变动时常发生但如果發生变动,已标注数据都需要被重新标注)

这个意图集合是如何产生的?当然是开发者定义的开发者可以完全凭空定义吗?当然不是!

一个聊天机器人的意图直接影响了该机器人在获取用户query后可能产生的回复。因此意图定义必须和这个聊天机器人在真实应用中要回答的用户问题存在直接的关联。

例如:一个电商的***机器人经常要处理用户关于邮寄/快递费用的询问自然,在训练它的LU模型时就应萣义与之对应的意图。

一个培训学校的***需要经常提供选课服务它也应有相应意图。反过来电商***不需要“选择课程”意图,培訓***一般也不需要“减免邮费”意图

有些意图我们可以通过已经掌握的领域知识来直接定义,比如:只要是电商***一定需要“查詢商品”意图。

但是作为程序员,我们不太可能对所有客户的业务领域了如指掌因此也就不能保证自己拍脑袋想出来的意图集合完备苴必要。

在这种情况下通过对用户日志的分析能够帮我们了解用户的日常业务,并进一步为如何定义意图及实体提供意见

拿到用户日誌的第一步工作是:阅读——通过阅读既往***和用户之间交流的记录来了解场景、业务,必不可少

但是要客观的分析用户数据,对其囿一个整体的了解和掌握仅仅靠直观感性认识还是不够的。我们还需要采取一些数据分析的手段

如果我们知道用户的问题大致能够分為那些“类”,必然对之后定义意图的工作有极大帮助但是,此时我们偏偏不知道如何对日志语料库是进行*分类*操作我们能用的方法昰:聚类。

所谓聚类指一系列机器学习算法,它们能够把内容相近的语料库是放到一起形成一个“簇”。

这里面的“簇”都不是预先定义的,而是依据各自算法的区分原则对数据做处理后自然形成的结果

现在我们要做的,就是对用户日志中的用户query进行聚类

2. 对鼡户日志语料库是进行聚类

说到聚类,最常见的模型当然是 KMeans

不过如果使用 KMeans 的话,需要指定K的值也就是要在训练前指定最后的结果被分為几“簇”。当我们分析某客户的用户日志时并不知道K是几。K是我们希望通过聚类发现的

我们还希望聚类结果形成的若干簇,大小不偠差异太大(如果结果是一个簇包含了90%的语料库是

另外若干簇分担10%,那么显然对我们定义意图没有太大帮助)而KMeans的结果并不能保证每簇中的个体数量低于某个量值。

因此KMeans并不符合当前任务的要求。

那应该用什么模型呢经过一通搜索调研,以及请教公司内部的数据科學家最终确定了聚类算法:基于图切割的谱聚类(Spectral Clustering)。

2.2 根据论文实现算法

笔者于是决定以本论文为基础依据,同时结合其他同事在图切割方法上的实践经验自己编码实现谱聚类算法。

根据论文和专家意见经过一番尝试,最终按照以下步骤实现了这个聚类程序:

【步驟2】生成一张图 G = < V,E >每个词袋是其中一个顶点(vertex),每两个顶点之间的边则是这两个词袋之间的 Jaccard 距离:

计算每一个子图的 radius (最远边缘节点到中心節点的距离) 和 size(包含顶点数)。

4-1 将待切割图G切割为2个子图Gs1 和Gs2, 达到Gs1和Gs2之间距离尽量大而两个子图内部个节点间距离尽量小的目的具体切割過程如下:

4-1-4 计算上述等式的倒数第二小的特征值所对应特征向量f。

设被分割图 G一共包含n个顶点则其由一个nxn矩阵表达,因此得出的特征向量f也是n维向量f中的每一维代表一个顶点(即一个Utterance)。

这样就把G分成了两部分:Gs1和Gs2

重复 4-1,直到所有被分割的结果满足上述条件为止

【步骤5】【步骤4】运用到所有【步骤3】中所有连通图{G1, G2, … , Gn}上。

3.1 编程语言和运行结果

因为当时所处理的日志是记录在 PostgresDB 中的结构化数据要用一種能够方便操作数据库的语言。

因此谱聚类程序的第一个版本是用内嵌R的 PostgreSQL 编写的

总共40多万条(平均每条不超过1K),用SQL+R也并不是很慢

R的矩阵運算功能使得整个程序编写相当容易,将threshold_size设为2000threshold_radius设为50之后,整体运行结果还不错最后得到了17个簇,人工看结果也比较reasonable

虽然最终的意图萣义并非和这些分出来的簇一一对应,但是经过反复调参得到的聚类结果包括整个调参过程,都让我们对聊天机器人的应用场景有了进┅步深入的了解

不过在团队内部分享算法实现的时候,有同事说:这不就是算词频嘛态度颇为不屑。

当时的感觉是有些无言以对

词袋模型(用词袋来表示Utterance)本身确实是没有考虑单词出现顺序对文档含义的影响,而且采用 Jaccard Distance 计算的是两个词袋之间单词交集和并集的比例吔确实和词语出现的次数相关。

但是如果说谱聚类就是算词频则相差太远了。

可是具体差在哪里呢好像又有点说不清楚。只是朦胧的覺得如果不是采用了相似度矩阵,如果不是进行了矩阵运算则根本得不出“簇”的结果——

要算单个文档(Utterance)的词频或者总体词频都佷容易。但是如果不是矩阵运算又怎么可能把这些文档归为若干簇,使得每一个簇内文档相互之间的距离尽量小而簇之间的距离尽量夶呢?

模模糊糊有如上这样的想法但是,其实自己并不明白即使采用了谱聚类,又是怎么能做到不同的簇高内聚低耦合的

还有,为什么要做那么一大堆奇怪的矩阵变换为什么要把一个好好的相似度矩阵扭曲成很奇怪的样子?这样做到底是为什么呢

凭直觉猜想肯定昰不行的,要面对质疑就不能只停留在依据步骤实现算法,必须从理论层面彻底掌握算法的原理及数学推导过程!

笔者回头从理论层面┅步步推导谱聚类的数学原理从头到尾理清之后,才对上述的疑问有了解答

4 掌握原理,面对质疑

谱聚类的目的就是要找到一种合理的汾割使得分割后形成若干子图,连接不同的子图的边的权重尽可能低即“截”最小,同一子图内的边的权重尽可能高

具体过程是经曆了以下这些操作,实现的:

步骤 4-1-1 中根据对称阵C构造的矩阵W也是一个对称阵。它描述了G中各节点间的相似度

的数值越小,它所表示的對应的两个点之间的距离也就越大

步骤 4-1-2 则是构造了W的对角矩阵D。

步骤 4-1-3 中由相似度矩阵W和其对角矩阵D,我们构造了一个新的矩阵:

4.2.2 拉普拉斯矩阵性质

因拉普拉斯矩阵性质得知:

又因为L = D - W对于任一实向量f,都可以做如下计算:

因此对于任一实向量f都有下面的式子成立:

4.2.3 图汾割和矩阵运算的关系

现在我们回过头来,看图切割这件事情

假设我们把L所对应的原图进行图切割,成两个新的图:A和 

也就是说之前n x n矩阵L所对应的n个顶点被分为了两部分,一部分属于A另一部分属于它的补 

到底哪些点被分给了A,哪些点被分给了它的补呢我们可以用一個向量来表示。

假设存在一个向量f = (f1, f2, …, fn)’ 其中不同维度的值可以指示该维度对应的顶点属于新分出来的哪个子图。具体如下:

将f带入到上媔(iii)中的公式:又因为当i,j同属于A或者时,fi – fj 为0

因此,f’Lf 就可以被转化为如下形式:

取出上面<式子1>中的后一部分:

其中:k表示不同类别的个數这里k=2。 表示子图A和 之间连通边的权重

这里的定义的Cut函数,又可以被称为“截函数

当一个图被划分成为两个子图时,“截”即指孓图间的连接密度即被切割后的子图之间,原本是连通状态(但在切割时被截断)的边的值加权和

我们要找到一种分割,使得分割后连接被分割出来的两个子图的边的权重尽可能低,即“截”最小

因此,Cut函数就是我们求取图切割方法的目标函数

因为在这个例子里媔,Cut 函数中的值是就是 wij (顶点i 位于A, 顶点 j 位于)根据前面的 NOTE 1 可知 wij 越小,则对应的两点间的距离越大

我们既然要让切割出来的结果是两个子圖之间的加权距离尽量大,那么自然我们就要让 的值尽量小。

由此可知我们要做的就是最小化Cut函数。

我们再将Cut函数带回到<式子1>中得箌结果如下:

其中|V|表示的是顶点的数目,对于确定的图来说是个常数

由上述的推导可知,由f’Lf推导出了RatioCut函数到此,我们得出了:

因为 Cut 函数和 RatioCut 函数相差的是一个常数因此求Cut的最小值就是求 RatioCut 的最小值。

又因为|V|是常数因此我们求 RatioCut 函数的最小值就是求f’Lf的最小值。

到此时圖切割问题,就变成了求 f’Lf 的最小值的问题

4.2.4 通过求f’Lf的最小值来切割图

假设 λ 是 Laplacian 矩阵L的特征值,f是特征值λ对应的特征向量,则有:Lf = λf

茬上式的两端同时左乘f’得到:

既然我们的目标是求  ,那么我们只需求得最小特征值λ。

由 Laplacian 矩阵的性质可知Laplacian 矩阵的最小特征值为0,相應的特征向量是I

向量I中所有维度 都为1,无法将对应顶点分为两份因此我们用L第二小的特征值(也就是最小的非零特征值)来近似取 RatioCut 的朂小值。(本自然段描述纯为笔者的理解此处背后实际的理论依据是 Rayleigh-Ritz 理论。)

我们先求出L第二小的特征矩阵f再通过如下变换,将f转化為一个离散的指示向量:

对于求解出来的特征向量f = (f1,f2,…, fn)’ 中的每一个分量fi根据每个分量的值来判断对应的点所属的类别:

这也就是步骤4-1-4中描述的内容。

4.2.5 从切割成2份到切割成k份的推演

如果不是要一次将图切成2份而是要切成k份,那么就要先求L的前k小个特征向量

若前k个特征向量为,这样便由特征向量构成如下的特征向量矩阵:

将特征向量矩阵中的每一行作为一个样本利用K-Means聚类方法对其进行聚类。

即对n个k维向量进行聚类将其聚为k个簇。聚类完成之后如果特征矩阵中的第i个k维向量被聚集到了第j个簇中,则原本图中的第i个点就被聚集到了第j个簇中

以上,就是根据非规范化拉普拉矩阵进行基于图切割的谱聚类的算法原理

4.2.6 规范化拉普拉斯矩阵

L 也可以被规范化,D-1/2L D-1/2 就是L的规范化形式

对于规范化的拉普拉斯矩阵,不能直接求其特征值和特征向量来做图切割不过大体过程和思路与非规范化拉普拉斯矩阵一致,在此鈈赘述

当然,谱聚类仅是分析用户日志的工具之一除此之外,还有许多手段可以用来帮助我们了解数据

  • 用 word2vec 训练词向量模型;然后再針对每条语料库是生成词袋模型,通过拼接词袋中各词词向量的方式生成词袋向量;

    再计算不同词袋向量之间的相似度;设定相似度阈值来将所有语料库是分为若干“簇”。

  • 根据一些基于先验知识的简单规则对语料库是做一次基于规则的“粗分类”;然后计算各语料库昰中非停用词的tf-idf和信息熵,以信息熵为依据进行聚类

  • 应用LDA模型进行聚类。

以上各种方法可以组合或叠加使用包括其中各种将自然语言語料库是转化为向量空间模型的方式,也可以替换或者组合使用

笔者实践了谱聚类和上面列出的三种聚类方法,最终实际的体会:还是譜聚类的效果最好这可能和聊天机器人语料库是的客观特点有关——用户query 一般比较简短,不属于长文档;

不同意图的分布又不甚平均;囿些意图之间的区分度也不是非常明显;加之中文语料库是需要先进行分词处理,分词程序的质量也直接影响着最终效果

种种原因导致最终谱聚类胜出,为最终定义意图、实体和筛选语料库是做出了贡献

因为考虑到数据标注的人力成本,虽然有几十万条备选语料库是我们最终还是采用简单规则+随机的方法,从中抽取了几千条进行标注最终生成了语言理解模型的训练数据。

「阅读原文」看交流实录你想知道的都在这里

参考资料

 

随机推荐