Как может получиться, что для одного и того же категориального признака (например, Temp
) я получу 3 разных прогноза?
Это потому, что ваш вывод Accumulator
нашел еговплоть до features
(что, конечно, не должно иметь место), поэтому модель просто «предсказывает» (по сути, копирует) эту часть ввода;вот почему прогнозы , поэтому"точны" ...
Похоже, что VectorAssembler
все испортило. Дело в том, что вам на самом деле не нужен VectorAssembler
здесь, поскольку на самом деле у вас есть только «одиночная» функция (закодированный вектор с горячим кодированием в EncodedItem
). Это может быть причиной того, что VectorAssembler
ведет себя здесь так (его просят "собрать" одну особенность), но в любом случае это будет ошибка.
Так чтоЯ предлагаю избавиться от VectorAssembler
и переименовать EncodedItem
напрямую в features
, то есть:
indexer = StringIndexer(inputCol="NameItem", outputCol="CategorizedItem", handleInvalid = "keep")
encoderInput = [indexer.getOutputCol()]
encoderOutput = ["features"] # 1st change
encoder = OneHotEncoderEstimator(inputCols=encoderInput, outputCols=encoderOutput)
lr = LinearRegression(labelCol="Accumulator")
pipeline = Pipeline(stages=[indexer, encoder, lr]) # 2nd change
lrModel = pipeline.fit(trainDF)
ОБНОВЛЕНИЕ (после обратной связи в комментариях)
Моя версия Spark - 1.4.4
К сожалению, я не могу воспроизвести проблему просто потому, что у меня нет доступа к Spark 1.4.4, который вы используете. Но я подтвердил, что он работает нормально в самой последней версии Spark 2.4.4 , что еще больше склоняет меня к мысли, что в версии 1.4 действительно была какая-то ошибка, которая впоследствии была исправлена. .
Вот воспроизведение в Spark 2.4.4 с использованием некоторых фиктивных данных, похожих на ваши:
spark.version
# '2.4.4'
from pyspark.ml.feature import VectorAssembler, OneHotEncoderEstimator, StringIndexer
from pyspark.ml.regression import LinearRegression
from pyspark.ml import Pipeline
# dummy data resembling yours:
df = spark.createDataFrame([['Speed', 44000],
['Temp', 23000],
['Temp', 5000],
['Speed', 75000],
['Weight', 5300],
['Height', 34500],
['Weight', 6500]],
['NameItem', 'Accumulator'])
df.show()
# result:
+--------+-----------+
|NameItem|Accumulator|
+--------+-----------+
| Speed| 44000|
| Temp| 23000|
| Temp| 5000|
| Speed| 75000|
| Weight| 5300|
| Height| 34500|
| Weight| 6500|
+--------+-----------+
indexer = StringIndexer(inputCol="NameItem", outputCol="CategorizedItem", handleInvalid = "keep")
encoderInput = [indexer.getOutputCol()]
encoderOutput = ["EncodedItem"]
encoder = OneHotEncoderEstimator(inputCols=encoderInput, outputCols=encoderOutput)
assemblerInput = encoderOutput
assembler = VectorAssembler(inputCols=assemblerInput, outputCol="features")
lr = LinearRegression(labelCol="Accumulator")
pipeline = Pipeline(stages=[indexer, encoder, assembler, lr])
lrModel = pipeline.fit(df)
lrModel.transform(df).show() # predicting on the same df, for simplicity
Результат последнего transform
равен
+--------+-----------+---------------+-------------+-------------+------------------+
|NameItem|Accumulator|CategorizedItem| EncodedItem| features| prediction|
+--------+-----------+---------------+-------------+-------------+------------------+
| Speed| 44000| 2.0|(4,[2],[1.0])|(4,[2],[1.0])| 59500.0|
| Temp| 23000| 1.0|(4,[1],[1.0])|(4,[1],[1.0])|14000.000000000004|
| Temp| 5000| 1.0|(4,[1],[1.0])|(4,[1],[1.0])|14000.000000000004|
| Speed| 75000| 2.0|(4,[2],[1.0])|(4,[2],[1.0])| 59500.0|
| Weight| 5300| 0.0|(4,[0],[1.0])|(4,[0],[1.0])| 5900.000000000004|
| Height| 34500| 3.0|(4,[3],[1.0])|(4,[3],[1.0])| 34500.0|
| Weight| 6500| 0.0|(4,[0],[1.0])|(4,[0],[1.0])| 5900.000000000004|
+--------+-----------+---------------+-------------+-------------+------------------+
откуда видно, что:
-
features
теперь не включает значения выходной переменной Accumulator
, как и должно быть;на самом деле, как я уже говорил выше, features
теперь идентично EncodedItem
, что делает VectorAssembler
избыточным, как и следовало ожидать, поскольку у нас есть только одна особенность. prediction
значения теперь идентичны для тех же значений NameItem
, опять же, как мы и ожидали, плюс они менее точны и, следовательно, более реалистичны.
Так что, безусловно, ваша проблема имеетделать с значительно устаревшей Spark версии 1.4.4, которую вы используете. Spark сделал скачки с версии 1.4, и вы должны серьезно подумать об обновлении ...