2016-11-11 263 views
3

我有一列短句子和一个分类变量列的spark数据框。我想对分类变量上的句子one-hot-encoding执行tf-idf,然后将其输出到驱动程序中的稀疏矩阵(一旦它的尺寸更小)(对于scikit-learn模型)。pyspark:稀疏向量到scipy稀疏矩阵

什么是以稀疏形式从火花中获取数据的最佳方式?似乎在稀疏向量上只有一个toArray()方法,它输出numpy数组。但是,文档确实说scipy稀疏数组can be used in the place of spark sparse arrays.

请记住,tf_idf值实际上是一列稀疏数组。理想情况下,将所有这些特征集成到一个大型稀疏矩阵中将会很好。

回答

5

一种可能的解决方案可以被表示为如下:

  • 转换功能,以RDD和提取载体:

    from pyspark.ml.linalg import SparseVector 
    from operator import attrgetter 
    
    df = sc.parallelize([ 
        (SparseVector(3, [0, 2], [1.0, 3.0]),), 
        (SparseVector(3, [1], [4.0]),) 
    ]).toDF(["features"]) 
    
    features = df.rdd.map(attrgetter("features")) 
    
  • 添加行指数:

    indexed_features = features.zipWithIndex() 
    
  • 变平至元组的RDD (i, j, value)

    def explode(row): 
        vec, i = row 
        for j, v in zip(vec.indices, vec.values): 
         yield i, j, v 
    
    entries = indexed_features.flatMap(explode) 
    
  • 收集和重塑:

    row_indices, col_indices, data = zip(*entries.collect()) 
    
  • 计算形状:

    shape = (
        df.count(), 
        df.rdd.map(attrgetter("features")).first().size 
    ) 
    
  • 创建稀疏矩阵:

    from scipy.sparse import csr_matrix 
    
    mat = csr_matrix((data, (row_indices, col_indices)), shape=shape) 
    
  • 快速理智检查:

    mat.todense() 
    

    随着预期的结果:

    matrix([[ 1., 0., 3.], 
         [ 0., 4., 0.]]) 
    

还有一句:

  • 转换的features每行矩阵:

    import numpy as np 
    
    def as_matrix(vec): 
        data, indices = vec.values, vec.indices 
        shape = 1, vec.size 
        return csr_matrix((data, indices, np.array([0, vec.values.size])), shape) 
    
    mats = features.map(as_matrix) 
    
  • ,并减少与vstack

    from scipy.sparse import vstack 
    
    mat = mats.reduce(lambda x, y: vstack([x, y])) 
    

    collectvstack

    mat = vstack(mats.collect())