Использование LSTM для предсказания бинарной классификации – точность застряла на уровне 50% – как использовать statefulness.

Вопрос или проблема

Я пытаюсь использовать модель LSTM для бинарной классификации; однако, когда я обучаю модель, значение функции потерь остается около 0.69 (т.е. –$\ln(0.5)$), а точность на уровне 0.5, что наводит меня на мысль, что модель не учится, так как эти значения указывают на случайное угадывание. Я пробовал изменять скорость обучения, количество блоков и объединять несколько LSTM, но мне кажется, что я что-то упускаю из виду при использовании состояния, хотя я и не уверен, что именно.

Мои временные ряды имеют форму $t = [x_0, …, x_N]$, и я хочу использовать скользящее окно с шагом 10 для использования 100 элементов для предсказания знака следующего элемента. Например, я хочу использовать элементы с 0 по 99 для предсказания знака 100-го элемента; затем использовать элементы с 10 по 109 для предсказания 110-го и так далее.

Поэтому я сформировал обучающий набор следующим образом:

$X = \begin{bmatrix}
x_{0} & x_{1} & x_{2} & \dots & x_{99} \\
x_{10} & x_{11} & x_{12} & \dots & x_{109} \\
…\\
\end{bmatrix}$

и мой вектор-цель, где положительный знак x – это 1, а отрицательный – 0.

$y = \begin{bmatrix}
\text{sgn}(x_{100}) \\
\text{sgn}(x_{110}) \\
\vdots \\
\end{bmatrix}
$

В моем случае $N = 1047700$, так что у меня есть $10477$ последовательностей длиной $100$. Моя идея состоит в том, чтобы использовать LSTM с следующим кодом:

model = Sequential()

model.add(LSTM(32, activation='tanh',input_shape=(X.shape[1],1)))
model.add(Dense(1,activation='sigmoid'))
adm = Adam(lr=0.001)
model.compile(loss="binary_crossentropy", optimizer=adm, metrics=['accuracy'])

model.fit(train_array,classified_returns, epochs=200, verbose=1,
         shuffle=False, validation_split=0.1)

Вот сводка модели:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_2 (LSTM)                (None, 32)                4608      
_________________________________________________________________
dense_13 (Dense)             (None, 1)                 33        
=================================================================
Total params: 4,641
Trainable params: 4,641
Non-trainable params: 0
_________________________________________________________________

Вот извлечение результатов обучения:

Train on 9429 samples, validate on 1048 samples
Epoch 1/200
9429/9429 [==============================] - 18s 2ms/step - loss: 0.6932 - acc: 0.5002 - val_loss: 0.6931 - val_acc: 0.503849
Epoch 2/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6933 - acc: 0.4984 - val_loss: 0.6931 - val_acc: 0.5048
Epoch 3/200
9429/9429 [==============================] - 15s 2ms/step - loss: 0.6932 - acc: 0.4994 - val_loss: 0.6930 - val_acc: 0.5048
Epoch 4/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4992 - val_loss: 0.6930 - val_acc: 0.5048
Epoch 5/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4987 - val_loss: 0.6930 - val_acc: 0.5048
Epoch 6/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4980 - val_loss: 0.6930 - val_acc: 0.5048
Epoch 7/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4978 - val_loss: 0.6930 - val_acc: 0.5038
Epoch 8/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4984 - val_loss: 0.6930 - val_acc: 0.5048
Epoch 9/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4986 - val_loss: 0.6930 - val_acc: 0.5048
Epoch 10/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4977 - val_loss: 0.6930 - val_acc: 0.5057
Epoch 11/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4980 - val_loss: 0.6930 - val_acc: 0.5057
Epoch 12/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4981 - val_loss: 0.6930 - val_acc: 0.5067
Epoch 13/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4987 - val_loss: 0.6930 - val_acc: 0.5076
Epoch 14/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4978 - val_loss: 0.6930 - val_acc: 0.5076
Epoch 15/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4974 - val_loss: 0.6930 - val_acc: 0.5076
Epoch 16/200
9429/9429 [==============================] - 15s 2ms/step - loss: 0.6932 - acc: 0.4976 - val_loss: 0.6930 - val_acc: 0.5076
Epoch 17/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4968 - val_loss: 0.6930 - val_acc: 0.5076
Epoch 18/200
9429/9429 [==============================] - 16s 2ms/step - loss: 0.6932 - acc: 0.4971 - val_loss: 0.6930 - val_acc: 0.5076

