KFold Cross Validation не устраняет переоснащение - PullRequest
2 голосов
/ 14 марта 2020

Я разделяю элементы в X и y, затем я предварительно обрабатываю данные теста поезда после разделения их с помощью k-перекрестной проверки. После этого я подгоняю данные поезда к моей модели регрессора случайных лесов и вычисляю показатель достоверности. Почему я препроцессирую после разделения? потому что люди говорят мне, что более правильно делать это таким образом, и я придерживаюсь этого принципа, потому что это ради производительности моей модели.

Я впервые использую перекрестную валидацию KFold, потому что моя оценка модели переоценивается и я думал, что смогу исправить это с помощью перекрестной проверки. Я все еще не понимаю, как это использовать, я прочитал документацию и некоторые статьи, но я не совсем понял, как на самом деле подразумевать это для моей модели, но я все равно попробовал, и моя модель все еще подходит. Используя тест на разделение или перекрестную проверку, в результате чего моя модель все еще равна 0,999, я не знаю, в чем моя ошибка, так как я очень новичок в использовании этого метода, но я думаю, что, возможно, я сделал это неправильно, так что это не исправит переобучение. Подскажите пожалуйста что не так с моим кодом и как это исправить

import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestRegressor
import scipy.stats as ss
avo_sales = pd.read_csv('avocados.csv')

avo_sales.rename(columns = {'4046':'small PLU sold',
                            '4225':'large PLU sold',
                            '4770':'xlarge PLU sold'},
                 inplace= True)

avo_sales.columns = avo_sales.columns.str.replace(' ','')
x = np.array(avo_sales.drop(['TotalBags','Unnamed:0','year','region','Date'],1))
y = np.array(avo_sales.TotalBags)

# X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2)


kf = KFold(n_splits=10)

for train_index, test_index in kf.split(x):
    X_train, X_test, y_train, y_test = x[train_index], x[test_index], y[train_index], y[test_index]

impC = SimpleImputer(strategy='most_frequent')
X_train[:,8] = impC.fit_transform(X_train[:,8].reshape(-1,1)).ravel()
X_test[:,8] = impC.transform(X_test[:,8].reshape(-1,1)).ravel()

imp = SimpleImputer(strategy='median')
X_train[:,1:8] = imp.fit_transform(X_train[:,1:8])
X_test[:,1:8] = imp.transform(X_test[:,1:8])

le = LabelEncoder()
X_train[:,8] = le.fit_transform(X_train[:,8])
X_test[:,8] = le.transform(X_test[:,8])

rfr = RandomForestRegressor()
rfr.fit(X_train, y_train)
confidence = rfr.score(X_test, y_test)
print(confidence)

Ответы [ 2 ]

6 голосов
/ 14 марта 2020

Причина, по которой вы переобучаетесь, заключается в том, что нерегулярная древовидная модель будет приспосабливаться к данным до тех пор, пока все обучающие образцы не будут правильно классифицированы. Смотрите, например, это изображение:

enter image description here

Как видите, это не очень хорошо обобщает. Если вы не укажете аргументы, которые упорядочивают деревья, модель будет плохо вписываться в тестовые данные, потому что в основном она просто изучит шум в обучающих данных. Есть много способов упорядочить деревья в sklearn, вы можете найти их здесь . Например:

  • max_features
  • min_samples_leaf
  • max_depth

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

enter image description here

Чтобы упорядочить вашу модель, создайте экземпляр модуля RandomForestRegressor() следующим образом:

rfr = RandomForestRegressor(max_features=0.5, min_samples_leaf=4, max_depth=6)

Эти значения аргументов являются произвольными, вам решать, какие из них лучше всего соответствуют вашим данным. Вы можете использовать спецификацию домена c для выбора этих значений или поиск настройки гиперпараметра, например GridSearchCV или RandomizedSearchCV.

Кроме этого, вложение среднего значения и медианы может внести много шума в ваши данные. Я бы советовал против этого, если у вас не было другого выбора.

4 голосов
/ 15 марта 2020

В то время как ответ @NicolasGervais доходит до сути вопроса, почему ваша конкретная c модель переоснащается, я думаю, что существует концептуальное недопонимание в отношении перекрестной проверки в исходном вопросе:

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

Это не случай.

Перекрестная проверка - это метод, который используется для оценки производительности данной модели на невидимых данных. Само по себе это не может улучшить точность. Другими словами, соответствующие оценки могут сказать вам, соответствует ли ваша модель данным обучения, но простое применение перекрестной проверки не делает вашу модель лучше.

Пример. Давайте рассмотрим набор данных с 10 точками и проведем через него линию:

import numpy as np 
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

X = np.random.randint(0,10,10)
Y = np.random.randint(0,10,10)

fig = plt.figure(figsize=(1,10))

def line(x, slope, intercept):     
    return slope * x + intercept

for i in range(5):

    # note that this is not technically 5-fold cross-validation
    # because I allow the same datapoint to go into the test set
    # several times. For illustrative purposes it is fine imho.
    test_indices = np.random.choice(np.arange(10),2)
    train_indices = list(set(range(10))-set(test_indices))

    # get train and test sets
    X_train, Y_train = X[train_indices], Y[train_indices]
    X_test, Y_test = X[test_indices], Y[test_indices]
    # training set has one feature and multiple entries
    # so, reshape(-1,1)
    X_train, Y_train, X_test, Y_test = X_train.reshape(-1,1), Y_train.reshape(-1,1), X_test.reshape(-1,1), Y_test.reshape(-1,1)

    # fit and evaluate linear regression
    reg = LinearRegression().fit(X_train, Y_train)
    score_train = reg.score(X_train, Y_train)
    score_test = reg.score(X_test, Y_test)

    # extract coefficients from model:
    slope, intercept = reg.coef_[0], reg.intercept_[0]

    print(score_test)
    # show train and test sets
    plt.subplot(5,1,i+1)
    plt.scatter(X_train, Y_train, c='k')
    plt.scatter(X_test, Y_test, c='r')

    # draw regression line
    plt.plot(np.arange(10), line(np.arange(10), slope, intercept))
    plt.ylim(0,10)
    plt.xlim(0,10)

    plt.title('train: {:.2f} test: {:.2f}'.format(score_train, score_test))

enter image description here

Вы можете Обратите внимание, что оценки на тренировках и тестах очень разные. Вы также можете видеть, что расчетные параметры меняются много с изменением поезда и набора тестов.

Это не делает вашу линейную модель лучше. Но теперь вы точно знаете, насколько это плохо:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...