извлечение запаздывающих функций массива numpy ( расширение размера) | изменение формы массива numpy с шагом=1

#numpy #time-series #lag

Вопрос:

У меня есть массив данных временных рядов формы (#timestamp,#features) . Я хотел бы извлечь для каждой строки ( timestamp ) n_lags (предыдущие строки) и изменить форму массива таким образом, чтобы у меня была форма (#samples, #lags now,#features) для ввода в слой LSTM Keras.

Рассмотрим этот игрушечный пример:

 import numpy as np
n_rows = 6
n_feat= 3
n_lag = 2

a = np.array(range(n_rows*n_feat)).reshape(n_rows, n_feat)

>>> a.shape = (6, 3)
>>> a = array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11],
           [12, 13, 14],
           [15, 16, 17]])
 

С помощью итерации по строкам я достигаю ожидаемого результата:

 b = np.empty(shape=(0, (n_lag   1), n_feat))
for idx, row in enumerate(a):
   temp = np.expand_dims(a[max(0, idx-n_lag):idx 1, :], 0)
   if temp.shape[1:] == b.shape[1:]:
       b = np.append(b, temp, axis=0)


>>> b.shape = (4, 3, 3)
>>> b = array([[[ 0.,  1.,  2.],
            [ 3.,  4.,  5.],
            [ 6.,  7.,  8.]],

           [[ 3.,  4.,  5.],
            [ 6.,  7.,  8.],
            [ 9., 10., 11.]],

           [[ 6.,  7.,  8.],
            [ 9., 10., 11.],
            [12., 13., 14.]],

           [[ 9., 10., 11.],
            [12., 13., 14.],
            [15., 16., 17.]]])
 

Примечание: в первых n_lags-1 строках недостаточно данных, и они будут отброшены в окончательном выводе

Вопрос: Я хотел бы знать, есть ли более элегантный / приятный способ, чем перебор строк.

Комментарии:

1. Не keras вопрос или lstm вопрос, пожалуйста, не спамьте нерелевантные теги (удалены).

2.поскольку этот вопрос направлен на форматирование данных в соответствии с keras lstm , я ожидал, что некоторым людям будет интересно увидеть связь. Никогда не собирался спамить теги, но спасибо за редактирование тегов в соответствии с руководством!

3. Нет проблем; на будущее, пожалуйста, имейте в виду, что теги должны касаться только содержания вопроса, а не его (общего) контекста.

4. Просто небольшой комментарий к коду. np.array(range(n_rows*n_feat)) может быть заменен на np.arange(n_rows*n_feat) . Нет необходимости использовать примитивные генераторы python.

Ответ №1:

Для этого вы можете использовать новый np.lib.stride_tricks.sliding_window_view

 n_rows = 6
n_feat= 3
n_lag = 2

a = np.array(range(n_rows*n_feat)).reshape(n_rows, n_feat)

b = np.lib.stride_tricks.sliding_window_view(a, window_shape=(n_feat, n_feat))
b
 

выход:

 array([[[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]]],


       [[[ 3,  4,  5],
         [ 6,  7,  8],
         [ 9, 10, 11]]],


       [[[ 6,  7,  8],
         [ 9, 10, 11],
         [12, 13, 14]]],


       [[[ 9, 10, 11],
         [12, 13, 14],
         [15, 16, 17]]]])
 

b просто изменит форму и шаги a , поэтому он будет содержать одну и ту же ячейку памяти a несколько раз. Другими словами, нет необходимости выделять новый массив.

Комментарии:

1. именно то, что я искал! Большое Спасибо! Довольно новый метод, хотя сначала пришлось обновить Numpy 🙂