Pyspark py4j PickleException: "ожидаемые нулевые аргументы для построения ClassDict"

этот вопрос направлен на лиц, знакомых с py4j - и может помочь решить ошибку маринования. Я пытаюсь добавить метод в pyspark PythonMLLibAPI, который принимает RDD namedtuple, выполняет некоторую работу и возвращает результат в виде RDD.

этот метод моделируется после PYthonMLLibAPI.метод trainALSModel (), аналогичный существующей соответствующие порции:

  def trainALSModel(
    ratingsJRDD: JavaRDD[Rating],
    .. )

на существующей python Класс рейтинга, используемый для моделирования нового кода:

class Rating(namedtuple("Rating", ["user", "product", "rating"])):
    def __reduce__(self):
        return Rating, (int(self.user), int(self.product), float(self.rating))

вот попытка, поэтому вот соответствующие классы:

новая python класс pyspark.mllib.кластеризация.MatrixEntry:

from collections import namedtuple
class MatrixEntry(namedtuple("MatrixEntry", ["x","y","weight"])):
    def __reduce__(self):
        return MatrixEntry, (long(self.x), long(self.y), float(self.weight))

новая метод foobarRDD В PythonMLLibAPI:

  def foobarRdd(
    data: JavaRDD[MatrixEntry]): RDD[FooBarResult] = {
    val rdd = data.rdd.map { d => FooBarResult(d.i, d.j, d.value, d.i * 100 + d.j * 10 + d.value)}
    rdd
  }

теперь давайте попробуем это:

from pyspark.mllib.clustering import MatrixEntry

def convert_to_MatrixEntry(tuple):
  return MatrixEntry(*tuple)

from pyspark.mllib.clustering import *
pic = PowerIterationClusteringModel(2)
tups = [(1,2,3),(4,5,6),(12,13,14),(15,7,8),(16,17,16.5)]
trdd = sc.parallelize(map(convert_to_MatrixEntry,tups))

# print out the RDD on python side just for validation
print "%s" %(repr(trdd.collect()))

from pyspark.mllib.common import callMLlibFunc
pic = callMLlibFunc("foobar", trdd)

соответствующие части результатов:

[(1,2)=3.0, (4,5)=6.0, (12,13)=14.0, (15,7)=8.0, (16,17)=16.5]

который показывает, что входной rdd является "целым". Однако маринование было недовольным:

5/04/27 21:15:44 ERROR Executor: Exception in task 6.0 in stage 1.0 (TID 14)
net.razorvine.pickle.PickleException: expected zero arguments for construction of ClassDict
(for pyspark.mllib.clustering.MatrixEntry)
    at net.razorvine.pickle.objects.ClassDictConstructor.construct(ClassDictConstructor.java:23)
    at net.razorvine.pickle.Unpickler.load_reduce(Unpickler.java:617)
    at net.razorvine.pickle.Unpickler.dispatch(Unpickler.java:170)
    at net.razorvine.pickle.Unpickler.load(Unpickler.java:84)
    at net.razorvine.pickle.Unpickler.loads(Unpickler.java:97)
    at org.apache.spark.mllib.api.python.SerDe$$anonfun$pythonToJava$$anonfun$apply.apply(PythonMLLibAPI.scala:1167)
    at org.apache.spark.mllib.api.python.SerDe$$anonfun$pythonToJava$$anonfun$apply.apply(PythonMLLibAPI.scala:1166)
    at scala.collection.Iterator$$anon.hasNext(Iterator.scala:371)
    at scala.collection.Iterator$$anon.hasNext(Iterator.scala:327)
    at scala.collection.Iterator$class.foreach(Iterator.scala:727)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
    at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:48)
    at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:103)
    at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:47)
    at scala.collection.TraversableOnce$class.to(TraversableOnce.scala:273)
    at scala.collection.AbstractIterator.to(Iterator.scala:1157)
    at scala.collection.TraversableOnce$class.toBuffer(TraversableOnce.scala:265)
    at scala.collection.AbstractIterator.toBuffer(Iterator.scala:1157)
    at scala.collection.TraversableOnce$class.toArray(TraversableOnce.scala:252)
    at scala.collection.AbstractIterator.toArray(Iterator.scala:1157)
    at org.apache.spark.rdd.RDD$$anonfun.apply(RDD.scala:819)
    at org.apache.spark.rdd.RDD$$anonfun.apply(RDD.scala:819)
    at org.apache.spark.SparkContext$$anonfun$runJob.apply(SparkContext.scala:1523)
    at org.apache.spark.SparkContext$$anonfun$runJob.apply(SparkContext.scala:1523)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:61)
    at org.apache.spark.scheduler.Task.run(Task.scala:64)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:212)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

Ниже приведен визуальный след стека вызова python:

enter image description here

3 ответов


У меня была та же ошибка, что и при использовании MLlib, и оказалось, что я вернул неправильный тип данных в одной из моих функций. Теперь он работает после простого приведения возвращаемого значения. Это может быть не тот ответ, который вы ищете, но это, по крайней мере, подсказка для направления.


имел ту же проблему, несколько раз. numpy типы не имеют неявных преобразований в pyspark.язык SQL.типы.

сделайте простое явное преобразование в собственную систему типов. В моем случае это было:

float(vector_a.dot(vector_b)

Я получил эту ошибку, используя Spark Version >= 2.0.

Spark переводит функциональность MLlib в новое пространство имен ML. В результате существует два типа SparseVector: ml.linalg.SparseVector и mllib.linalg.SparseVector

некоторые функции MLlib по-прежнему ожидают более старые mllib вид

from pyspark.ml.linalg import Vectors
# convert ML vector to older MLlib vector
old_vec = Vectors.fromML(new_vec)

HTH