2016-03-12 39 views
14

Attualmente sto cercando di creare un modello semplice per la previsione delle serie temporali. L'obiettivo sarebbe quello di addestrare il modello con una sequenza in modo che il modello sia in grado di prevedere i valori futuri.Come addestrare un RNN con celle LSTM per la previsione delle serie temporali

Sto usando le celle tensorflow e lstm per farlo. Il modello viene addestrato con backpropagation troncato nel tempo. La mia domanda è come strutturare i dati per la formazione.

Per esempio supponiamo che vogliamo imparare la sequenza indicata:

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

E noi srotolare la rete per num_steps=4.

Opzione 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 
... 

Opzione 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 
... 

Opzione 3

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

Opzione 4

Qualsiasi aiuto sarebbe apprezzato.

+0

tra le opzioni elencate, mi sembra che l'opzione 3 sarebbe l'opzione più ragionevole se si può effettivamente supporre che 4 valori del passato siano sufficienti, ad un buon grado di approssimazione, per predire il valore attuale (quindi è più circa i dati, rispetto a un metodo particolare che usi per la previsione) .. –

+0

Ovviamente io uso più degli ultimi 4 valori, questo è solo un piccolo esempio per una più semplice dimostrazione. Inoltre sentiti libero di suggerire un'altra opzione rispetto ai 4 presentati. – Jakob

risposta

1

credo opzione 1 è più vicino alla implementazione di riferimento in /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) 

Tuttavia, un'altra opzione è quella di selezionare un puntatore nel vostro array di dati in modo casuale per ogni sequenza di allenamento.

5

Sto per apprendere gli LSTM in TensorFlow e provare a implementare un esempio che (fortunatamente) cerca di prevedere alcune serie temporali/serie di numeri generati da una semplice operazione matematica.

Ma io sto usando un modo diverso per strutturare i dati per la formazione, motivato da Unsupervised Learning of Video Representations using LSTMs:

LSTM Future Predictor Model

Opzione 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 
... 

Accanto a questo lavoro, ho (provato) per trarre ispirazione dagli esempi forniti da TensorFlow RNN. Il mio attuale soluzione completa si presenta così:

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])) 

uscita Esempio di questo è simile al seguente:

### 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] 
... 

Il modello è un LSTM-autoencoder avere 2 strati ciascuno.

Sfortunatamente, come si può vedere nei risultati, questo modello non apprende correttamente la sequenza.Potrei essere il caso che sto solo facendo un brutto errore da qualche parte, o che i 1000-10000 passaggi di formazione sono solo un modo per pochi per un LSTM. Come ho detto, sto anche iniziando a capire/utilizzare correttamente gli LSTM. Ma spero che questo possa darti qualche spunto per l'implementazione.

+1

Attualmente sto usando l'opzione 2 con un certo successo. Ciò che mi mette in dubbio è che il modello non "vede" i dati in ordine. Per quanto ho capito, lo stato interno della rete è influenzato da tutti i valori che il modello ha "visto" finora. Pertanto, se si avvia una nuova sequenza, è necessario ripristinare lo stato interno. Nel modulo che si alimentano i dati, il modello vede molta ripetizione nei dati. Ma potrei sbagliarmi, non sono ancora sicuro. – Jakob

+0

Grazie per questo suggerimento. Non ho mai pensato di reimpostare lo stato per ogni nuova sequenza da imparare. Lo controllerò più tardi questo giorno. Inoltre, ho visto che ho commesso un errore nel Decoder-LSTM: qui, accidentalmente utilizzo la stessa sequenza di input dell'encoder-LSTM, che è sbagliato. Quello che volevo fare qui è usare l'output dell'ultima cella LSTM (t-1) come input della cella corrente (t). – bsautermeister

+0

Ho appena controllato. Nel codice pubblicato sopra, lo stato iniziale è un tensore di zero in ogni iterazione. Quindi, dovrebbe andare bene. Tuttavia, non so perché non stia ancora imparando nulla di utile ... – bsautermeister