Tentando usar o TensorFlow para prever dados financeiros de séries temporais

10

Sou novo no ML e no TensorFlow (comecei há algumas horas atrás) e estou tentando usá-lo para prever os próximos pontos de dados em uma série temporal. Estou pegando minha opinião e fazendo isso com ela:

/----------- x ------------\
.-------------------------------.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
'-------------------------------'
     \----------- y ------------/

O que eu pensei que estava fazendo é usar x como dados de entrada e y como a saída desejada para essa entrada, para que, de 0 a 6, eu pudesse obter 1-7 (os 7 em particular). No entanto, quando executo meu gráfico com x como entrada, o que recebo é uma previsão que se parece mais com x que com y .

Aqui está o código (com base nesta postagem e nesta postagem ):

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plot
import pandas as pd
import csv

def load_data_points(filename):
    print("Opening CSV file")
    with open(filename) as csvfile:
        print("Creating CSV reader")
        reader = csv.reader(csvfile)
        print("Reading CSV")
        return [[[float(p)] for p in row] for row in reader]

flatten = lambda l: [item for sublist in l for item in sublist]

data_points = load_data_points('dataset.csv')

print("Loaded")

prediction_size = 10
num_test_rows = 1
num_data_rows = len(data_points) - num_test_rows
row_size = len(data_points[0]) - prediction_size

# Training data
data_rows = data_points[:-num_test_rows]
x_data_points = np.array([row[:-prediction_size] for row in data_rows]).reshape([-1, row_size, 1])
y_data_points = np.array([row[prediction_size:] for row in data_rows]).reshape([-1, row_size, 1])

# Test data
test_rows = data_points[-num_test_rows:]
x_test_points = np.array([[data_points[0][:-prediction_size]]]).reshape([-1, row_size, 1])
y_test_points = np.array([[data_points[0][prediction_size:]]]).reshape([-1, row_size, 1])

tf.reset_default_graph()

num_hidden = 100

x = tf.placeholder(tf.float32, [None, row_size, 1])
y = tf.placeholder(tf.float32, [None, row_size, 1])

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=num_hidden, activation=tf.nn.relu)
rnn_outputs, _ = tf.nn.dynamic_rnn(basic_cell, x, dtype=tf.float32)

learning_rate = 0.001

stacked_rnn_outputs = tf.reshape(rnn_outputs, [-1, num_hidden])
stacked_outputs = tf.layers.dense(stacked_rnn_outputs, 1)
outputs = tf.reshape(stacked_outputs, [-1, row_size, 1])

loss = tf.reduce_sum(tf.square(outputs - y))
optimizer = tf.train.AdamOptimizer(learning_rate)
training_op = optimizer.minimize(loss)

init = tf.global_variables_initializer()

iterations = 1000

with tf.Session() as sess:
    init.run()
    for ep in range(iterations):
        sess.run(training_op, feed_dict={x: x_data_points, y: y_data_points})
        if ep % 100 == 0:
            mse = loss.eval(feed_dict={x: x_data_points, y: y_data_points})
            print(ep, "\tMSE:", mse)

    y_pred = sess.run(stacked_outputs, feed_dict={x: x_test_points})

    plot.rcParams["figure.figsize"] = (20, 10)

    plot.title("Actual vs Predicted")
    plot.plot(pd.Series(np.ravel(x_test_points)), 'g:', markersize=2, label="X")
    plot.plot(pd.Series(np.ravel(y_test_points)), 'b--', markersize=2, label="Y")
    plot.plot(pd.Series(np.ravel(y_pred)), 'r-', markersize=2, label="Predicted")
    plot.legend(loc='upper left')
    plot.xlabel("Time periods")
    plot.tick_params(
        axis='y',
        which='both',
        left='off',
        right='off',
        labelleft='off')
    plot.show()

O resultado mostrado no gráfico abaixo é uma previsão que segue x , em vez de ser deslocada para a esquerda (e incluindo os pontos previstos à direita), como deve ser a aparência de y . Obviamente, o desejo é que a linha vermelha seja o mais próxima possível da azul.

