我已经设置了一个CrossValidator对象,它与一个线性回归管道和一个可供选择的超参数网格相结合。更具体地说,我对两个超参数的组合产生的9个不同的设置运行5次交叉验证(每个设置采用3个值),并通过将collectSubModels标志设置为True来跟踪所有45个生成的模型:
...
lr = LinearRegression(featuresCol="features", labelCol="label")
pipeline = Pipeline(stages=indexers + [encoder] + [assembler] + [lr])
param_grid = ParamGridBuilder()
.addGrid(lr.regParam, [0.0, 0.05, 0.1])
.addGrid(lr.elasticNetParam, [0.0, 0.5, 1.0])
.build()
cross_val = CrossValidator(estimator=pipeline,
estimatorParamMaps=param_grid,
evaluator=RegressionEvaluator(metricName="rmse"),
numFolds=5,
collectSubModels=True
)
Run cross-validation, and choose the best set of parameters
cv_model = cross_val.fit(train)
return cv_model
一切似乎都很顺利,除了当我打印出每个模型的性能(即RMSE)时(即每个折叠9个模型),我试图“手动”计算每个折叠的平均值,结果得到的9个平均值与使用CrossValidator的内部avgMetrics属性时得到的值完全不匹配。
*************** Fold #1 ***************
--- Model #1 out of 9 ---
Parameters: lambda=[0.000]; alpha=[0.000]
RMSE: 149354.656
*** Fold #2 ***
--- Model #1 out of 9 ---
Parameters: lambda=[0.000]; alpha=[0.000]
RMSE: 146038.521
*** Fold #3 ***
--- Model #1 out of 9 ---
Parameters: lambda=[0.000]; alpha=[0.000]
RMSE: 148739.919
*** Fold #4 ***
--- Model #1 out of 9 ---
Parameters: lambda=[0.000]; alpha=[0.000]
RMSE: 146816.473
*** Fold #5 ***
--- Model #1 out of 9 ---
Parameters: lambda=[0.000]; alpha=[0.000]
RMSE: 149868.621
如您所见,RMSE的所有值都低于150000。
[150091.7372030353, 150091.7372030353, 150091.7372030353, 150091.7345116686, 150093.66131828527, 150090.52769066638, 150091.7338301999, 150090.52716106002, 150091.59829053417]
有9个元素如预期,但没有一个看起来是正确的!事实上,尽管我的45款车型(不仅仅是上面列出的5款)都没有达到这些数字,但它们都在15万辆以上。
看起来avgMetrics的填充方式是错误的。我知道早在2016年就有一个问题,这个值错误地包含了交叉验证指标的总和,而不是平均值,但显然这个问题已经解决了。
我还试图检查CrossValidator对象的_-fit方法的当前实现,尽管我没有花太多时间在这方面,但显然一切看起来都很好:
for i in range(nFolds):
validateLB = i * h
validateUB = (i + 1) * h
condition = (df[randCol] >= validateLB) & (df[randCol] < validateUB)
validation = df.filter(condition).cache()
train = df.filter(~condition).cache()
tasks = _parallelFitTasks(est, train, eva, validation, epm, collectSubModelsParam)
for j, metric, subModel in pool.imap_unordered(lambda f: f(), tasks):
metrics[j] += (metric / nFolds)
if collectSubModelsParam:
subModels[i][j] = subModel
其他人也经历过同样的问题吗?
编辑:我盲目地认为问题(如果有的话)出在avgMetrics属性上;但是,可能这些平均值实际上是正确的,而我在上面通过调用打印出来的单个度量值。小结.rootMeanSquaredError在每个子模型上计算错误。不管怎样,两者之间显然存在矛盾。