Подтвердить что ты не робот

Форма ввода LSTM в нейронной сети из кадра данных

Я пытаюсь реализовать LSTM с Keras.

Я знаю, что для LSTM в Keras требуется трехмерный тензор с формой (nb_samples, timesteps, input_dim) в качестве входных данных. Однако я не совсем уверен, как должны выглядеть входные данные в моем случае, поскольку у меня есть только одна выборка из T наблюдений для каждого входа, а не несколько выборок, т.е. (nb_samples=1, timesteps=T, input_dim=N). Лучше ли разделить каждый из моих входов на выборки длины T/M? T составляет около нескольких миллионов наблюдений для меня, так как долго каждый образец в этом случае должно быть, т.е., как бы я выбрал M?

Кроме того, я прав, что этот тензор должен выглядеть примерно так:

[[[a_11, a_12, ..., a_1M], [a_21, a_22, ..., a_2M], ..., [a_N1, a_N2, ..., a_NM]], 
 [[b_11, b_12, ..., b_1M], [b_21, b_22, ..., b_2M], ..., [b_N1, b_N2, ..., b_NM]], 
 ..., 
 [[x_11, x_12, ..., a_1M], [x_21, x_22, ..., x_2M], ..., [x_N1, x_N2, ..., x_NM]]]

где M и N определены как прежде, а x соответствует последнему образцу, который я получил бы при расщеплении, как обсуждалось выше?

Наконец, учитывая кадр данных pandas с T наблюдениями в каждом столбце и N столбцами, по одному на каждый вход, как я могу создать такой вход для подачи в Keras?

4b9b3361

Ответ 1

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

import pandas as pd
import numpy as np
# Get some time series data
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/timeseries.csv")
df.head()

Временной диапазон данных:

Date      A       B       C      D      E      F      G
0   2008-03-18  24.68  164.93  114.73  26.27  19.21  28.87  63.44
1   2008-03-19  24.18  164.89  114.75  26.22  19.07  27.76  59.98
2   2008-03-20  23.99  164.63  115.04  25.78  19.01  27.04  59.61
3   2008-03-25  24.14  163.92  114.85  27.41  19.61  27.84  59.41
4   2008-03-26  24.44  163.45  114.84  26.86  19.53  28.02  60.09

Вы можете построить вводы ввода в вектор, а затем использовать функцию pandas .cumsum() для построения последовательности для временных рядов:

# Put your inputs into a single list
df['single_input_vector'] = df[input_cols].apply(tuple, axis=1).apply(list)
# Double-encapsulate list so that you can sum it in the next step and keep time steps as separate elements
df['single_input_vector'] = df.single_input_vector.apply(lambda x: [list(x)])
# Use .cumsum() to include previous row vectors in the current row list of vectors
df['cumulative_input_vectors'] = df.single_input_vector.cumsum()

Выход может быть настроен аналогичным образом, но вместо последовательности будет один вектор:

# If your output is multi-dimensional, you need to capture those dimensions in one object
# If your output is a single dimension, this step may be unnecessary
df['output_vector'] = df[output_cols].apply(tuple, axis=1).apply(list)

Входные последовательности должны иметь одинаковую длину, чтобы запускать их через модель, поэтому вам нужно заполнить их как максимальную длину ваших кумулятивных векторов:

# Pad your sequences so they are the same length
from keras.preprocessing.sequence import pad_sequences

max_sequence_length = df.cumulative_input_vectors.apply(len).max()
# Save it as a list   
padded_sequences = pad_sequences(df.cumulative_input_vectors.tolist(), max_sequence_length).tolist()
df['padded_input_vectors'] = pd.Series(padded_sequences).apply(np.asarray)

Данные обучения можно вытащить из фрейма данных и ввести в массивы numpy. Обратите внимание, что входные данные, которые выводятся из фреймворка данных, не будут создавать 3D-массив. Он создает массив массивов, что не то же самое.

Вы можете использовать hstack и reshape для создания трехмерного входного массива.

# Extract your training data
X_train_init = np.asarray(df.padded_input_vectors)
# Use hstack to and reshape to make the inputs a 3d vector
X_train = np.hstack(X_train_init).reshape(len(df),max_sequence_length,len(input_cols))
y_train = np.hstack(np.asarray(df.output_vector)).reshape(len(df),len(output_cols))

Чтобы доказать это:

>>> print(X_train_init.shape)
(11,)
>>> print(X_train.shape)
(11, 11, 6)
>>> print(X_train == X_train_init)
False

После получения данных обучения вы можете определить размеры вашего слоя ввода и выходных уровней.

# Get your input dimensions
# Input length is the length for one input sequence (i.e. the number of rows for your sample)
# Input dim is the number of dimensions in one input vector (i.e. number of input columns)
input_length = X_train.shape[1]
input_dim = X_train.shape[2]
# Output dimensions is the shape of a single output vector
# In this case it just 1, but it could be more
output_dim = len(y_train[0])

Постройте модель:

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

# Build the model
model = Sequential()

# I arbitrarily picked the output dimensions as 4
model.add(LSTM(4, input_dim = input_dim, input_length = input_length))
# The max output value is > 1 so relu is used as final activation.
model.add(Dense(output_dim, activation='relu'))

model.compile(loss='mean_squared_error',
              optimizer='sgd',
              metrics=['accuracy'])

Наконец, вы можете обучить модель и сохранить журнал тренировок как историю:

# Set batch_size to 7 to show that it doesn't have to be a factor or multiple of your sample size
history = model.fit(X_train, y_train,
              batch_size=7, nb_epoch=3,
              verbose = 1)

Вывод:

Epoch 1/3
11/11 [==============================] - 0s - loss: 3498.5756 - acc: 0.0000e+00     
Epoch 2/3
11/11 [==============================] - 0s - loss: 3498.5755 - acc: 0.0000e+00     
Epoch 3/3
11/11 [==============================] - 0s - loss: 3498.5757 - acc: 0.0000e+00 

Что это. Используйте model.predict(X), где X является тем же самым форматом (отличным от количества выборок) как X_train, чтобы сделать прогнозы из модели.

Ответ 2

Форма тензора

Вы правы, что Keras ожидает трехмерный тензор для нейронной сети LSTM, но я думаю, что часть, которую вам не хватает, - это то, что Keras ожидает, что каждое наблюдение может иметь несколько измерений.

Например, в Keras я использовал векторы слов для представления документов для обработки естественного языка. Каждое слово в документе представлено n-мерным числовым вектором (поэтому, если n = 2 слово "cat" будет представлено чем-то вроде [0.31, 0.65]). Для представления одного документа векторы слов выстраиваются последовательно (например, "Кошка сидела". = [[0.12, 0.99], [0.31, 0.65], [0.94, 0.04]]). Документ был бы единственным образцом в KERS LSTM.

Это аналогично вашим наблюдениям по временным рядам. Документ похож на временной ряд, и слово похоже на одно наблюдение в вашем временном ряду, но в вашем случае это просто, что представление вашего наблюдения - это просто размеры n = 1.

Из-за этого, я думаю, ваш тензор должен быть чем-то вроде [[[a1], [a2], ... , [aT]], [[b1], [b2], ..., [bT]], ..., [[x1], [x2], ..., [xT]]], где x соответствует nb_samples, timesteps = T и input_dim = 1, потому что каждое ваше наблюдение - только одно число.

Размер партии

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

<сильные > Примеры

Если вы ищете пример кода, на Keras Github, есть несколько примеров использования LSTM и других типов сетей, которые имеют последовательный ввод.