- Вопрос или проблема
- Полученные результаты следующие:
- Ответ или решение
- Подходящие стратегии разделения данных для анализа временных рядов
- Введение
- Оптимальная стратегия разделения данных
- Вопрос о подходах к разделению данных
- Вопрос о производительности и проблемах с моделью
- Настройка гиперпараметров
- Вопрос о необходимости использовать временные метки
- Заключение
Вопрос или проблема
Предположим, у меня есть набор данных, который содержит временную метку (нестандартная колонка временной метки без формата даты и времени) в качестве одного признака и count
в качестве метки/цели для предсказания в следующем формате dataframe pandas:
X y
Timestamp label
+--------+-----+
|TS_24hrs|count|
+--------+-----+
|0 |157 |
|1 |334 |
|2 |176 |
|3 |86 |
|4 |89 |
... ...
|270 |192 |
|271 |196 |
|270 |251 |
|273 |138 |
+--------+-----+
274 строка × 2 столбца
Я уже реализовал регрессию RF в sklearn с помощью pipeline()
после разбиения данных по следующей стратегии для 274 записей:
- разделить данные на [обучающую выборку + валидационную выборку] Ссылка например, первые 200 записей [160 + 40]
- сохранить невидимую [тестовую выборку] для окончательного прогнозирования например, последние 74 записи (после 200-й строки\события)
#print(train.shape) #(160, 2)
#print(validation.shape) #(40, 2)
#print(test.shape) #(74, 2)
Примечание: Существуют два дополнительных подхода, которые особенно используются в моделях регрессии DL, которые не совместимы с моей стратегией разбиения и затрудняют сравнение производительности моделей из-за различного размера формы:
- период просмотра,
- преобразовать набор данных временных рядов в набор данных для управляемого обучения
Пожалуйста, смотрите этот пост для получения дополнительных деталей.
Я пробовал 3 различных подхода к разделению данных перед fit(X,y)
регрессионной модели в pipeline следующим образом, включая/исключая метку y
:
# Загрузить данные временных рядов как dataframe
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('/content/U2996_24hrs_.csv', sep=",")
# Срез первых 200 записей для обучающей и валидационной выборки
df200 = df[:200]
# Остальные записи = 74 события (после 200-го события) сохранены как невидимая выборка для прогнозирования
test = df[200:] #test
# Разделить данные на обучающие и тестовые наборы
#---------------------Подход 1------------
from sklearn.model_selection import train_test_split
train, validation = train_test_split(df200 , test_size=0.2, shuffle=False) #train + validation
#---------------------------------------------
#---------------------Подход 2------------
from sklearn.model_selection import train_test_split
X = df200[['TS_24hrs']]
y = df200['count']
X_train, X_val, y_train, y_val = train_test_split(X, y , test_size=0.2, shuffle=False, random_state=0)
X_test = test['count'].values.reshape(-1,1)
#---------------------------------------------
#---------------------Подход 3------------
X = df200['TS_24hrs'][:160].values.reshape(-1,1) #train
y = df200['count'][:160].values
Xv = df200['TS_24hrs'][160:].values.reshape(-1,1) #validation
yv = df200['count'][160:].values
Xt = test['TS_24hrs'].values.reshape(-1,1) #test(unseen)
yt = test['count'].values
#---------------------------------------------
# Обучить и адаптировать модель RF
from sklearn.ensemble import RandomForestRegressor
#rf_model = RandomForestRegressor(random_state=10).fit(train, train['count']) #X, y
# создать конвейер от начала до конца и передать данные в регрессионную модель и обучить внутри конвейера. Это позволяет избежать утечки тестовой/валидационной выборки в обучающую выборку
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline, make_pipeline
rf_pipeline1 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(train, train['count']) #Подход 1 обучающая выборка включает метку
rf_pipeline2 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X_train,y_train) #Подход 2 обучающая выборка исключает метку
rf_pipeline3 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X, y) #Подход 3 обучающая выборка исключает метку
# Отображение конвейера с шагом предварительной обработки и регрессией
from sklearn import set_config
set_config(display="text")
#print(rf_pipeline)
# Используйте конвейер для прогнозирования по валидационной и тестовой выборке
y_predictions_test1 = rf_pipeline1.predict(test)
y_predictions_test2 = rf_pipeline2.predict(X_test)
y_predictions_test3 = rf_pipeline3.predict(Xt)
# Преобразуйте результат предсказания в dataframe для облегчения графика
df_pre_test_rf1 = pd.DataFrame({'TS_24hrs':test['TS_24hrs'], 'count_prediction_test':y_predictions_test1})
df_pre_test_rf2 = pd.DataFrame({'TS_24hrs':test['TS_24hrs'], 'count_prediction_test':y_predictions_test2})
df_pre_test_rf3 = pd.DataFrame({'TS_24hrs':test['TS_24hrs'], 'count_prediction_test':y_predictions_test3})
# Оценка производительности с MAE
# Оценка производительности путем расчета потерь и показателей по невидимой тестовой выборке
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error, explained_variance_score, r2_score
rf_mae_test1 = mean_absolute_error(test['count'], df_pre_test_rf1['count_prediction_test'])
rf_mae_test2 = mean_absolute_error(test['count'], df_pre_test_rf2['count_prediction_test'])
rf_mae_test3 = mean_absolute_error(test['count'], df_pre_test_rf3['count_prediction_test'])
# визуализировать прогноз или предсказание RF конвейера и RF конвейера на основе TSS
import matplotlib.pyplot as plt
fig, ax = plt.subplots( figsize=(10,4))
train['count'].plot(label="Обучающая выборка", c="b")
validation['count'].plot(label="Валидационная выборка", linestyle=":", c="b")
test['count'].plot(label="Тестовая выборка (невидимая)", c="cyan")
#график прогнозов
df_pre_test_rf1['count_prediction_test'].plot(label=f'RF_forecast_test (подход 1) MAE={rf_mae_test1:.2f}', linestyle="--", c="red", marker="+")
df_pre_test_rf2['count_prediction_test'].plot(label=f'RF_forecast_test (подход 2) MAE={rf_mae_test2:.2f}', linestyle="--", c="green", marker="+")
df_pre_test_rf3['count_prediction_test'].plot(label=f'RF_forecast_test (подход 3) MAE={rf_mae_test3:.2f}', linestyle="--", c="orange", marker="+", alpha= 0.4)
plt.legend()
plt.title('График сравнительных результатов использованных подходов, обученных в конвейере RF ')
plt.ylabel('count', fontsize=15)
plt.xlabel('Timestamp [24hrs]', fontsize=15)
plt.show()
Полученные результаты следующие:
Выход:
Вопрос 1: Какой подход правильный? Почему остальные неправильные?
- Подход 1
- Подход 2
- Подход 3
Вопрос 2: Почему подход 2 имеет неприемлемое предсказание на своей валидационной выборке (это похоже на постоянную линию), в то время как он имеет приемлемый прогноз на невидимой тестовой выборке?
Вопрос 3: Нужна ли нам настройка гиперпараметров для получения оптимальных результатов, включая её в конвейер RF, например, GridSearchCV()? Я использовал, но результаты не улучшились, как показано ниже:
# Загрузить данные временных рядов как dataframe
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('/content/U2996_24hrs_.csv', sep=",")
# Срез первых 200 записей для обучающей и валидационной выборки
df200 = df[:200]
# Остальные записи = 74 события (после 200-го события) сохранены как невидимая выборка для прогнозирования
test = df[200:] #test
# Разделить данные на обучающие и тестовые наборы
#---------------------Подход 2------------
from sklearn.model_selection import train_test_split
X = df200[['TS_24hrs']]
y = df200['count']
X_train, X_val, y_train, y_val = train_test_split(X, y , test_size=0.2, shuffle=False, random_state=0)
X_test = test['count'].values.reshape(-1,1)
#---------------------------------------------
# Обучить и адаптировать модель RF
from sklearn.ensemble import RandomForestRegressor
#rf_model = RandomForestRegressor(random_state=10).fit(train, train['count']) #X, y
# создать конвейер от начала до конца и передать данные в регрессионную модель и обучить внутри конвейера. Это позволяет избежать утечки тестовой/валидационной выборки в обучающую выборку
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline, make_pipeline
# Конвейер подхода 2
rf_pipeline2 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X_train,y_train) #Подход 2 обучающая выборка исключает метку
# Конвейер подхода 2 (оптимальный)
# Параметры конвейера можно установить, используя имена параметров, разделенные '__':
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits = 5)
param_grid = {
"RF__n_estimators": [10, 50, 100],
"RF__max_depth": [1, 5, 10, 25],
"RF__max_features": [*np.arange(0.1, 1.1, 0.1)],}
rf_pipeline2o = Pipeline([('scaler', MinMaxScaler()),('RF', GridSearchCV(rf_pipeline2,
param_grid=param_grid,
n_jobs=2,
cv=tscv,
refit=True))]).fit(X_train,y_train) #Подход 2 обучающая выборка исключает метку
# Отображение конвейера с шагом предварительной обработки и регрессией
from sklearn import set_config
set_config(display="text")
#print(rf_pipeline2)
#print(rf_pipeline2o)
# Используйте конвейер для прогнозирования по валидационной и тестовой выборке
y_predictions_test2 = rf_pipeline2.predict(X_test)
y_predictions_test2o = rf_pipeline2o.predict(X_test)
# Преобразуйте результат предсказания в dataframe для графика
df_pre_test_rf2 = pd.DataFrame({'TS_24hrs':test['TS_24hrs'], 'count_prediction_test':y_predictions_test2})
df_pre_test_rf2o = pd.DataFrame({'TS_24hrs':test['TS_24hrs'], 'count_prediction_test':y_predictions_test2o})
# оценка производительности с MAE
# Оценка производительности путем расчета потерь и показателей по невидимой тестовой выборке
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error, explained_variance_score, r2_score
rf_mae_test2 = mean_absolute_error(test['count'], df_pre_test_rf2['count_prediction_test'])
rf_mae_test2o = mean_absolute_error(test['count'], df_pre_test_rf2o['count_prediction_test'])
# визуализировать прогноз или предсказание RF конвейера и RF конвейера на основе TSS
import matplotlib.pyplot as plt
fig, ax = plt.subplots( figsize=(10,4))
train['count'].plot(label="Обучающая выборка", c="b")
validation['count'].plot(label="Валидационная выборка", linestyle=":", c="b")
test['count'].plot(label="Тестовая выборка (невидимая)", c="cyan")
#график прогнозов
df_pre_test_rf2['count_prediction_test'].plot(label=f'RF_forecast_test (подход 2) MAE={rf_mae_test2:.2f}', linestyle="--", c="green", marker="+")
df_pre_test_rf2o['count_prediction_test'].plot(label=f'RF_forecast_test (оптимальный подход) MAE={rf_mae_test2o:.2f}', linestyle="--", c="pink", marker="+", alpha= 0.4)
plt.legend()
plt.title('График сравнительных результатов использованных подходов, обученных в конвейере RF ')
plt.ylabel('count', fontsize=15)
plt.xlabel('Timestamp [24hrs]', fontsize=15)
plt.show()
Выход: Иногда немного лучше\ухудшается по сравнению с не оптимальным конвейером\регрессионной моделью, несмотря на то, что установлен random_state=10
, но все же частично предсказывает постоянное значение, и я не могу понять, почему?
Мое наблюдение на данный момент показывает: Это проблема с спецификацией конвейера.
Редактирование: расширение эксперимента
Исключая колонку Timestamp (признак X) и включая её в индекс внутри dataframe
# Загрузить данные временных рядов как dataframe
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('/content/U2996_24hrs_.csv', sep=",")
df = df.set_index('TS_24hrs') #установить индекс, используя временную метку <--------------------------------digest
# Срез первых 200 записей для обучающей и валидационной выборки
df200 = df[:200]
# Остальные записи = 74 события (после 200-го события) сохранены как невидимая выборка для прогнозирования
test = df[200:]
# Разделить данные на обучающие и тестовые наборы
#---------------------Подход 1------------
from sklearn.model_selection import train_test_split
#X_train, X_test, y_train, y_test = train_test_split(X, y , test_size=0.27, shuffle=False, random_state=0)
train, validation = train_test_split(df200 , test_size=0.2, shuffle=False)
test = df[200:] #остальные записи (после 200-го события)
#---------------------------------------------
# ---------------------Подход 2------------
from sklearn.model_selection import train_test_split
X = df200.index.values.reshape(-1,1)
y = df200['count']
X_train, X_val, y_train, y_val = train_test_split(X, y , test_size=0.2, shuffle=False, random_state=0)
X_test = test['count'].values.reshape(-1,1)
# ---------------------------------------------
# ---------------------Подход 3------------
X = df200.index[:160].values.reshape(-1,1) #train
y = df200['count'][:160].values
Xv = df200.index[160:].values.reshape(-1,1) #validation
yv = df200['count'][160:].values
Xt = test.index.values.reshape(-1,1) #test(unseen)
yt = test['count'].values
# ---------------------------------------------
# Обучить и адаптировать модель RF
from sklearn.ensemble import RandomForestRegressor
#rf_model = RandomForestRegressor().fit(train, train['count']) #X, y
# создать конвейер от начала до конца и передать данные в регрессионную модель и обучить внутри конвейера. Это позволяет избежать утечки тестовой/валидационной выборки в обучающую выборку
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline, make_pipeline
rf_pipeline1 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(train, train['count']) #Подход 1 обучающая выборка включает метку
rf_pipeline2 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X_train,y_train) #Подход 2 обучающая выборка исключает метку
rf_pipeline3 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X, y) #Подход 3 обучающая выборка исключает метку
# Отображение конвейера с шагом предварительной обработки и регрессией
from sklearn import set_config
set_config(display="text")
#print(rf_pipeline)
# Используйте конвейер для прогнозирования по валидационной и тестовой выборке
y_predictions_test1 = rf_pipeline1.predict(test)
y_predictions_test2 = rf_pipeline2.predict(X_test)
y_predictions_test3 = rf_pipeline3.predict(Xt)
# Преобразуйте результат предсказания в dataframe для облегчения графика
df_pre_test_rf1 = pd.DataFrame({'TS_24hrs':test.index, 'count_prediction_test':y_predictions_test1}).set_index('TS_24hrs')
df_pre_test_rf2 = pd.DataFrame({'TS_24hrs':test.index, 'count_prediction_test':y_predictions_test2}).set_index('TS_24hrs')
df_pre_test_rf3 = pd.DataFrame({'TS_24hrs':test.index, 'count_prediction_test':y_predictions_test3}).set_index('TS_24hrs')
# оценка производительности с MAE
# Оценка производительности путем расчета потерь и показателей по невидимой тестовой выборке
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error, explained_variance_score, r2_score
rf_mae_test1 = mean_absolute_error(test['count'], df_pre_test_rf1['count_prediction_test'])
rf_mae_test2 = mean_absolute_error(test['count'], df_pre_test_rf2['count_prediction_test'])
rf_mae_test3 = mean_absolute_error(test['count'], df_pre_test_rf3['count_prediction_test'])
# визуализировать прогноз или предсказание RF конвейера и RF конвейера на основе TSS
import matplotlib.pyplot as plt
fig, ax = plt.subplots( figsize=(10,4))
train['count'].plot(label="Обучающая выборка", c="b")
validation['count'].plot(label="Валидационная выборка", linestyle=":", c="b")
test['count'].plot(label="Тестовая выборка (невидимая)", c="cyan")
#график прогнозов
df_pre_test_rf1['count_prediction_test'].plot(label=f'RF_forecast_test (подход 1) MAE={rf_mae_test1:.2f}', linestyle="--", c="red", marker="+")
df_pre_test_rf2['count_prediction_test'].plot(label=f'RF_forecast_test (подход 2) MAE={rf_mae_test2:.2f}', linestyle="--", c="green", marker="+")
df_pre_test_rf3['count_prediction_test'].plot(label=f'RF_forecast_test (подход 3) MAE={rf_mae_test3:.2f}', linestyle="--", c="orange", marker="+", alpha= 0.4)
plt.legend()
plt.title('График сравнительных результатов использованных подходов, обученных в конвейере RF \n исключая колонку временной метки (признак X) и включая её в индекс внутри dataframe')
plt.ylabel('count', fontsize=15)
plt.xlabel('Timestamp [24hrs]', fontsize=15)
plt.show()
Отбрасывая временную метку и рассматривая целевую колонку как оба признака X и метку y (дублирование)
# Загрузить данные временных рядов как dataframe
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('/content/U2996_24hrs_.csv', sep=",")
df = df.set_index('TS_24hrs') #установить индекс, используя временную метку <--------------------------------digest
# Срез первых 200 записей для обучающей и валидационной выборки
df200 = df[:200]
# Остальные записи = 74 события (после 200-го события) сохранены как невидимая выборка для прогнозирования
test = df[200:]
# Разделить данные на обучающие и тестовые наборы
#---------------------Подход 1------------
from sklearn.model_selection import train_test_split
#X_train, X_test, y_train, y_test = train_test_split(X, y , test_size=0.27, shuffle=False, random_state=0)
train, validation = train_test_split(df200 , test_size=0.2, shuffle=False)
test = df[200:] #остальные записи (после 200-го события)
#---------------------------------------------
# ---------------------Подход 2------------
from sklearn.model_selection import train_test_split
X = df200.index.values.reshape(-1,1)
y = df200['count']
X_train, X_val, y_train, y_val = train_test_split(X, y , test_size=0.2, shuffle=False, random_state=0)
X_test = test['count'].values.reshape(-1,1)
# ---------------------------------------------
# ---------------------Подход 3------------
X = df200.index[:160].values.reshape(-1,1) #train
y = df200['count'][:160].values
Xv = df200.index[160:].values.reshape(-1,1) #validation
yv = df200['count'][160:].values
Xt = test.index.values.reshape(-1,1) #test(unseen)
yt = test['count'].values
# ---------------------------------------------
# Обучить и адаптировать модель RF
from sklearn.ensemble import RandomForestRegressor
#rf_model = RandomForestRegressor().fit(train, train['count']) #X, y
# создать конвейер от начала до конца и передать данные в регрессионную модель и обучить внутри конвейера. Это позволяет избежать утечки тестовой/валидационной выборки в обучающую выборку
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline, make_pipeline
rf_pipeline1 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(train, train['count']) #Подход 1 обучающая выборка включает метку
rf_pipeline2 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X_train,y_train) #Подход 2 обучающая выборка исключает метку
rf_pipeline3 = Pipeline([('scaler', MinMaxScaler()),('RF', RandomForestRegressor(random_state=10))]).fit(X, y) #Подход 3 обучающая выборка исключает метку
# Отображение конвейера с шагом предварительной обработки и регрессией
from sklearn import set_config
set_config(display="text")
#print(rf_pipeline)
# Используйте конвейер для прогнозирования по валидационной и тестовой выборке
y_predictions_test1 = rf_pipeline1.predict(test)
y_predictions_test2 = rf_pipeline2.predict(X_test)
y_predictions_test3 = rf_pipeline3.predict(Xt)
# Преобразуйте результат предсказания в dataframe для облегчения графика
df_pre_test_rf1 = pd.DataFrame({'TS_24hrs':test.index, 'count_prediction_test':y_predictions_test1}).set_index('TS_24hrs')
df_pre_test_rf2 = pd.DataFrame({'TS_24hrs':test.index, 'count_prediction_test':y_predictions_test2}).set_index('TS_24hrs')
df_pre_test_rf3 = pd.DataFrame({'TS_24hrs':test.index, 'count_prediction_test':y_predictions_test3}).set_index('TS_24hrs')
# оценка производительности с MAE
# Оценка производительности путем расчета потерь и показателей по невидимой тестовой выборке
from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error, explained_variance_score, r2_score
rf_mae_test1 = mean_absolute_error(test['count'], df_pre_test_rf1['count_prediction_test'])
rf_mae_test2 = mean_absolute_error(test['count'], df_pre_test_rf2['count_prediction_test'])
rf_mae_test3 = mean_absolute_error(test['count'], df_pre_test_rf3['count_prediction_test'])
# визуализировать прогноз или предсказание RF конвейера и RF конвейера на основе TSS
import matplotlib.pyplot as plt
fig, ax = plt.subplots( figsize=(10,4))
train['count'].plot(label="Обучающая выборка", c="b")
validation['count'].plot(label="Валидационная выборка", linestyle=":", c="b")
test['count'].plot(label="Тестовая выборка (невидимая)", c="cyan")
#график прогнозов
df_pre_test_rf1['count_prediction_test'].plot(label=f'RF_forecast_test (подход 1) MAE={rf_mae_test1:.2f}', linestyle="--", c="red", marker="+")
df_pre_test_rf2['count_prediction_test'].plot(label=f'RF_forecast_test (подход 2) MAE={rf_mae_test2:.2f}', linestyle="--", c="green", marker="+")
df_pre_test_rf3['count_prediction_test'].plot(label=f'RF_forecast_test (подход 3) MAE={rf_mae_test3:.2f}', linestyle="--", c="orange", marker="+", alpha= 0.4)
plt.legend()
plt.title('График сравнительных результатов использованных подходов, обученных в конвейере RF \n исключая временную метку и учитывая целевую колонку как оба признака X и метку y (дублирование)')
plt.ylabel('count', fontsize=15)
plt.xlabel('Timestamp [24hrs]', fontsize=15)
plt.show()
Вопрос 4:
- Является ли обязательным, чтобы не использовать колонку временной метки в фрейме и интегрировать её в индекс? Если да, следует ли отбросить временную метку:
TS_24hrs
[X] и оставитьcount
[y] только как метку в фрейме? - Дублирование временной метки:
TS_24hrs
[X] после её включения в индекс и отображения для модели в качестве признака, является ли это важным?
Моё наблюдение в этом эксперименте показывает, что sklearn игнорирует индексы, рассматривая информацию, передаваемую в .fit()
. Похоже, что включение\исключение колонки временной метки в dataframe не оказывает влияния на все подходы и не имеет значения, является ли это:
- через наличие двух колонок (временная метка:
TS_24hrs
[X] и целевая колонкаcount
[y]) в dataframe - или используя индекс/значения в dataframe. !
Есть ли какое-либо объяснение этому?
Одна из возможных причин непоследовательного поведения может заключаться в том, что scikit-learn предназначен для обучения с учетом весов признаков для предсказания целей. Колонка временной метки является индексом, а не признаком в соответствии с scikit-learn. Набор данных не имеет признаков в соответствии с scikit-learn. Колонка count является целевой.
Лучшим вариантом было бы использовать пакет, специально разработанный для данных временных рядов.
Ответ или решение
Подходящие стратегии разделения данных для анализа временных рядов
Введение
Когда мы работаем с данными временных рядов, важно правильно организовать процесс обучения, проверки и тестирования модели. Исправное разделение данных позволяет избежать утечек информации и обеспечивает надежность оценки производительности моделей. В настоящем ответе я рассмотрю оптимальные стратегии разделения данных для оценки производительности алгоритмов машинного и глубокого обучения, таких как регрессия на основе случайных лесов (RF) или других методов, используя ваши замечания как исходные данные.
Оптимальная стратегия разделения данных
Для временных рядов рекомендуется использовать временное разделение:
- Обучающий набор: первые N записей из данных.
- Валидационный набор: следующий набор записей после обучающего.
- Тестовый набор: оставшиеся данные, которые должны остаться невидимыми для всех этапов обучения и проверки.
Схема:
- Обучающий набор — 160 записей (примерно 58%).
- Валидационный набор — 40 записей (примерно 14%).
- Тестовый набор — 74 записи (примерно 27%).
Это обеспечивает целостность канала информации и минимизирует риск утечек данных, поскольку каждое временное событие остается в своем временном контексте.
Вопрос о подходах к разделению данных
-
Подход 1: Разделение на обучение и проверку без использования случайного шuffling. Это правильный подход, так как вы, по сути, делаете чёткое разделение на наборы, что позволяет модели обучаться на временной последовательности данных.
-
Подход 2: Разделение на X и y с использованием train_test_split с параметром shuffle=False. Этот подход тоже корректный, пока целевая переменная (target) остаётся синхронизированной с временными рядами.
-
Подход 3: Прямое манипулирование индексами с выделением каждой части данных для обучения и проверки. Этот метод тоже приемлем, если контроль над индексами сохранен, и данные не смешиваются между собой.
Вопрос о производительности и проблемах с моделью
Почему подход 2 показывает постоянную линию для валидационного набора?
Если мы наблюдаем постоянные предсказания, возможно, это связано с выбором параметров или же недостаточной сложностью модели. Может быть, имеющиеся данные не обеспечивают достаточного разнообразия для обучения, либо модель лучше подстраивается под тестовые данные, находясь в предвзятости.
Настройка гиперпараметров
Неправильная настройка гиперпараметров также влияет на производительность модели. Использование таких методов, как GridSearchCV, может помочь найти более оптимальные значения.
Вопрос о необходимости использовать временные метки
-
Целесообразно ли выводить временные метки из набора данных?
Временные метки (timestamp) следует рассматривать как дополнительные признаки (features), их можно оставить. Однако использование их в индексе не является обязательным. -
Насчет дублирования временных меток:
Если временные метки используются как индексы, их дублирование в самом наборе данных не имеет значения, но помнить о чистоте данных необходимо.
Заключение
Следуя упомянутым стратегиям и рекомендациям, вы сможете более эффективно организовать свои данные временных рядов, что является ключом к успешному обучению моделей, независимо от их типа (машинное или глубокое обучение). Адекватное разделение обучающего, проверочного и тестового наборов позволит вам получить более точные и надежные результаты, улучшая достижения вашей модели в реальных приложениях.