Python pyspark计算稀疏向量的距离矩阵

Python pyspark计算稀疏向量的距离矩阵,python,apache-spark,scipy,pyspark,sparse-matrix,Python,Apache Spark,Scipy,Pyspark,Sparse Matrix,我正在尝试建立一种通用方法来计算许多稀疏向量(100k向量,长度为250k)的距离矩阵。在我的示例中,数据用scipy csr矩阵表示。这就是我正在做的: 首先,我定义了一种将csr行转换为pyspark SparseVector的方法: def csr_to_sparse_vector(row): return SparseVector(row.shape[1], sorted(row.indices), row.data) 现在,我将行转换为向量,并将它们保存到一个列表中,然后将该

我正在尝试建立一种通用方法来计算许多稀疏向量(100k向量,长度为250k)的距离矩阵。在我的示例中,数据用scipy csr矩阵表示。这就是我正在做的:

首先,我定义了一种将csr行转换为pyspark SparseVector的方法:

def csr_to_sparse_vector(row):
    return SparseVector(row.shape[1], sorted(row.indices), row.data)
现在,我将行转换为向量,并将它们保存到一个列表中,然后将该列表馈送到SparkContext:

sparse_vectors = [csr_to_sparse_vector(row) for row in refs_sample]
rdd = sc.parallelize(sparse_vectors)
在下一步中,我使用笛卡尔函数构建所有对(类似于本文:)

在这个实验中,我想使用tje Jaccard相似性,它被相应地定义为:

def jacc_sim(pair):
    dot_product = pair[0].dot(pair[1])
    try:
        sim = dot_product / (pair[0].numNonzeros() + pair[1].numNonzeros())
    except ZeroDivisionError:
        return 0.0
    return sim
现在我应该映射函数并收集结果:

distance_matrix = rdd2.map(lambda x: jacc_sim(x)).collect()
我在一个小样本上运行这段代码,两个样本上都只有100个文档,一个本地机器和一个有180个节点的集群。这项任务需要很长时间,最终崩溃:

有什么建议可能有什么问题吗

另外,如果距离度量是对称的sim(x,y)=sim(y,x),我们只需要矩阵的上三角。我发现一篇文章通过过滤()解决了这个问题:

rdd2=rdd.cartesian(rdd.filter)(lambda x:x[0]

但这对SparseVector列表不起作用。

是列表有问题,还是SparseVector构成了列表?一个想法是尝试将SparseVector转换为DenseVector,我在这里找到了一个建议()。计算结果没有什么不同,只是Spark是如何处理的。

问题在于配置错误,导致我将数据拆分为1000个分区。解决方案就是明确地告诉spark他应该创建多少个分区(例如10个):

此外,我通过枚举扩展了稀疏向量列表,这样我就可以过滤出不属于上三角矩阵的对:

sparse_vectors = [(i, csr_to_sparse_vector(row)) for i, row in enumerate(authors)]
rdd = sc.parallelize(sparse_vectors, 10)
rdd2 = rdd.cartesian(rdd).filter(lambda x: x[0][0] < x[1][0])
rdd2.map(lambda x: jacc_sim(x)).filter(lambda x: x is not None).saveAsTextFile('hdfs:///user/username/similarities')

这对我来说非常有效,我希望其他人也会发现它很有用

嘿,先生,谢谢你抽出时间。我的spark配置有问题,导致了崩溃。@nadre,很高兴你找到了它。该配置是spark库或您的机器特有的。
rdd = sc.parallelize(sparse_vectors, 10)
sparse_vectors = [(i, csr_to_sparse_vector(row)) for i, row in enumerate(authors)]
rdd = sc.parallelize(sparse_vectors, 10)
rdd2 = rdd.cartesian(rdd).filter(lambda x: x[0][0] < x[1][0])
rdd2.map(lambda x: jacc_sim(x)).filter(lambda x: x is not None).saveAsTextFile('hdfs:///user/username/similarities')
def jacc_sim(pair):
    id_0 = pair[0][0]
    vec_0 = pair[0][1]
    id_1 = pair[1][0]
    vec_1 = pair[1][1]
    dot_product = vec_0.dot(vec_1)
    try:
        sim = dot_product / (vec_0.numNonzeros() + vec_1.numNonzeros())
        if sim > 0:
            return (id_0, id_1, sim)
    except ZeroDivisionError:
        pass
    return None