使用Sparkit-Learn进行奇怪的转置行为

时间:2017-01-26 22:30:27

标签: apache-spark scikit-learn pyspark

我使用Sparkit-Learn的SparkCountVectorizerSparkTfidfVectorizer将一堆文档转换为TFIDF矩阵。

我创建了TFIDF矩阵并且它具有正确的尺寸(496,861个文档由189,398个不同的标记):

>>> tfidf
<class 'splearn.rdd.SparseRDD'> from PythonRDD[20] at RDD at PythonRDD.scala:48
>>> tfidf.shape
(496861, 189398)

切片单个向量会返回正确的输出(1个文档由189,398个不同的标记):

>>> tfidf.flatMap(lambda x: x).take(1)
[<1x189398 sparse matrix of type '<class 'numpy.float64'>'
        with 49 stored elements in Compressed Sparse Row format>]

现在我希望获得每个文档的转置(即,尺寸为189,398的向量乘以1):

>>> tfidf.flatMap(lambda x: x.T).take(1)

但这是我得到的:

[<1x7764 sparse matrix of type '<class 'numpy.float64'>'
        with 77 stored elements in Compressed Sparse Row format>]

因此,我得到1x7764向量而不是189389x1向量。我理解7764:当我读取数据时我.repartition() 64件,结果是,496861(文件数)除以64是7763.4。我不明白为什么Sparkit-Learn在一个案例(lambda x: x)中按平面行进行迭代,在另一个案例中用分区进行迭代(lambda x: x.T)。我完全糊涂了。

如果它很重要,我的最终目标是过滤TFIDF矩阵,以便我只获得某些列中具有非零值的向量(即,只包含某些单词的文档)并且索引未转置的1x189389向量不会工作(在我[0]之后我放了多少x我总是找回相同的1x189389向量。

1 个答案:

答案 0 :(得分:1)

你转移了一个错误的东西。 splearn.rdd.SparseRDD存储数据块,因此您可以转置块而不是单个向量。如果块有7764行和18938列,则转置一个有18938行和7764列,这些列将在展平时逐行迭代。

您需要的是:

(tfidf
    # Iterate over each block and yield the rows
    # block-size x 18938 -> 1 x 18938
    .flatMap(lambda x: x) 
    # Take each row and transpose it
    # 1 x 18938 -> 1 x 18938
    .map(lambda x: x.T))

(tfidf
    # Iterate over each row in block (generator expression) 
    # and transpose it block-size x 18938 -> block-size x 18938 x 1
    #
    # and then flatten (with flatMap) yielding rows 18938 x 1
    .flatMap(lambda xs: (x.T for x in xs)))

注意:我并不熟悉Sparkit-learn所以可以有更优雅的解决方案。