如何在PySpark中序列化LabeledPoint RDD?

时间:2015-11-12 15:49:11

标签: python apache-spark pyspark apache-spark-mllib

使用PySpark的saveAsHadoopFile()时出现错误,使用saveAsSequenceFile()时出现同样的错误。我需要保存(key,val)的RDD,其中键是字符串,val是LabeledPoint RDD(标签,SparseVector)。错误如下所示。谷歌搜索几个来源似乎我应该能够在IPython笔记本中做到这一点。我需要序列化这个大型RDD,这样我就可以用Java来处理它了,因为一些Spark的MLLib功能还没有用于python。根据这个post,这应该是可行的。

看看这个page我看到了:

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

所以我真的不知道为什么我会收到这个错误。

  

代码:       labeledDataRDD.saveAsSequenceFile(' / TMP / pysequencefile /&#39)

     

错误:

     

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:构造ClassDict的预期零参数(对于numpy.dtype)       at net.razorvine.pickle.objects.ClassDictConstructor.construct(ClassDictConstructor.java:23)

编辑:我发现了这个:

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_'>

1 个答案:

答案 0 :(得分:1)

问题的根源不是腌制自己。如果是,你就不会看到<Page Name="Failure"> <Text Name="FailureHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text> <Text Name="FailureInstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text> <Text Name="FailureUninstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text> <Text Name="FailureRepairHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text> <Hypertext Name="FailureLogFileLink" X="11" Y="121" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext> <Hypertext Name="FailureMessageText" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" ></Hypertext> <Hypertext Name="CustomMessage" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" >[CustomMessage]</Hypertext> <Text Name="FailureRestartText" X="11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text> <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button> <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button> 。如果您查看saveAsSequenceFile文档,则会看到它需要两个步骤:

  
      
  1. Pyrolite用于将pickled Python RDD转换为Java对象的RDD。
  2.   
  3. 此Java RDD的键和值将转换为Writable并写出。
  4.   

您的程序在第一步失败,但即使它没有,我也不确定什么是预期的Java对象以及如何读回来。

我只是将数据写为Parquet文件,而不是使用序列文件:

 <Variable Name="CustomMessage" Value="Hi"/>
 <MsiProperty Name="CustomMessage" Value="[CustomMessage]"/>

回读并转换:

session["CustomMessage"]="Please enter valid details";

或者如果您更喜欢类似Java的方法:

net.razorvine.pickle.PickleException

修改

一般而言,Spark SQL中不支持NumPy类型作为独立值。如果您在RDD中有Numpy类型,则首先将它们转换为标准Python类型:

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")