基于MPI的分布式LR、FM、FFM模型

        MPI版本的分布式LR模型是最先实现的,我在读研一时就有这个打算,当时就想着用自己实现的分布式模型做CTR预估,直到去年才真正实现。将代码实现的一些细节简单记录一下,方便以后继续优化。代码地址在:https://github.com/xswang/Field-aware-Factorization-Machine-mpi

       程序启动后会根据参数启动对应的进程数,每个进程功能是等价的,都要负责计算,不过会指定某个节点做参数的allreduce, 在代码中我指定了rank 0。

       hosts文件中是集群IP地址。

       n2n_config.h是配置文件,用来设置是否online,FTRL的各种参数等等。

       main.cpp主要就是MPI rank设置,程序启动过程。

       param.h是参数的设置,基本不需要改动。

       predict.h是计算AUC的,是个分布式来算的。基于MPI实现的可分布式计算AUC的代码在这里:https://github.com/xswang/AUC-caculate-mpi , 就不再单独用一篇笔记解释代码,一般每人关注AUC的算法细节,只需要记得在算ROC曲线下面积时按纵横轴scale就行了,剩下的就很好理解。

       learner中提供了几种优化算法,主要是FtrlLearner,在这个算法实现中,通过一些方式可以在实现LR模型的同时,也实现了FM和FFM模型。OWLQN没在这里实现,可以看这里:https://github.com/xswang/logistic-regression-owlqn-mpi/blob/master/src/owlqn.h,不过这个并行的OWLQN并没有有来的及做正确性测试,所以它目前是不能用的。

       在ftrl_learner.h中update_w()函数和update_v()函数,其中update_w()函数就是标准的参数w的更新算法,update_v是针对FM和FFM模型的更新算法,在第98行,如果用户配置只是用LR模型,直接break。第102行,f是FFM模型中每个特征拥有的latnet factor vector个数,如果用户只是用FM模型,则将f设置为0,也就是每个特征只对应一个latent factor vector,这针对这一个vector更行,否则将更新特征对应的所有的latent factor vector.

       在ftrl_learner.cpp中,run()函数是入口,根据配置文件选择是哪种训练方式。无论哪种方式,都使用了线程池,多线程之间需要同步的地方通过加锁实现。allreduce_gradient()函数主要负责梯度的收集,allreduce_weight负责模型更新和发送。整个过程体现了星型拓扑结构:rank 0作为主节点,收集梯度并更新模型之后,将参数发送给其它节点。

       在代码实现时用到了openblas科学计算库已经一个修改过的线程池。

       在代码写完之后,我使用了三台机器对LR和FM模型进行了测试,根据测试集AUC变化情况,FM的ROC曲线在最开始更陡峭,但是最终和LR差不多,也就是FM能更快的学习,但是最终结果并不明显比LR好,这可能也和当时没有充分调参有关。不过至少说明这个分布式FM模型代码是可用的。FFM模型并没有测,主要是速度太慢。

       比较遗憾的是并没有对MPI版本的LR和ps-lite版本的LR进行对比过。

       目前Parameter Server框架比较流行,也许没人会再用MPI同步训练模型了。LR模型基本上都已经在各个公司上线,FM也有不少公司开始探索,基于ps-lite的FM和FFM模型是我的下一个计划。2014时用DNN做CTR预估还是个很神秘的事情,然而现在也被打破了神秘感,不少公司都在探索。不过目前DNN模型还没有一个很好的离散特征值输入的分布式训练系统,线下训练可能会比较慢,上线也比较困难。

       

Leave a Reply

Your email address will not be published. Required fields are marked *