Вопрос или проблема
В настоящее время я пытаюсь разработать модель, которая принимает временной ряд данных о электроэнергии из домохозяйства в качестве входных данных и должна дисагрегировать эти данные о основном электроснабжении на конкретное потребление энергии устройств, что является целевыми данными.
Частота данных, которую я использую, составляет 10 секунд.
Моя идея заключается в использовании модели LSTM-секвенции для указывающего моделирования, которая принимает последовательность агрегированных данных о электроснабжении в качестве входных данных и предсказывает среднюю точку этой последовательности для одного устройства/субсчетчика.
Вот код, который создает набор данных, как описано выше:
def create_dataset(path_to_dataset:str, device:str, building:int, window:int, start_train:str, end_train:str):
dataset = DataSet(path_to_dataset)
input = next(dataset.buildings[building].elec.mains().load())
target = next(dataset.buildings[building].elec.submeters().select_using_appliances(type=device).load())
input = input['power']['active']
target = target['power']['active']
print(len(input))
print(len(target))
# ресемплирование
target = target.resample('1T').mean()
input_train = input[start_train:end_train].values
target_train = target[start_train:end_train].values
input_train = input_train.reshape(-1, 1)
target_train = target_train.reshape(-1, 1)
# scaler = MinMaxScaler(feature_range=(0,1))
# input_train = scaler.fit_transform(input_train)
# target_train = scaler.fit_transform(target_train)
print(len(input_train))
print(len(target_train))
x_train = []
y_train = []
for i in range(window,len(input_train)):
x_train.append(input_train[i-window:i].tolist())
# y_train.append([np.mean(target_train[i-window:i])])
y = [target_train[i-window:i]]
y = y[int(len(y)/2)]
y_train.append(y)
input_test = input[end_train:].values
target_test = target[end_train:].values
input_test = input_test.reshape(-1, 1)
target_test = target_test.reshape(-1, 1)
# input_test = scaler.fit_transform(input_test)
# target_test = scaler.fit_transform(target_test)
x_test = []
y_test = []
for i in range(window,len(input_test)):
x_test.append(input_test[i-window:i].tolist())
# y_test.append([np.mean(target_test[i-window:i])])
y = [target_train[i-window:i]]
y = y[int(len(y)/2)]
y_test.append(y)
return np.asarray(x_train), np.asarray(y_train), np.asarray(x_test), np.asarray(y_test)
x_train, y_train, x_test, y_test = create_dataset(r'dataset.h5', 'toaster', 1, 10, '2022-06-04 02:00:00', '2022-08-01 02:00:00')
Однако я получаю действительно плохие результаты. Я пробовал разные функции потерь, функции активации, нормализацию данных, но ничего действительно не улучшило предсказания. Вот как я строю модель:
def create_model(x_train, y_train, epochs, window, features):
model = Sequential()
model.add(LSTM(64, activation = 'relu', return_sequences=True, input_shape = (window, features)))
model.add(LSTM(64,return_sequences=True))
model.add(LSTM(64))
model.add(Dense(1))
# Компилирование модели
model.compile(optimizer="adam", loss="mse", metrics=['accuracy'])
# К callbacks для ранней остановки
es_callback = callbacks.EarlyStopping(
monitor="accuracy", min_delta=1e-3, patience=2, verbose=1, mode="auto", restore_best_weights=True)
# Обучение модели
history = model.fit(x_train, y_train, epochs = epochs, callbacks=[es_callback], validation_split=0.1)
return model, history
Например, я обучал сеть для устройства “тостер”, который в основном выключен (y_test равно 0.0). Предсказания этого не учитывают, а вместо этого предсказывают значения рядом с этим.
predictions = model.predict(x_test)
predictions
array([[-0.14068991],
[-0.12829399],
[-0.11637664],
...,
[-0.0779351 ],
[-0.07779408],
[-0.07804739]], dtype=float32)
y_test
array([[[0.],
[0.],
[0.],
...,
[0.],
[0.],
[0.]],
[[0.],
[0.],
[0.],
...,
[0.],
[0.],
Я вообще использую правильную модель? Я думаю, что то, что я пытаюсь сделать, это регрессия, и я думал, что LSTM будет правильным выбором для этого.
Заранее спасибо за ваши идеи и улучшения.
Предсказания модели не будут одинаковыми. Вам нужно установить порог, чтобы получить значение. Например, вы можете установить порог ошибки как 0.5, значения больше или меньше на 0.5 будут считаться одинаковыми.
Ответ или решение
Разработка модели для дизагрегирования данных о потреблении энергии с использованием LSTM
Вопрос, который вы рассматриваете, связан с задачей дизагрегирования данных о потреблении энергии в индивидуальных устройствах на основе времени общих показателей энергопотребления в домохозяйствах. Вы выбрали модель LSTM для этой задачи, что является разумным решением, учитывая временной характер данных. Однако результаты вашей модели не соответствуют ожиданиям, и давайте рассмотрим возможные улучшения и аспекты, которые стоит учесть.
1. Основные шаги в оптимизации модели
-
Преобразование данных: Вы уже используете 10-секундные интервалы данных, что хорошо при высокочастотных временных рядах. Однако стоит убедиться, что перед тренировкой данные должным образом нормализованы. Вам следует попробовать различные методы масштабирования, такие как MinMaxScaler или StandardScaler, и протестировать, какой из них наилучшим образом подходит для вашего набора данных.
-
Структура модели: Ваша архитектура LSTM выглядит неплохо, однако вы можете попробовать уменьшить количество единиц в слоях LSTM или добавить слой Dropout для борьбы с переобучением. Попробуйте и другие конфигурации, чтобы найти оптимальное количество нейронов и слоев.
-
Функция потерь и метрики: Вы используете MSE как функцию потерь. Это хороший выбор для регрессии, однако также стоит рассмотреть MAE (Mean Absolute Error), так как она может быть менее чувствительной к выбросам. Также важно следить за метрикой, по которой вы производите валидацию. Вместо ‘accuracy’ (которая не имеет смысла для регрессии) можно использовать ‘mse’ или ‘mae’.
2. Изменение способа подготовки данных
Ваш код по подготовке данных, включая создание случаем выборок, имеет смысл, однако следует обратить особое внимание на способ разбиения целевых данных:
for i in range(window, len(input_train)):
x_train.append(input_train[i-window:i].tolist())
y = [target_train[i-window:i]]
y = y[int(len(y)/2)]
y_train.append(y)
Выбор значения из середины блока целевых данных может не давать точного представления о потреблении устройства. Рассмотрите возможность прогнозирования средних значений, медиан или других статистик вместо использования только одного элемента.
3. Улучшение процесса обучения
Настройка гиперпараметров, таких как скорость обучения и размер пакета, имеет критически важное значение. Попробуйте:
- Адаптивные оптимизаторы: Используйте такие оптимизаторы, как AdamW или RMSprop с изменяемым шагом обучения.
- Размер пакета: Экспериментируйте с размером пакета, так как маленькие или большие размеры могут значительно изменить динамику обучения.
4. Результаты и анализ
Результаты ваших модельных прогнозов указывают на проблему смещения в предсказаниях. Например, если ваши предсказания находятся близко к нулю, это может быть связано с тем, что модель "обучается" игнорировать множество нулевых значений в вашем целевом наборе. Скорее всего, многие устройства не работают постоянно, и это необходимо учесть. Попробуйте ввести пороги для прогнозов, чтобы лучше учитывать периодические изменения нагрузки.
5. Проведение валидации модели
Не забывайте проверить вашу модель на другом подмножестве данных, чтобы удостовериться, что полученные результаты репрезентативны. Используйте методы кросс-валидации для весовых выборок, чтобы избежать переобучения.
Заключение
Вы находитесь на верном пути к разработке модели для дизагрегирования данных о потреблении энергии с использованием LSTM. Обратите внимание на обзор архитектуры модели, предобработку данных, настройку гиперпараметров и подход к анализу результатов. Лишь собрав все эти аспекты вместе, вы сможете добиться улучшенной производительности. Удачи в вашем проекте!