Scikit-learn:并行化随机梯度下降

时间:2014-01-10 18:47:32

标签: python parallel-processing machine-learning mpi scikit-learn

我有一个相当大的训练矩阵(超过10亿行,每行两个特征)。有两个类(0和1)。 这对于一台机器来说太大了,但幸运的是我有大约200台MPI主机供我使用。每个都是一个适度的双核工作站。

功能生成已成功分发。

Multiprocessing scikit-learn中的答案表明可以分发SGDC分类器的工作:

  

您可以跨核心分发数据集,执行partial_fit,获取权重向量,对它们求平均值,将它们分配给估算器,再次进行部分拟合。

当我在每个估算器上第二次运行partial_fit时,我从哪里开始获取最终的汇总估算器?

我最好的猜测是再次对coefs和截距进行平均,并使用这些值进行估算。结果估计器给出的结果与使用fit()在整个数据上构造的估计量不同。

详细

每个主机生成局部矩阵和局部向量。这是测试集的n行和相应的n个目标值。

每个主机使用局部矩阵和局部向量来制作SGDC分类器并进行部分拟合。然后每个都将coef向量和截距发送到root。 Root对这些进行平均并将它们发送回主机。主机执行另一个partial_fit并将coef向量和截距发送到root。

Root构造一个具有这些值的新估算器。

local_matrix = get_local_matrix()
local_vector = get_local_vector()

estimator = linear_model.SGDClassifier()
estimator.partial_fit(local_matrix, local_vector, [0,1])

comm.send((estimator.coef_,estimator.intersept_),dest=0,tag=rank)

average_coefs = None
avg_intercept = None

comm.bcast(0,root=0)
if rank > 0:
    comm.send( (estimator.coef_, estimator.intercept_ ), dest=0, tag=rank)
else:
    pairs = [comm.recv(source=r, tag=r) for r in range(1,size)]
    pairs.append( (estimator.coef_, estimator.intercept_) )
    average_coefs = np.average([ a[0] for a in pairs ],axis=0)
    avg_intercept = np.average( [ a[1][0] for a in pairs ] )

estimator.coef_ = comm.bcast(average_coefs,root=0)
estimator.intercept_ = np.array( [comm.bcast(avg_intercept,root=0)] )
estimator.partial_fit(metric_matrix, edges_exist,[0,1])

if rank > 0:
    comm.send( (estimator.coef_, estimator.intercept_ ), dest=0, tag=rank)
else:
    pairs = [comm.recv(source=r, tag=r) for r in range(1,size)]
    pairs.append( (estimator.coef_, estimator.intercept_) )
    average_coefs = np.average([ a[0] for a in pairs ],axis=0)
    avg_intercept = np.average( [ a[1][0] for a in pairs ] )

    estimator.coef_ = average_coefs
    estimator.intercept_ = np.array( [avg_intercept] )
    print("The estimator at rank 0 should now be working")

谢谢!

2 个答案:

答案 0 :(得分:10)

在具有1e9个样本和2个特征的数据集上训练线性模型很可能在数据实际上是线性可分的情况下不足或浪费CPU / IO时间。不要浪费时间考虑用线性模型并行化这样的问题:

  • 要么切换到更复杂的模型类(例如,在适合内存的数据的较小分区上训练随机森林并聚合它们)

  • 或者选择增加和训练线性模型的数据集的随机子样本。测量保持测试的预测准确性,并在看到收益递减时停止(可能在少数几个样本的数千个样本之后)。

答案 1 :(得分:5)

您所遇到的是正常和预期的。首先,使用SGD意味着您永远不会达到确切的结果。您将快速收敛到最佳解决方案(因为这是一个凸起的问题)然后在剩余的区域内盘旋。单独使用整个数据集的不同运行应该每次产生略微不同的结果。

  

我从那里去哪里获得最终的汇总估算器?

理论上,你会一直这样做,直到你对融合感到满意为止。对你正在做的事完全没必要。其他系统切换到使用更复杂的方法(如L-BFGS)来收敛到最终解决方案,因为他们对解决方案有一个良好的“热启动”。然而,这不会让你在准确性方面有任何大幅提升(想想如果你运气好的话可能会获得整整一个百分点) - 所以不要认为它是成败。考虑它是什么,一个微调。

其次是线性模型不能很好地并行化。尽管有vowpalwabbit和其他一些库的说法,但你不会在并行训练线性模型时进行线性扩展。简单地平均中间结果是并行化这样一个系统的一种坏方法,遗憾的是它与并行训练线性模型一样好。

事实是,你只有2个功能。您应该能够使用较小的数据子集轻松训练更复杂的模型。只有2个功能,10亿行是过度杀伤。