多参数分类器的最优参数估计
Optimal parameter estimation for a classifier with multiple parameters
左图显示了扫描单个阈值并记录相应的真阳性率(TPR)和假阳性率(FPR)形成的标准ROC曲线。
右图显示了我的问题设置,其中有 3 个参数,对于每个参数,我们只有 2 个选择。如图所示,它一起产生 8 个点。在实践中,我打算对 100 多个参数进行数千种可能的组合,但在这种缩小比例的情况下,概念保持不变。
我打算在这里找到 2 个东西:
- 确定给定数据的最佳参数
- 为所有参数组合提供总体性能得分
对于左侧的 ROC 曲线,可以使用以下方法轻松完成:
- 最佳参数:TPR 和 FPR 的最大差异与成本分量(我相信它被称为 J 统计量?)
- 整体表现:曲线下面积(图中阴影部分)
但是我右图的案例,我不知道我选择的方法是不是通常使用的标准原理方法。
最优参数集:TPR和FPR最大差值相同
Parameter score = TPR - FPR * cost_ratio
整体表现:所有表现的平均值"parameter scores"
我找到了很多关于具有单个阈值的 ROC 曲线的参考 material,虽然还有其他技术可用于确定性能,但此问题中提到的技术绝对被认为是标准方法。对于右侧呈现的场景,我没有找到这样的阅读 material。
底线,这里的问题有两个方面:(1) 提供在我的问题场景中评估最佳参数集和整体性能的方法,(2) 提供声称建议的方法是标准方法的参考给定的场景。
P.S.: 我首先在 "Cross Validated" 论坛上发布了这个问题,但没有得到任何回复,事实上,15 小时内只有 7 次浏览。
我觉得我们正在谈论 scikit-learn 中的 Grid Search。它 (1) 提供了评估最佳(超)参数的方法,并且 (2) 在广受欢迎且被广泛引用的统计软件包中实现。
我将对 aberger
之前关于网格搜索的回答进行一些扩展。与模型的任何调整一样,最好使用一部分数据优化超参数并使用另一部分数据评估这些参数,因此 GridSearchCV 最适合此目的。
首先,我将创建一些数据并将其拆分为训练和测试
import numpy as np
from sklearn import model_selection, ensemble, metrics
np.random.seed(42)
X = np.random.random((5000, 10))
y = np.random.randint(0, 2, 5000)
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.3)
这给了我们一个分类问题,这就是我认为你所描述的,尽管这同样适用于回归问题。
现在想想您可能想要优化哪些参数会很有帮助。交叉验证的网格搜索是一个计算量大的过程,因此搜索 space 越小,完成的速度就越快。我将展示 RandomForestClassifier
的示例,因为它是我的首选模型。
clf = ensemble.RandomForestClassifier()
parameters = {'n_estimators': [10, 20, 30],
'max_features': [5, 8, 10],
'max_depth': [None, 10, 20]}
所以现在我有了我的基本估算器和我想要优化的参数列表。现在我只需要考虑如何评估我将要构建的每个模型。从您的问题来看,您似乎对 ROC AUC 感兴趣,所以这就是我将在本示例中使用的内容。尽管您可以从 scikit 中的许多默认指标中进行选择,甚至可以定义您自己的指标。
gs = model_selection.GridSearchCV(clf, param_grid=parameters,
scoring='roc_auc', cv=5)
gs.fit(X_train, y_train)
这将为我提供的所有可能的参数组合拟合一个模型,使用 5 折交叉验证评估这些参数使用 ROC AUC 的执行情况。一旦合适,我们就可以查看最佳参数并提取性能最佳的模型。
print gs.best_params_
clf = gs.best_estimator_
输出:
{'max_features': 5, 'n_estimators': 30, 'max_depth': 20}
现在,您可能想要在所有训练数据上重新训练您的分类器,因为目前它是使用交叉验证训练的。有些人不愿意,但我是再培训师!
clf.fit(X_train, y_train)
现在我们可以评估模型在我们的训练集和测试集上的表现如何。
print metrics.classification_report(y_train, clf.predict(X_train))
print metrics.classification_report(y_test, clf.predict(X_test))
输出:
precision recall f1-score support
0 1.00 1.00 1.00 1707
1 1.00 1.00 1.00 1793
avg / total 1.00 1.00 1.00 3500
precision recall f1-score support
0 0.51 0.46 0.48 780
1 0.47 0.52 0.50 720
avg / total 0.49 0.49 0.49 1500
我们可以看到这个模型由于在测试集上的低分而过度训练。但这并不奇怪,因为数据只是随机噪声!希望在使用信号对数据执行这些方法时,您最终会得到一个经过良好调整的模型。
编辑
这是 'everyone does it' 的情况之一,但没有真正明确的参考表明这是最好的方法。我建议寻找一个接近您正在处理的分类问题的示例。例如使用 Google Scholar 搜索 "grid search" "SVM" "gene expression"
左图显示了扫描单个阈值并记录相应的真阳性率(TPR)和假阳性率(FPR)形成的标准ROC曲线。
右图显示了我的问题设置,其中有 3 个参数,对于每个参数,我们只有 2 个选择。如图所示,它一起产生 8 个点。在实践中,我打算对 100 多个参数进行数千种可能的组合,但在这种缩小比例的情况下,概念保持不变。
我打算在这里找到 2 个东西:
- 确定给定数据的最佳参数
- 为所有参数组合提供总体性能得分
对于左侧的 ROC 曲线,可以使用以下方法轻松完成:
- 最佳参数:TPR 和 FPR 的最大差异与成本分量(我相信它被称为 J 统计量?)
- 整体表现:曲线下面积(图中阴影部分)
但是我右图的案例,我不知道我选择的方法是不是通常使用的标准原理方法。
最优参数集:TPR和FPR最大差值相同
Parameter score = TPR - FPR * cost_ratio
整体表现:所有表现的平均值"parameter scores"
我找到了很多关于具有单个阈值的 ROC 曲线的参考 material,虽然还有其他技术可用于确定性能,但此问题中提到的技术绝对被认为是标准方法。对于右侧呈现的场景,我没有找到这样的阅读 material。
底线,这里的问题有两个方面:(1) 提供在我的问题场景中评估最佳参数集和整体性能的方法,(2) 提供声称建议的方法是标准方法的参考给定的场景。
P.S.: 我首先在 "Cross Validated" 论坛上发布了这个问题,但没有得到任何回复,事实上,15 小时内只有 7 次浏览。
我觉得我们正在谈论 scikit-learn 中的 Grid Search。它 (1) 提供了评估最佳(超)参数的方法,并且 (2) 在广受欢迎且被广泛引用的统计软件包中实现。
我将对 aberger
之前关于网格搜索的回答进行一些扩展。与模型的任何调整一样,最好使用一部分数据优化超参数并使用另一部分数据评估这些参数,因此 GridSearchCV 最适合此目的。
首先,我将创建一些数据并将其拆分为训练和测试
import numpy as np
from sklearn import model_selection, ensemble, metrics
np.random.seed(42)
X = np.random.random((5000, 10))
y = np.random.randint(0, 2, 5000)
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.3)
这给了我们一个分类问题,这就是我认为你所描述的,尽管这同样适用于回归问题。
现在想想您可能想要优化哪些参数会很有帮助。交叉验证的网格搜索是一个计算量大的过程,因此搜索 space 越小,完成的速度就越快。我将展示 RandomForestClassifier
的示例,因为它是我的首选模型。
clf = ensemble.RandomForestClassifier()
parameters = {'n_estimators': [10, 20, 30],
'max_features': [5, 8, 10],
'max_depth': [None, 10, 20]}
所以现在我有了我的基本估算器和我想要优化的参数列表。现在我只需要考虑如何评估我将要构建的每个模型。从您的问题来看,您似乎对 ROC AUC 感兴趣,所以这就是我将在本示例中使用的内容。尽管您可以从 scikit 中的许多默认指标中进行选择,甚至可以定义您自己的指标。
gs = model_selection.GridSearchCV(clf, param_grid=parameters,
scoring='roc_auc', cv=5)
gs.fit(X_train, y_train)
这将为我提供的所有可能的参数组合拟合一个模型,使用 5 折交叉验证评估这些参数使用 ROC AUC 的执行情况。一旦合适,我们就可以查看最佳参数并提取性能最佳的模型。
print gs.best_params_
clf = gs.best_estimator_
输出:
{'max_features': 5, 'n_estimators': 30, 'max_depth': 20}
现在,您可能想要在所有训练数据上重新训练您的分类器,因为目前它是使用交叉验证训练的。有些人不愿意,但我是再培训师!
clf.fit(X_train, y_train)
现在我们可以评估模型在我们的训练集和测试集上的表现如何。
print metrics.classification_report(y_train, clf.predict(X_train))
print metrics.classification_report(y_test, clf.predict(X_test))
输出:
precision recall f1-score support
0 1.00 1.00 1.00 1707
1 1.00 1.00 1.00 1793
avg / total 1.00 1.00 1.00 3500
precision recall f1-score support
0 0.51 0.46 0.48 780
1 0.47 0.52 0.50 720
avg / total 0.49 0.49 0.49 1500
我们可以看到这个模型由于在测试集上的低分而过度训练。但这并不奇怪,因为数据只是随机噪声!希望在使用信号对数据执行这些方法时,您最终会得到一个经过良好调整的模型。
编辑
这是 'everyone does it' 的情况之一,但没有真正明确的参考表明这是最好的方法。我建议寻找一个接近您正在处理的分类问题的示例。例如使用 Google Scholar 搜索 "grid search" "SVM" "gene expression"