簡體   English   中英

如何在PySpark中序列化LabeledPoint RDD?

[英]How do I serialize a LabeledPoint RDD in PySpark?

使用PySpark的saveAsHadoopFile()時出現錯誤,使用saveAsSequenceFile()時出現同樣的錯誤。 我需要保存(key,val)的RDD,其中鍵是字符串,val是LabeledPoint RDD(標簽,SparseVector)。 錯誤如下所示。 谷歌搜索幾個來源似乎我應該能夠在IPython筆記本中做到這一點。 我需要序列化這個大型RDD,以便我可以用Java處理它,因為Spark的MLLib功能還沒有用於python。 根據這篇文章,這應該是可行的。

看看這個頁面,我看到:

_picklable_classes = [
    'LinkedList',
    'SparseVector',
    'DenseVector',
    'DenseMatrix',
    'Rating',
    'LabeledPoint',
]

所以我真的不知道為什么我會收到這個錯誤。

代碼:labeledDataRDD.saveAsSequenceFile('/ tmp / pysequencefile /')

錯誤:

Py4JJavaError:調用z:org.apache.spark.api.python.PythonRDD.saveAsSequenceFile時發生錯誤。 :org.apache.spark.SparkException:由於階段失敗而中止作業:階段527.0中的任務0失敗1次,最近失敗:階段527.0中丟失任務0.0(TID 1454,localhost):n​​et.razorvine.pickle.PickleException:在net.razorvine.pickle.objects.ClassDictConstructor.construct(ClassDictConstructor.java:23)中構造ClassDict(for numpy.dtype)的預期零參數

編輯:我發現了這個:

public class More ...ClassDictConstructor implements IObjectConstructor     {
12
13  String module;
14  String name;
15
16  public More ...ClassDictConstructor(String module, String name) {
17      this.module = module;
18      this.name = name;
19  }
20
21  public Object More ...construct(Object[] args) {
22      if (args.length > 0)
23          throw new PickleException("expected zero arguments for construction of ClassDict (for "+module+"."+name+")");
24      return new ClassDict(module, name);
25  }
26}

我沒有直接使用上面的construct()方法..所以我不知道為什么我嘗試的saveAs ..方法在它不需要時傳遞參數。

編輯2:遵循zero323建議(謝謝)使用了一個小故障。 當我嘗試使用zero323編寫的內容時,我收到錯誤(見下文)。 但是,當我派生出一個更簡單的RDD時,它可以工作並將這個更簡單的RDD保存到.parquet文件的目錄中(將其分解為幾個.parquet文件)。 更簡單的RDD如下:

simplerRDD = labeledDataRDD.map(lambda (k,v): (v.label, v.features))
sqlContext.createDataFrame(simplerRDD, ("k", "v")).write.parquet("labeledData_parquet_file")

嘗試保存labeledDataRDD時出錯:

/usr/local/Cellar/apache-spark/1.5.1/libexec/python/pyspark/sql/types.pyc in _infer_schema(row)
    831         raise TypeError("Can not infer schema for type: %s" % type(row))
    832 
--> 833     fields = [StructField(k, _infer_type(v), True) for k, v in items]
    834     return StructType(fields)
    835 

/usr/local/Cellar/apache-spark/1.5.1/libexec/python/pyspark/sql/types.pyc in _infer_type(obj)
    808             return _infer_schema(obj)
    809         except TypeError:
--> 810             raise TypeError("not supported type: %s" % type(obj))
    811 
    812 

TypeError: not supported type: <type 'numpy.unicode_'>

問題的根源不是酸洗自己。 如果是,你就不會看到net.razorvine.pickle.PickleException 如果你看一下saveAsSequenceFile文檔,你會發現它需要兩個步驟:

  1. Pyrolite用於將pickled Python RDD轉換為Java對象的RDD。
  2. 此Java RDD的鍵和值將轉換為Writable並寫出。

你的程序在第一步就失敗了,但即使它沒有,我也不確定什么是預期的Java對象以及如何閱讀它。

我只是將數據寫為Parquet文件,而不是使用序列文件:

from pyspark.mllib.regression import LabeledPoint

rdd = sc.parallelize([
   ("foo", LabeledPoint(1.0, [1.0, 2.0, 3.0])),
   ("bar", LabeledPoint(2.0, [4.0, 5.0, 6.0]))])

sqlContext.createDataFrame(rdd, ("k", "v")).write.parquet("a_parquet_file")

讀回來並轉換:

import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.sql.Row
import org.apache.spark.rdd.RDD

val rdd: RDD[(String, LabeledPoint)] = sqlContext.read.parquet("a_parquet_file")
  .select($"k", $"v.label", $"v.features")
  .map{case Row(k: String, label: Double, features: Vector) =>
    (k, LabeledPoint(label, features))}

rdd.sortBy(_._1, false).take(2)

// Array[(String, org.apache.spark.mllib.regression.LabeledPoint)] = 
//  Array((foo,(1.0,[1.0,2.0,3.0])), (bar,(2.0,[4.0,5.0,6.0])))

或者如果您更喜歡類似Java的方法:

def rowToKeyLabeledPointPair(r: Row): Tuple2[String, LabeledPoint] = {
  // Vector -> org.apache.spark.mllib.linalg.Vector
  Tuple2(r.getString(0), LabeledPoint(r.getDouble(1), r.getAs[Vector](2)))
}

sqlContext.read.parquet("a_parquet_file")
  .select($"k", $"v.label", $"v.features")
  .map(rowToKeyLabeledPointPair)

編輯

一般而言,Spark SQL中不支持NumPy類型作為獨立值。 如果您在RDD中有Numpy類型,則首先將它們轉換為標准Python類型:

tmp = rdd.map(lambda kv: (str(kv[0]), kv[1]))
sqlContext.createDataFrame(tmp, ("k", "v")).write.parquet("a_parquet_file")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM