Próba użycia TensorFlow do przewidywania danych szeregów czasowych finansowych


10

Jestem nowy w ML i TensorFlow (zacząłem kilka godzin temu) i próbuję go wykorzystać do przewidywania kolejnych punktów danych w szeregu czasowym. Biorę swój wkład i robię to przy tym:

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

Myślałem, że robię to, używając x jako danych wejściowych i y jako pożądanego wyniku dla tego wejścia, tak więc biorąc pod uwagę 0-6, mógłbym otrzymać 1-7 (w szczególności 7). Jednak kiedy uruchamiam mój wykres z x jako wejściem, otrzymuję prognozę, która wygląda bardziej jak x niż y .

Oto kod (oparty na tym poście i tym poście ):

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

Wynik pokazany na poniższym wykresie jest prognozą, która następuje po x , zamiast być przesuniętym w lewo (i włączając przewidywane punkty po prawej), tak jak powinno być przypominać y . Oczywiście pragnienie jest, aby czerwona linia była jak najbliżej niebieskiej, jak to możliwe.

wykres

Nie mam pojęcia, co z tym wszystkim robię, więc proszę, ELI5.

Aha, moje punkty danych to dość małe liczby (rzędu 0,0001). Jeśli nie pomnożę ich przez, powiedzmy, 1000000, wyniki będą tak małe, że czerwona linia będzie prawie płaska na dole wykresu. Dlaczego? Zgaduję, że to z powodu kwadratu w funkcji fitness. Czy dane powinny zostać znormalizowane przed użyciem, a jeśli tak, to do czego? 0-1? Jeśli użyję:

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

moje prognozy zmieniają się bardziej gwałtownie w miarę postępu: wahać się

Edycja: Jestem głupi i podaję tylko jeden przykład do nauki, a nie 500, prawda? Powinienem dawać wiele próbek 500-punktowych, prawda?


Mam ten sam problem - mianowicie, że wyjście RNN podąża za wejściem (X), a nie celem (Y). O dziwo, gdy wejście do tego samego RNN jest prostą serią sinusoidalną, uczy się poprawnie, tj. Przewiduje Y.
Ryszard Cetnarski

Udostępnij swój plik dataset.csv
Ashwin Tomar

Odpowiedzi:


2

Ok chodźmy część po części. Jest tu sporo części, w których nie bierzesz pod uwagę stronniczości w swojej sieci.

Wybór danych wejściowych i wyjściowych

Jeśli wektor 0-6 zostanie określony, naprawdę nie ma potrzeby generowania 1-7. 1-6 jest już znane, a dodanie dodatkowych danych wyjściowych tylko zwiększy złożoność modelu. O ile nie dysponujesz znaczną ilością danych, chcesz maksymalnie uprościć swój model, aby uzyskać dobrą wydajność. Tak więc wyprowadziłbym prosty neuron o wartości ciągłej. Możesz użyć RMSE jako funkcji utraty z wyjściem regresji z sieci neuronowej.

Dodatkowo powinieneś uzupełnić próbki, które umieściłeś w swojej przestrzeni wejściowej o dodatkowe informacje, które według ciebie mogłyby zawierać informacje o linii trendu. Na przykład, gdybym miał 2 różne produkty, bitcoiny i złoto, a ich wektor wejściowy byłby taki sam, mógłbym oczekiwać, że złoto będzie miało bardzo małe wahania, ale bitcoiny będą miały bardzo duże wahania.

Funkcje wprowadzania danych do sieci zawierają wszystkie informacje, z których Twoja sieć się uczy. Dlatego chcesz się upewnić, że dostarczasz wystarczające informacje, aby mieć sensowną prognozę.

Głębokie uczenie się wymaga danych

Będziesz potrzebował ponad 100 000 instancji. Każde wystąpienie jest zestawem funkcji. Powinny być rysowane niezależnie i tak, aby były identycznie rozmieszczone. Innymi słowy, chcesz uzyskać wiele linii trendu z różnych źródeł danych, z którymi chcesz korzystać z sieci, a następnie losowo wybierzesz 0-6 punktów, czyli twoje cechy, i 7, które będą twoją etykietą.

Zastanów się nad dystrybucją danych, której próbujesz się nauczyć. Jeśli chcesz, aby twoja sieć klasyfikowała koty / psy, musisz podać szeroki zakres różnych wyglądających kotów i psów, aby sieć mogła zidentyfikować wariancję występującą w obu tych klasach. Jeśli nadmiernie ograniczysz źródło danych, będzie ono miało duże odchylenie i nie uogólni na nowe dane, które później będziesz w nim zasilał.


Wypróbuj te rzeczy i daj nam znać, co się stanie.


2

Być może przewidywanie jest takie samo jak dane wejściowe, odzwierciedla to, że twoja sieć jest niedoświadczona. Tak zwany model trwałości do prognozowania szeregów czasowych jest często używany jako podstawa dla innych modeli. Model trwałości wykorzystuje ostatnią obserwację jako prognozę. Jest prosty i często zapewnia odpowiednią dokładność. Domyślam się, że twoja sieć zaczyna się od nauki modelu trwałości i tylko jeśli trenujesz go więcej i możliwe jest stworzenie lepszego modelu, nauczy się go - ale to wymaga dużo szkolenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.