Machine learning 通过Spark MLlib回归估计数值
我正在培训Spark MLlib线性回归器,但我相信我不了解库的部分实际使用 我有一个功能(Machine learning 通过Spark MLlib回归估计数值,machine-learning,pyspark,regression,apache-spark-mllib,apache-spark-ml,Machine Learning,Pyspark,Regression,Apache Spark Mllib,Apache Spark Ml,我正在培训Spark MLlib线性回归器,但我相信我不了解库的部分实际使用 我有一个功能(NameItem)和一个输出(累加器)。 第一种是分类的(速度、温度等),第二种是双精度数字 训练集由数百万个条目组成,它们不是线性相关的(我用热图和相关指数检查) 问题:我想通过线性回归估计给定NameItem值的累加器值,但我认为这不是我实际要做的 问题:我怎么做 我首先将数据集划分为训练集和数据集: (trainDF,testDF)=df.randomspilt((0.80,0.20),seed=4
NameItem
)和一个输出(累加器
)。
第一种是分类的(速度、温度等),第二种是双精度数字
训练集由数百万个条目组成,它们不是线性相关的(我用热图和相关指数检查)
问题:我想通过线性回归估计给定NameItem
值的累加器
值,但我认为这不是我实际要做的
问题:我怎么做
我首先将数据集划分为训练集
和数据集
:
(trainDF,testDF)=df.randomspilt((0.80,0.20),seed=42)
之后,我尝试了管道方法,正如大多数教程所示:
1) 我将名称项编入索引
indexer = StringIndexer(inputCol="NameItem", outputCol="CategorizedItem", handleInvalid = "keep")
2) 然后我把它编码了
encoderInput = [indexer.getOutputCol()]
encoderOutput = ["EncodedItem"]
encoder = OneHotEncoderEstimator(inputCols=encoderInput, outputCols=encoderOutput)
3) 而且还组装了它
assemblerInput = encoderOutput
assembler = VectorAssembler(inputCols=assemblerInput, outputCol="features")
之后,我继续进行有效的培训:
lr = LinearRegression(labelCol="Accumulator")
pipeline = Pipeline(stages=[indexer, encoder, assembler, lr])
lrModel = pipeline.fit(trainDF)
predictions = lrModel.transform(testDF).show(5, False)
这就是我在测试集上应用预测时得到的结果:
lr = LinearRegression(labelCol="Accumulator")
pipeline = Pipeline(stages=[indexer, encoder, assembler, lr])
lrModel = pipeline.fit(trainDF)
predictions = lrModel.transform(testDF).show(5, False)
对于相同的分类特征(例如Temp
),我怎么可能得到3种不同的预测
尽管它们非常接近预期值,但我觉得有点不对劲
对于相同的分类特征(例如Temp
),我怎么可能得到3种不同的预测
这是因为不知何故,您的输出累加器
已经进入了特性
(当然不应该是这样),因此模型只是“预测”(基本上复制)输入的这一部分;这就是为什么预测如此“准确”
似乎矢量汇编程序把事情搞砸了。事实上,这里并不真正需要vectorsembler
,因为实际上您只有一个“单一”功能(EncodedItem
中的一个热编码稀疏向量)。这可能就是为什么VectorAssembler
在这里的行为是这样的(它被要求“组装”单个功能),但在任何情况下,这都是一个bug
因此,我建议去掉矢量汇编程序
,直接将编码数据项
重命名为功能
,即:
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。但我已经证实,它在Spark2.4.4的最新版本中工作正常,这使我更倾向于相信v1.4中确实存在一些bug,但后来这些bug已经得到了解决
下面是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
最后一次转换的结果是
+--------+-----------+---------------+-------------+-------------+------------------+
|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|
+--------+-----------+---------------+-------------+-------------+------------------+
从这里您可以看到:
功能
现在不包括输出变量累加器的值,因为它实际上应该是这样的;事实上,正如我前面所说,特性
现在与编码数据项
相同,这使得矢量汇编程序
变得多余,这正是我们所期望的,因为我们只有一个特性
现在,预测
值对于名称项
的相同值是相同的,这也是我们所期望的,而且它们不太准确,因此更真实
因此,最确定的是,您的问题与您正在使用的过时的Spark版本1.4.4有关。自从V1.4以来,SCAP已经飞跃了,你应该认真考虑更新……/P>你真的有688个类别在<代码> NameItem > /Cord>?现在没有时间深入调查,所以请尝试下面的答案,留下反馈,明天下午我可能会回来深入调查(你的Spark版本是什么?)。我的Spark版本是1.4.4