С помощью какой техники, адаптированной к временным рядам, я могу заменить перекрестную проверку в моей регрессионной модели Keras MLP в Python

В настоящее время я работаю с набором данных временных рядов из 46 строк о метеорологических измерениях примерно каждые 3 часа в день в течение одной недели. Мои объясняющие переменные (X) состоят из 26 переменных, и некоторые переменные имеют разные единицы измерения (градусы, миниметры, г/м3 и т. д.). Моя переменная для объяснения (y) состоит только из одной переменной температуры.

Моя цель - предсказать температуру (y) на слоте 12-24 часа с помощью ансамбля переменных (X)

Для этого я использовал Keras Tensorflow и Python с моделью регрессора MLP:

X = df_forcast_cap.loc[:, ~df_forcast_cap.columns.str.startswith('l')] 
X = X.drop(['temperature_Y'],axis=1)
y = df_forcast_cap['temperature_Y']
y = pd.DataFrame(data=y)

# normalize the dataset X
scaler = MinMaxScaler(feature_range=(0, 1))
scaler.fit_transform(X)
normalized = scaler.transform(X)

# normalize the dataset y
scaler = MinMaxScaler(feature_range=(0, 1))
scaler.fit_transform(y)
normalized = scaler.transform(y)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# define base model
def norm_model():
    # create model
    model = Sequential()
    model.add(Dense(26, input_dim=26, kernel_initializer='normal', activation='relu'))# 30 is then number of neurons
    #model.add(Dense(6, kernel_initializer='normal', activation='relu'))
    model.add(Dense(1, kernel_initializer='normal'))

    # Compile model
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

# evaluate model with standardized dataset
estimator = KerasRegressor(build_fn=norm_model, epochs=(100), batch_size=5, verbose=1)
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, y, cv=kfold)

print(results)

[-0.00454741 -0.00323181 -0.00345096 -0.00847261 -0.00390925 -0.00334816
 -0.00239754 -0.00681044 -0.02098541 -0.00140129]


# invert predictions
X_train = scaler.inverse_transform(X_train)
y_train = scaler.inverse_transform(y_train)
X_test = scaler.inverse_transform(X_test)
y_test = scaler.inverse_transform(y_test)
results = scaler.inverse_transform(results)

print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))
Results: -0.01 (0.01) MSE

(1) Я читал, что перекрестная проверка не адаптирована для прогнозирования временных рядов. Итак, мне интересно, какие еще методы существуют и какие из них более адаптированы к временным рядам.

(2) Во-вторых, я решил нормализовать свои данные, потому что мой набор данных X состоит из разных показателей (градусы, миниметры, г/м3 и т. д.), а моя переменная для объяснения y находится в градусах. Таким образом, я знаю, что мне придется иметь дело с более сложной интерпретацией MSE, потому что ее результат не будет в той же единице, что и моя переменная y. Но для следующего шага моего исследования мне нужно сохранить результат предсказания y (сделанный моделью MLP), и мне нужно, чтобы эти значения были в степени. Итак, я попытался инвертировать нормализацию, но безуспешно, когда я печатаю свои результаты, прогнозируемые значения все еще находятся в нормализованном формате (см. Мой код выше). Кто-нибудь видит мою ошибку?


person JEG    schedule 11.07.2019    source источник


Ответы (1)


Модель, которую вы представили выше, рассматривает один экземпляр из 26 измерений, чтобы сделать прогноз. Из вашего описания кажется, что вы хотели бы делать прогнозы на основе последовательности этих измерений. Я не уверен, что полностью понял описание, но я предполагаю, что у вас есть последовательность из 46 измерений, каждое из которых имеет 26 значений, которые, по вашему мнению, должны быть хорошими предикторами температуры. Если это так, входная форма вашей модели должна быть (46, 26,). 46 здесь называется time_steps, 26 — это количество функций.

Для временного ряда необходимо выбрать дизайн модели. Есть 2 подхода: рекуррентная сеть или сверточная сеть (или смесь 2-го). Сверточная сеть обычно используется для обнаружения закономерностей во входных данных, которые могут находиться где-то в данных. Например, предположим, что вы хотите обнаружить заданную форму на изображении. Сверточные сети — хорошая отправная точка. Рекуррентные сети обновляют свое внутреннее состояние после каждого временного шага. Они могут обнаруживать шаблоны так же, как и сверточная сеть, но вы можете думать о них как о менее независимых от позиции.

Простой пример сверточного подхода.

import tensorflow as tf
from tensorflow import keras

from tensorflow.keras.layers import *
from tensorflow.keras.models import Sequential, Model