gráfico

Não tenho ideia do que estou fazendo com tudo isso, então, por favor, ELI5.

Ah, também, meus pontos de dados são números bastante pequenos (ordem de 0,0001). Se eu não os multiplicar por, digamos, 1000000, os resultados são tão pequenos que a linha vermelha fica quase plana na parte inferior do gráfico. Por quê? Suponho que seja por causa da quadratura na função de condicionamento físico. Os dados devem ser normalizados antes do uso e, em caso afirmativo, para quê? 0-1? Se eu usar:

normalized_points = [(p - min_point) / (max_point - min_point) for p in data_points]

minha previsão flutua mais rapidamente à medida que avança: flutuante

Edit: Eu estou sendo burro e apenas dando um exemplo para aprender, não 500, não sou? Então, eu deveria dar várias amostras de 500 pontos, certo?

Isvara
fonte
Eu tenho o mesmo problema - ou seja, que a saída do RNN segue a entrada (X) e não o destino (Y). Estranhamente, quando a entrada para o mesmo RNN é uma série sine simples aprende corretamente, ou seja, prevê a Y.
Ryszard Cetnarski
Por favor, compartilhe seu arquivo dataset.csv
Ashwin Tomar

Respostas:

2

Ok, vamos parte por parte. Há algumas partes aqui em que você não leva em consideração o viés na sua rede.

Escolhendo suas entradas e saídas

Se o vetor 0-6 for determinado, realmente não há necessidade de gerar 1-7. O 1-6 já é conhecido e a adição de saídas adicionais adicionará complexidade ao seu modelo. A menos que você tenha quantidades substanciais de dados, deseje manter o modelo o mais simples possível para obter um bom desempenho. Assim, eu produziria um neurônio simples com um valor contínuo. Você pode usar o RMSE como sua função de perda com uma saída de regressão da sua rede neural.

Além disso, você deve suplementar as amostras que você coloca em seu espaço de entrada com algumas informações adicionais que possam parecer conter informações sobre a linha de tendência. Por exemplo, se eu tivesse 2 produtos diferentes, bitcoin e ouro, e seu vetor de entrada fosse o mesmo, eu poderia esperar que o ouro tivesse muito pouca flutuação, mas o bitcoin tivesse uma flutuação muito alta.

Seus recursos de entrada na sua rede contêm todas as informações com as quais sua rede aprenderá. Portanto, você quer ter certeza de que está fornecendo informações suficientes para ter uma previsão significativa.

O aprendizado profundo requer muita informação

Você precisará de aproximadamente 100.000 instâncias. Cada instância é um conjunto de recursos. Estes devem ser desenhados de forma independente e de forma que sejam distribuídos de forma idêntica. Em outras palavras, você deseja obter várias linhas de tendência de uma fonte variada de dados com a qual deseja usar sua rede e, em seguida, irá desenhar aleatoriamente de 0 a 6 pontos, que são seus recursos, e 7, que será seu rótulo.

Considere a distribuição de dados que você está tentando aprender. Se você deseja que sua rede classifique gatos / cães, é necessário fornecer uma ampla variedade de cães e gatos com aparência diferente, para que a rede possa identificar a variação existente em ambas as classes. Se você restringir demais a fonte de dados, ela terá um alto viés e não será generalizada para novos dados que você fornecerá posteriormente.


Experimente estas coisas e deixe-nos saber o que acontece.

JahKnows
fonte
2

Talvez a previsão seja a mesma que a entrada reflita que sua rede está com pouca formação. O chamado modelo de persistência para previsão de séries temporais é frequentemente usado como base para outros modelos. O modelo de persistência está usando a última observação como uma previsão. É simples e geralmente produz uma precisão razoável. Meu palpite é que sua rede começa aprendendo o modelo de persistência, e somente se você treiná-lo mais e for possível fazer um modelo melhor, ele aprenderá - mas isso requer muito treinamento.

Ryszard Cetnarski
fonte