之前搞对话系统时接触了StarSpace (抛开事实不谈,首先这个名字就比Glove、Elmo、Transformer……来的有诗意),用于计算 Intent 和 Action 的关系,效果还不错,一查发现,原来师出名门,来自Facebook AI Research2017年底发表的经典论文《StarSpace: Embed All The Things!》,一种通用的神经嵌入模型,要 Embedding 一切,霸气十足。
当然面对不同的场景,没有万能算法,推荐StaSpace也是希望各位在遇到Embeding问题时,除了Word2Vec、Node2Vec、Bert等算法外,能够多一种选择。
论文开篇也是毫不掩饰,直入主题。既然要 Embedding 万物,那凡是需要 Embedding 的任务,以下任务StarSpace都可以胜任:
在每种情况下,模型都是通过嵌入由离散特征组成的实体并相互比较,根据任务类型来学习它们之间的相似性。StarSpace可以被视为一种直接且高效的 strong baseline,和Word2Vec、Glove、fasttext等相比毫不逊色,甚至优于它们,当然最大的特点还是通用,把各种各样的数据投射到向量空间中,包括但不限于:文本、文章、主题、标签、知识图谱等。
口说无凭,作者在①文本分类②知识库关系预测③文档推荐④文章检索⑤句子匹配⑥学习句子向量6个不同任务上做了对比实验,评估算法的质量。
论文的目标是获得实体(entities)的embedding,而实体是一个很泛泛的概念,一个词、一句话、一个节点、一个用户……都可以成为一个实体,可以用稀疏向量(one-hot)来表示:
以上稀疏向量转化为dense embedding就很简单了,把稀疏向量乘以一个 词典大小 embedding维度 的矩阵即可。
StarSpace可以很自由的去比较不同类型的实体。
F 为 包 含 D 个 特 征 的 字 典 , 表 示 为 D × d 的 矩 阵 , 则 F i 为 第 i 个 特 征 生 成 的 d 维 e m b e d d i n g , 那 么 实 体 a 的 e m b e d d i n g 为 ∑ i ∈ D F i , 即 每 个 f e a t u r e 都 有 一 个 嵌 入 , 由 于 一 个 实 体 a 具 有 不 同 的 f e a t u r e , 所 以 构 成 实 体 a 的 嵌 入 就 是 这 些 特 征 的 加 和 ( 或 加 权 和 ) ( 和 w o r d 2 v e c 之 后 进 行 s e n t e n c e e m b e d d i n g 是 一 样 的 ) 。 也 就 是 说 , 与 其 他 嵌 入 模 型 一 样 , 首 先 要 给 打 算 e m b e d d i n g 的 集 合 中 ( 论 文 称 为 字 典 , 包 含 诸 如 单 词 等 特 征 ) 每 个 离 散 特 征 分 配 一 个 d 维 向 量 。 实 体 由 字 典 中 的 特 征 包 表 示 , 它 们 的 嵌 入 是 隐 式 学 习 的 , 一 个 实 体 也 可 以 由 单 个 ( 唯 一 ) 属 性 构 成 , 例 如 单 个 单 词 、 名 称 、 用 户 或 项 目 I D 。 为 了 训 练 模 型 , 需 要 比 较 实 体 的 距 离 , 也 就 是 最 小 化 一 下 损 失 函 数 : \small F为包含D个特征的字典,表示为D \times d的矩阵,则F_i为第i个特征生成的d维\\ embedding, 那么实体a的embedding为\sum_{i\in D}F_i ,即每个feature都有一个嵌入,\\由于一个实体a具有不同的feature,所以构成实体a的嵌入就是这些特征的加和\\(或加权和)(和word2vec之后进行 \,sentence\,embedding\,是一样的)。也就是说,\\与其他嵌入模型一样,首先要给打算embedding的集合中(论文称为字典,包含\\诸如单词等特征) 每个离散特征分配一个d维向量。实体由字典中的特征包表示,\\它们的嵌入是隐式学习的,一个实体也可以由 单个(唯一)属性构成,例如单个\\单词、名称、用户或项目ID。为了训练模型,需要比较实体的距离,也就是最小化\\一下损失函数: F为包含D个特征的字典,表示为D×d的矩阵,则Fi为第i个特征生成的d维embedding,那么实体a的embedding为∑i∈DFi,即每个feature都有一个嵌入,由于一个实体a具有不同的feature,所以构成实体a的嵌入就是这些特征的加和(或加权和)(和word2vec之后进行sentenceembedding是一样的)。也就是说,与其他嵌入模型一样,首先要给打算embedding的集合中(论文称为字典,包含诸如单词等特征)每个离散特征分配一个d维向量。实体由字典中的特征包表示,它们的嵌入是隐式学习的,一个实体也可以由单个(唯一)属性构成,例如单个单词、名称、用户或项目ID。为了训练模型,需要比较实体的距离,也就是最小化一下损失函数: ∑ ( a , b ) ∈ E + , b − ∈ E − L b a t c h ( s i m ( a , b ) , s i m ( a , b 1 − ) , . . . , s i m ( a , b k − ) ) \small \sum_{(a,b)\in E^+,b^-\in E^-}L^{batch}(sim(a,b),sim(a,b^-_1),...,sim(a,b^-_k)) (a,b)∈E+,b−∈E−∑Lbatch(sim(a,b),sim(a,b1−),...,sim(a,bk−)) ∙ 正 实 体 对 ( a , b ) 来 自 E + ∙ 负 实 体 b i − 来 自 E − , 通 过 负 采 样 每 次 从 b a t c h 中 选 k 个 负 实 体 对 ∙ 相 似 度 函 数 s i m ( , ) 可 以 选 择 余 弦 或 内 积 ∙ 损 失 函 数 也 提 供 了 两 种 方 式 : m a r g i n r a n k i n g l o s s 和 n e g t i v e l o g l o s s o f s o f t m a x , 通 常 前 者 表 现 更 好 \scriptsize \bullet正实体对(a,b)来自E^+ \\ \bullet 负实体b^-_i来自E^-,通过负采样每次从batch中选k个负实体对\\ \bullet 相似度函数sim(,)可以选择余弦或内积 \\ \bullet损失函数也提供了两种方式:margin\,ranking\,loss和negtive\,log\,loss\,of\,softmax,通常前者表现更好 ∙正实体对(a,b)来自E+∙负实体bi−来自E−,通过负采样每次从batch中选k个负实体对∙相似度函数sim(,)可以选择余弦或内积∙损失函数也提供了两种方式:marginrankingloss和negtiveloglossofsoftmax,通常前者表现更好
从上一节可以看出,starspace的前向传播还是很简单的,就是两个embedding层。下面来看一看StarSpace具体是怎么做的。
举个:
老板让我们把商品评论向量化,实现可以给用户评论打标签的功能。我们找了一些数据,并自己打了标签,di表示评论,li表示标签:
①用共现矩阵来展示的话:
②将其他评论和标签的关系也加入其中:可以看出,d2和d5都有l1、l3,d1也有l1,但是没有l3,所以我们希望模型学习的过程中,d2和d5的向量离l3越来越近,而d1距离l3越来越远。这样就形成了一个个簇,像星座群一样(是不是有StarSpace那味了)。
③用 bag-of-words 把d1表示成[0,0,1,0,1,0] ,用 one-hot 来表示标签,把l1表示为[0,0,0,0,0,1] ,则通过下面的结构,把这两者给关联起来:④上图中希望d1评论的向量能够和l1标签比较的接近,为了能够向量能够进行计算,需要维度统一,由于sparse不同,所以要在输入和 dense layer 中间增加一个 feed forward 层来让维度统一。LABEL 就是共现矩阵中的关系。
⑤上面只是 positive example,negative example 则要进行 k-negative sampling。共现矩阵中未打✅的就是负样本。
以上就是StarSpace的整体结构:
StarSpace 的实战应用支持多种模式,无监督、有监督、单标签、多标签的都有。虽然Meta官方版本是用C++实现的,但是好在项目中提供了 python wrapper,可以方便我们在 python 的项目中使用。
我们可以通过调整 trainMode 和 trainFile 的格式来让 StarSpace 完成不同类型的任务。
下面看一下在文本分类任务的表现:
Github:https://github.com/facebookresearch/StarSpace