2016-03-12 14 views
14

Obecnie próbuję zbudować prosty model do przewidywania szeregów czasowych. Celem byłoby szkolenie modelu z sekwencją, tak aby model był w stanie przewidzieć przyszłe wartości.Jak wytrenować RNN z komórkami LSTM do prognozowania szeregów czasowych

Używam do tego komórek tensorflow i lstm. Model jest trenowany z obciętą wsteczną propagacją w czasie. Moje pytanie dotyczy struktury danych do szkolenia.

Na przykład załóżmy, że chcemy poznać daną sekwencję:

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

I rozwinąć sieć num_steps=4.

Wariant 1

input data    label  
1,2,3,4     2,3,4,5 
5,6,7,8     6,7,8,9 
9,10,11,12    10,11,12,13 
... 

Wariant 2

input data    label  
1,2,3,4     2,3,4,5 
2,3,4,5     3,4,5,6 
3,4,5,6     4,5,6,7 
... 

Wariant 3

input data    label  
1,2,3,4     5 
2,3,4,5     6 
3,4,5,6     7 
... 

Opcja 4

input data    label  
1,2,3,4     5 
5,6,7,8     9 
9,10,11,12    13 
... 

Każda pomoc zostanie doceniona.

+0

wśród wymienionych opcji, wydaje mi się, że opcja 3 byłaby najrozsądniejszą opcją, jeśli rzeczywiście można założyć, że 4 przeszłe wartości są wystarczające, w dobrym stopniu przybliżone, aby przewidzieć obecną wartość (więc chodzi bardziej o dane, niż o konkretnej metodzie, której używasz do przewidywania) .. –

+0

Oczywiście używam więcej niż ostatnich 4 wartości, to tylko mały przykład dla łatwiejszej demonstracji. Zapraszam również do zaproponowania innej opcji niż przedstawione 4. – Jakob

Odpowiedz

1

wierzę Wariant 1 jest najbliżej realizacji odniesienia w /tensorflow/models/rnn/ptb/reader.py

def ptb_iterator(raw_data, batch_size, num_steps): 
    """Iterate on the raw PTB data. 

    This generates batch_size pointers into the raw PTB data, and allows 
    minibatch iteration along these pointers. 

    Args: 
    raw_data: one of the raw data outputs from ptb_raw_data. 
    batch_size: int, the batch size. 
    num_steps: int, the number of unrolls. 

    Yields: 
    Pairs of the batched data, each a matrix of shape [batch_size, num_steps]. 
    The second element of the tuple is the same data time-shifted to the 
    right by one. 

    Raises: 
    ValueError: if batch_size or num_steps are too high. 
    """ 
    raw_data = np.array(raw_data, dtype=np.int32) 

    data_len = len(raw_data) 
    batch_len = data_len // batch_size 
    data = np.zeros([batch_size, batch_len], dtype=np.int32) 
    for i in range(batch_size): 
    data[i] = raw_data[batch_len * i:batch_len * (i + 1)] 

    epoch_size = (batch_len - 1) // num_steps 

    if epoch_size == 0: 
    raise ValueError("epoch_size == 0, decrease batch_size or num_steps") 

    for i in range(epoch_size): 
    x = data[:, i*num_steps:(i+1)*num_steps] 
    y = data[:, i*num_steps+1:(i+1)*num_steps+1] 
    yield (x, y) 

Jednak Inną opcją jest wybranie wskaźnik do macierzy danych losowo dla każdego sekwencja treningowa.

5

Zaraz będę uczyć się LSTM w TensorFlow i spróbuję zaimplementować przykład, który (na szczęście) próbuje przewidzieć szereg czasowy/numer seryjny za pomocą prostego układu matematycznego.

Ale używam inny sposób do struktury danych do szkolenia motywowane Unsupervised Learning of Video Representations using LSTMs:

LSTM Future Predictor Model

Wariant 5:

input data    label  
1,2,3,4     5,6,7,8 
2,3,4,5     6,7,8,9 
3,4,5,6     7,8,9,10 
... 

Poza tym papierze, I (próbował), aby czerpać inspirację z podanych przykładów RNN TensorFlow. Mój obecny kompletne rozwiązanie wygląda tak:

import math 
import random 
import numpy as np 
import tensorflow as tf 

LSTM_SIZE = 64 
LSTM_LAYERS = 2 
BATCH_SIZE = 16 
NUM_T_STEPS = 4 
MAX_STEPS = 1000 
LAMBDA_REG = 5e-4 


def ground_truth_func(i, j, t): 
    return i * math.pow(t, 2) + j 


def get_batch(batch_size): 
    seq = np.zeros([batch_size, NUM_T_STEPS, 1], dtype=np.float32) 
    tgt = np.zeros([batch_size, NUM_T_STEPS], dtype=np.float32) 

    for b in xrange(batch_size): 
     i = float(random.randint(-25, 25)) 
     j = float(random.randint(-100, 100)) 
     for t in xrange(NUM_T_STEPS): 
      value = ground_truth_func(i, j, t) 
      seq[b, t, 0] = value 

     for t in xrange(NUM_T_STEPS): 
      tgt[b, t] = ground_truth_func(i, j, t + NUM_T_STEPS) 
    return seq, tgt 


# Placeholder for the inputs in a given iteration 
sequence = tf.placeholder(tf.float32, [BATCH_SIZE, NUM_T_STEPS, 1]) 
target = tf.placeholder(tf.float32, [BATCH_SIZE, NUM_T_STEPS]) 

