机器学习超参数调优总结(PySpark ML)

人工智能 机器学习
CrossValidator交叉验证器首先将数据集分割为一组折叠数据集,这些折叠数据集用作单独的训练数据集和测试数据集。例如,当k=3次时,CrossValidator将生成3对(训练,测试)数据集,每对数据集使用2/3的数据进行训练,1/3的数据进行测试。

ML中的一个重要任务是模型选择,或者使用数据为给定任务找到最佳的模型或参数。这也称为调优。可以对单个的估计器(如LogisticRegression​)进行调优,也可以对包括多种算法、特性化和其他步骤的整个pipeline​进行调优。用户可以一次调优整个Pipeline​,而不是分别调优 Pipeline 中的每个元素。

ML中的一个重要任务是模型选择,或者使用数据为给定任务找到最佳的模型或参数。这也称为调优。可以对单个的Estimator​(如LogisticRegression​)进行调优,也可以对包括多种算法、特性化和其他步骤的整个pipeline​进行调优。用户可以一次调优整个Pipeline​,而不是分别调优Pipeline中的每个元素。

MLlib支持使用CrossValidator和TrainValidationSplit等工具进行模型选择。这些工具需要具备以下条件:

  • 估计器:要调优的算法或管道pipeline
  • 一组参数:可选择的参数,有时称为搜索的“参数网格”
  • 评估者:度量拟合模型在测试数据上的表现

这些模型选择工具的工作方式如下:

  • 他们将输入数据拆分为单独的训练和测试数据集。
  • 对于每个(训练、测试)对,它们遍历ParamMap 集合:

对于每个ParamMap​,使用这些参数拟合Estimator​,得到拟合的Model​,并使用Evaluator​ 评估Model的性能。

  • 他们选择Model由表现最好的一组参数产生。

为了帮助构造参数网格,用户可以使用ParamGridBuilder。默认情况下,参数网格中的参数集以串行方式计算。在使用CrossValidator或TrainValidationSplit运行模型选择之前,可以通过将并行度设置为2或更多(1的值将是串行的)来并行地进行参数评估。并行度的值应该谨慎选择,以便在不超过集群资源的情况下最大化并行度,较大的值不一定会提高性能。一般来说,10以上的值对大多数集群来说应该足够了。

交叉验证

CrossValidator交叉验证器首先将数据集分割为一组折叠数据集,这些折叠数据集用作单独的训练数据集和测试数据集。例如,当k=3次时,CrossValidator将生成3对(训练,测试)数据集,每对数据集使用2/3的数据进行训练,1/3的数据进行测试。为了评估一个特定的ParamMap, CrossValidator通过在3个不同的(训练,测试)数据集对上拟合Estimator产生的3个模型计算平均评估度量。

在确定最佳ParamMap之后,CrossValidator最终使用最佳ParamMap和整个数据集重新匹配Estimator。

from pyspark.ml import Pipeline
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import BinaryClassificationEvaluator
from pyspark.ml.feature import HashingTF, Tokenizer
from pyspark.ml.tuning import CrossValidator, ParamGridBuilder

# 准备训练文件,并做好标签。
training = spark.createDataFrame([
(0, "a b c d e spark", 1.0),
(1, "b d", 0.0),
(2, "spark f g h", 1.0),
(3, "hadoop mapreduce", 0.0),
(4, "b spark who", 1.0),
(5, "g d a y", 0.0),
(6, "spark fly", 1.0),
(7, "was mapreduce", 0.0),
(8, "e spark program", 1.0),
(9, "a e c l", 0.0),
(10, "spark compile", 1.0),
(11, "hadoop software", 0.0)
], ["id", "text", "label"])

# 配置一个ML管道,它由树stages组成:tokenizer、hashingTF和lr。
tokenizer = Tokenizer(inputCol="text", outputCol="words")
hashingTF = HashingTF(inputCol=tokenizer.getOutputCol(), outputCol="features")
lr = LogisticRegression(maxIter=10)
pipeline = Pipeline(stages=[tokenizer, hashingTF, lr])

# 我们现在将Pipeline作为一个Estimator,将其包装在CrossValidator实例中。
# 这将允许我们共同选择所有管道阶段的参数。
# 交叉验证器需要一个Estimator、一组Estimator ParamMaps和一个Evaluator。
# 我们使用ParamGridBuilder来构造一个用于搜索的参数网格。
# hashingTF.numFeatures 的3个值, lr.regParam的2个值,
# 这个网格将有3 x 2 = 6的参数设置供CrossValidator选择。


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

