使用Pyspark进行超参数调整

4

我正在处理一个数据集,使用线性回归来拟合模型。在最终确定之前,我想尝试使用超参数调优来获得最佳的可用模型。

我一直在通过管道运行数据,首先将字符串转换为数字,然后对其进行编码,再将所有列向量化,最后在应用线性回归之前进行缩放。我希望知道如何设置网格来开始超参数调优。

import pyspark.ml.feature as ft
WD_indexer = ft.StringIndexer(inputCol="Wind_Direction", outputCol="WD-num")
WD_encoder = ft.OneHotEncoder(inputCol="WD-num", outputCol='WD-vec')
featuresCreator = ft.VectorAssembler(inputCols=["Dew_Point", "Temperature",
                                            "Pressure", "WD-vec", "Wind_Speed","Hours_Snow","Hours_Rain"], outputCol='features')

from pyspark.ml.feature import StandardScaler
feature_scaler = StandardScaler(inputCol="features",outputCol="sfeatures")

from pyspark.ml.regression import LinearRegression
lr = LinearRegression(featuresCol="sfeatures",labelCol="PM_Reading")

因此,流程管道看起来像这样:

from pyspark.ml import Pipeline
pipeline = Pipeline( stages = [WD_indexer, WD_encoder, featuresCreator, feature_scaler, lr] )

我该如何为这个管道设置网格?
谢谢
2个回答

5

我知道这个问题是两年前发布的,但仍然值得让大家了解最新发现和你问题的一种备选解决方案。正如Frank Kane在这里详细解释的那样,CrossValidator相当耗费,因为需要评估指定超参数值的每种可能组合。因此,建议您使用TrainValidationSplit,它每种组合仅评估单个随机的训练/测试数据拆分。在处理非常大的数据集时,这可能非常有用。以下是来自spark文档的示例代码(在这里找到更多详细信息):

# We use a ParamGridBuilder to construct a grid of parameters to search over.
# TrainValidationSplit will try all combinations of values and determine best model using
# the evaluator.
paramGrid = ParamGridBuilder()\
    .addGrid(lr.regParam, [0.1, 0.01]) \
    .addGrid(lr.fitIntercept, [False, True])\
    .addGrid(lr.elasticNetParam, [0.0, 0.5, 1.0])\
    .build()

# In this case the estimator is simply the linear regression.
# A TrainValidationSplit requires an Estimator, a set of Estimator ParamMaps, and an Evaluator.
tvs = TrainValidationSplit(estimator=lr,
                           estimatorParamMaps=paramGrid,
                           evaluator=RegressionEvaluator(),
                           # 80% of the data will be used for training, 20% for validation.
                           trainRatio=0.8)

# Run TrainValidationSplit, and choose the best set of parameters.
model = tvs.fit(train)

当运行我的LR模型的pramGrid时,出现错误:“PipelineModel”对象没有“fitIntercept”属性。有什么想法是什么问题? - Sylwia Kmiec
1
@SylwiaKmiec,没有看到示例代码很难回答你的问题,但我认为这个链接可能会对你有所帮助:https://stackoverflow.com/questions/61257344/attributeerror-pipelinemodel-object-has-no-attribute-fitmultiple。你可能是将管道模型传递给参数网格而不是管道对象。 - ahajib
谢谢,我实际上已经解决了这个问题(不记得具体是什么问题了),但非常感谢您提供的链接! - Sylwia Kmiec

3

您可以使用pyspark ml.tuning类中的参数网格构建器来设置一个网格,并使用交叉验证进行测试。

from pyspark.ml.tuning import CrossValidator, ParamGridBuilder

然后您可以决定要运行的不同参数及其值: 您需要为每个参数添加一个网格,以及相应的值数组 例如,对于线性回归,您可以传递lr.regParam、lr.maxIter、lr.elasticNetParam的值。

paramGrid = ParamGridBuilder().addGrid(lr.maxIter, [10, 100, 1000]).addGrid(lr.regParam, [0.1, 0.01]).build()

您还可以使用featuresCreator.inputCols从流水线中更改向量汇编器、字符串索引器和独热编码的参数等。

crossval = CrossValidator(estimator=pipeline,
                      estimatorParamMaps=paramGrid,
                      evaluator=RegressionEvaluator(),
                      numFolds=2)  # use 3+ folds in practice

您可以通过交叉验证运行训练数据,以获取最佳模型。
cvModel = crossval.fit(training)

非常感谢。我会尝试一下。如果我使用神经网络,如何设置网格层的参数? - mirfarali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接