如何并行化随机梯度下降



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

功能生成已成功分发。

多处理器scikit学习中的答案表明,可以分发SGD分类器的工作:

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

当我在每个估计器上第二次运行partial_fit时,我该从哪里获得最终的聚合估计器?

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

详细信息

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

每个主机使用局部矩阵和局部向量来制作SGD分类器并进行部分拟合。然后,每个都将coeff向量和截距发送给root。Root对这些数据进行平均并将其发送回主机。主机执行另一个partial_fit,并将coeff向量和截距发送给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")

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

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

  • 或者选择递增和训练线性模型的数据集的随机子样本。在一个持续的测试中测量预测准确性,当你看到回报递减时(可能是在少数群体的数万个样本之后)停止。

您所经历的一切都是正常的,也是意料之中的。首先,使用SGD意味着你永远不会得到确切的结果。您将很快收敛到最优解(因为这是一个凸问题),然后在该区域徘徊以获得剩余部分。单独使用整个数据集的不同运行每次都会产生稍微不同的结果。

从那里我可以得到最终的聚合估计器?

理论上,你只需要一遍又一遍地这样做,直到你对收敛感到满意。对你正在做的事情来说完全没有必要。其他系统转向使用更复杂的方法(如L-BFGS)来收敛到最终解决方案,因为它们在解决方案上有了一个良好的"暖启动"。然而,这不会让你在准确性上有任何显著的提高(如果幸运的话,可能会得到整整一个百分点),所以不要认为这是成败的关键。想想它是什么,一个微调。

其次是线性模型不能很好地并行化。尽管有vowpalwabbit和其他一些库的声明,但并行训练线性模型并不能实现线性扩展。简单地对中间结果求平均值是使这样的系统并行化的糟糕方法,遗憾的是,这与并行训练线性模型的效果差不多。

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

相关内容

  • 没有找到相关文章

最新更新