Numpy 是否可以使用pyspark加速对非常大的数组的每列进行回归分析?

Numpy 是否可以使用pyspark加速对非常大的数组的每列进行回归分析?,numpy,pyspark,Numpy,Pyspark,我有一个非常大的数组。我想对数组的每一列进行线性回归。为了加快计算速度,我创建了一个列表,其中数组的每一列都是它的元素。然后,我使用pyspark创建了一个RDD,并在其上进一步应用了一个已定义的函数。我在创建RDD时遇到了内存问题(即并行化) 我试图通过设置spark-defaults.conf将spark.driver.memory提高到50g,但程序似乎仍然死机 将numpy导入为np 从sklearn.linear\u模型导入线性回归 从sklearn.metrics导入r2_分数,均方

我有一个非常大的数组。我想对数组的每一列进行线性回归。为了加快计算速度,我创建了一个列表,其中数组的每一列都是它的元素。然后,我使用pyspark创建了一个RDD,并在其上进一步应用了一个已定义的函数。我在创建RDD时遇到了内存问题(即并行化)

我试图通过设置spark-defaults.conf将spark.driver.memory提高到50g,但程序似乎仍然死机

将numpy导入为np
从sklearn.linear\u模型导入线性回归
从sklearn.metrics导入r2_分数,均方误差
从pyspark导入SparkContext
sc=SparkContext(“本地”,“获取线性系数”)
def getLinearCoefficients(列):
y=列[~np.isnan(列)]#提取列中非nan值
x=np.where(~np.isnan(列))[0]+1#提取相应的索引加1
#只有当存在不少于3个数据对时,我们才进行线性回归插值。
如果y.shape[0]>=3:
模型=线性回归(拟合_截距=真)#初始化线性回归模型
model.fit(x[:,np.newaxis],y)#使用数据拟合模型
n=y.形状[0]
斜率=模型系数[0]
截距=模型截距_
r2=r2_得分(y,模型预测(x[:,np.newaxis]))
rmse=np.sqrt(均方误差(y,model.predict(x[:,np.newaxis]))
其他:
n、 斜率,截距,r2,rmse=np.nan,np.nan,np.nan,np.nan,np.nan,np.nan
返回n,斜率,截距,r2,rmse
random_array=np.random.rand(3002000*2000)#这里我们使用一个没有缺失数据的随机数组进行测试。
columns=[random_array.T中的col对应col]
columnsRDD=sc.parallelize(列)
ColumnsLinearDd=columnsRDD.map(getLinearCoefficients)
n=np.array([e[0]表示ColumnSLineardD.collect()中的e)
slope=np.array([e[1]表示列slineardd.collect()中的e)
intercept=np.array([e[2]表示ColumnSlineardd.collect()中的e)
r2=np.array([e[3]表示ColumnSLineardD.collect()中的e)
rmse=np.array([e[4]表示ColumnSlineardd.collect()中的e)
程序输出停滞,如下所示

Exception in thread "dispatcher-event-loop-0" java.lang.OutOfMemoryError
        at java.io.ByteArrayOutputStream.hugeCapacity(ByteArrayOutputStream.java:123)
        at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:117)
        at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
        at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
        at org.apache.spark.util.ByteBufferOutputStream.write(ByteBufferOutputStream.scala:41)
        at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1877)
        at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1786)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1189)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
        at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:43)
        at org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:100)
        at org.apache.spark.scheduler.TaskSetManager$$anonfun$resourceOffer$1.apply(TaskSetManager.scala:486)
        at org.apache.spark.scheduler.TaskSetManager$$anonfun$resourceOffer$1.apply(TaskSetManager.scala:467)
        at scala.Option.map(Option.scala:146)
        at org.apache.spark.scheduler.TaskSetManager.resourceOffer(TaskSetManager.scala:467)
        at org.apache.spark.scheduler.TaskSchedulerImpl$$anonfun$org$apache$spark$scheduler$TaskSchedulerImpl$$resourceOfferSingleTaskSet$1.apply$mcVI$sp(TaskSchedulerImpl.scala:315)
        at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
        at org.apache.spark.scheduler.TaskSchedulerImpl.org$apache$spark$scheduler$TaskSchedulerImpl$$resourceOfferSingleTaskSet(TaskSchedulerImpl.scala:310)
        at org.apache.spark.scheduler.TaskSchedulerImpl$$anonfun$resourceOffers$4$$anonfun$apply$11.apply(TaskSchedulerImpl.scala:412)
        at org.apache.spark.scheduler.TaskSchedulerImpl$$anonfun$resourceOffers$4$$anonfun$apply$11.apply(TaskSchedulerImpl.scala:409)
        at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
        at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
        at org.apache.spark.scheduler.TaskSchedulerImpl$$anonfun$resourceOffers$4.apply(TaskSchedulerImpl.scala:409)
        at org.apache.spark.scheduler.TaskSchedulerImpl$$anonfun$resourceOffers$4.apply(TaskSchedulerImpl.scala:396)
        at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
        at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
        at org.apache.spark.scheduler.TaskSchedulerImpl.resourceOffers(TaskSchedulerImpl.scala:396)
        at org.apache.spark.scheduler.local.LocalEndpoint.reviveOffers(LocalSchedulerBackend.scala:86)
        at org.apache.spark.scheduler.local.LocalEndpoint$$anonfun$receive$1.applyOrElse(LocalSchedulerBackend.scala:64)
        at org.apache.spark.rpc.netty.Inbox$$anonfun$process$1.apply$mcV$sp(Inbox.scala:117)
        at org.apache.spark.rpc.netty.Inbox.safelyCall(Inbox.scala:205)
        at org.apache.spark.rpc.netty.Inbox.process(Inbox.scala:101)
        at org.apache.spark.rpc.netty.Dispatcher$MessageLoop.run(Dispatcher.scala:221)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

