Различные результаты при использовании train_test_split против ручного разделения данных - PullRequest
1 голос
/ 10 мая 2019

У меня есть фрейм данных pandas, на котором я хочу делать прогнозы и получать среднеквадратичную ошибку для каждой функции. Я следую онлайн-руководству, которое разбивает набор данных вручную, но я подумал, что было бы удобнее использовать train_test_split из sklearn.model_selection. К сожалению, я получаю разные результаты при просмотре значений rmse после разделения данных вручную по сравнению с использованием train_test_split.

(надеюсь) воспроизводимый пример:

import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

np.random.seed(0)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=['feature_1','feature_2','feature_3','feature_4'])
df['target'] = np.random.randint(2,size=100)
df2 = df.copy()

Вот функция knn_train_test, которая разбивает данные вручную, соответствует модели, делает прогнозы и т. Д .:

def knn_train_test(train_col, target_col, df):
    knn = KNeighborsRegressor()
    np.random.seed(0)

    # Randomize order of rows in data frame.
    shuffled_index = np.random.permutation(df.index)
    rand_df = df.reindex(shuffled_index)

    # Divide number of rows in half and round.
    last_train_row = int(len(rand_df) / 2)

    # Select the first half and set as training set.
    # Select the second half and set as test set.
    train_df = rand_df.iloc[0:last_train_row]
    test_df = rand_df.iloc[last_train_row:]

    # Fit a KNN model using default k value.
    knn.fit(train_df[[train_col]], train_df[target_col])

    # Make predictions using model.
    predicted_labels = knn.predict(test_df[[train_col]])

    # Calculate and return RMSE.
    mse = mean_squared_error(test_df[target_col], predicted_labels)
    rmse = np.sqrt(mse)
    return rmse

rmse_results = {}
train_cols = df.columns.drop('target')

# For each column (minus `target`), train a model, return RMSE value
# and add to the dictionary `rmse_results`.
for col in train_cols:
    rmse_val = knn_train_test(col, 'target', df)
    rmse_results[col] = rmse_val

# Create a Series object from the dictionary so 
# we can easily view the results, sort, etc
rmse_results_series = pd.Series(rmse_results)
rmse_results_series.sort_values()

#Output
feature_3    0.541110
feature_2    0.548452
feature_4    0.559285
feature_1    0.569912
dtype: float64

Теперь вот функция knn_train_test2, которая разбивает данные с помощью train_test_split:

def knn_train_test2(train_col, target_col, df2):

    knn = KNeighborsRegressor()
    np.random.seed(0)

    X_train, X_test, y_train, y_test = train_test_split(df2[[train_col]],df2[[target_col]], test_size=0.5)

    knn.fit(X_train,y_train)

    predictions = knn.predict(X_test)

    mse = mean_squared_error(y_test,predictions)

    rmse = np.sqrt(mse)

    return rmse

rmse_results = {}
train_cols = df2.columns.drop('target')

for col in train_cols:
    rmse_val = knn_train_test2(col, 'target', df2)
    rmse_results[col] = rmse_val


rmse_results_series = pd.Series(rmse_results)
rmse_results_series.sort_values()

# Output
feature_4    0.522303
feature_3    0.556417
feature_1    0.569210
feature_2    0.572713
dtype: float64

Почему я получаю разные результаты? Я думаю, что я неправильно понимаю процесс разделения> train> в целом, или, возможно, неправильно понимаю / неправильно определяю train_test_split. Заранее спасибо

Ответы [ 3 ]

1 голос
/ 10 мая 2019

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

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

1 голос
/ 10 мая 2019

Ваша пользовательская реализация train_test_split отличается от реализации scikit-learn, поэтому вы получаете разные результаты для одного и того же начального числа.

Здесь вы можете найти официальную реализацию.Первое, что примечательно, это то, что scikit-learn делает по умолчанию 10 итераций перестановки и разбиения.(проверьте параметр n_splits)

Только , если ваш подход точно такой же , что и подход scitkit-learn, вы можете ожидать того жерезультат для того же семени.

1 голос
/ 10 мая 2019

Разделение данных вручную - это просто разделение, но train_test_split также будет случайным образом разделять данные. Попробуйте исправить случайное число и посмотрите, сможете ли вы получать одинаковые результаты каждый раз при использовании train_test_split.

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