Где я должен определить модель sklearn в настройке проверки kfold?

Я новичок в машинном обучении, и у меня есть путаница в перекрестной проверке K-fold. Когда я пишу цикл fold for, где именно я должен определить модель sklearn (а не модель PyTorch). Я видел некоторый учебник, в котором они определяют модель внутри цикла fold for и прогнозируют X_validation, используя ту же модель. Но тогда мы будем определять k-различную модель внутри этого цикла for, и окончательной моделью будет та, которая обучается только на последней сгибке, она не имеет никакой связи ни с одной из предыдущих сгибов.

  • На мой взгляд, мы должны определить Scikitlearn-модель вне перекрестной проверки Kfold, пожалуйста, объясните мне, правильно ли я думаю, или с этим подходом связана какая-либо проблема утечки данных?

Ниже приведена реализация, которую я использую в своем проекте. Здесь я определил модель sklearn внутри kfold for loop.

import pandas as pd
from sklearn import linear_model
from sklearn import metrics

import config 
from lr_pipeline import lr_pipe

def run_training(fold):
    # load a single fold here
    df = pd.read_csv(config.TRAIN_FOLDS)
    df_train = df[df.kfold != fold].reset_index(drop=True)
    df_val = df[df.kfold == fold].reset_index(drop=True)

    # get X_train, X_val, y_train and y_val
    X_train = df_train.drop(['id','target_class','kfold'],axis=1)
    y_train = df_train['target_class']

    X_val = df_val.drop(['id','target_class','kfold'],axis=1)
    y_val = df_val['target_class']

    # preprocessing pipeline here
    X_train = lr_pipe.fit_transform(X_train)
    X_val = lr_pipe.transform(X_val)

    # train clf
    clf = linear_model.LogisticRegression()
    clf.fit(X_train,y_train)

    # metric
    pred = clf.predict_proba(X_val)[:,1]
    auc = metrics.roc_auc_score(y_val,pred)
    print(f"fold={fold}, auc={auc}")

    df_val.loc[:,"lr_pred"] = pred
    return df_val[["id","kfold","target_class","lr_pred"]]

if __name__ == '__main__':
    dfs = []
    for i in range(5):
        temp_df = run_training(i)
        dfs.append(temp_df)
    fin_valid_df = pd.concat(dfs)


    print(fin_valid_df.shape)
    fin_valid_df.to_csv(config.LR_MODEL_PRED,index=False)

person DINABANDHU BEHERA    schedule 27.02.2021    source источник


Ответы (1)


Позвольте мне начать с короткой предыстории. Большинство моделей машинного обучения имеют два набора параметров:

Во-первых, так называемые гиперпараметры, например. для линейной регрессии — коэффициент регуляризации alpha, для дерева решений — depth дерева, для K ближайших соседей (KNN) — number of neighbors и т. д.

Во-вторых, есть параметры модели, например. для линейной регрессии — веса (w и b в X w + b), для дерева решений — конкретное разбиение на каждом уровне дерева, а KNN — это редкий случай модели без каких-либо параметров.

Параметры модели оцениваются с помощью алгоритма обучения (это происходит, когда вы вводите model.fit(X, y)), а гиперпараметры — нет. Гиперпараметры определяются пользователем. Вопрос в том, как их выбрать, а ответ — перекрестная проверка. Это может быть k-кратная перекрестная проверка или любой другой метод проверки, такой как разделение на поезд-тест, случайное перемешивание или другие.

Итак, что касается вашего первоначального вопроса. Хотя гиперпараметры двух моделей, обученных на разных складках, могут быть одинаковыми, параметры будут разными, так как параметры получаются путем обучения алгоритм из обучающих данных. Таким образом, на самом деле не имеет значения, создаете ли вы свою модель внутри цикла for или снаружи, модели, обученные на разных сгибах, будут независимыми и разными. Но цель перекрестной проверки состоит не в том, чтобы обучить модель, а в том, чтобы определить лучший набор гиперпараметров.

Однако все чаще и чаще я вижу, как люди усредняют модели, обученные по разным кратностям, без переобучения модели на всем наборе поездов, тем самым уменьшая дисперсию прогноза, в этом случае может быть полезно определить модель внутри цикла for и сохранить это экземпляр, чтобы использовать его позже, например:

def run_training(fold):
    ...
    clf = linear_model.LogisticRegression()
    clf.fit(X_train,y_train)
    pred = clf.predict_proba(X_val)[:,1]
    return clf

Я рекомендую вам придерживаться этого подхода и сделать что-то вроде этого:

clfs = []
aucs_train = []
aucs_val = []
for train, val in kf.split(X, y):
    clf = run_training(train)
    clfs.append(clf)
    y_pred_train = clf.predict(X[train])[:, 1]
    y_pred_val = clf.predict(X[val])[:, 1]
    aucs_train.append(auc(y[train], y_pred_train))
    aucs_val.append(auc(y[val], y_pred_val))

В этом случае clfs будет содержать классификатор, обученный на разных сгибах, и вы можете использовать их как для проверки, так и для прогнозирования на удержании/тестовом наборе.

person Anvar Kurmukov    schedule 27.02.2021