我想可以使用pyspark来加速计算,但我怎么能做到呢?是否修改spark-defaults.conf中的其他参数?或者对数组的每一列进行矢量化(我知道Python3中的range()函数就是这样做的,而且速度更快。)?

这样做行不通。你基本上做了三件事:

  • 您正在使用RDD进行并行化
  • 您正在调用getLinearCoefficients()函数,最后
  • 您调用它来使用您现有的代码
  • 第一点没有错,但是第二步和第三步有一个巨大的错误。您的getLinearCoefficients()函数没有从pyspark中获益,因为您使用了numpy和sklearn(为了更好的解释,请看一下这个)。对于您正在使用的大多数函数,都有一个pyspark等价物。 第三步的问题是collect()函数。调用collect()时,pyspark会将RDD的所有行带到驱动程序,并在那里执行sklearn函数。因此,您只能得到sklearn允许的并行化。使用pyspark在您当前的操作方式中是完全没有意义的,甚至可能是一个缺点。Pyspark不是一个允许并行运行python代码的框架。当您希望与pyspark并行执行代码时,必须使用pyspark函数

    那你能做什么呢

    • 首先,您可以使用LinearRecession类的参数使用多个核心进行计算。这允许您至少使用一台机器的所有内核
    • 您可以做的另一件事是,远离sklearn,使用pyspark的线性回归(看看和)。有了这一点,您可以使用整个集群进行线性回归

    对于样本数超过100k的大型数据集,不建议使用
    线性回归。一般建议使用
    SGDRegressor
    并正确设置参数,以便使用OLS损耗:

    from sklearn.linear_model import SGDRegressor
    
    并将您的
    线性回归
    替换为:

    model = SGDRegressor(loss=’squared_loss’, penalty=’none’, fit_intercept=True)
    
    设置
    loss='squared\u loss'
    penal='none'
    SGDRegressor
    设置为使用OLS而不使用正则化,因此它应该产生类似于
    线性回归的结果

    尝试一些选项,如
    learning\u rate
    eta0
    /
    power\u t
    ,以找到最佳性能


    此外,我建议使用分割数据集并使用测试集进行评分。一个好的测试大小是
    test\u size=.3

    谢谢您的评论。我同意你的观点,在pyspark中使用.collect()方法是不可取的,因为这样会消耗太多内存。但我猜那些带有.collect()的代码不涉及getLinearCoefficients()函数。我想我的代码也有问题:columnsRDD=sc.parallelize(columns)。为了说明这一点,我还编写了一个附在原始问题后面的框架程序。非常感谢您关于使用pyspark函数的建议。我是pyspark的新手,将通过时间学习它!我已经扩展了我的帖子,对getLinearCoefficients()函数进行了一些介绍。我认为你的另一个关于你的骨架计划的问题应该在一个单独的问题中解决。尽管没有尝试,我认为你的答案是好的。我应该使用pyspark等价函数来利用它的优势。我已将有关骨架程序的问题移至另一页()。希望你也能帮忙。谢谢你的评论。你的答案很好,但老实说不适合我的问题,因为我的问题是用300个样本进行100k回归,而不是用100k样本进行回归。不管怎样,我认为你的回答很有用