具有固定步长输出误差的 TensorFlow RNN 模型
TensorFlow RNN-Model with fixed step output error
我开始了一个非常简单的 RNN 项目来巩固我在 TF 方面的知识,基本上是一个使用 LSTM 和 TF 的简单序列生成器。该项目只是一个多对一的序列生成,输入是一个 4 整数 window,输出每个 window 只有一个浮点数。输入的最小数量是 1,最大数量是 61,所以我可以从 61 开始预测。我刚刚使用了一批所有输入,其形状为 [58,4,1],输出形状为 [58,1]。为了更好地可视化,输入和输出已写在下面。
Inputs Labels
[[[ 1],[ 2],[ 3],[ 4]], -------> [[0.0493],
[[ 2],[ 3],[ 4],[ 5]], -------> [0.0634],
[[ 3],[ 4],[ 5],[ 6]], -------> [0.0773],
[[ 4],[ 5],[ 6],[ 7]], -------> [0.0909],
.. .. .. .. -------> ... ,
[[55],[56],[57],[58]], -------> [0.5503],
[[56],[57],[58],[59]], -------> [0.5567],
[[57],[58],[59],[60]], -------> [0.5630],
[[58],[59],[60],[61]]] -------> [0.5693]]
训练部分进行得非常顺利,我可以在 500 个时期内达到大约 0.991 的准确度,但是当我尝试预测从 61 到 118 的某些值时,输出对于所有预测值都有一个固定的下降幅度,但不知何故正确的行为。
因为这个项目的目的只是为了学习基础知识,所以我决定使用TF中最简单的功能,所以seq2seq
设施被搁置了。 RNN的代码写在下面
def build_lstm(cell_lengh, cell_depth, batch_size, keep_prob):
def lstm_row(cell_length, keep_prob):
cell_row = tf.contrib.rnn.BasicLSTMCell(cell_lengh)
cell_row = tf.contrib.rnn.DropoutWrapper(cell_row, keep_prob)
return cell_row
cell = tf.contrib.rnn.MultiRNNCell([lstm_row(cell_lengh, keep_prob) for _ in range(cell_depth)])
initial_state = cell.zero_state(batch_size, tf.float32)
return cell, initial_state
tf.reset_default_graph()
inputs = tf.placeholder(tf.float32, [None, feature_length, 1], name='inputs')
labels = tf.placeholder(tf.float32, [None, output_length], name='labels')
keep_prob = tf.placeholder(tf.float32, name='kpprob')
lstm_cell, initial_state = build_lstm(40, 2, batch_size=batch_size, keep_prob=keep_prob)
lstm_output, final_state = tf.nn.dynamic_rnn(lstm_cell, inputs, initial_state=initial_state)
lstm_outout_seq = lstm_output[:,-1,:]
dense_0 = tf.layers.dense(inputs=lstm_outout_seq, units=120, activation=tf.nn.relu)
dropout_0 = tf.layers.dropout(dense_0, rate=0.7)
with tf.variable_scope('sigmoid'):
W = tf.Variable(tf.truncated_normal((120, 1), stddev=0.1), name='weights')
b = tf.Variable(tf.zeros(1), name='bias')
logits = tf.matmul(dropout_0, W) + b
output = tf.nn.sigmoid(logits, name='output')
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=labels))
correct_predictions = tf.abs(output - labels)
total_correct = tf.ones_like(correct_predictions)
accuracy = tf.reduce_mean(total_correct - correct_predictions)
learning_rate = tf.placeholder(tf.float32, name='learning_rate')
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
l_rate = 0.001
epochs = 500
kp_prob = 0.7
with tf.Session() as session:
session.run(tf.global_variables_initializer())
for e in range(epochs):
new_state = session.run([initial_state])
feeder = {
inputs: wnd_x,
labels: wnd_y_scl,
keep_prob: kp_prob,
learning_rate: l_rate,
initial_state: new_state
}
session_loss,
session_accuracy,
session_output, _,
last_state = session.run([loss, accuracy, output,
optimizer, final_state], feed_dict=feeder)
print('Epoch {0}/{1}:\t'.format(e, epochs),
'training loss {0}\t'.format(session_loss),
'accuracy {0}\t'.format(session_accuracy))
new_state = session.run([initial_state])
feeder = {
inputs: unseen_data_rsp,
keep_prob: 1.0,
initial_state: new_state
}
session_output = session.run([output], feed_dict=feeder)
如前所述,在推理阶段,预测已固定下降,但不知何故具有正确的行为,即曲线的导数随时间步长正确变化。
在训练阶段我有以下输出:
Epoch 999/1000: training loss = 0.5913468599319458 | accuracy = 0.9909629225730896
Input Label Output
[[ 1],[ 2],[ 3],[ 4]] --> [0.0493] ... [0.0591]
[[ 2],[ 3],[ 4],[ 5]] --> [0.0634] ... [0.0802]
[[ 3],[ 4],[ 5],[ 6]] --> [0.0773] ... [0.0777]
[[ 4],[ 5],[ 6],[ 7]] --> [0.0909] ... [0.1035]
.. .. .. .. ... ... ...
[[55],[56],[57],[58]] --> [0.5503] ... [0.5609]
[[56],[57],[58],[59]] --> [0.5567] ... [0.5465]
[[57],[58],[59],[60]] --> [0.5630] ... [0.5543]
[[58],[59],[60],[61]] --> [0.5693] ... [0.5614]
在推理阶段我有以下输出:
Input Prediction
[[ 58],[ 59],[ 60],[ 61]] --> [0.4408]
[[ 59],[ 60],[ 61],[ 62]] --> [0.4459]
[[ 60],[ 61],[ 62],[ 63]] --> [0.4510]
[[ 61],[ 62],[ 63],[ 64]] --> [0.4559]
... ... ... ... ... ...
[[112],[113],[114],[115]] --> [0.6089]
[[113],[114],[115],[116]] --> [0.6101]
[[114],[115],[116],[117]] --> [0.6113]
[[115],[116],[117],[118]] --> [0.6124]
如您所见,推理的第一个输入与训练的最后一个输入相同。我在这里不明白的是为什么相同的输入会给我 2 个不同的输出,以及为什么这些输出有一个固定的降压,大约 0.11。谢谢你们的帮助,对于冗长的文字感到抱歉,我可以根据要求缩短它。
在推理过程中,您正在重置状态。所以你在同一个输入上得到两个不同的值,因为在这两种情况下网络的状态是不同的。
要在预测后保持状态,您需要执行以下操作:
#iterate for each prediction {
feeder = {
inputs: unseen_data_rsp,
keep_prob: 1.0,
initial_state: last_state
}
session_output, last_state = session.run([output,final_state], feed_dict=feeder)
}
另外,为了通过推理的第一个输入准确地获得训练结果,您需要首先呈现所有训练示例,以确保您以正确的状态开始推理。另一种方法是保存网络状态,然后您可以在预测期间重复使用。
我开始了一个非常简单的 RNN 项目来巩固我在 TF 方面的知识,基本上是一个使用 LSTM 和 TF 的简单序列生成器。该项目只是一个多对一的序列生成,输入是一个 4 整数 window,输出每个 window 只有一个浮点数。输入的最小数量是 1,最大数量是 61,所以我可以从 61 开始预测。我刚刚使用了一批所有输入,其形状为 [58,4,1],输出形状为 [58,1]。为了更好地可视化,输入和输出已写在下面。
Inputs Labels
[[[ 1],[ 2],[ 3],[ 4]], -------> [[0.0493],
[[ 2],[ 3],[ 4],[ 5]], -------> [0.0634],
[[ 3],[ 4],[ 5],[ 6]], -------> [0.0773],
[[ 4],[ 5],[ 6],[ 7]], -------> [0.0909],
.. .. .. .. -------> ... ,
[[55],[56],[57],[58]], -------> [0.5503],
[[56],[57],[58],[59]], -------> [0.5567],
[[57],[58],[59],[60]], -------> [0.5630],
[[58],[59],[60],[61]]] -------> [0.5693]]
训练部分进行得非常顺利,我可以在 500 个时期内达到大约 0.991 的准确度,但是当我尝试预测从 61 到 118 的某些值时,输出对于所有预测值都有一个固定的下降幅度,但不知何故正确的行为。
因为这个项目的目的只是为了学习基础知识,所以我决定使用TF中最简单的功能,所以seq2seq
设施被搁置了。 RNN的代码写在下面
def build_lstm(cell_lengh, cell_depth, batch_size, keep_prob):
def lstm_row(cell_length, keep_prob):
cell_row = tf.contrib.rnn.BasicLSTMCell(cell_lengh)
cell_row = tf.contrib.rnn.DropoutWrapper(cell_row, keep_prob)
return cell_row
cell = tf.contrib.rnn.MultiRNNCell([lstm_row(cell_lengh, keep_prob) for _ in range(cell_depth)])
initial_state = cell.zero_state(batch_size, tf.float32)
return cell, initial_state
tf.reset_default_graph()
inputs = tf.placeholder(tf.float32, [None, feature_length, 1], name='inputs')
labels = tf.placeholder(tf.float32, [None, output_length], name='labels')
keep_prob = tf.placeholder(tf.float32, name='kpprob')
lstm_cell, initial_state = build_lstm(40, 2, batch_size=batch_size, keep_prob=keep_prob)
lstm_output, final_state = tf.nn.dynamic_rnn(lstm_cell, inputs, initial_state=initial_state)
lstm_outout_seq = lstm_output[:,-1,:]
dense_0 = tf.layers.dense(inputs=lstm_outout_seq, units=120, activation=tf.nn.relu)
dropout_0 = tf.layers.dropout(dense_0, rate=0.7)
with tf.variable_scope('sigmoid'):
W = tf.Variable(tf.truncated_normal((120, 1), stddev=0.1), name='weights')
b = tf.Variable(tf.zeros(1), name='bias')
logits = tf.matmul(dropout_0, W) + b
output = tf.nn.sigmoid(logits, name='output')
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=labels))
correct_predictions = tf.abs(output - labels)
total_correct = tf.ones_like(correct_predictions)
accuracy = tf.reduce_mean(total_correct - correct_predictions)
learning_rate = tf.placeholder(tf.float32, name='learning_rate')
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
l_rate = 0.001
epochs = 500
kp_prob = 0.7
with tf.Session() as session:
session.run(tf.global_variables_initializer())
for e in range(epochs):
new_state = session.run([initial_state])
feeder = {
inputs: wnd_x,
labels: wnd_y_scl,
keep_prob: kp_prob,
learning_rate: l_rate,
initial_state: new_state
}
session_loss,
session_accuracy,
session_output, _,
last_state = session.run([loss, accuracy, output,
optimizer, final_state], feed_dict=feeder)
print('Epoch {0}/{1}:\t'.format(e, epochs),
'training loss {0}\t'.format(session_loss),
'accuracy {0}\t'.format(session_accuracy))
new_state = session.run([initial_state])
feeder = {
inputs: unseen_data_rsp,
keep_prob: 1.0,
initial_state: new_state
}
session_output = session.run([output], feed_dict=feeder)
如前所述,在推理阶段,预测已固定下降,但不知何故具有正确的行为,即曲线的导数随时间步长正确变化。
在训练阶段我有以下输出:
Epoch 999/1000: training loss = 0.5913468599319458 | accuracy = 0.9909629225730896
Input Label Output
[[ 1],[ 2],[ 3],[ 4]] --> [0.0493] ... [0.0591]
[[ 2],[ 3],[ 4],[ 5]] --> [0.0634] ... [0.0802]
[[ 3],[ 4],[ 5],[ 6]] --> [0.0773] ... [0.0777]
[[ 4],[ 5],[ 6],[ 7]] --> [0.0909] ... [0.1035]
.. .. .. .. ... ... ...
[[55],[56],[57],[58]] --> [0.5503] ... [0.5609]
[[56],[57],[58],[59]] --> [0.5567] ... [0.5465]
[[57],[58],[59],[60]] --> [0.5630] ... [0.5543]
[[58],[59],[60],[61]] --> [0.5693] ... [0.5614]
在推理阶段我有以下输出:
Input Prediction
[[ 58],[ 59],[ 60],[ 61]] --> [0.4408]
[[ 59],[ 60],[ 61],[ 62]] --> [0.4459]
[[ 60],[ 61],[ 62],[ 63]] --> [0.4510]
[[ 61],[ 62],[ 63],[ 64]] --> [0.4559]
... ... ... ... ... ...
[[112],[113],[114],[115]] --> [0.6089]
[[113],[114],[115],[116]] --> [0.6101]
[[114],[115],[116],[117]] --> [0.6113]
[[115],[116],[117],[118]] --> [0.6124]
如您所见,推理的第一个输入与训练的最后一个输入相同。我在这里不明白的是为什么相同的输入会给我 2 个不同的输出,以及为什么这些输出有一个固定的降压,大约 0.11。谢谢你们的帮助,对于冗长的文字感到抱歉,我可以根据要求缩短它。
在推理过程中,您正在重置状态。所以你在同一个输入上得到两个不同的值,因为在这两种情况下网络的状态是不同的。
要在预测后保持状态,您需要执行以下操作:
#iterate for each prediction {
feeder = {
inputs: unseen_data_rsp,
keep_prob: 1.0,
initial_state: last_state
}
session_output, last_state = session.run([output,final_state], feed_dict=feeder)
}
另外,为了通过推理的第一个输入准确地获得训练结果,您需要首先呈现所有训练示例,以确保您以正确的状态开始推理。另一种方法是保存网络状态,然后您可以在预测期间重复使用。