В настоящий момент мой набор данных имеет форму X: [4000,20], Y: [4000].
Я хочу обучить LSTM с помощью TensorFlow, чтобы предсказать значение Y (регрессия), учитывая 10 предыдущих входов d-функций, но мне сложно выполнять это в TensorFlow.
Основная проблема, с которой я сейчас сталкиваюсь, заключается в понимании того, как TensorFlow ожидает, что ввод будет отформатирован. Я видел различные примеры, такие как this, но эти примеры относятся к одной большой строке непрерывных временных рядов. Мои данные - разные образцы, каждый из которых независимый временной ряд.
Ответ 1
Документация tf.nn.dynamic_rnn
гласит:
inputs
: Входы RNN. Если time_major == False
(по умолчанию), это должен быть Тензор формы: [batch_size, max_time, ...]
или вложенный кортеж таких элементов.
В вашем случае это означает, что вход должен иметь форму [batch_size, 10, 2]
. Вместо того, чтобы тренироваться во всех 4000 последовательностях, вы должны использовать только batch_size
многие из них на каждой итерации обучения. Что-то вроде следующего должно работать (добавлено изменение для ясности):
batch_size = 32
# batch_size sequences of length 10 with 2 values for each timestep
input = get_batch(X, batch_size).reshape([batch_size, 10, 2])
# Create LSTM cell with state size 256. Could also use GRUCell, ...
# Note: state_is_tuple=False is deprecated;
# the option might be completely removed in the future
cell = tf.nn.rnn_cell.LSTMCell(256, state_is_tuple=True)
outputs, state = tf.nn.dynamic_rnn(cell,
input,
sequence_length=[10]*batch_size,
dtype=tf.float32)
Из документации, outputs
будет иметь форму [batch_size, 10, 256]
, то есть один 256-вывод для каждого временного времени. state
будет кортежем форм [batch_size, 256]
. Вы можете предсказать свое окончательное значение, по одному для каждой последовательности, из этого:
predictions = tf.contrib.layers.fully_connected(state.h,
num_outputs=1,
activation_fn=None)
loss = get_loss(get_batch(Y).reshape([batch_size, 1]), predictions)
Число 256 в формах outputs
и state
определяется cell.output_size
соответственно. cell.state_size
. При создании LSTMCell
, как указано выше, они одинаковы. Также см. документацию LSTMCell.
Ответ 2
(Этот ответ "устраняет" проблему, когда прямой np.reshape() не организует конечный массив так, как мы этого хотим. Если мы хотим напрямую изменить форму в 3D, np.reshape сделает это, но следите за окончательной организацией вход).
В моей личной попытке окончательно решить эту проблему подачи входной формы для RNN и больше не путать, я дам свое "личное" объяснение этого.
В моем случае (и я думаю, что многие другие могут иметь эту схему организации в своих матрицах возможностей), большинство блогов за пределами "не помогают". Давайте попробуем, как преобразовать 2D-матрицу объектов в 3D-матрицу для RNN.
Допустим, у нас есть этот тип организации в нашей матрице объектов: у нас есть 5 наблюдений (т.е. строк - для соглашения, я думаю, что это самый логичный термин для использования), и в каждой строке у нас есть 2 функции для КАЖДОГО временного шага (и у нас есть 2 временные шаги), вот так:
(df
, чтобы лучше понять мои слова)
In [1]: import numpy as np
In [2]: arr = np.random.randint(0,10,20).reshape((5,4))
In [3]: arr
Out[3]:
array([[3, 7, 4, 4],
[7, 0, 6, 0],
[2, 0, 2, 4],
[3, 9, 3, 4],
[1, 2, 3, 0]])
In [4]: import pandas as pd
In [5]: df = pd.DataFrame(arr, columns=['f1_t1', 'f2_t1', 'f1_t2', 'f2_t2'])
In [6]: df
Out[6]:
f1_t1 f2_t1 f1_t2 f2_t2
0 3 7 4 4
1 7 0 6 0
2 2 0 2 4
3 3 9 3 4
4 1 2 3 0
Теперь мы возьмем значения для работы с ними. Дело в том, что RNNs включают измерение "временного шага" в свой вклад из-за их архитектурной природы. Мы можем представить это измерение как суммирующие двумерные массивы один за другим для количества временных шагов, которые у нас есть. В этом случае у нас есть два временных шага; поэтому у нас будет два двухмерных массива: один для временного шага 1, а за ним - второй для временного шага 2.
На самом деле, в том 3D-входе, который нам нужно сделать, у нас еще есть 5 наблюдений. Дело в том, что нам нужно расположить их по-разному: RNN возьмет первую строку (или указанный пакет - но мы будем здесь все упрощать) первого массива (т.е. timestep1) и первую строку второго сложенного массива (т.е. timestep2). Затем второй ряд... до последнего (пятый в нашем примере). Таким образом, в каждом ряду каждого временного шага нам, разумеется, нужно разделить две функции на разные массивы, каждый из которых соответствует его временному шагу. Давайте посмотрим на это с помощью цифр.
Я сделаю два массива для облегчения понимания. Помните, что из-за нашей организационной схемы в df вы, возможно, заметили, что нам нужно взять первые два столбца (т.е. функции 1 и 2 для временного шага 1) в качестве ПЕРВОГО Массива стека и последних двух столбцов, то есть 3-й и 4-й, как наш ВТОРОЙ массив из стека, так что все, наконец, имеет смысл.
In [7]: arrStack1 = arr[:,0:2]
In [8]: arrStack1
Out[8]:
array([[3, 7],
[7, 0],
[2, 0],
[3, 9],
[1, 2]])
In [9]: arrStack2 = arr[:,2:4]
In [10]: arrStack2
Out[10]:
array([[4, 4],
[6, 0],
[2, 4],
[3, 4],
[3, 0]])
Наконец, единственное, что нам нужно сделать, это сложить оба массива ("один за другим"), как если бы они были частью одной и той же конечной структуры:
In [11]: arrfinal3D = np.stack([arrStack1, arrStack2])
In [12]: arrfinal3D
Out[12]:
array([[[3, 7],
[7, 0],
[2, 0],
[3, 9],
[1, 2]],
[[4, 4],
[6, 0],
[2, 4],
[3, 4],
[3, 0]]])
In [13]: arrfinal3D.shape
Out[13]: (2, 5, 2)
Вот и все: у нас есть наша матрица признаков, готовая для подачи в ячейку RNN, с учетом нашей организации матрицы 2D-объектов.
(Для одного лайнера относительно всего этого вы можете использовать:
In [14]: arrfinal3D_1 = np.stack([arr[:,0:2], arr[:,2:4]])
In [15]: arrfinal3D_1
Out[15]:
array([[[3, 7],
[7, 0],
[2, 0],
[3, 9],
[1, 2]],
[[4, 4],
[6, 0],
[2, 4],
[3, 4],
[3, 0]]])
Надеюсь это поможет!