推荐系统中的embedding应该怎么做?

看看kdd21中的新思路

Posted by Wenqian on July 23, 2021

为什么要有embedding?

需要embedding主要是因为目前推荐系统中的ctr或cvr预估模型开始越来越多地使用深度学习模型,考虑到神经网络并不是很善于直接处理离散数据,我们需要把它先映射到一个连续空间再喂给神经网络。另外,由于离散特征往往都很稀疏,embedding往往也起到了降维的作用,尤其是对于那些取值上百万千万的id特征。

当前的常见做法

目前对于id类特征进行embedding的常见做法是将其先进行one-hot编码,然后进行full embedding或者hash embedding。

full embedding

full embedding其实就是给one-hot向量左乘一个权重矩阵W,假设ne-hot向量的第k位是1,那么W的第k列就是最后的embedding。因此采用这种做法来进行embedding一般需要存储权重矩阵W(也被叫做look-up table),这样在训练完成后进行inference的过程其实就是一次查表。整个结构可以看做是基于one-hot编码的一层无bias的神经网络(也没有激活层)。

hash embedding

full embedding存在两个问题:一是embedding table的大小随着离散特征取值数量的增长而线性增长,那么对于数量非常大的id类特征来说,其embedding table会非常大;二是full embedding无法处理未见过的特征值,例如新用户或者新物品(针对user_id和item_id)。hash embedding就可以解决这两个问题,它的做法是利用hash方程H来对one-hot编码向量进行降维,例如从n维降到m维(m<n),但注意降维后它仍然是个one-hot编码。由于进行了降维,因此embedding table的大小会少很多,但是同时也带来了embedding碰撞的问题,即多个原始取值在经过hash后取值一样。常见的解决办法是采取多个hash方程,然后把结果拼在一起。之后的生成embedding table的方式其实和full embedding是一样的,也是一层神经网络(无bias和激活函数)。

DHE(Deep Hash Embeddings)

hash embedding同样有两个问题:一是基于one-hot编码,导致其原始空间每个维度的熵太低;二是存在embedding碰撞的可能。由此谷歌提出了一种深度hash embedding(DHE)的方法来解决现有embedding方式的问题[1]。文章将embedding的过程分为编码和解码两部分。一个好的编码方法应该包含四个特性:

  1. 独特性
  2. 同等相似性
  3. 高维特性
  4. 高香农熵

独特性是说不同的原始特征取值应该对应不同的编码值;同等相似性是说在没有额外信息的情况下,不同原始取值对应的编码值之间的相似性应该是一致的;高维特性是说编码后的值维度不能太低,否则无法包含太多信息;高香农熵是说我们希望编码的每个维度都能尽可能的包含更多信息。

作者采用的是一种dense hash encoding的方式,选取k个全域哈希方程(universal hash function)来将原始特征映射为一个k维实数稠密编码,每一维的取值范围为{1, 2, …, m},m可以取一个很大的数,例如10^6。由于该结果每一维其实都是整数,不好直接喂给神经网络,因此后面需要再接上一个变换函数,来将每个维度的取值映射到一个平均分布或高斯分布上。k的取值也可以比较大,作者最后是选择了1024。

后面的解码部分则比较简单,就是一个DNN,激活函数采用的是比较新的Mish激活函数,另外还加上BN层来稳定训练过程。

我个人觉得这篇文章最大的优点是梳理了当前主要的一些离散特征的embedding方式,并且给出了构造encoder时需要考虑的几个特征。最大的问题其实很明显,那就是效率太差!且不说用Mish激活函数这种“炼丹操作”,一同复杂的DHE网络搞下来,训练和infer的过程可能都变慢了。按照作者的实验结果,即使在GPU上,DHE进行infer的耗时也是Hash embedding的4~5倍,是full embedding的9倍左右,这在实际应用场景中大概率就是既没什么效果提升,还涨频响的操作,没人会用的,可能也就只能发发文章。

稠密特征的embedding

上面提到的都是如何对离散特征进行embedding,那稠密特征呢?感觉这块的研究确实相对较少,一般做法就是这么几种:

  1. 不进行处理,直接喂给神经网络,或者进行一些简单的处理,例如标准化。
  2. field embedding,即同一个field共享一个均匀分布的field embedding,并在之后将其乘上特征的原始取值来作为最后的结果。
  3. 先进行离散化,然后当做离散特征进行embedding。离散化的方式一般有EDD(即按照取值进行均匀切分)、EFD(即按照各个取值的出现频率进行均匀切分)、LD(对数离散化,即先取对数,再进行离散化)以及TD(基于树模型,例如GBDT进行离散化)。

在工业界中,采用方法3的比较多。但是先进行离散化会产生三个问题:一是无法将离散化过程和最后的训练目标进行统一,只能人为切割成两个阶段;二是可能出现相近取值进行embedding后得到的embedding向量距离比较远;三是可能出现原始值比较远的经过embedding后取值一样(比如桶数比较少的时候)。

由此,这篇文章的作者提出了一种新的处理稠密特征的embedding方式 —— AutoDis[2]。他们认为一个好的embedding方法应该具有以下三个特点:

  1. 高模型容量
  2. 可端对端训练
  3. 独特表示(unique representation),即不同原始值对应不同embedding

AutoDis的主要思路是将离散化的过程进行优化,由原来的hard discretization变为soft discretization。hard离散化其实就是根据各种方式进行分桶,无论什么值,最后只能落入有限的几个桶内。soft离散化简单来说就是允许你落到多个桶内,每个桶都落一点点,最后的结果相当于是各个桶对应embedding的加权和,具体算法详见原论文,感觉还是蛮有意思的。和上面一篇文章不同的是,这个方法对耗时的影响没有很大,大约加了4%,感觉还是可以接受,以后有机会说不定可以试试。

总的来说,KDD2021的两篇文章写的还是不错的,对本方向上现有方法的总结以及自身方法论的描述都做的很好。当然,算法到底在工业界有没有用那就见仁见智了。我个人觉得阅读后还是觉得很有收获的,两篇文章都值得一读。

Reference

[1] Learning to Embed Categorical Features without Embedding Tables for Recommendation[J]. 2020.

[2] Guo H , Chen B , Tang R , et al. AutoDis: Automatic Discretization for Embedding Numerical Features in CTR Prediction[J]. 2020.