Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 基于预排序输入的Spark特征向量变换_Apache Spark_Apache Spark Mllib_Naivebayes - Fatal编程技术网

Apache spark 基于预排序输入的Spark特征向量变换

Apache spark 基于预排序输入的Spark特征向量变换,apache-spark,apache-spark-mllib,naivebayes,Apache Spark,Apache Spark Mllib,Naivebayes,我在HDFS上以制表符分隔的文件中有一些数据,如下所示: label | user_id | feature ------------------------------ pos | 111 | www.abc.com pos | 111 | www.xyz.com pos | 111 | Firefox pos | 222 | www.example.com pos | 222 | www.xyz.com pos | 222

我在HDFS上以制表符分隔的文件中有一些数据,如下所示:

label | user_id | feature
------------------------------
  pos | 111     | www.abc.com
  pos | 111     | www.xyz.com
  pos | 111     | Firefox
  pos | 222     | www.example.com
  pos | 222     | www.xyz.com
  pos | 222     | IE
  neg | 333     | www.jkl.com
  neg | 333     | www.xyz.com
  neg | 333     | Chrome
我需要对其进行转换,为每个用户id创建一个特征向量,以训练
org.apache.spark.ml.classification.NaiveBayes
模型

我目前的做法基本上是:

  • 将原始数据加载到数据帧中
  • 使用StringIndexer为功能编制索引
  • 转到RDD并按用户id分组,然后将特征索引映射到稀疏向量中
  • 关键是这个。。。数据已按用户id预先排序。利用这一点的最佳方式是什么?想到可能会发生多少不必要的工作,我感到很痛苦

    如果有一点代码有助于理解我当前的方法,下面是地图的要点:

    val featurization = (vals: (String,Iterable[Row])) => {
      // create a Seq of all the feature indices
      // Note: the indexing was done in a previous step not shown
      val seq = vals._2.map(x => (x.getDouble(1).toInt,1.0D)).toSeq
    
      // create the sparse vector
      val featureVector = Vectors.sparse(maxIndex, seq)
    
      // convert the string label into a Double
      val label = if (vals._2.head.getString(2) == "pos") 1.0 else 0.0
    
      (label, vals._1, featureVector)
    }
    
    d.rdd
      .groupBy(_.getString(1))
      .map(featurization)
      .toDF("label","user_id","features")
    
    让我们从

    如果我在磁盘上的数据保证按密钥进行预排序,该密钥将用于组聚合或缩减,Spark有没有办法利用这一点

    视情况而定。若您应用的操作可以从映射端聚合中获益,那个么通过预排序数据而无需在代码中进行任何进一步的干预,您可以获得很多好处。共享同一密钥的数据应该位于相同的分区上,并且可以在洗牌之前在本地聚合

    不幸的是,在这种特殊情况下,它不会有多大帮助。即使您启用地图端聚合(
    groupBy(Key)
    没有使用is,因此您需要自定义实现)或聚合特征向量(您可以在我的答案中找到一些示例),也没有多少好处。您可以在这里和那里保存一些工作,但仍然需要在节点之间传输所有索引

    如果你想获得更多,你就必须多做一点工作。我可以看到两种利用现有订单的基本方法:

  • 使用自定义Hadoop输入格式只生成完整的记录(标签、id、所有功能),而不是逐行读取数据。如果您的数据每个id有固定的行数,您甚至可以尝试使用
    NLineInputFormat
    ,然后将
    mapPartitions
    应用于聚合记录

    这无疑是一个更详细的解决方案,但不需要额外的Spark洗牌

  • 像往常一样读取数据,但对
    groupBy
    使用自定义分区器。据我所知,使用
    rangePartitioner
    应该可以正常工作,但请确保您可以尝试以下过程:

    • 使用
      mapPartitionsWithIndex
      查找每个分区的最小/最大id
    • 创建一个分区器,它可以保持最小值非常有洞察力。谢谢你的帮助。