广告行业中那些趣事系列30:实际业务超好用的SimBERT

2022-05-05 13:33:45 浏览数 (2)

导读:本文是“数据拾光者”专栏的第三十篇文章,这个系列将介绍在广告行业中自然语言处理和推荐系统实践。本篇从理论到实际讲解了实际项目中使用很多的SimBERT模型,对于希望将SimBERT应用于实际项目中的小伙伴可能有所帮助。

摘要:本篇从理论到实际讲解了实际项目中使用很多的SimBERT模型。首先介绍了业务使用背景,主要用SimBERT的相似文本生成和相似文本检索能力;然后详细介绍了SimBERT的原理,SimBERT是基于UniLM来完成文本生成任务,重点介绍了SimBERT的损失函数和训练流程;最后源码实践了SimBERT,通过广告文案生成模型实践了相似文本生成任务,并基于SimBERT Faiss实践了相似文本检索任务。对于希望将SimBERT应用于实际项目中的小伙伴可能有所帮助。

下面主要按照如下思维导图进行学习分享:

01 背景介绍

咱们还是按照老惯例先讲下SimBERT的业务应用背景,因为总觉得做一件事最重要的是先搞清楚目的是什么,明确目标然后聚焦完成。SimBERT是追一科技开源的一款基于BERT根据文本语义相似度进行召回的项目,下面是开源项目github地址以及项目说明:https://github.com/ZhuiyiTechnology/simbert

SimBERT主要的应用场景分成相似文本生成和相似文本检索,下面分别进行详细说明。

1.1 相似文本生成

相似文本生成任务其实就是用户输入一段文本,SimBERT会生成相似的文本。下面是生成任务效果展示图:

图1 生成任务效果展示图

看到这儿是不是觉得有点眼熟,这个任务其实和我们的文案生成模型非常相似,广告主输入一些生成条件,比如“捕鱼游戏,好玩,金币”,模型就会生成对应的广告文案。下面是我们根据SimBERT构造文案生成模型的效果图:

图2 文案生成模型效果图

不仅如此,根据SimBERT进行微改造还可以实现很多下游Seq2Seq任务,比如自动摘要任务等等。

1.2相似文本检索

相似文本检索任务就是用户输入一段文本,模型会从文本库检索出语义相似的文本。这个任务的本质是获取文本的语义向量,然后在文本库中根据相似度(这里计算相似度的方法很多,比如余弦相似度等等)计算和当前文本的语义向量相近的文本向量,这里文本库存储的也是文本对应的语义向量。因为最重要的是获取文本的语义向量,所以用BERT或者SimBERT都可以。

1.3文本分类任务获取伪标签语料

基于SimBERT生成相似文本和检索相似文本的能力,我们会在文本分类任务中通过SimBERT来获取更多的伪标签语料。通过SimBERT根据现有的标注语料来生成相似文本,或者构建搜索库从搜索库中检索相似文本可以获取很多语义相关性较好的伪标签语料数据。这在实际的业务中也证明了可以有效提升我们分类器的效果。在之前的文章《广告行业中那些趣事系列28:基于半监督或自监督解决文本分类中样本不均衡问题》我们主要就是利用SimBERT检索文本库从而获取大量的伪标签语料来提升分类器的效果。

小结下,这一节主要讲了SimBERT的主要应用场景,主要分成相似文本生成能力和相似文本检索能力。利用相似文本生成能力我们可以构造文案生成模型,利用相似文本检索能力我们能给文本分类任务增加伪标签语料,提升分类器能力

02 详解SimBERT

上面讲了SimBERT的应用场景,本节主要讲下SimBERT的原理。

2.1 Seq2Seq任务和UniLM模型

讲SimBERT之前需要讲下Seq2Seq任务和UniLM模型。在之前的文章《广告行业中那些趣事系列29:基于BERT构建文案生成模型》中说过Seq2Seq任务是输入一段文本,模型会输出另外一段文本。Seq2Seq任务主要使用编码器和解码器结构,编码器会将输入的一段文本编码成固定大小的向量hn,然后解码器会根据这个向量hn通过自回归的方式来解码生成对应的文本。BERT因为使用的是双向可见的注意力机制,对于每个词来说所有词都是可见的,所以主要用来做NLU自然语言理解任务,比如文本分类啥的。后来微软通过构建前缀双向可见的注意力机制将BERT改造成可以处理NLG自然语言生成任务,这就是UniLM模型。通过UniLM我们可以完成文本生成任务,这就是SimBERT可以进行文本生成的前提。

2.2 SimBERT的文本生成能力就来源于UniLM模型

上一节说过SimBERT同时具备相似文本生成能力和相似文本检索能力,因为相似文本检索能力其实BERT也可以做,所以咱们重点关注SimBERT的相似文本生成能力。SimBERT本身就是基于UniLM模型完成的,所以自然具备文本生成能力。

2.3 SimBERT的损失函数和训练流程

SimBERT模型训练属于有监督学习任务,使用的训练数据是相似语句对,下面是训练数据样式:

图3 SimBERT训练数据格式

从上图可以看出,训练数据是相似文本对的方式,包括一条文本和对应的相似语义文本列表。SimBERT模型的损失函数包括两部分,第一块是构建Seq2Seq任务,也就是通过输入文本去预测对应相似文本;第二块是构建语义相似度任务,会根据文本对应的CLS向量来计算相似度。下面是SimBERT训练方式的示意图:

图4 SimBERT训练方式的示意图

