Bei Daten, die mit kontinuierlichen Werten wie Zeitreihendaten korreliert zu sein scheinen, speichert RNN die Eingaben nacheinander, hält die Statuswerte im Netzwerk und gibt die endgültige Ausgabe aus, nachdem alle Eingaben abgeschlossen sind. Herr.
Zeitreihendaten aus der realen Welt sind zu verrauscht, und sprachbasierte Daten wie die Tutorials von Tensorflow sind als "Zeitreihen" schwer vorstellbar. Und ich kann die Spezifikationen der RNNCell-Klasse nicht erfassen, also werde ich aufgeben und ein experimentell einfaches Selbst-Feedback-Modell erstellen.
Chaos ist berühmt für seinen Schmetterlingseffekt, sieht aber auf den ersten Blick zufällig aus, ist aber tatsächlich nützlich, um Ereignisse zu analysieren, die so etwas wie ein bestimmtes Gesetz haben.
Ich werde als Beispiel die Logistikkarte verwenden, die am einfachsten persönlich zu verstehen ist.
Es gibt eine supereinfache Formel, mit der der Wert von $ x (t) $ zu einem Zeitpunkt $ t $ aus dem Wert des vorherigen Zeitpunkts $ x (t-1) $ und dem eindeutigen Parameter $ r $ abgeleitet werden kann.
x_t = rx_{t-1}(1-x_{t-1})
Oder wenn Sie den nächsten Zeitpunkt vorhersagen möchten, wird es so sein.
x_{t+1} = rx_t(1-x_t)
$ x $ ist 0 ≤ x ≤ 1
$ r $ ist 0 ≤ r ≤ 4
Irgendwo in diesem Chaos hat diese Formel einen enormen Anstieg des Wertes, den $ x $ von etwa 3,6 annehmen kann.
Wenn Sie $ x $ als Zeitreihendaten betrachten, ist dies eine wunderbare Zufallszahl. Wenn Sie es mit einem völlig zufälligen Wert in chronologischer Reihenfolge vergleichen, werden Sie den Unterschied nur kennen, wenn Sie etwas sagen.
Das Tolle am Chaos ist, dass wenn Sie $ x_t $ und $ x_ {t + 1} $ streuen, Sie eine coole Form (Fraktal) erhalten. Der Unterschied ist auch im Vergleich zum Zufallswert deutlich. Es scheint bei $ r $ zu beginnen. Ah schön.
Nun, es ist so ein schönes Chaos, aber selbst wenn es zufällig aussieht, scheint es leicht vorherzusagen, ob Sie die Regeln befolgen. Es ist jedoch verrückt. Dies ist der Grund, warum Chaos Chaos ist, aber es ist schwierig, kontinuierliche Daten vorherzusagen, da selbst ein geringfügiger Unterschied in den Anfangswerten und Parametern zu völlig unterschiedlichen Werten führt.
Vergleichen wir es angemessen.
generator.py
def logistic(r, t_first, num_steps):
array = []
for i in range(num_steps):
if "t" not in locals():
t = t_first
else:
t = tt
tt = r*t*(1-t)
array.append(tt)
return array
initial = 0.5
data1 = logistic(3.91, initial, 100)
data2 = logistic(3.9100000000001, initial, 100)
data3 = logistic(3.91, initial+0.0000001, 100)
Selbst wenn der Fehler des geschätzten Wertes eine ultrahohe Genauigkeit von 1e-10% oder weniger ist, ist es schwierig, an 60 Datenzielen vorherzusagen.
** Umgekehrt können Sie, wenn Sie zurückgehen, um nach $ r $ zu suchen, einige kurzfristige Vorhersagen treffen. ** ** **
logistic_rnn.py
import os, sys
import numpy as np
import tensorflow as tf
num_steps = 1 # Number of inputs. logistic map only needs a current input
batch_size = 100
epoch_size = 10000
initial = 0.5 # 0 <= x <= 1: to generate data
L = 0.01 # learing rate
PRE_STEPS = 30 # Number of predictions. how far do you want to predict?
N_HIDDEN = 30 # Hidden nodes
'''
generate data
'''
def logistic(r, t_first, num_steps):
array = []
for i in range(num_steps):
if "t" not in locals():
t = t_first
else:
t = tt
tt = r*t*(1-t)
array.append(tt)
return array
def logmap_iterator(raw_data, batch_size, num_steps, prediction_steps):
raw_data = np.array(raw_data)
data_len = len(raw_data)
batch_len = data_len // batch_size
data = np.zeros([batch_size, batch_len])
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+1)*num_steps:(i+1)*num_steps+(prediction_steps)]
yield(x, y)
raw_data = logistic(3.91, initial, num_steps*batch_size*epoch_size)
'''
mini-RNN Model
'''
x = tf.placeholder("float", [None, num_steps])
y = tf.placeholder("float", [None, PRE_STEPS])
weights = {
'hidden': tf.get_variable("hidden", shape=[1, N_HIDDEN], initializer=tf.truncated_normal_initializer(stddev=0.1)),
'out': tf.get_variable("out", shape=[N_HIDDEN, 1], initializer=tf.truncated_normal_initializer(stddev=0.1))
}
biases = {
'hidden': tf.get_variable("b_hidden", shape=[N_HIDDEN], initializer=tf.truncated_normal_initializer(stddev=0.1)),
'out': tf.get_variable("b_out", shape=[1], initializer=tf.truncated_normal_initializer(stddev=0.1))
}
def simple_reg(x, _weights, _biases, K = 1.0):
with tf.variable_scope("weight"):
h1 = tf.matmul(x, _weights['hidden']) + _biases['hidden']
h1 = tf.nn.dropout(tf.nn.sigmoid(h1), K)
o1 = tf.matmul(h1, _weights['out']) + _biases['out']
with tf.variable_scope("weight", reuse=True):
h2 = tf.matmul(o1, _weights['hidden']) + _biases['hidden']
h2 = tf.nn.dropout(tf.nn.sigmoid(h2), K)
o2 = tf.matmul(h2, _weights['out']) + _biases['out']
o = tf.concat(1, [o1, o2])
def more_step(predicted_value, o):
with tf.variable_scope("weight", reuse=True):
h = tf.matmul(predicted_value, _weights['hidden']) + _biases['hidden']
h = tf.nn.dropout(tf.nn.sigmoid(h), K)
o_v = tf.matmul(h, _weights['out']) + _biases['out']
o = tf.concat(1, [o, o_v])
return o, o_v
for i in range(PRE_STEPS-2):
if "o_v" not in locals():
o, o_v = more_step(o2, o)
else:
print o_v
o, o_v = more_step(o_v, o)
return o, o1
o, o1 = simple_reg(x, weights, biases)
z = tf.split(1, PRE_STEPS, y)
z = z[0]
cost = tf.reduce_sum(tf.square(o1 - z))
optimizer = tf.train.AdamOptimizer(L).minimize(cost)
init = tf.initialize_all_variables()
with tf.Session() as sess:
saver = tf.train.Saver()
sess.run(init)
for step in range(10):
gen = logmap_iterator(raw_data, batch_size, num_steps, PRE_STEPS)
for i in range(epoch_size-batch_size):
s, a = gen.next()
training = sess.run([optimizer, o, cost], {x:s, y:a})
if i % 100 == 0:
print "i", i, "cost", training[2]
print "initial input", s[0][:5]
print "pred", training[1][0][:5]
print "answ", a[0][:5]
if i % 2000 == 2000:
L = L/2
save_path = saver.save(sess, "dynamic_model.ckpt")
Die Form des Modells sieht so aus. Ich habe den Illustrator zum ersten Mal seit langer Zeit berührt ...
Die Anzahl der ausgeblendeten Ebenen ist angemessen, und der Grund für die Verwendung von $ sigmoid $ ist einfach, dass die Ausgabe zwischen 0 und 1 liegt. Die Eingabe ist nur eine Zahl, da es keinen anderen Sinn als $ x_t $ macht, $ x_ {t + 1} $ zu finden. Daher gibt es keine gemeinsame Nutzung von Statuswerten innerhalb des Netzwerks. (Es ist ein Geheimnis, dass der Verlust nicht gut abnahm, als der Input erhöht wurde) Ich glaube nicht, dass dies offiziell RNN genannt werden kann, aber es ist ein Feedloop.
(Tatsächlich schätzt es $ r $ aus aufeinanderfolgenden $ \ in x_n $ und gibt $ x_ {n + 1} $ aus und fügt $ x_ {n + 1} $ der Eingabe erneut zu $ x_ {n + ... hinzu. Ich denke, es wäre genauer, es auf} $ zu setzen, aber ich konnte Tensorflows RNN Cell
nicht gut verwenden.)
Mit den Ergebnissen war ich vorerst persönlich zufrieden.
Frühes Lernen
Schließlich wird sich der Verlust um "1e-5" beruhigen, und die beste Vorhersage wird so aussehen.
Ich habe dies nicht für andere chaotische Gleichungen wie Lorenz versucht, daher bin ich mir nicht sicher.
Recommended Posts