这是预期的行为。像其他
MLlib模型一样,Python对象只是Scala模型的包装,实际处理被委派给JVM对应对象。由于工作人员无法访问Py4J网关,因此无法从操作或转换中调用Java /Scala方法。
通常,MLlib模型提供一种可以直接在RDD上运行的辅助方法,但实际情况并非如此。
Word2VecModel提供了
getVectors一种方法,该方法可将单词从单词返回到向量,但不幸的是它是一个
JavaMap这样的方法,因此在转换中不起作用。您可以尝试这样的事情:
from pyspark.mllib.linalg import DenseVectorvectors_ = model.getVectors() # py4j.java_collections.JavaMapvectors = {k: DenseVector([x for x in vectors_.get(k)]) for k in vectors_.keys()}获取Python字典,但速度会非常慢。另一个选择是将该对象以Python可以使用的形式转储到磁盘上,但是需要对Py4J进行一些修改,最好避免这种情况。相反,让我们将模型读取为Dataframe:
lookup = sqlContext.read.parquet("path_to_word2vec_model/data").alias("lookup")我们将得到以下结构:
lookup.printSchema()## root## |-- word: string (nullable = true)## |-- vector: array (nullable = true)## | |-- element: float (containsNull = true)
可以通过以下方式将单词映射到向量
join:
from pyspark.sql.functions import colwords = sc.parallelize([('hello', ), ('test', )]).toDF(["word"]).alias("words")words.join(lookup, col("words.word") == col("lookup.word"))## +-----+-----+--------------------+## | word| word| vector|## +-----+-----+--------------------+## |hello|hello|[-0.030862354, -0...|## | test| test|[-0.13154022, 0.2...|## +-----+-----+--------------------+如果数据适合驱动程序/工作程序内存,则可以尝试通过广播进行收集和映射:
lookup_bd = sc.broadcast(lookup.rdd.collectAsMap())rdd = sc.parallelize([['Hello'],['test']])rdd.map(lambda ws: [lookup_bd.value.get(w) for w in ws])