上图是SimBERT训练方式的示意图,右边是Seq2Seq任务部分,将输入文本和对应的相似文本通过SEP进行拼接,比如现在有sentence1和sentence2,那么会将数据转化成CLS_sentence1_SEP_sentence2_SEP这样的方式。然后根据sentence1去预测sentence2;左边是语义相似度部分,本质是把batch里面不相似的样本作为负样本,然后通过softmax函数计算相似样本的相似度。举例说明,上面6条数据中,和第1条样本s1相似的是s2,其他都不相似,将本身Mask掉,那么就会得到Mask_1_0_0_0_0这样的数据。这里需要说明的是因为使用UniLM模型所以数据中有效的仅仅是CLS_sentence1_SEP部分。SimBERT通过这种训练方式,既可以完成相似文本生成任务,还可以获取文本语义向量完成相似文本检索任务。

小结下,本节主要讲了SimBERT的原理。SimBERT同时拥有相似文本检索能力和相似文本生成能力,其中重点是相似文本生成能力。利用UniLM的前缀双向可见的注意力机制SimBERT可以很好的进行文本生辰任务。SimBERT通过构建Seq2Seq任务和语义相似度任务就可以很好的实现相似文本生成。

03 源码实践SimBERT

上一节主要讲了SimBERT的原理,这节会分别从相似文本生成和相似文本检索来实践SimBERT。

3.1 实践相似文本生成任务

相似文本生成任务因为和文案生成模型非常相似,所以这里主要实践文案生成模型。基本上可以复用SimBERT的训练流程。

文案生成模型损失函数代码如下图所示:

图5 文案生成模型损失函数代码

构建模型非常简单,只需要下面几行代码就可以搞定,构建文案生成模型代码如下图所示:

图6 构建文案生成模型代码

文案生成模型解码器部分使用随机采样生成random_sample函数,解码器每轮解码的时候会从概率值top(k)里随机采样一个token用于生成,这种方式有利于生成结果的多样性。而对于自动摘要类任务,解码器则主要使用beam search策略,因为同一篇文档得到的摘要一般是确定的。具体代码如下图所示:

图7 文案生成模型解码器代码

这里重点讲下文案生成模型的训练数据集构建。模拟广告主使用文案生成模型来生成广告文案,主要是输入行业标签、对应的关键词,然后模型会生成对应的文案。任务初期主要根据行业标签来生成对应的文案,后续会根据更加丰富的生成条件来生成对应的文案,下面是训练数据举例:

图8 文案生成模型初期和后续版本数据集

如上图所示,文案生成模型初期是根据行业标签名来生成对应的文案。这种方式的生成条件粒度比较粗,参考头条的巨量创意平台,会同时根据行业和用户输入的关键词来生成对应的广告文案,相当于生成的文案不仅是属于当前行业标签,而且会尽量包含用户输入的关键词,相当于生成的文案粒度更细了。针对这种情况,后续版本会在初期版本的基础上再增加细粒度的训练数据,比如输入是“传奇游戏,爆率”时对应的文案也尽量包含爆率或者同义词,这样生成的文案就会更加符合广告主的需求。

3.2 实践相似文本检索任务

相似文本检索任务其实就是先根据SimBERT或者BERT来获得文本对应的语义向量,同时将文本库中的文本也加工成语义向量,最后计算向量相似度找距离最近的文本作为相似文本。目前线上主要使用基于SimBERT Faiss的方案来构建大规模相似文本检索。整体流程如下所示:

  • 安装faiss库

Python环境下安装faiss库如果用pip会报错,主要需要使用conda。需要提前保证是完整的conda环境,下面是conda安装faiss的命令:

代码语言:javascript复制
conda install faiss-gpu cudatoolkit=10.0 -cpytorch
conda install faiss-cp
  • 通过simbert来生成文本库的向量

这个过程其实就是用simbert将文本数据转化成对应的768维度向量。

  • 使用pca进行降维(可选操作)

因为我们线上主要是短文本,所以使用pca将768维向量转化成256维向量。在内存一定的情况下通过降维可以有效提升文本检索库的量级。这个流程是可选项,如果文本库量级本身不大,那么直接用768维度也没问题。

  • 使用faiss生成索引

使用faiss生成对应的索引需要选择合适的index类型。这里重点注意下内存开销,如果不在意内存占用空间,使用“HNSWx”,如果稍微有点在意,使用“...,Flat“,如果很在意,使用”PCARx,...,SQ8“,如果非常非常在意,使用"OPQx_y,...,PQx"。

  • 输入文本根据索引进行检索

最后就是根据输入文本去检索库里面检索相似文本流程。

下面给一个基于SimBERT Faiss的方案来构建大规模相似文本检索的例子,根据一个csv文本的数据集先构建Faiss索引库,然后输入文本,输出相似的文本。开源代码在这里:https://github.com/wilsonlsm006/simbert_task/simbert_search.py

总结及反思

本篇从理论到实际讲解了实际项目中使用很多的SimBERT模型。首先介绍了业务使用背景,主要用SimBERT的相似文本生成和相似文本检索能力;然后详细介绍了SimBERT的原理,SimBERT是基于UniLM来完成文本生成任务,重点介绍了SimBERT的损失函数和训练流程;最后源码实践了SimBERT,通过广告文案生成模型实践了相似文本生成任务,并基于SimBERT Faiss实践了相似文本检索任务。对于希望将SimBERT应用于实际项目中的小伙伴可能有所帮助。

0 人点赞