机器学习算法具有超参数,可以让你根据特定数据集定制算法的行为。
超参数与参数不同,参数是模型通过学习算法找到的内部系数或权重。与参数不同,超参数由实践者在配置模型时指定。
通常,对于给定数据集上的给定算法的超参数,很难知道使用什么值,因此使用随机搜索或网格搜索策略来尝试不同的超参数值是很常见的。
算法的超参数越多,调优过程就越慢。因此,希望选择模型超参数的最小子集进行搜索或调优。
并非所有模型超参数都同等重要。一些超参数对机器学习算法的行为,进而对性能有不成比例的影响。
作为一名机器学习实践者,你必须知道要关注哪些超参数才能快速获得良好的结果。
在本教程中,你将发现对于一些顶级机器学习算法最重要的超参数。
开始你的项目,阅读我的新书《Python 机器学习精通》,其中包括分步教程和所有示例的Python 源代码文件。
让我们开始吧。
- **2020年1月更新**:已针对 scikit-learn v0.22 API 的变更进行更新。

分类机器学习算法的超参数
照片作者:shuttermonkey,保留部分权利。
分类算法概述
我们将仔细研究您可能用于分类的顶级机器学习算法的重要超参数。
我们将研究您需要关注的超参数以及在您的数据集上调优模型时建议尝试的值。
这些建议基于算法教科书的建议、从业者的实际建议,以及我自己的经验。
我们将研究的七种分类算法如下:
- 逻辑回归
- 岭分类器
- K-最近邻 (KNN)
- 支持向量机 (SVM)
- 装袋决策树 (Bagging)
- 随机森林
- 随机梯度提升
我们将结合它们在 scikit-learn 实现 (Python) 中的应用来考虑这些算法;尽管如此,您也可以将相同的超参数建议用于其他平台,例如 Weka 和 R。
此外,对于每种算法都提供了一个简单的网格搜索示例,您可以将其作为分类预测建模项目的起点。
注意:如果您在使用不同的超参数值,甚至与本教程中建议的超参数不同的超参数方面取得了成功,请在下面的评论中告诉我。我很乐意听到您的反馈。
让我们开始吧。
逻辑回归
逻辑回归实际上没有需要调优的关键超参数。
有时,您可以通过不同的求解器(solver)看到性能或收敛性的有用差异。
- solver 在 ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'] 中
正则化(penalty)有时会有帮助。
- penalty 在 ['none', 'l1', 'l2', 'elasticnet'] 中
注意:并非所有求解器都支持所有正则化项。
C 参数控制正则化强度,这也会很有效。
- C 在 [100, 10, 1.0, 0.1, 0.01] 中
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上对逻辑回归的关键超参数进行网格搜索。
为减少警告/错误,省略了一些组合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# 逻辑回归关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV 从 sklearn.线性模型 导入 LogisticRegression # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = LogisticRegression() solvers = ['newton-cg', 'lbfgs', 'liblinear'] penalty = ['l2'] c_values = [100, 10, 1.0, 0.1, 0.01] # 定义网格搜索 grid = dict(solver=solvers,penalty=penalty,C=c_values) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
最佳:0.945333 使用 {'C': 0.01, 'penalty': 'l2', 'solver': 'liblinear'} 0.936333 (0.016829) 使用: {'C': 100, 'penalty': 'l2', 'solver': 'newton-cg'} 0.937667 (0.017259) 使用: {'C': 100, 'penalty': 'l2', 'solver': 'lbfgs'} 0.938667 (0.015861) 使用: {'C': 100, 'penalty': 'l2', 'solver': 'liblinear'} 0.936333 (0.017413) 使用: {'C': 10, 'penalty': 'l2', 'solver': 'newton-cg'} 0.938333 (0.017904) 使用: {'C': 10, 'penalty': 'l2', 'solver': 'lbfgs'} 0.939000 (0.016401) 使用: {'C': 10, 'penalty': 'l2', 'solver': 'liblinear'} 0.937333 (0.017114) 使用: {'C': 1.0, 'penalty': 'l2', 'solver': 'newton-cg'} 0.939000 (0.017195) 使用: {'C': 1.0, 'penalty': 'l2', 'solver': 'lbfgs'} 0.939000 (0.015780) 使用: {'C': 1.0, 'penalty': 'l2', 'solver': 'liblinear'} 0.940000 (0.015706) 使用: {'C': 0.1, 'penalty': 'l2', 'solver': 'newton-cg'} 0.940333 (0.014941) 使用: {'C': 0.1, 'penalty': 'l2', 'solver': 'lbfgs'} 0.941000 (0.017000) 使用: {'C': 0.1, 'penalty': 'l2', 'solver': 'liblinear'} 0.943000 (0.016763) 使用: {'C': 0.01, 'penalty': 'l2', 'solver': 'newton-cg'} 0.943000 (0.016763) 使用: {'C': 0.01, 'penalty': 'l2', 'solver': 'lbfgs'} 0.945333 (0.017651) 使用: {'C': 0.01, 'penalty': 'l2', 'solver': 'liblinear'} |
岭分类器
岭回归是一种用于预测数值的正则化线性回归模型。
然而,当应用于分类时,它可能非常有效。
也许最重要的调优参数是正则化强度(alpha)。一个好的起点可能是 [0.1 到 1.0] 范围内的值。
- alpha 在 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] 中
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上对 RidgeClassifier 的关键超参数进行网格搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 岭分类器关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV from sklearn.linear_model import RidgeClassifier # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = RidgeClassifier() alpha = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] # 定义网格搜索 grid = dict(alpha=alpha) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 5 6 7 8 9 10 11 |
最佳:0.974667 使用 {'alpha': 0.1} 0.974667 (0.014545) 使用: {'alpha': 0.1} 0.974667 (0.014545) 使用: {'alpha': 0.2} 0.974667 (0.014545) 使用: {'alpha': 0.3} 0.974667 (0.014545) 使用: {'alpha': 0.4} 0.974667 (0.014545) 使用: {'alpha': 0.5} 0.974667 (0.014545) 使用: {'alpha': 0.6} 0.974667 (0.014545) 使用: {'alpha': 0.7} 0.974667 (0.014545) 使用: {'alpha': 0.8} 0.974667 (0.014545) 使用: {'alpha': 0.9} 0.974667 (0.014545) 使用: {'alpha': 1.0} |
K-最近邻 (KNN)
KNN 最重要的超参数是邻居的数量(n_neighbors)。
测试值在 1 到 21 之间,可能只测试奇数。
- n_neighbors 在 [1 到 21] 中
测试选择邻居组成的距离度量(metric)也可能很有趣。
- metric 在 ['euclidean', 'manhattan', 'minkowski'] 中
有关更全面的列表,请参阅
通过不同的权重(weights)测试邻居的贡献也可能很有趣。
- weights 在 ['uniform', 'distance'] 中
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上对 KNeighborsClassifier 的关键超参数进行网格搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# KNeighborsClassifier 关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV from sklearn.neighbors import KNeighborsClassifier # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = KNeighborsClassifier() n_neighbors = range(1, 21, 2) weights = ['uniform', 'distance'] metric = ['euclidean', 'manhattan', 'minkowski'] # 定义网格搜索 grid = dict(n_neighbors=n_neighbors,weights=weights,metric=metric) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 5 6 7 8 9 10 11 12 |
最佳:0.937667 使用 {'metric': 'manhattan', 'n_neighbors': 13, 'weights': 'uniform'} 0.833667 (0.031674) 使用: {'metric': 'euclidean', 'n_neighbors': 1, 'weights': 'uniform'} 0.833667 (0.031674) 使用: {'metric': 'euclidean', 'n_neighbors': 1, 'weights': 'distance'} 0.895333 (0.030081) 使用: {'metric': 'euclidean', 'n_neighbors': 3, 'weights': 'uniform'} 0.895333 (0.030081) 使用: {'metric': 'euclidean', 'n_neighbors': 3, 'weights': 'distance'} 0.909000 (0.021810) 使用: {'metric': 'euclidean', 'n_neighbors': 5, 'weights': 'uniform'} 0.909000 (0.021810) 使用: {'metric': 'euclidean', 'n_neighbors': 5, 'weights': 'distance'} 0.925333 (0.020774) 使用: {'metric': 'euclidean', 'n_neighbors': 7, 'weights': 'uniform'} 0.925333 (0.020774) 使用: {'metric': 'euclidean', 'n_neighbors': 7, 'weights': 'distance'} 0.929000 (0.027368) 使用: {'metric': 'euclidean', 'n_neighbors': 9, 'weights': 'uniform'} 0.929000 (0.027368) 使用: {'metric': 'euclidean', 'n_neighbors': 9, 'weights': 'distance'} ... |
支持向量机 (SVM)
SVM 算法,与梯度提升一样,非常流行,非常有效,并提供了大量的超参数来调优。
也许第一个重要的参数是核的选择,它将控制输入变量投影的方式。有许多可供选择,但线性、多项式和 RBF 是最常见的,实际上可能只剩线性和 RBF。
- kernels 在 ['linear', 'poly', 'rbf', 'sigmoid'] 中
如果多项式核效果不错,那么深入研究度参数(degree)是个好主意。
另一个关键参数是正则化(C),它可以取一系列值,并对每个类的结果区域的形状产生显著影响。对数尺度可能是一个好的起点。
- C 在 [100, 10, 1.0, 0.1, 0.001] 中
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上对 SVC 的关键超参数进行网格搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# SVC 关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV from sklearn.svm import SVC # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = SVC() kernel = ['poly', 'rbf', 'sigmoid'] C = [50, 10, 1.0, 0.1, 0.01] gamma = ['scale'] # 定义网格搜索 grid = dict(kernel=kernel,C=C,gamma=gamma) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
最佳:0.974333 使用 {'C': 1.0, 'gamma': 'scale', 'kernel': 'poly'} 0.973667 (0.012512) 使用: {'C': 50, 'gamma': 'scale', 'kernel': 'poly'} 0.970667 (0.018062) 使用: {'C': 50, 'gamma': 'scale', 'kernel': 'rbf'} 0.945333 (0.024594) 使用: {'C': 50, 'gamma': 'scale', 'kernel': 'sigmoid'} 0.973667 (0.012512) 使用: {'C': 10, 'gamma': 'scale', 'kernel': 'poly'} 0.970667 (0.018062) 使用: {'C': 10, 'gamma': 'scale', 'kernel': 'rbf'} 0.957000 (0.016763) 使用: {'C': 10, 'gamma': 'scale', 'kernel': 'sigmoid'} 0.974333 (0.012565) 使用: {'C': 1.0, 'gamma': 'scale', 'kernel': 'poly'} 0.971667 (0.016948) 使用: {'C': 1.0, 'gamma': 'scale', 'kernel': 'rbf'} 0.966333 (0.016224) 使用: {'C': 1.0, 'gamma': 'scale', 'kernel': 'sigmoid'} 0.972333 (0.013585) 使用: {'C': 0.1, 'gamma': 'scale', 'kernel': 'poly'} 0.974000 (0.013317) 使用: {'C': 0.1, 'gamma': 'scale', 'kernel': 'rbf'} 0.971667 (0.015934) 使用: {'C': 0.1, 'gamma': 'scale', 'kernel': 'sigmoid'} 0.972333 (0.013585) 使用: {'C': 0.01, 'gamma': 'scale', 'kernel': 'poly'} 0.973667 (0.014716) 使用: {'C': 0.01, 'gamma': 'scale', 'kernel': 'rbf'} 0.974333 (0.013828) 使用: {'C': 0.01, 'gamma': 'scale', 'kernel': 'sigmoid'} |
装袋决策树 (Bagging)
装袋决策树最重要的参数是树的数量(n_estimators)。
理想情况下,应增加此值,直到模型没有进一步改进。
好的值可能是 10 到 1,000 的对数尺度。
- n_estimators 在 [10, 100, 1000] 中
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上为 BaggingClassifier 的关键超参数进行网格搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# BaggingClassifier 关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV from sklearn.ensemble import BaggingClassifier # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = BaggingClassifier() n_estimators = [10, 100, 1000] # 定义网格搜索 grid = dict(n_estimators=n_estimators) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 |
最佳:0.873667 使用 {'n_estimators': 1000} 0.839000 (0.038588) 使用: {'n_estimators': 10} 0.869333 (0.030434) 使用: {'n_estimators': 100} 0.873667 (0.035070) 使用: {'n_estimators': 1000} |
随机森林
最重要的参数是每次拆分时要采样的随机特征的数量(max_features)。
您可以尝试整数值范围,例如 1 到 20,或 1 到输入特征数量的一半。
- max_features [1 到 20]
或者,您可以尝试一套不同的默认值计算器。
- max_features 在 ['sqrt', 'log2'] 中
随机森林的另一个重要参数是树的数量(n_estimators)。
理想情况下,应增加此值,直到模型没有进一步改进。
好的值可能是 10 到 1,000 的对数尺度。
- n_estimators 在 [10, 100, 1000] 中
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上为 BaggingClassifier 的关键超参数进行网格搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# RandomForestClassifier 关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV from sklearn.ensemble import RandomForestClassifier # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = RandomForestClassifier() n_estimators = [10, 100, 1000] max_features = ['sqrt', 'log2'] # 定义网格搜索 grid = dict(n_estimators=n_estimators,max_features=max_features) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 5 6 7 |
最佳:0.952000 使用 {'max_features': 'log2', 'n_estimators': 1000} 0.841000 (0.032078) 使用: {'max_features': 'sqrt', 'n_estimators': 10} 0.938333 (0.020830) 使用: {'max_features': 'sqrt', 'n_estimators': 100} 0.944667 (0.024998) 使用: {'max_features': 'sqrt', 'n_estimators': 1000} 0.817667 (0.033235) 使用: {'max_features': 'log2', 'n_estimators': 10} 0.940667 (0.021592) 使用: {'max_features': 'log2', 'n_estimators': 100} 0.952000 (0.019562) 使用: {'max_features': 'log2', 'n_estimators': 1000} |
随机梯度提升
也称为梯度提升机 (GBM) 或特定实现(如 XGBoost)的名称。
梯度提升算法有许多参数需要调优。
有一些重要的参数组合需要考虑。第一个是学习率,也称为收缩率或 eta(learning_rate),以及模型中的树数量(n_estimators)。两者都可以按对数尺度考虑,尽管方向不同。
- learning_rate 在 [0.001, 0.01, 0.1] 中
- n_estimators [10, 100, 1000]
另一组组合是用于每棵树的行数或数据子集(subsample)和每棵树的深度(max_depth)。这些可以分别以 0.1 和 1 的间隔进行网格搜索,尽管可以直接测试常见值。
- subsample 在 [0.5, 0.7, 1.0] 中
- max_depth 在 [3, 7, 9] 中
有关调优 XGBoost 实现的更详细建议,请参阅
有关超参数的完整列表,请参阅
下面的示例演示了在合成二分类数据集上为 GradientBoostingClassifier 的关键超参数进行网格搜索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# GradientBoostingClassifier 关键超参数的网格搜索示例 from sklearn.datasets import make_blobs from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.model_selection import GridSearchCV from sklearn.ensemble import GradientBoostingClassifier # 定义数据集 X, y = make_blobs(n_samples=1000, centers=2, n_features=100, cluster_std=20) # 定义模型和参数 model = GradientBoostingClassifier() n_estimators = [10, 100, 1000] learning_rate = [0.001, 0.01, 0.1] subsample = [0.5, 0.7, 1.0] max_depth = [3, 7, 9] # 定义网格搜索 grid = dict(learning_rate=learning_rate, n_estimators=n_estimators, subsample=subsample, max_depth=max_depth) cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) grid_search = GridSearchCV(estimator=model, param_grid=grid, n_jobs=-1, cv=cv, scoring='accuracy',error_score=0) grid_result = grid_search.fit(X, y) # 总结结果 print("最佳:%f 使用 %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) 配合: %r" % (mean, stdev, param)) |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。请考虑多次运行示例并比较平均结果。
运行示例会打印最佳结果以及所有评估过的组合的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
最佳:0.936667 使用 {'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 1000, 'subsample': 0.5} 0.803333 (0.042058) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 10, 'subsample': 0.5} 0.783667 (0.042386) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 10, 'subsample': 0.7} 0.711667 (0.041157) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 10, 'subsample': 1.0} 0.832667 (0.040244) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 100, 'subsample': 0.5} 0.809667 (0.040040) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 100, 'subsample': 0.7} 0.741333 (0.043261) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 100, 'subsample': 1.0} 0.881333 (0.034130) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 1000, 'subsample': 0.5} 0.866667 (0.035150) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 1000, 'subsample': 0.7} 0.838333 (0.037424) 使用: {'learning_rate': 0.001, 'max_depth': 3, 'n_estimators': 1000, 'subsample': 1.0} 0.838333 (0.036614) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 10, 'subsample': 0.5} 0.821667 (0.040586) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 10, 'subsample': 0.7} 0.729000 (0.035903) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 10, 'subsample': 1.0} 0.884667 (0.036854) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 100, 'subsample': 0.5} 0.871333 (0.035094) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 100, 'subsample': 0.7} 0.729000 (0.037625) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 100, 'subsample': 1.0} 0.905667 (0.033134) 使用: {'learning_rate': 0.001, 'max_depth': 7, 'n_estimators': 1000, 'subsample': 0.5} ... |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
总结
在本教程中,您了解了顶级机器学习算法的关键超参数以及如何配置它们。
您是否有其他超参数建议?请在下面的评论中告诉我。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
感谢您的精彩文章!有个小问题:为什么您为交叉验证设置
n_repeats=3
?据我所知,cv 会将数据分成几个折叠,计算每个折叠上的指标并取平均值。是否需要重复此过程 3 次?好问题。
重复有助于平滑一些使用大量随机性或在非常小的数据集上使用的模型的方差。与 1 次 CV 相比,重复 CV 通常可以更好地估计模型的平均技能。
感谢这篇精彩的文章。
更改岭分类器的参数并未改变结果。是因为合成数据集还是示例中存在其他问题?
是的,很可能是因为合成数据集太简单了。
我通常使用 TPE 进行超参数优化,它在搜索大型参数空间方面做得很好。Hyperas 和 hyperopt 甚至可以让你并行进行!https://github.com/maxpumperla/hyperas
此外,keras 最近推出了自己的 HO 工具,称为 keras-tuner,它看起来易于使用。
https://github.com/keras-team/keras-tuner
感谢分享。
亲爱的 Jason,
关于机器学习模型泛化能力的文章怎么样?例如,我们在分布 X 的数据集(训练集 + 验证集)上训练和调优一个特定的学习算法,并将其应用于源自分布 Y 的一些数据。在实践中,学习到的模型通常会失败,因此问题是如何除了正则化等基本方法之外,来对抗这个问题……
此致
感谢您的建议。
是的,我在这方面有几十个教程。也许可以从这里开始
https://machinelearning.org.cn/introduction-to-regularization-to-reduce-overfitting-and-improve-generalization-error/
感谢 Jason 的文章。我有一个后续问题。在类别高度不平衡(例如欺诈)的情况下,这些模型中哪一个最好?为什么?
谢谢,
Rich
总的来说没有最好的模型。我建议测试一系列不同的不平衡分类技术,并找出最适合您特定数据集的方法。
xgboost 未包含?为什么只有 7 种算法?
这些是 sklearn 中流行的算法。
要调优 xgboost,请参阅一系列教程,也许从这里开始
https://machinelearning.org.cn/start-here/#xgboost
你好 Jason,一如既往的精彩教程!我有一个问题,为什么在所有示例中都使用 RepeatedStratifiedKFold,即使在那些情况下本不应该不平衡?它比普通的 KFold 更好吗?
谢谢!
这是一个好习惯,也许是最佳实践。
嗨,Jason!
关于调优 RandomForest 的问题。对于我的超调优结果,最佳参数的 precision_score 与抽样检查非常相似。我很难理解这是如何可能的。
从抽样检查来看,结果证明模型几乎没有技能,只比“无技能”好一点,所以我认为它有潜力。然而,最佳参数则不然。
我目前正在使用 RandomizedSearchCV 调优一个二分类 RandomForestClassifier(…refit=’precision’)。Precision 是:make_scorer(precision_score, average = ‘weighted’)。数据集是平衡的。
也许平均结果的差异在统计学上不显著。所以数字看起来不同,但平均行为并无不同。
哦,我明白了。有什么方法可以弄清楚这一点吗?我目前正在研究特征选择,正如这里所述:https://machinelearning.org.cn/feature-selection-with-real-and-categorical-data/
是的,这里有一些关于如何使用假设检验来比较结果的建议
https://machinelearning.org.cn/statistical-significance-tests-for-comparing-machine-learning-algorithms/
或者你也可以改变你的测试平台,例如更多的重复、更多的折叠,以帮助更好地暴露算法之间的差异。
谢谢。我将从那里开始。当我抽样检查不同类型的分类模型时,它们也返回了非常相似的统计数据,这也非常非常奇怪。一切都差不多:只比“无技能”好一点。
您的当前问题可能无法在当前形式/框架下进行预测。
我将尝试不同的模型。通过不同的特征选择和特征重要性测试,特征是相关的且重要的。结合行业知识,我也知道这些特征可以帮助确定目标变量(问题)。我不会放弃!
听起来很棒!
嗨,Jason,
文章写得很好,非常清晰!您主要谈论了分类问题的算法,您是否有回归算法的总结?或者差不多相似?谢谢!
谢谢!
目前还没有,也许很快就会有。
那太好了,我一定会关注的,谢谢 Jason!
谢谢。
先生,在超参数优化之后,我们应用什么技术来进一步改进结果?
看这里
https://machinelearning.org.cn/machine-learning-performance-improvement-cheat-sheet/
非常感谢。
1. 为什么您将 random_state=1 设置为交叉验证?
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
根据我的理解,在具有不同随机状态的 test_train_split 中,我们会得到不同的准确率,为了避免这种情况,我们会进行交叉验证。
2. 是否有必要将 random_state=1 设置为交叉验证?
3. 在您上面所有的示例中,我们从 gridsearch 结果中获得训练数据集的准确率。这是对的吗?
# 总结结果
print(“Best: %f using %s” % (grid_result.best_score_, grid_result.best_params_))
我认为我们应该从 grid_result(即我们最好的模型)中计算测试数据集的准确率。
随机种子是固定的,以确保每次运行代码时都能得到相同的结果——这有助于教程。
您可以设置任何您喜欢的值
https://machinelearning.org.cn/faq/single-faq/what-value-should-i-set-for-the-random-number-seed
我们没有使用训练/测试分割,我们使用的是重复的 k-fold 交叉验证来估计每个配置的性能。
关于 RandomForest 的参数,我在 SKLearn 网站上看到:“版本 0.22 中已更改:n_estimators 的默认值从 0.22 中的 10 更改为 100。”——在您的代码中,您最多有 1000 个,以防您想更新您的代码:)
谢谢。
就 RF 而言,越多越好,但有一个限制。
我喜欢您的教程。我认为您做得很好。我从您那里学到了很多。我一直在考虑购买您的其中一本书,但您有太多书了,我不知道该买哪一本。我意识到超参数调优是多么重要,并且我注意到每个模型都不同,我需要一个总结性的信息来源,让我对为每个模型尝试哪些超参数有一个大致的了解,以及尽可能快速有效地进行该过程的技术。我听说过贝叶斯超参数优化技术。如果我能学会如何用 scikitlearn 来做,那就太好了。此外,我特别对 XGBoost 感兴趣,因为我在您的博客中读到它倾向于表现得非常好。您推荐我哪本书来学习如何使用 Python 快速有效地进行超参数调优(如果可能,特别提一下 XGBoost)?
谢谢!
我建议使用免费教程,只有在需要更多信息或想系统地学习一个主题时才购买书籍。
你好 Jason,谢谢你的帖子。关于这个问题,random_state 参数不会导致每次分割和重复的结果都相同吗?或者 random_state 应用于哪里?
当 random_state 在网格搜索的 cv 对象上设置时,它确保每个超参数配置都在相同的数据分割上进行评估。
为什么使用 Repeated Stratified K fold?
这是对分类任务进行模型评估的最佳实践。
在流行的(fashion mnist)数据集中最适合使用哪些分类算法?
并且哪些超参数更受欢迎?
一个 CNN。
你好 Jason,这篇文章很棒!
我想知道,由于网格搜索是通过交叉验证实现的,一旦选择了最佳超参数组合,是否需要再次进行交叉验证来测试具有最佳参数的模型性能?
不,但如果你想确认结果,也可以这样做。
你好 Jason,感谢你的帖子,我有一个关于分类器优化的一个问题。据我所知,为了调优一个分类器,我们应该找到它的最佳工作点,它可以计算使用 ROC 曲线及其与 Y=-X 的交点。ROC 曲线是通过改变超参数来计算的。因此,最佳工作点的相应超参数将是最佳超参数。
我的问题是,为什么你在 GridSearchCV 中使用(scoring=’accuracy’)?
换句话说,为什么你不考虑用于计算 ROC 曲线的灵敏度和精确度指标?
我建议优化 ROC AUC 并将 ROC 曲线作为诊断。
你好 Jason,谢谢你的帖子,我有一些快速的问题
1. 关于我的数据集,我的数据集中有一些离散变量(例如:人们的数量……)作为特征。我应该先对数据执行 StandardScaler 来缩放我的数据,然后再进行 GridSearchCV,还是可以在不缩放的情况下进行?
2. 您为 RepeatedStratifiedKFold 设置了 random_state。那么每个模型呢?我们是否也应该为模型设置 random_state,例如:model = LogisticRegression(random_state=1) 然后再用 GridSearchCV 进行调优?
顺便说一句,这些离散变量的范围仅在 [0,5] 之间。