Учебники

Временной ряд — модель LSTM

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

LSTM — это класс возвратных нейронных сетей. Поэтому, прежде чем мы сможем перейти к LSTM, важно понять нейронные сети и рекуррентные нейронные сети.

Нейронные сети

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

Рекуррентные нейронные сети

Это класс нейронных сетей, предназначенных для работы с временными данными. Нейроны RNN имеют состояние / память ячейки, и ввод обрабатывается в соответствии с этим внутренним состоянием, которое достигается с помощью петель в нейронной сети. В RNN существуют повторяющиеся модули «tanh» слоев, которые позволяют им сохранять информацию. Однако ненадолго, поэтому нам нужны модели LSTM.

LSTM

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

Нейронная сеть

На рисунке выше изображены четыре слоя нейронной сети в желтых прямоугольниках, точечные операторы в зеленых кружках, ввод в желтых кружках и состояние ячейки в голубых кружках. Модуль LSTM имеет состояние ячейки и три шлюза, что дает им возможность выборочно изучать, отключать или сохранять информацию от каждого из модулей. Состояние ячейки в LSTM помогает информации проходить через единицы без изменения, позволяя только несколько линейных взаимодействий. Каждое устройство имеет вход, выход и шлюз забывания, который может добавлять или удалять информацию в состояние ячейки. Врата забытия решает, какая информация из предыдущего состояния ячейки должна быть забыта, для чего она использует сигмовидную функцию. Входной вентиль управляет потоком информации в текущем состоянии ячейки, используя точечную операцию умножения sigmoid и tanh соответственно. Наконец, выходной вентиль решает, какую информацию следует передать в следующее скрытое состояние

Теперь, когда мы поняли внутреннюю работу модели LSTM, давайте реализуем ее. Чтобы понять реализацию LSTM, мы начнем с простого примера — прямой линии. Давайте посмотрим, сможет ли LSTM узнать взаимосвязь прямой линии и предсказать ее.

Сначала давайте создадим набор данных, изображающий прямую линию.

В [402]:

x = numpy.arange (1,500,1)
y = 0.4 * x + 30
plt.plot(x,y)

Из [402]:

[<matplotlib.lines.Line2D at 0x1eab9d3ee10>]

Фрагмент кода 19

В [403]:

trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
train = numpy.array(list(zip(trainx,trainy)))
test = numpy.array(list(zip(trainx,trainy)))

Теперь, когда данные были созданы и разбиты на обучающие и тестовые. Давайте преобразуем данные временного ряда в форму контролируемых обучающих данных в соответствии со значением периода оглядки назад, которое, по сути, представляет собой число лагов, которые, как видно, предсказывают значение в момент времени «t».

Так что временной ряд, как это —

time variable_x
t1  x1
t2  x2
 :   :
 :   :
T   xT

Когда период просмотра равен 1, преобразуется в —

x1   x2
x2   x3
 :    :
 :    :
xT-1 xT

В [404]:

def create_dataset(n_X, look_back):
   dataX, dataY = [], []
   for i in range(len(n_X)-look_back):
      a = n_X[i:(i+look_back), ]
      dataX.append(a)
      dataY.append(n_X[i + look_back, ])
   return numpy.array(dataX), numpy.array(dataY)

В [405]:

look_back = 1
trainx,trainy = create_dataset(train, look_back)
testx,testy = create_dataset(test, look_back)

trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
testx = numpy.reshape(testx, (testx.shape[0], 1, 2))

Теперь мы будем тренировать нашу модель.

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

В [ ]:

from keras.models import Sequential
from keras.layers import LSTM, Dense

model = Sequential()
model.add(LSTM(256, return_sequences = True, input_shape = (trainx.shape[1], 2)))
model.add(LSTM(128,input_shape = (trainx.shape[1], 2)))
model.add(Dense(2))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
model.save_weights('LSTMBasic1.h5')

В [407]:

model.load_weights('LSTMBasic1.h5')
predict = model.predict(testx)

Теперь посмотрим, как выглядят наши прогнозы.

В [408]:

plt.plot(testx.reshape(398,2)[:,0:1], testx.reshape(398,2)[:,1:2])
plt.plot(predict[:,0:1], predict[:,1:2])

Из [408]:

[<matplotlib.lines.Line2D at 0x1eac792f048>]

Фрагмент кода 22

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

В [409]:

x = numpy.arange (1,500,1)
y = numpy.sin(x)
plt.plot(x,y)

Из [409]:

[<matplotlib.lines.Line2D at 0x1eac7a0b3c8>]

Фрагмент кода 23

В [410]:

trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
train = numpy.array(list(zip(trainx,trainy)))
test = numpy.array(list(zip(trainx,trainy)))

В [411]:

look_back = 1
trainx,trainy = create_dataset(train, look_back)
testx,testy = create_dataset(test, look_back)
trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
testx = numpy.reshape(testx, (testx.shape[0], 1, 2))

В [ ]:

model = Sequential()
model.add(LSTM(512, return_sequences = True, input_shape = (trainx.shape[1], 2)))
model.add(LSTM(256,input_shape = (trainx.shape[1], 2)))
model.add(Dense(2))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
model.save_weights('LSTMBasic2.h5')

В [413]:

model.load_weights('LSTMBasic2.h5')
predict = model.predict(testx)

В [415]:

plt.plot(trainx.reshape(398,2)[:,0:1], trainx.reshape(398,2)[:,1:2])
plt.plot(predict[:,0:1], predict[:,1:2])

Out [415]:

[<matplotlib.lines.Line2D at 0x1eac7a1f550>]

Фрагмент кода 23

Теперь вы готовы перейти к любому набору данных.