随机网格搜索交叉验证
优化机器学习超参数最流行的方法之一是scikiti-learn中的RandomizedSearchCV()。让我们仔细分析一下是什么意思。
在随机网格搜索交叉验证中,我们首先创建一个超参数网格,我们想通过尝试优化这些超参数的值,让我们看一个随机森林回归器的超参数网格示例,并看看是如何设置它的:
#NumberoftreesinRandomForestrf_n_estimators= [int(x) forxinnp.linspace(200, 1000, 5)] rf_n_estimators.append(1500) rf_n_estimators.append(2000) #Maximumnumberoflevelsintreerf_max_depth= [int(x) forxinnp.linspace(5, 55, 11)] #Addthedefaultasapossiblevaluerf_max_depth.append(None) #Numberoffeaturestoconsiderateverysplitrf_max_features= ['auto', 'sqrt', 'log2'] #Criteriontosplitonrf_criterion= ['mse', 'mae'] #Minimumnumberofsamplesrequiredtosplitanoderf_min_samples_split= [int(x) forxinnp.linspace(2, 10, 9)] #Minimumdecreaseinimpurityrequiredforsplittohappenrf_min_impurity_decrease= [0.0, 0.05, 0.1] #Methodofselectingsamplesfortrainingeachtreerf_bootstrap= [True, False] #Createthegridrf_grid= {'n_estimators': rf_n_estimators, 'max_depth': rf_max_depth, 'max_features': rf_max_features, 'criterion': rf_criterion, 'min_samples_split': rf_min_samples_split, 'min_impurity_decrease': rf_min_impurity_decrease, 'bootstrap': rf_bootstrap}
首先,我们为要优化的每个超参数创建一个可能的取值列表,然后使用上面所示的带有键值对的字典来设置网格。为了找到和理解机器学习模型的超参数,你可以查阅模型的官方文档。
生成的网格如下所示:
顾名思义,随机网格搜索交叉验证使用交叉验证来评估模型性能。随机搜索意味着算法不是尝试所有可能的超参数组合(在我们的例子中是27216个组合),而是随机从网格中为每个超参数选择一个值,并使用这些超参数的随机组合来评估模型。
用计算机将所有可能的组合都尝试一遍是非常昂贵的,而且需要很长时间。随机选择超参数可以显著地加快这个过程,并且通常为尝试所有可能的组合提供了一个类似的好的解决方案。让我们看看随机网格搜索交叉验证是如何使用的。
随机森林的超参数整定
使用先前创建的网格,我们可以为我们的随机森林回归器找到最佳的超参数。因为数据集相对较小,我将使用3折的CV并运行200个随机组合。因此,随机网格搜索CV总共将要训练和评估600个模型(200个组合的3倍)。由于与其他机器学习模型(如xgboost)相比,随机森林的计算速度较慢,运行这些模型需要几分钟时间。一旦这个过程完成,我们就可以得到最佳的超参数。
以下展示了如何使用RandomizedSearchCV():
#Createthemodeltobetunedrf_base=RandomForestRegressor() #CreatetherandomsearchRandomForestrf_random=RandomizedSearchCV(estimator=rf_base, param_distributions=rf_grid, n_iter=200, cv=3, verbose=2, random_state=42, n_jobs=-1) #Fittherandomsearchmodelrf_random.fit(X_train_temp, y_train_temp) #Viewthebestparametersfromtherandomsearchrf_random.best_params_
我们将在最终模型中使用这些超参数,并在测试集上对模型进行测试。
xgboost的超参数整定
对于我们的xgboost回归,过程基本上与随机森林相同。由于模型的性质,我们试图优化的超参数有一些是相同的,有一些是不同的。您可以在这里找到xgb回归器超参数的完整列表和解释。我们再次创建网格:
#Numberoftreestobeusedxgb_n_estimators= [int(x) forxinnp.linspace(200, 2000, 10)] #Maximumnumberoflevelsintreexgb_max_depth= [int(x) forxinnp.linspace(2, 20, 10)] #Minimumnumberofinstacesneededineachnodexgb_min_child_weight= [int(x) forxinnp.linspace(1, 10, 10)] #TreeconstructionalgorithmusedinXGBoostxgb_tree_method= ['auto', 'exact', 'approx', 'hist', 'gpu_hist'] #Learningratexgb_eta= [xforxinnp.linspace(0.1, 0.6, 6)] #Minimumlossreductionrequiredtomakefurtherpartitionxgb_gamma= [int(x) forxinnp.linspace(0, 0.5, 6)] #Learningobjectiveusedxgb_objective= ['reg:squarederror', 'reg:squaredlogerror'] #Createthegridxgb_grid= {'n_estimators': xgb_n_estimators, 'max_depth': xgb_max_depth, 'min_child_weight': xgb_min_child_weight, 'tree_method': xgb_tree_method, 'eta': xgb_eta, 'gamma': xgb_gamma, 'objective': xgb_objective}
生成的网格如下所示:
为了使性能评估具有可比性,我还将使用具有200个组合的3折CV来进行xgboost:
#Createthemodeltobetunedxgb_base=XGBRegressor() #CreatetherandomsearchRandomForestxgb_random=RandomizedSearchCV(estimator=xgb_base, param_distributions=xgb_grid, n_iter=200, cv=3, verbose=2, random_state=420, n_jobs=-1) #Fittherandomsearchmodelxgb_random.fit(X_train_temp, y_train_temp) #Gettheoptimalparametersxgb_random.best_params_
最优超参数如下:
同样的,这些将在最终的模型中使用。
虽然对有些人来说这可能是显而易见的,但我只是想在这里提一下:我们为什么不为多元线性回归做超参数优化是因为模型中没有超参数需要调整,它只是一个多元线性回归。
现在我们已经获得了最佳的超参数(至少在交叉验证方面),我们终于可以在测试数据上评估我们的模型了,我们就可以根据我们从一开始就持有的测试数据来评估我们的模型了!
最终模型的评估
在评估了我们的机器学习模型的性能并找到了最佳超参数之后,是时候对模型进行最后的测试了。
我们对模型进行了训练,这些数据是我们用于进行评估的数据的80%,即除了测试集之外的所有数据。我们使用上一部分中找到的超参数,然后比较模型在测试集上的表现。
让我们创建和训练我们的模型:
#CreatethefinalMultipleLinearRegressionmlr_final=LinearRegression() #CreatethefinalRandomForestrf_final=RandomForestRegressor(n_estimators=200, min_samples_split=6, min_impurity_decrease=0.0, max_features='sqrt', max_depth=25, criterion='mae', bootstrap=True, random_state=42) #CreatethefnalExtremeGradientBoosterxgb_final=XGBRegressor(tree_method='exact', objective='reg:squarederror', n_estimators=1600, min_child_weight=6, max_depth=8, gamma=0, eta=0.1, random_state=42) #Trainthemodelsusing80%oftheoriginaldatamlr_final.fit(X_train_temp, y_train_temp) rf_final.fit(X_train_temp, y_train_temp) xgb_final.fit(X_train_temp, y_train_temp)
我定义了一个函数,该函数对所有最终模型进行评分,并创建了一个更容易比较的数据帧:
#Defineafunctionthatcomparesallfinalmodelsdeffinal_comparison(models, test_features, test_labels): scores=pd.DataFrame() formodelinmodels: predictions=model.predict(test_features) mae=round(mean_absolute_error(test_labels, predictions), 4) mse=round(mean_squared_error(test_labels, predictions), 4) r2=round(r2_score(test_labels, predictions), 4) errors=abs(predictions-test_labels) mape=100*np.mean(errors/test_labels) accuracy=round(100-mape, 4) scores[str(model)] = [mae, mse, r2, accuracy] scores.index= ['Mean Absolute Error', 'Mean Squared Error', 'R^2', 'Accuracy'] returnscores
使用我们的三个最终模型调用该函数并调整列标题将会得到以下最终计算结果:
#Callthecomparisonfunctionwiththethreefinalmodelsfinal_scores=final_comparison([mlr_final, rf_final, xgb_final], X_test, y_test) #Adjustthecolumnheadersfinal_scores.columns= ['Linear Regression', 'Random Forest', 'Extreme Gradient Boosting']
获胜者是:随机森林回归!
随机森林的R-squared达到80%,测试集的准确率为97.6%,这意味着它的预测平均只有2.4%的偏差。这是个不错的结果!
在此分析中,多元线性回归的表现并不逊色,但xgboost并没有达到其所宣传的效果。
总结评论
整个分析过程和实际操作过程都很有趣。我一直在研究Fitbit是如何计算睡眠分数的,现在我很高兴能更好地理解它。最重要的是,我建立了一个机器学习模型,可以非常准确地预测睡眠分数。话虽如此,我还是想强调几件事:
- 正如我在第2部分中提到的,对多元线性回归系数的解释可能不准确,因为特征之间存在高度的多重共线性。
- 我用于分析的数据集相当小,因为它依赖于从Fitbit获得的286个数据点。这限制了结果的可推广性,需要更大的数据集才能训练出更健壮的模型。
- 该分析仅使用了Fitbit的一个人的睡眠数据,因此可能不能很好地推广到其他睡眠模式、心率等不同的人。
我希望你喜欢这篇关于如何使用机器学习来预测Fitbit睡眠分数的全面分析,并且了解了不同睡眠阶段的重要性以及睡眠过程中所花费的时间。