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.
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:
Edycja: Jestem głupi i podaję tylko jeden przykład do nauki, a nie 500, prawda? Powinienem dawać wiele próbek 500-punktowych, prawda?