5

Учитывая мой pyspark Row объект:Невозможно преобразовать тип <класс 'pyspark.ml.linalg.SparseVector'> в вектор

>>> row 
Row(clicked=0, features=SparseVector(7, {0: 1.0, 3: 1.0, 6: 0.752})) 
>>> row.clicked 
0 
>>> row.features 
SparseVector(7, {0: 1.0, 3: 1.0, 6: 0.752}) 
>>> type(row.features) 
<class 'pyspark.ml.linalg.SparseVector'> 

Однако row.features не смог пройти isinstance (row.features, Vector) тест ,

>>> isinstance(SparseVector(7, {0: 1.0, 3: 1.0, 6: 0.752}), Vector) 
True 
>>> isinstance(row.features, Vector) 
False 
>>> isinstance(deepcopy(row.features), Vector) 
False 

Эта странная ошибка вызвала у меня огромные проблемы. Без передачи «isinstance (row.features, Vector)» «Я не могу сгенерировать LabeledPoint с помощью функции карты. Буду очень благодарен, если кто-нибудь сможет решить эту проблему.

ответ

6

Вряд ли ошибка. Вы не указали code required to reproduce the issue, но, скорее всего, используете Spark 2.0 с трансформаторами ML и сравниваете неправильные объекты.

Давайте проиллюстрируем это на примере. Простые данные

from pyspark.ml.feature import OneHotEncoder 

row = OneHotEncoder(inputCol="x", outputCol="features").transform(
    sc.parallelize([(1.0,)]).toDF(["x"]) 
).first() 

Теперь давайте импорт различных векторных классов:

from pyspark.ml.linalg import Vector as MLVector, Vectors as MLVectors 
from pyspark.mllib.linalg import Vector as MLLibVector, Vectors as MLLibVectors 
from pyspark.mllib.regression import LabeledPoint 

и сделать тесты:

isinstance(row.features, MLLibVector) 
False 
isinstance(row.features, MLVector) 
True 

Как вы видите, что мы имеем pyspark.ml.linalg.Vector не pyspark.mllib.linalg.Vector, который не совместим со старым API:

LabeledPoint(0.0, row.features) 
TypeError         Traceback (most recent call last) 
... 
TypeError: Cannot convert type <class 'pyspark.ml.linalg.SparseVector'> into Vector 

Вы можете преобразовать объект ML в MLLib один:

from pyspark.ml import linalg as ml_linalg 

def as_mllib(v): 
    if isinstance(v, ml_linalg.SparseVector): 
     return MLLibVectors.sparse(v.size, v.indices, v.values) 
    elif isinstance(v, ml_linalg.DenseVector): 
     return MLLibVectors.dense(v.toArray()) 
    else: 
     raise TypeError("Unsupported type: {0}".format(type(v))) 

LabeledPoint(0, as_mllib(row.features)) 
LabeledPoint(0.0, (1,[],[])) 

или просто:

LabeledPoint(0, MLLibVectors.fromML(row.features)) 
LabeledPoint(0.0, (1,[],[])) 

, но в целом вам следует избегать ситуаций, когда это необходимо.

+0

Спасибо большое. Это было решено! Я очень благодарен! –

4

Если вы просто хотите преобразовать SparseVectors из pyspark.ml в pyspark.mllib SparseVectors, вы можете использовать MLUtils. Скажите df - это ваш dataframe, а столбец SparseVectors называется «функциями». Тогда следующие несколько строк позволяют достичь этого:

from pyspark.mllib.utils import MLUtils 
df = MLUtils.convertVectorColumnsFromML(df, "features") 

Эта проблема возникла для меня, потому что при использовании CountVectorizer из pyspark.ml.feature я не мог создать LabeledPoints, из-за несовместимости с Спарсевектор из pyspark.ml

Интересно, почему их последняя документация CountVectorizer не использует «новый» класс SparseVector. Поскольку алгоритмам классификации нужны LabeledPoints, это не имеет смысла для меня ...

UPDATE: я понял, что библиотека мл предназначена для DataFrame-объектов и mllib библиотека для RDD-объектов. Рекомендуется использовать DataFrame-Datastructure, так как Spark> 2,0, потому что SparkSession более совместим, чем SparkContext (но сохраняет объект SparkContext) и доставляет DataFrame вместо RDD. Я нашел этот пост, который дал мне «ага» -эффект: mllib and ml. Спасибо Альберто Бонсанто :).

Использовать f.e. NaiveBayes из mllib, мне пришлось преобразовать свой DataFrame в объекты LabeledPoint для NaiveBayes из mllib.

Но проще использовать NaiveBayes из ml, потому что вам не нужны метки LabeledPoints, но вы можете просто указать набор функций и классов для вашего фрейма данных.

PS: Я боролся с этим проблемы в течение нескольких часов, так что я чувствовал, что мне нужно, чтобы разместить его здесь :)