fc1_weight = tf.get_variable('w1', [LSTM_SIZE, 1], initializer=tf.random_normal_initializer(mean=0.0, stddev=1.0)) 
fc1_bias = tf.get_variable('b1', [1], initializer=tf.constant_initializer(0.1)) 

# ENCODER 
with tf.variable_scope('ENC_LSTM'): 
    lstm = tf.nn.rnn_cell.LSTMCell(LSTM_SIZE) 
    multi_lstm = tf.nn.rnn_cell.MultiRNNCell([lstm] * LSTM_LAYERS) 
    initial_state = multi_lstm.zero_state(BATCH_SIZE, tf.float32) 
    state = initial_state 
    for t_step in xrange(NUM_T_STEPS): 
     if t_step > 0: 
      tf.get_variable_scope().reuse_variables() 

     # state value is updated after processing each batch of sequences 
     output, state = multi_lstm(sequence[:, t_step, :], state) 

learned_representation = state 

# DECODER 
with tf.variable_scope('DEC_LSTM'): 
    lstm = tf.nn.rnn_cell.LSTMCell(LSTM_SIZE) 
    multi_lstm = tf.nn.rnn_cell.MultiRNNCell([lstm] * LSTM_LAYERS) 
    state = learned_representation 
    logits_stacked = None 
    loss = 0.0 
    for t_step in xrange(NUM_T_STEPS): 
     if t_step > 0: 
      tf.get_variable_scope().reuse_variables() 

     # state value is updated after processing each batch of sequences 
     output, state = multi_lstm(sequence[:, t_step, :], state) 
     # output can be used to make next number prediction 
     logits = tf.matmul(output, fc1_weight) + fc1_bias 

     if logits_stacked is None: 
      logits_stacked = logits 
     else: 
      logits_stacked = tf.concat(1, [logits_stacked, logits]) 

     loss += tf.reduce_sum(tf.square(logits - target[:, t_step]))/BATCH_SIZE 

reg_loss = loss + LAMBDA_REG * (tf.nn.l2_loss(fc1_weight) + tf.nn.l2_loss(fc1_bias)) 

train = tf.train.AdamOptimizer().minimize(reg_loss) 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 

    total_loss = 0.0 
    for step in xrange(MAX_STEPS): 
     seq_batch, target_batch = get_batch(BATCH_SIZE) 

     feed = {sequence: seq_batch, target: target_batch} 
     _, current_loss = sess.run([train, reg_loss], feed) 
     if step % 10 == 0: 
      print("@{}: {}".format(step, current_loss)) 
     total_loss += current_loss 

    print('Total loss:', total_loss) 

    print('### SIMPLE EVAL: ###') 
    seq_batch, target_batch = get_batch(BATCH_SIZE) 
    feed = {sequence: seq_batch, target: target_batch} 
    prediction = sess.run([logits_stacked], feed) 
    for b in xrange(BATCH_SIZE): 
     print("{} -> {})".format(str(seq_batch[b, :, 0]), target_batch[b, :])) 
     print(" `-> Prediction: {}".format(prediction[0][b])) 

Przykładowe wyjście to wygląda następująco:

### SIMPLE EVAL: ### 
# [input seq] -> [target prediction] 
# `-> Prediction: [model prediction] 
[ 33. 53. 113. 213.] -> [ 353. 533. 753. 1013.]) 
`-> Prediction: [ 19.74548721 28.3149128 33.11489105 35.06603241] 
[ -17. -32. -77. -152.] -> [-257. -392. -557. -752.]) 
`-> Prediction: [-16.38951683 -24.3657589 -29.49801064 -31.58583832] 
[ -7. -4. 5. 20.] -> [ 41. 68. 101. 140.]) 
`-> Prediction: [ 14.14126873 22.74848557 31.29668617 36.73633194] 
... 

Model jest LSTM-autoencoder posiadający 2 warstw każdy.

Niestety, jak widać w wynikach, model ten nie nauczy się poprawnie sekwencji.Może to być przypadek, że robię gdzieś zły błąd, lub że 1000-10000 kroków treningowych jest po prostu mało dla LSTM. Jak już powiedziałem, zaczynam także poprawnie rozumieć/używać LSTM. Ale mam nadzieję, że może to dać pewne inspiracje dotyczące realizacji.

+1

Używam obecnie opcji 2 z pewnym sukcesem. Co sprawia, że ​​kwestionuję twoje podejście, że model nie "widzi" danych w kolejności. O ile zrozumiałem, na stan wewnętrzny sieci mają wpływ wszystkie wartości, które model "widział" do tej pory. Dlatego, jeśli rozpoczniesz nową sekwencję, musisz zresetować stan wewnętrzny. W formularzu, w którym podajesz dane, model widzi wiele powtórzeń w danych. Ale mogę się mylić, nie jestem jeszcze pewien. – Jakob

+0

Dziękuję za tę wskazówkę. Nigdy nie myślałem o resetowaniu stanu dla każdej nowej sekwencji do nauki. Sprawdzę to później w tym dniu. Dodatkowo, widziałem, że popełniłem błąd w dekoderze LSTM: tu, przypadkowo używam tej samej sekwencji wejściowej co w Encoder-LSTM, która jest błędna. Chciałem tutaj użyć wyjścia ostatniej komórki LSTM (t-1) jako wejścia do bieżącej komórki (t). – bsautermeister

+0

Po prostu to sprawdzam. W powyższym kodzie stan początkowy to zero-tensor w każdej iteracji. Powinno być dobrze. Niemniej jednak nie wiem, dlaczego nadal nie uczę się niczego użytecznego ... – bsautermeister

Powiązane problemy