Как мы видим, модель не учится. Может кто-то указать мне правильное направление использования состояния?

Как использовать stateful LSTMs хорошо задокументировано в официальной документации Keras. Также есть хороший блог пост здесь.

В разделе о рекуррентных слоях есть заметка:

Примечание по использованию состояния в RNNs

Вы можете установить RNN слои в состояние ‘stateful’, что означает, что состояния, вычисленные для образцов в одном пакете, будут повторно использоваться как начальные состояния для образцов в следующем пакете. Это предполагает одно к одному сопоставление между образцами в различных последовательных пакетах.

Чтобы включить состояние: – укажите stateful=True в конструкторе слоя. – укажите фиксированный размер пакета для вашей модели, передав при использовании последовательной модели: batch_input_shape=(...) в первый слой вашей модели. в противном случае для функциональной модели с 1 или более входными слоями: batch_shape=(...) во все первые слои вашей модели. Это ожидаемая форма ваших входных данных, включая размер пакета. Это должен быть кортеж целых чисел, напр. (32, 10, 100). – укажите shuffle=False при вызове fit().

Чтобы сбросить состояния вашей модели, вызовите .reset_states() либо для конкретного слоя, либо для всей вашей модели.

Небольшое затруднение

Небольшая трудность, которую вы должны исправить самостоятельно, заключается в том, чтобы убедиться, что количество ваших образцов является целым кратным вашего размера пакета: num_samples % batch_size == 0. Вы должны убедиться в этом вручную, так как Keras просто возьмет оставшиеся образцы для последнего пакета, и это обычно меньше, чем желаемый размер пакета.

.

Ответ или решение

Использование LSTM для бинарной классификации может быть непростой задачей, особенно если точность застряла на уровне 50%, что указывает на случайные угаданные результаты. Для достижения прогресса, прежде чем переходить к stateful LSTM, необходимо проанализировать некоторые ключевые аспекты модели и данных.

Анализ задачи

  1. Предварительная подготовка данных:
    Убедитесь, что данные правильно нормализованы (например, в диапазоне от 0 до 1) и что в них нет аномалий, которые могут повлиять на обучение модели.

  2. Проверка модели:

    • Архитектура модели должна быть адекватна сложности задачи. Возможно, стоит увеличить количество нейронов или слоев в сети для повышения выразительной способности модели.
    • Убедитесь, что функция активации и функция потерь соответствуют бинарной классификации.
  3. Гиперпараметры:

    • Настройка скорости обучения: попробуйте различные значения, чтобы найти оптимальную скорость обучения.
    • Измените размеры batches и количества epoch для более тщательного поиска.

Использование Statefulness в LSTM

Если уверены, что данные и архитектура модели подготовлены правильно, можно рассмотреть использование stateful LSTM для улучшения результатов.

Внедрение Stateful LSTM

  1. Изменение параметров слоя LSTM:
    Установите параметр stateful=True в конструкторе слоя LSTM. Это позволит сохранять состояние между последовательными batches.

  2. Настройка формы ввода:
    Поскольку вы планируете использовать stateful LSTM, вам потребуется зафиксировать размер batches. Например, задайте batch_input_shape=(batch_size, timesteps, features) для первого слоя в модели.

  3. Контроль размера batches:
    Убедитесь, что размер вашей обучающей выборки делится нацело на размер batches (num_samples % batch_size == 0). В противном случае последние batches могут содержать меньшее количество данных, что повредит обучению.

  4. Настройки обучения:
    Убедитесь, что при вызове метода fit установлен параметр shuffle=False, чтобы последовательные batches обеспечивали непрерывность данных.

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

  6. Оптимизация и настройка:
    Можно экспериментировать с различными комбинациями гиперпараметров и архитектуры модели. Это включает в себя вариации количества нейронов, уровней dropout, изменения активаций и так далее.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...