对于一个神经网络来说,有效地处理稀疏数据是很有挑战性的。由于缺乏代表性模型和数据集的公开可用细节,导致对推荐系统的研究进展缓慢。
DLRM(Deep Learning Recommendation Model)是深度学习推荐模型的实现,用于个性化推荐。DLRM通过结合协同过滤和基于预测分析的方法的原理,在其他模型的基础上取得了进展,这使得它能够有效地处理生产规模的数据,并提供最先进的结果。
DLRM 提供两个版本的代码,分别使用 PyTorch 和 Caffe2。此外,DLRM 还有一个使用 Glow C++算子实现的变体。为了适应不同框架,各个版本的代码略有不同,但整体结构类似。
dense feature和sparse indices嵌入的向量必须相同。dense用MLP来处理成一个向量,sparse indice用embdding_lookup嵌入到相同维度的向量。
模型(不同方式表达的两个模型图):
我按着DLRM随机生成的数据来讲解,有3个类(sparese feature)标签,一个dense feature标签。
DLRM_Net(
#用于sparse feature特征处理的网络结构
(emb_EmbeddingBag): ModuleList(
(0): EmbeddingBag(4, 2, mode=sum) # 第一类可有4个one-hot长度
(1): EmbeddingBag(3, 2, mode=sum) #第二类可有3个one-hot长度
(2): EmbeddingBag(2, 2, mode=sum) #第三类可有2个one-hot长度
)
#用于bottom_MLP处理的网络结构
(bottom_MLP): Sequential( #这是用于编码dense features设置的神经网络,输入4个神经单元,输出2个神经元
(0): Linear(in_features=4, out_features=3, bias=True)
(1): ReLU()
(2): Linear(in_features=3, out_features=2, bias=True)
(3): ReLU() #底部输出用的是Relu函数
)
#用于sparse feature和dense feature交互的网络结构
(top_MLP): Sequential( #这是用于处理交互的神经网络,输入8(为啥是8?下面会讲)个神经单元,输出1个(也就是最后的预测值)
(0): Linear(in_features=8, out_features=4, bias=True)
(1): ReLU()
(2): Linear(in_features=4, out_features=2, bias=True)
(3): ReLU()
(4): Linear(in_features=2, out_features=1, bias=True)
(5): Sigmoid() #顶部输出用的是Sigmoid函数
)
)
下面会详细介绍一下模型怎么进行交互的,这是模型最重要的部分。
比如dense feature数据处理后的向量为 [tensor([[0.41190, 0.00000]])]
3个类(sparse feature)标签嵌入后的向量为:tensor([[
[-0.05473, -0.15156],
[ 0.12820, 0.25686],
[ 0.18523, -0.57685]]])
首先dense feature和类别嵌入向量两两进行点积(就是对应元素相乘然后相加)得到他们之间的交互:
4个向量会有【n(n-1)/2】6种可能(也就是6个值):
tensor([[-0.02254, 0.05280, -0.04594, 0.07629, 0.07729, -0.12442]])
然后再和处理过后dense feature特征进行拼接得到:
tensor([[0.41190, 0.00000,-0.02254, 0.05280, -0.04594, 0.07629, 0.07729, -0.12442]])
这里就变成8个输入了,解释了上面标红的内容。
之后将这8个输入TOP—MLP网络并进行训练就可以了。
论文代码 :https://github.com/facebookresearch/dlrm
数据集下载地址:http://labs.criteo.com/2014/02/download-kaggle-display-advertising-challenge-dataset/
需要的软件包:
pytorch-nightly (6/10/19)
onnx (可选)
torchviz (可选)
Criteo数据集的首选硬件应该是:
CPU — 8核以上
GPU — 推荐
Ram — 64GB (任何低于内存大小的将不起作用)
代码文件说明:
dlrm_s_pytorch.py:在PyTorch框架下实现DLRM的文件
dlrm_s_caffe2.py文件:在caffe2框架下实现DLRM的代码文件
每个框架的代码略有不同,以适应每个框架的具体情况,但是总体结构是相似的。
测试代码能否正常运行,是否满足程序运行条件,打开程序当前位置的终端路径,然后输入:
python dlrm_s_pytorch.py --mini-batch-size=2 --data-size=6
$ python dlrm_s_pytorch.py --mini-batch-size=2 --data-size=6
time/loss/accuracy (if enabled):
Finished training it 1/3 of epoch 0, -1.00 ms/it, loss 0.451893, accuracy 0.000%
Finished training it 2/3 of epoch 0, -1.00 ms/it, loss 0.402002, accuracy 0.000%
Finished training it 3/3 of epoch 0, -1.00 ms/it, loss 0.275460, accuracy 0.000%
运行真实的数据集:
$dlrm_pt_bin --arch-sparse-feature-size=16 --arch-mlp-bot="13-512-256-64-16" --arch-mlp-top="512-256-1" --data-generation=dataset --data-set=kaggle --processed-data-file=./input/kaggle_processed.npz --loss-function=bce --round-targets=True --learning-rate=0.1 --mini-batch-size=128 --print-freq=1024 --print-time $dlrm_extra_option 2>&1 | tee run_kaggle_pt.log
--arch-sparse-feature-size=16 表示每个sparse feature特征嵌入到长度为16的向量(论文中有26个sparse feature)
--arch-mlp-bot="13-512-256-64-16 表示dense feature嵌入特征用的网络结构,13表示输入神经元个数,16表示输出神经元个数
--arch-mlp-top="512-256-1 表示top-MLP的结构,输入神经元个数是程序自己计算出来的。26(sparse)+1(dense)=27,两两交互产生351个值,与dense feaature处理后的长度为16的向量拼接得到367个值,作为top的输入(这些过程在程序中是自己计算出来的,好处是我们不用定义输入层,只需修改隐藏层和输出层就行),实际上top-MLP的网络架构为:367-512-256-1。输入神经元个数为376,输出神经元个数为1.
并行计算:
DLRM 基准模型提供了并行化的解决方案。但是这超出了论文的内容,作者没有细说,Facebook 研究团队计划优化这一系统,并在以后的博客中公开详细的性能细节。
模型的保存和加载
训练时,模型可以使用 --save-model=保存。如果在测试时准确率提升,则模型会被保存。查看测试精确率的命令是: --test-freq intervals。
可以使用 --load-model=加载之前保存的模型。加载的模型可以继续用于训练,通过 checkpoint 文件保存。如果只要求用模型进行测试,则需要特别命令—inference-only。