Метрики перекрестной проверки в scikit-learn для каждого разделения данных - PullRequest
0 голосов
/ 15 января 2019

Пожалуйста, мне просто нужно получить статистику перекрестной проверки явно для каждого разбиения данных (X_test, y_test).

Итак, чтобы попытаться это сделать, я сделал:

kf = KFold(n_splits=n_splits)

X_train_tmp = []
y_train_tmp = []
X_test_tmp = []
y_test_tmp = []
mae_train_cv_list = []
mae_test_cv_list = []

for train_index, test_index in kf.split(X_train):

    for i in range(len(train_index)):
        X_train_tmp.append(X_train[train_index[i]])
        y_train_tmp.append(y_train[train_index[i]])

    for i in range(len(test_index)):
        X_test_tmp.append(X_train[test_index[i]])
        y_test_tmp.append(y_train[test_index[i]])

    model.fit(X_train_tmp, y_train_tmp) # FIT the model = SVR, NN, etc.

    mae_train_cv_list.append( mean_absolute_error(y_train_tmp, model.predict(X_train_tmp)) # MAE of the train part of the KFold.

    mae_test_cv_list.append( mean_absolute_error(y_test_tmp, model.predict(X_test_tmp)) ) # MAE of the test part of the KFold.

    X_train_tmp = []
    y_train_tmp = []
    X_test_tmp = []
    y_test_tmp = []

Это правильный способ получения средней абсолютной ошибки (MAE) для каждого разделения перекрестной проверки с помощью, например, KFold?

Большое спасибо!

Maicon PЛоренцо

1 Ответ

0 голосов
/ 15 января 2019

Есть некоторые проблемы с вашим подходом.

Для начала вам, конечно, не нужно добавлять данные вручную один за другим в свои списки обучения и проверки (т. Е. Ваши 2 внутренних цикла for); простая индексация сделает эту работу.

Кроме того, мы обычно никогда не вычисляем и не сообщаем об ошибке тренировочных сгибов резюме - только ошибка с проверочными сгибами.

Имея это в виду и переключая терминологию на «валидация» вместо «тест», вот простой воспроизводимый пример с использованием данных Бостона, который должен быть легко адаптирован к вашему случаю:

from sklearn.model_selection import KFold
from sklearn.datasets import load_boston
from sklearn.metrics import mean_absolute_error
from sklearn.tree import DecisionTreeRegressor

X, y = load_boston(return_X_y=True)
n_splits = 5
kf = KFold(n_splits=n_splits, shuffle=True)
model = DecisionTreeRegressor(criterion='mae')

cv_mae = []

for train_index, val_index in kf.split(X):
    model.fit(X[train_index], y[train_index])
    pred = model.predict(X[val_index])
    err = mean_absolute_error(y[val_index], pred)
    cv_mae.append(err)

, после чего ваш cv_mae должен выглядеть примерно так (детали могут отличаться из-за случайного характера резюме):

[3.5294117647058827,
 3.3039603960396042,
 3.5306930693069307,
 2.6910891089108913,
 3.0663366336633664]

Конечно, все эти явные вещи на самом деле не нужны; Вы могли бы сделать работу намного проще с cross_val_score. Есть небольшой улов:

from sklearn.model_selection import cross_val_score
cv_mae2 =cross_val_score(model, X, y, cv=n_splits, scoring="neg_mean_absolute_error")
cv_mae2
# result
array([-2.94019608, -3.71980198, -4.92673267, -4.5990099 , -4.22574257])

Помимо отрицательного знака, который на самом деле не является проблемой, вы заметите, что дисперсия результатов выглядит значительно выше по сравнению с нашим cv_mae выше; и причина в том, что мы не перемешали наши данные. К сожалению, cross_val_score не предоставляет опцию тасования, поэтому мы должны сделать это вручную, используя shuffle. Итак, наш окончательный код должен быть:

from sklearn.model_selection import cross_val_score
from sklearn.utils import shuffle
X_s, y_s =shuffle(X, y)
cv_mae3 =cross_val_score(model, X_s, y_s, cv=n_splits, scoring="neg_mean_absolute_error")
cv_mae3
# result:
array([-3.24117647, -3.57029703, -3.10891089, -3.45940594, -2.78316832])

, что значительно меньше дисперсии между сгибами и намного ближе к нашему начальному cv_mae ...

...