average_tmp = 0.0

model = Sequential([
    InputLayer(input_shape=(46,26,)),
    Conv1D(16, 4),
    Conv1D(32, 4),
    Conv1D(64, 2),
    Conv1D(128, 4),
    MaxPooling1D(),
    Flatten(),
    Dense(256, activation='relu'),
    Dense(1, bias_initializer=keras.initializers.Constant(average_tmp)),
])

model.compile('adam', 'mse')
model.summary()

Смешанный подход заменит слой Flatten выше узлом LSTM. Вероятно, это было бы разумной отправной точкой для начала экспериментов.

(1) Я читал, что перекрестная проверка не адаптирована для прогнозирования временных рядов. Итак, мне интересно, какие еще методы существуют и какие из них более адаптированы к временным рядам.

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

Примеры методов регуляризации, которые вы, вероятно, захотите рассмотреть:

  • Сохранение весов модели в эпоху с более низкой оценкой проверки.
  • Удаление и/или пакетная нормализация.
  • регуляризация ядра.

(2) Во-вторых, я решил нормализовать свои данные, потому что мой набор данных X состоит из разных показателей (градусы, миниметры, г/м3 и т. д.), а моя переменная для объяснения y находится в градусах.

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

Таким образом, я знаю, что мне придется иметь дело с более сложной интерпретацией MSE, потому что ее результат не будет в той же единице, что и моя переменная y.

Это ортогонально. Входные данные не предполагаются в той же единице, что и y. Мы предполагаем, что в DNN мы можем создать комбинацию линейного преобразования весов (плюс нелинейные активации). Это не имеет неявного предположения о единицах.

Но для следующего шага моего исследования мне нужно сохранить результат предсказания y (сделанный моделью MLP), и мне нужно, чтобы эти значения были в степени. Итак, я попытался инвертировать нормализацию, но безуспешно, когда я печатаю свои результаты, прогнозируемые значения все еще находятся в нормализованном формате (см. Мой код выше). Кто-нибудь видит мою ошибку?

scaler.inverse_transform(results) должно помочь. Нет смысла обратно преобразовывать входы X_ и Y_. И, вероятно, это поможет вам сохранить ваш код, если вы не будете использовать одно и то же имя переменной для обоих масштабаторов X и Y.

Также можно воздержаться от масштабирования Y. Если вы решите это сделать, я бы посоветовал вам инициализировать смещение выходного слоя средним значением Y.

person Pedro Marques    schedule 11.07.2019
comment
Спасибо за подробный ответ. Не могли бы вы подробно рассказать, почему мой input_dim неверен? Чтобы построить свою модель, я следовал руководству по регрессионному обучению с библиотекой глубокого обучения Keras на Python (machinelearningmastery.com/). В этом руководстве X содержит 13 переменных, поэтому они используют model.add(Dense(13, input_dim=13,.........) Что может быть не так для регрессии MLP? - person JEG; 12.07.2019
comment
Это действительно зависит от того, как вы сформулируете проблему. Я интерпретировал ваше описание выше как говорящее, что вы хотели бы предсказать переменную (температуру) на основе нескольких показаний 26 переменных. Возможно, я неправильно вас понял. Помогает, если вы можете четко определить проблему независимо от того, как ее реализовать: т.е. от чего зависит прогноз? Если вывод зависит только от одного чтения 26 переменных, то правильная входная форма будет (26,); если вывод должен зависеть от нескольких показаний, то входная форма должна быть (N, 26,), где N — длина последовательности. - person Pedro Marques; 12.07.2019
comment
На самом деле, я думаю, что вы правильно поняли проблему. Я хотел бы научить свою модель прогнозировать температуру, которая будет основана на матрице X, которая содержит такие переменные, как влажность, ветер, облачный покров и температуры, прогнозируемые многими синоптиками. У меня также есть массив y, который содержит реальные наблюдаемые температуры. Таким образом, со всеми этими данными моя цель состоит в том, чтобы (в идеале) предсказать температуру, максимально близкую к реальной температуре, на основе имеющихся у меня информационных данных (влажность и т. д.) - person JEG; 15.07.2019
comment
Если каждый прогноз основан на матрице, то форма ваших входных данных должна быть матрицей. Вы можете попробовать следовать примеру кода, который был в моем исходном ответе. Если вам нужно убедиться, что вы правильно генерируете данные... т. е. для каждого значения y, которое, как вы знаете, является истинным, вам нужно сгенерировать матрицу X значений, известных до y, которая приведет вас к этому выводу. - person Pedro Marques; 15.07.2019