使用 K 折交叉验证标准化数据

Posted

技术标签:

【中文标题】使用 K 折交叉验证标准化数据【英文标题】:standardize data with K-Fold cross validation 【发布时间】:2020-03-15 07:10:05 【问题描述】:

我正在使用 StratifiedKFold,所以我的代码如下所示

def train_model(X,y,X_test,folds,model):
    scores=[]
    for fold_n, (train_index, valid_index) in enumerate(folds.split(X, y)):
        X_train,X_valid = X[train_index],X[valid_index]
        y_train,y_valid = y[train_index],y[valid_index]        
        model.fit(X_train,y_train)
        y_pred_valid = model.predict(X_valid).reshape(-1,)
        scores.append(roc_auc_score(y_valid, y_pred_valid))
    print('CV mean score: 0:.4f, std: 1:.4f.'.format(np.mean(scores), np.std(scores)))
folds = StratifiedKFold(10,shuffle=True,random_state=0)
lr = LogisticRegression(class_weight='balanced',penalty='l1',C=0.1,solver='liblinear')
train_model(X_train,y_train,X_test,repeted_folds,lr)

现在在训练模型之前,我想对数据进行标准化,那么哪种方法是正确的? 1)

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

在调用 train_model 函数之前这样做

2) 像这样在函数内部进行标准化

def train_model(X,y,X_test,folds,model):
    scores=[]
    for fold_n, (train_index, valid_index) in enumerate(folds.split(X, y)):
        X_train,X_valid = X[train_index],X[valid_index]
        y_train,y_valid = y[train_index],y[valid_index]
        scaler = StandardScaler()
        X_train = scaler.fit_transform(X_train)
        X_vaid = scaler.transform(X_valid)
        X_test = scaler.transform(X_test)
        model.fit(X_train,y_train)
        y_pred_valid = model.predict(X_valid).reshape(-1,)

        scores.append(roc_auc_score(y_valid, y_pred_valid))

    print('CV mean score: 0:.4f, std: 1:.4f.'.format(np.mean(scores), np.std(scores)))

根据我在第二个选项中的知识,我没有泄漏数据。所以如果我不使用管道,哪种方式是正确的,如果我想使用交叉验证,如何使用管道?

【问题讨论】:

【参考方案1】:

确实,第二个选项更好,因为缩放器看不到 X_valid 的值来缩放 X_train

现在,如果您要使用管道,您可以这样做:

from sklearn.pipeline import make_pipeline

def train_model(X,y,X_test,folds,model):
    pipeline = make_pipeline(StandardScaler(), model)
    ...

然后使用pipeline 而不是model。在每次fitpredict 调用时,它都会自动标准化手头的数据。

请注意,您也可以使用 scikit-learn 中的 cross_val_score 函数,参数为 scoring='roc_auc'

【讨论】:

所以如果我想使用 cross_val_score 而不是首先我必须创建 folds = StratifiedKFold(10,shuffle=True,random_state=0) 之后使用 StandardScaler 制作管道,然后使用 cross_val_score(pipeline, X,y,cv=folds,scoring='roc_auc') 所以这里的 X 和 y 表示整个火车数据对吗? 是的,整个列车数据,它会根据您传递给cv 的参数为您处理拆分,在您的情况下为 cv-splitter。 所以如果我使用 cross_val_score 而不是我不必使用 for 循环和 folds.splits(X,y) 两者都是一样的,对吧? @Utsav Patel 很抱歉删除了我的答案,但我担心我的答案不是很清楚。你可以在这里找到我真正的意思,希望它有用stats.stackexchange.com/questions/27627/…【参考方案2】:

何时标​​准化您的数据可能是一个更适合Cross Validated 的问题。

IMO 如果您的数据很大,那么它可能并不重要(如果您使用的是 k-fold,情况可能并非如此),但既然可以,最好在交叉验证中进行(k -fold),或选项 2。

另外,请参阅this,了解有关交叉验证中过度拟合的更多信息。

【讨论】:

以上是关于使用 K 折交叉验证标准化数据的主要内容,如果未能解决你的问题,请参考以下文章

交叉验证,K折交叉验证的偏差和方差分析

交叉验证(cross validation)是什么?K折交叉验证(k-fold crossValidation)是什么?

k折交叉验证模型选择方法

R:训练数据集的 k 折交叉验证

如何在朴素贝叶斯分类器中使用 k 折交叉验证?

在使用 k 折交叉验证训练训练数据后如何测试数据?