Python Scikit学习:并行化随机梯度下降

Python Scikit学习:并行化随机梯度下降,python,parallel-processing,machine-learning,mpi,scikit-learn,Python,Parallel Processing,Machine Learning,Mpi,Scikit Learn,我有一个相当大的培训矩阵(超过10亿行,每行两个功能)。有两个类(0和1)。 这对于一台机器来说太大了,但幸运的是我有大约200台MPI主机可供使用。每个都是一个普通的双核工作站 功能生成已成功分发 中的答案表明,可以分配SGDClassizer的工作: 您可以将数据集分布在各个核之间,进行部分拟合,获得权重向量,对其进行平均,将其分配给估计器,然后再次进行部分拟合 当我对每个估计器第二次运行partial_fit时,我应该从哪里得到最终的聚合估计器 我最好的猜测是再次平均COEF和截距,并用这

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

功能生成已成功分发

中的答案表明,可以分配SGDClassizer的工作:

您可以将数据集分布在各个核之间,进行部分拟合,获得权重向量,对其进行平均,将其分配给估计器,然后再次进行部分拟合

当我对每个估计器第二次运行partial_fit时,我应该从哪里得到最终的聚合估计器

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

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

每个主机使用本地矩阵和本地向量生成SGDClassizer并进行部分拟合。然后,每个发送coef向量和截距到root。Root将这些平均值发送回主机。主机进行另一次部分拟合,并将coef向量和截距发送到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")

谢谢大家!

如果数据实际上是线性可分离的,则在具有1e9个样本和2个特征的数据集上训练线性模型很可能会拟合不足或浪费CPU/IO时间。不要浪费时间考虑将此类问题与线性模型并行:

  • 或者切换到更复杂的模型类(例如,在内存中适合的较小数据分区上训练随机林并将其聚合)

  • 或者选择递增数据集的随机子样本并训练线性模型。在一个延迟测试中测量预测准确度,当你看到收益递减时停止(可能是在少数群体的数千个样本的10秒之后)


    • 你所经历的一切都是正常的,也是意料之中的。第一个事实是,使用SGD意味着你永远不会得到准确的结果。您将快速收敛到最佳解决方案(因为这是一个凸问题),然后在该区域停留剩余时间。单独对整个数据集进行不同的运行,每次应产生略有不同的结果

      我应该从哪里得到最终的总体估计

      从理论上讲,您只需不断重复,直到您对收敛感到满意为止。对你正在做的事情完全没有必要。其他系统使用更复杂的方法(如L-BFGS)来收敛到最终解决方案,因为它们对解决方案有了良好的“热启动”。然而,这不会给你带来任何准确的收益(如果你运气好的话,也许会得到一个百分点)——所以不要认为是成败。考虑它是什么,一个精细的调整。 第二个事实是线性模型不能很好地并行化。尽管有vowpalwabbit和其他一些库的声明,但是并行训练线性模型并不能得到线性伸缩。简单地对中间结果求平均是并行化这样一个系统的一个糟糕的方法,不幸的是,这和并行训练线性模型一样好


      事实上,您只有两个功能。您应该能够仅使用较小的数据子集轻松地训练更复杂的模型。10亿行对于2个特性来说是多余的

      普遍的共识似乎是对我的数据进行抽样。我想我只是把它复杂化了。谢谢。非常感谢你的详细回答。很明显,我工作过度,没有必要。我将使用更小的子集。