我在Spyder上使用findspark.init()
设置了一个简单的PySpark环境,并且我在localhost上运行代码。我很困惑简单矩阵乘法如何在Spark中使用BlockMatrix花费数小时和数小时的时间,而相同的代码需要几分钟才能在numpy上运行。
以下是我使用的代码:
import numpy as np
import pandas as pd
from sklearn import cross_validation as cv
import itertools
import random
import findspark
import time
start=time.time()
findspark.init()
from pyspark.mllib.linalg.distributed import *
from pyspark.sql import SparkSession
from pyspark import SparkContext, SparkConf
conf = SparkConf().setAppName('myapp')
sc = SparkContext(conf=conf)
spark = SparkSession(sc)
from pyspark.mllib.linalg.distributed import *
def as_block_matrix(rdd, rowsPerBlock=1024, colsPerBlock=1024):
return IndexedRowMatrix(
rdd.zipWithIndex().map(lambda xi: IndexedRow(xi[1], xi[0]))
).toBlockMatrix(rowsPerBlock, colsPerBlock)
def prediction(P,Q):
# np.r_[ pp,np.zeros(len(pp)) ].reshape(2,20)
Pn=np.r_[ P,np.zeros(len(P)),np.zeros(len(P)),np.zeros(len(P)),np.zeros(len(P)) ].reshape(5,len(P))
Qn=np.r_[ Q,np.zeros(len(Q)),np.zeros(len(Q)),np.zeros(len(Q)),np.zeros(len(Q)) ].reshape(5,len(Q))
A = Pn[:1]
B = Qn[:1].T
distP = sc.parallelize(A)
distQ = sc.parallelize(B)
mat=as_block_matrix(distP).multiply(as_block_matrix(distQ))
blocksRDD = mat.blocks
m=(list(blocksRDD.collect())[0][1])
#print(m)
return m.toArray()[0,0]
for epoch in range(1):
for u, i in zip(users,items):
e = R[u, i] - prediction(P[:,u],Q[:,i])
答案 0 :(得分:1)
不知道矩阵的大小使得回答这个问题变得更加困难,但是如果你正在处理高维稀疏矩阵,那么pyspark进行矩阵乘法的方式就有一个可能存在的问题。为了乘以稀疏矩阵,pyspark将稀疏矩阵转换为密集矩阵。这在文档中说明:
指出:
multiply(other)Left将此BlockMatrix与另一个BlockMatrix相乘。此矩阵的colsPerBlock必须等于other的rowsPerBlock。如果other包含任何SparseMatrix块,则必须将它们转换为DenseMatrix块。输出BlockMatrix仅包含DenseMatrix块。这可能会导致一些性能问题,直到添加了对两个稀疏矩阵相乘的支持。
据我所知,如果您打算使用内置矩阵数据类型,那么就没有很好的解决方法。一种解决方法是放弃矩阵数据类型,并使用rdd或dataframe join操作手动滚动自己的矩阵乘法。例如,如果您可以使用数据框,则以下内容已经过测试,并且可以大规模运行:
from pyspark.sql.functions import sum
def multiply_df_matrices(A,B):
return A.join(B,A['column']==B['row'])\
.groupBy(A['row'],B['column'])\
.agg(sum(A['value']*B['value']).alias('value'))
你可以通过加入两个rdds来做类似的事情。