Intentar usar TensorFlow para predecir datos de series de tiempo financieras

10

Soy nuevo en ML y TensorFlow (comencé hace unas horas), y estoy tratando de usarlo para predecir los próximos puntos de datos en una serie de tiempo. Estoy tomando mi entrada y haciendo esto con ella:

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

Lo que pensé que estaba haciendo es usar x como datos de entrada e y como salida deseada para esa entrada, de modo que dado 0-6 podría obtener 1-7 (el 7 en particular). Sin embargo, cuando ejecuto mi gráfico con x como entrada, lo que obtengo es una predicción que se parece más a x que a y .

Aquí está el código (basado en esta publicación y esta publicación ):

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

El resultado que se muestra en el gráfico a continuación es una predicción que sigue a x , en lugar de desplazarse hacia la izquierda (e incluir los puntos predichos a la derecha) como debería parecerse a y . Obviamente, el deseo es que la línea roja esté lo más cerca posible de la azul.

grafico

No tengo idea de lo que estoy haciendo con todo esto, así que por favor ELI5.

Ah, también, mis puntos de datos son números bastante pequeños (orden de 0.0001). Si no los multiplico por, digamos, 1000000, los resultados son tan pequeños que la línea roja es casi plana en la parte inferior del gráfico. ¿Por qué? Supongo que se debe a la cuadratura en la función fitness. ¿Deberían normalizarse los datos antes de su uso y, en caso afirmativo, a qué? 0-1? Si yo uso:

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

mi predicción fluctúa más salvajemente a medida que avanza: fluctuante

Editar: Estoy siendo tonto y solo le doy un ejemplo para aprender, no 500, ¿no? Entonces debería darle varias muestras de 500 puntos, ¿verdad?

Isvara
fuente
Tengo el mismo problema, es decir, que la salida del RNN sigue la entrada (X) y no el objetivo (Y). Curiosamente, cuando la entrada al mismo RNN es una serie seno simple que aprende correctamente, es decir, predice la Y.
Ryszard Cetnarski
Comparta su archivo dataset.csv
Ashwin Tomar

Respuestas:

2

Ok, vamos parte por parte. Hay bastantes partes aquí donde no se tiene en cuenta el sesgo en su red.

Elegir sus entradas y salidas

Si se determina el vector 0-6, realmente no hay necesidad de generar 1-7. El 1-6 ya es conocido y agregar salidas adicionales solo agregará complejidad a su modelo. A menos que tenga cantidades sustanciales de datos, desea mantener su modelo lo más simple posible para obtener un buen rendimiento. Por lo tanto, generaría una neurona simple con un valor continuo. Puede usar RMSE como su función de pérdida con una salida de regresión de su red neuronal.

Además, debe complementar las muestras que coloca en su espacio de entrada con información adicional que podría pensar que contendría información sobre la línea de tendencia. Por ejemplo, si tuviera 2 productos diferentes, bitcoin y oro, y su vector de entrada fuera el mismo, podría esperar que el oro tuviera muy poca fluctuación, pero el bitcoin tendría una fluctuación muy alta.

Sus funciones de entrada a su red contienen toda la información de la que aprenderá su red. Por lo tanto, debe asegurarse de proporcionar información suficiente para tener una predicción significativa.

El aprendizaje profundo requiere mucha información

Necesitará aproximadamente más de 100,000 instancias. Cada instancia es un conjunto de características. Estos deben dibujarse de forma independiente y de manera que estén distribuidos de forma idéntica. En otras palabras, desea obtener múltiples líneas de tendencia de una fuente variada de datos con los que desea utilizar su red y luego dibujará aleatoriamente 0-6 puntos, esas son sus características y 7, que serán su etiqueta.

Considere la distribución de datos que está tratando de aprender. Si desea que su red clasifique gatos / perros, debe proporcionar una amplia gama de gatos y perros de aspecto diferente para que la red pueda identificar la variación que existe en ambas clases. Si restringe demasiado la fuente de datos, tendrá un alto sesgo y no se generalizará a datos novedosos que luego ingresará.


Pruebe estas cosas y díganos qué sucede.

JahKnows
fuente
2

Tal vez la predicción sea la misma que la entrada refleja que su red está poco capacitada. El llamado modelo de persistencia para la predicción de series de tiempo, a menudo se usa como línea de base para otros modelos. El modelo de persistencia está utilizando la última observación como predicción. Es simple y a menudo produce una precisión razonable. Supongo que su red comienza aprendiendo el modelo de persistencia, y solo si lo entrena más y es posible hacer un mejor modelo, lo aprenderá, pero esto requiere mucho entrenamiento.

Ryszard Cetnarski
fuente