我有一个3500个观测值x 70个特征的数据集,这是我的训练集;我还有一个600个观测值x 70个特征的数据集,这是我的验证集。目标是将观察结果正确分类为0或1。
我使用Xgboost
,我的目标是在分类阈值= 0.5
时达到最高的精度。
我正在进行网格搜索:
import numpy as np
import pandas as pd
import xgboost
# Import datasets from edge node
data_train = pd.read_csv('data.csv')
data_valid = pd.read_csv('data_valid.csv')
# Specify 'data_test' as validation set for the Grid Search below
from sklearn.model_selection import PredefinedSplit
X, y, train_valid_indices = train_valid_merge(data_train, data_valid)
train_valid_merge_indices = PredefinedSplit(test_fold=train_valid_indices)
# Define my own scoring function to see
# if it is called for both the training and the validation sets
from sklearn.metrics import make_scorer
custom_scorer = make_scorer(score_func=my_precision, greater_is_better=True, needs_proba=False)
# Instantiate xgboost
from xgboost.sklearn import XGBClassifier
classifier = XGBClassifier(random_state=0)
# Small parameters' grid ONLY FOR START
# I plan to use way bigger parameters' grids
parameters = {'n_estimators': [150, 175, 200]}
# Execute grid search and retrieve the best classifier
from sklearn.model_selection import GridSearchCV
classifiers_grid = GridSearchCV(estimator=classifier, param_grid=parameters, scoring=custom_scorer,
cv=train_valid_merge_indices, refit=True, n_jobs=-1)
classifiers_grid.fit(X, y)
............................................... .............................
train_valid_merge
-指定我自己的验证集:
我想用我的训练集(data_train
)对每个模型进行训练,并使用我的独特/单独的验证集(data_valid
)对超参数进行调整。因此,我定义了一个名为train_valid_merge
的函数,该函数将我的训练和验证集连接起来,以便可以将它们输入到GridSeachCV
中,并且我还使用了PredefineSplit
来指定哪个是训练和这是此合并集上的验证集:
def train_valid_merge(data_train, data_valid):
# Set test_fold values to -1 for training observations
train_indices = [-1]*len(data_train)
# Set test_fold values to 0 for validation observations
valid_indices = [0]*len(data_valid)
# Concatenate the indices for the training and validation sets
train_valid_indices = train_indices + valid_indices
# Concatenate data_train & data_valid
import pandas as pd
data = pd.concat([data_train, data_valid], axis=0, ignore_index=True)
X = data.iloc[:, :-1].values
y = data.iloc[:, -1].values
return X, y, train_valid_indices
............................................... .............................
custom_scorer
-指定我自己的得分指标:
我定义了自己的评分函数,该函数仅返回精度,以查看是否同时针对训练和验证集调用了该精度:
def my_precision(y_true, y_predict):
# Check length of 'y_true' to see if it is the training or the validation set
print(len(y_true))
# Calculate precision
from sklearn.metrics import precision_score
precision = precision_score(y_true, y_predict, average='binary')
return precision
............................................... .............................
运行整个程序(对于parameters = {'n_estimators': [150, 175, 200]}
时,将在print(len(y_true))
函数中从my_precision
打印以下内容:
600
600
3500
600
3500
3500
,这意味着训练和验证集都会调用评分功能。但是我已经测试过,不仅可以调用计分功能,还可以使用训练集和验证集的结果来确定网格搜索中的最佳模型(即使我已将其指定为仅使用验证集的结果)。
例如,使用我们的3个参数值('n_estimators': [150, 175, 200]
),它同时考虑了训练和验证集(2套)的得分,因此得出(3个参数)x(2套)= 6个不同的网格结果。因此,它会从所有这些网格结果中挑选出最佳的超参数集,因此最终可能会从训练集中的结果中挑选出一个,而我只想考虑验证集(3个结果)。
但是,如果我在my_precision
函数中添加类似内容来规避训练集(通过将其所有精度值都设置为0):
# Remember that the training set has 3500 observations
# and the validation set 600 observations
if(len(y_true>600)):
return 0
然后(据我测试),我当然可以为我的规范找到最佳模型,因为训练集的精度结果太小,因为它们全都为0至。
我的问题如下:
为什么自定义评分功能同时考虑了训练和验证集以选择最佳模型,而我已train_valid_merge_indices
指定网格搜索的最佳模型应仅是根据验证集选择的?
完成模型的选择和排名后,如何使GridSearchCV
仅考虑验证集和模型的得分? >
答案 0 :(得分:1)
我有一套独特的训练套和一套独特的验证套。我想在训练集上训练我的模型,并根据我在不同验证集上的性能找到最佳超参数。
那么您最肯定不需要PredefinedSplit
或GridSearchCV
:
import pandas as pd
from xgboost.sklearn import XGBClassifier
from sklearn.metrics import precision_score
# Import datasets from edge node
data_train = pd.read_csv('data.csv')
data_valid = pd.read_csv('data_valid.csv')
# training data & labels:
X = data_train.iloc[:, :-1].values
y = data_train.iloc[:, -1].values
# validation data & labels:
X_valid = data_valid.iloc[:, :-1].values
y_true = data_valid.iloc[:, -1].values
n_estimators = [150, 175, 200]
perf = []
for k_estimators in n_estimators:
clf = XGBClassifier(n_estimators=k_estimators, random_state=0)
clf.fit(X, y)
y_predict = clf.predict(X_valid)
precision = precision_score(y_true, y_predict, average='binary')
perf.append(precision)
和perf
将包含验证集上各个分类器的性能...
答案 1 :(得分:0)
这意味着对训练集和验证集都调用了评分函数...
这可能是真的。
<块引用>...但我已经测试过,评分函数不仅被调用,而且来自训练集和验证集的结果用于从网格搜索中确定最佳模型(即使我已指定它仅使用验证集结果)。
但这可能不是真的。
有一个参数return_train_score
;当 True
时,对训练数据进行评分并将其作为 cv_results_
属性的一部分返回。在 v0.21 之前,此参数的默认值为 True
,而在 False
之后。但是,这些分数不用于确定最佳超参数,除非您有客户 scoring
方法将它们考虑在内。 (如果您认为自己有反例,请提供 cv_results_
和 best_params_
。)
为什么自定义评分函数要同时考虑训练和验证集来挑选最佳模型,而我已经用我的 train_valid_merge_indices
指定网格搜索的最佳模型应该只根据验证集?
它(可能)不是,见上文。
<块引用>如何让 GridSearchCV
在模型的选择和排名完成时只考虑验证集和模型的分数?
它默认这样做。