crossval = CrossValidator(estimator=pipeline,
estimatorParamMaps=paramGrid,
evaluator=BinaryClassificationEvaluator(),
numFolds=2) # 使用3+ folds

# 运行交叉验证,并选择最佳参数集。
cvModel = crossval.fit(training)

# 准备测试未标注的文件
test = spark.createDataFrame([
(4, "spark i j k"),
(5, "l m n"),
(6, "mapreduce spark"),
(7, "apache hadoop")
], ["id", "text"])

# 对测试文档进行预测, cvModel使用发现的最佳模型(lrModel)
prediction = cvModel.transform(test)
selected = prediction.select("id", "text", "probability", "prediction")
for row in selected.collect():
print(row)

训练验证拆分

除了 CrossValidator 之外,Spark 还提供了用于超参数调优的 TrainValidationSplit。TrainValidationSplit 只计算每个参数组合一次,而在 CrossValidator 的情况下是k次。因此,它的成本较低,但当训练数据集不够大时,它不会产生可靠的结果。

与 CrossValidator 不同,TrainValidationSplit 创建单个(训练、测试)数据集对。它使用 trainRatio 参数将数据集分成这两部分。例如,当trainRatio=0.75 时,TrainValidationSplit 将生成一个训练和测试数据集对,其中 75% 的数据用于训练,25% 用于验证。

像 CrossValidator 一样,TrainValidationSplit 最终使用最佳 ParamMap 和整个数据集匹配 Estimator。

from pyspark.ml.evaluation import RegressionEvaluator
from pyspark.ml.regression import LinearRegression
from pyspark.ml.tuning import ParamGridBuilder, TrainValidationSplit

# Prepare training and test data.
data = spark.read.format("libsvm")\
.load("data/mllib/sample_linear_regression_data.txt")
train, test = data.randomSplit([0.9, 0.1], seed=12345)

lr = LinearRegression(maxIter=10)

# 我们使用ParamGridBuilder来构造一个用于搜索的参数网格。
# TrainValidationSplit将尝试所有值的组合,并使用评估器确定最佳模型。
paramGrid = ParamGridBuilder()\
.addGrid(lr.regParam, [0.1, 0.01]) \
.addGrid(lr.fitIntercept, [False, True])\
.addGrid(lr.elasticNetParam, [0.0, 0.5, 1.0])\
.build()

# 在这种情况下,估计器是简单的线性回归。
# TrainValidationSplit需要一个Estimator、一组Estimator ParamMaps 和一个 Evaluator。
tvs = TrainValidationSplit(estimator=lr,
estimatorParamMaps=paramGrid,
evaluator=RegressionEvaluator(),
# 80%的数据将用于培训,20%用于验证。
trainRatio=0.8)

# 运行TrainValidationSplit,并选择最佳参数集。
model = tvs.fit(train)

# 对测试数据进行预测。模型是参数组合后性能最好的模型。
model.transform(test)\
.select("features", "label", "prediction")\
.show()

责任编辑:武晓燕 来源: 数据STUDIO
相关推荐

2021-01-22 11:18:58

Python机器学习超参数

2024-07-16 16:13:14

2024-11-25 08:20:35

2022-08-09 13:44:37

机器学习PySpark M数据分析

2010-09-25 13:05:07

JVM参数

2022-08-30 00:31:12

机器学习超参数调优算法

2012-01-10 14:35:08

JavaJVM

2021-03-17 11:35:11

JVM代码Java

2023-06-06 15:42:13

Optuna开源

2012-01-10 15:13:56

JavaJVM

2017-11-07 11:00:59

数据库调优DBMS

2023-07-28 14:49:00

黑盒优化机器学习

2010-03-04 10:56:52

JVM参数

2021-03-26 06:05:17

Tomcat

2023-11-10 11:23:20

JVM内存

2010-09-26 13:48:51

JVM调优

2019-12-20 14:21:26

JVM调优垃圾回收

2012-01-10 14:18:40

JavaJVM

2011-03-31 13:40:34

2013-03-20 17:30:18

点赞
收藏

51CTO技术栈公众号