【问题标题】:LSTM+FFN performs more poorly than FFNLSTM+FFN 性能比 FFN 差
【发布时间】:2021-08-11 14:05:21
【问题描述】:

我正在构建几个简单的网络来预测未来一小时内 500 个车站的自行车租赁情况,给定过去 24 小时内所有车站的租赁情况。我正在使用两种架构,一种使用图卷积(相当于每小时使用其他站点的学习线性组合更新每个站点)和 FNN 层进行预测,第二种使用图形卷积 -> LSTM - > FNN 到预测。

在我描述更多之前,我的模型的性能越来越差,其中包括一个 LSTM 单元,这让我感到困惑。

请参阅这两张图片以了解每种架构的描述,对于每种架构,我还添加了每小时元数据(天气、时间等)作为变体,它们在图像中以红色显示,与我的问题无关。文章底部的图片链接。 [架构一:GCNN + FNN][1] [架构二:GCNN + LSTM + FNN][2]

令人困惑的是,第一个模型的测试 RMSE 为 3.46,第二个模型的测试 RMSE 为 3.57。有人可以向我解释为什么第二个不会更低,因为它似乎正在运行完全相同的进程,除了额外的 LSTM 单元。

以下是我的 GCNN+FNN 模型代码的相关 sn-ps:

def gcnn_ddgf(hidden_layer, node_num, feature_in, horizon, learning_rate, beta, batch_size, early_stop_th, training_epochs, X_training, Y_training, X_val, Y_val, X_test, Y_test, scaler, display_step):

n_output_vec = node_num * horizon # length of output vector at the final layer 
early_stop_k = 0 # early stop patience
best_val = 10000
traing_error = 0
test_error = 0
pred_Y = []

tf.reset_default_graph()

batch_size = batch_size
early_stop_th = early_stop_th
training_epochs = training_epochs

# tf Graph input and output
X = tf.placeholder(tf.float32, [None, node_num, feature_in]) # X is the input signal
Y = tf.placeholder(tf.float32, [None, n_output_vec]) # y is the regression output

# define dictionaries to store layers weight & bias
weights_hidden = {}
weights_A = {}
biases = {}
vec_length = feature_in
weights_hidden['h1'] = tf.Variable(tf.random_normal([vec_length, hidden_layer], stddev=0.5))
biases['b1'] = tf.Variable(tf.random_normal([1, hidden_layer], stddev=0.5))
weights_A['A1'] = tf.Variable(tf.random_normal([node_num, node_num], stddev=0.5))
    
weights_hidden['out'] = tf.Variable(tf.random_normal([hidden_layer, horizon], stddev=0.5))
biases['bout'] = tf.Variable(tf.random_normal([1, horizon], stddev=0.5))

# Construct model
pred= gcn(X, weights_hidden, weights_A, biases, node_num, horizon) #see below
pred = scaler.inverse_transform(pred)
Y_original = scaler.inverse_transform(Y)

cost = tf.sqrt(tf.reduce_mean(tf.pow(pred - Y_original, 2))) 
                           
#optimizer = tf.train.RMSPropOptimizer(learning_rate, decay).minimize(cost)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, beta1=beta).minimize(cost)

# Initializing the variables
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    for epoch in range(training_epochs):

        avg_cost_sq = 0.
        num_train = X_training.shape[0]
        total_batch = int(num_train/batch_size)

        for i in range(total_batch):
            
            _, c = sess.run([optimizer, cost], feed_dict={X: X_training[i*batch_size:(i+1)*batch_size,], 
                                                  Y: Y_training[i*batch_size:(i+1)*batch_size,]})

            avg_cost_sq += np.square(c) * batch_size #/ total_batch 
            
        # rest part of training dataset
        if total_batch * batch_size != num_train:
            _, c = sess.run([optimizer, cost], feed_dict={X: X_training[total_batch*batch_size:num_train,], 
                                      Y: Y_training[total_batch*batch_size:num_train,]})
            avg_cost_sq += np.square(c) * (num_train - total_batch*batch_size)
        
        avg_cost = np.sqrt(avg_cost_sq / num_train)
          
        # validation
        c_val, = sess.run([cost], feed_dict={X: X_val, Y: Y_val})
                                
        if c_val < best_val:
            # testing
            c_tes, preds, Y_true = sess.run([cost, pred, Y_original], feed_dict={X: X_test,Y: Y_test})
            best_val = c_val
            test_error = c_tes
            traing_error = avg_cost
            pred_Y = preds
            early_stop_k = 0 # reset to 0

        # update early stopping patience
        if c_val >= best_val:
            early_stop_k += 1

        # threshold
        if early_stop_k == early_stop_th:
            break
        
        if epoch % display_step == 0:
            print ("Epoch:", '%04d' % (epoch+1), "Training RMSE: ","{:.9f}".format(avg_cost))
            print("Validation RMSE: ", c_val)
            print("Lowest test RMSE: ", test_error)

    print("epoch is ", epoch)
    print("training RMSE is ", traing_error)
    print("Optimization Finished! the lowest validation RMSE is ", best_val)
    print("The test RMSE is ", test_error)

return best_val, pred_Y ,Y_true,test_error

# code that creates the model
def gcn(signal_in, weights_hidden, weights_A, biases, node_num, horizon):

signal_in = tf.transpose(signal_in, [1, 0, 2]) # node_num, batch, feature_in
feature_len = signal_in.shape[2] # feature vector length at the node of the input graph

signal_in = tf.reshape(signal_in, [node_num, -1]) # node_num, batch*feature_in

Adj = 0.5*(weights_A['A1'] + tf.transpose(weights_A['A1'])) 
Adj = normalize_adj(Adj)
Z = tf.matmul(Adj, signal_in) # node_num, batch*feature_in 
Z = tf.reshape(Z, [-1, int(feature_len)]) # node_num * batch, feature_in
signal_output = tf.add(tf.matmul(Z, weights_hidden['h1']), biases['b1'])
signal_output = tf.nn.relu(signal_output) # node_num * batch, hidden_vec

final_output = tf.add(tf.matmul(signal_output, weights_hidden['out']), biases['bout'])  # node_num * batch, horizon
# final_output = tf.nn.relu(final_output) 
final_output = tf.reshape(final_output, [node_num, -1, horizon]) # node_num, batch, horizon
final_output = tf.transpose(final_output, [1, 0, 2]) # batch, node_num, horizon
final_output = tf.reshape(final_output, [-1, node_num*horizon]) # batch, node_num*horizon

return final_output

以及GCNN+LSTM+FNN模型的代码:

def gcnn_ddgf_lstm(node_num, feature_in, learning_rate, beta, batch_size, early_stop_th, training_epochs, X_training, 
               Y_training, X_val, Y_val, X_test, Y_test, scaler,  lstm_layer):
n_output_vec = node_num # length of output vector at the final layer 

early_stop_k = 0 # early stop patience
display_step = 1 # frequency of printing results
best_val = 10000
traing_error = 0
test_error = 0
predic_res = []

tf.reset_default_graph()

batch_size = batch_size
early_stop_th = early_stop_th
training_epochs = training_epochs

# tf Graph input and output
X = tf.placeholder(tf.float32, [None, node_num, feature_in]) # X is the input signal
Y = tf.placeholder(tf.float32, [None, n_output_vec]) # y is the regression output
lstm_cell = tf.nn.rnn_cell.LSTMCell(lstm_layer, state_is_tuple=True)

# define dictionaries to store layers weight & bias
weights_hidden = {}
weights_A = {}
biases = {}

weights_A['A1'] = tf.Variable(tf.random_normal([node_num, node_num], stddev=0.5))  
weights_hidden['h1'] = tf.Variable(tf.random_normal([lstm_layer, node_num], stddev=0.5))
biases['h1'] = tf.Variable(tf.random_normal([1, node_num], stddev=0.5))
weights_hidden['out'] = tf.Variable(tf.random_normal([node_num, node_num], stddev=0.5))
biases['bout'] = tf.Variable(tf.random_normal([1, node_num], stddev=0.5))

# Construct model
pred= gcn_lstm(X, weights_hidden, weights_A, biases, node_num, lstm_cell)
# pred = scaler.inverse_transform(pred)
# Y_original = scaler.inverse_transform(Y)

cost = tf.sqrt(tf.reduce_mean(tf.pow(pred - Y, 2)))              
      
#optimizer = tf.train.RMSPropOptimizer(learning_rate, decay).minimize(cost)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, beta1=beta).minimize(cost)

# Initializing the variables
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    for epoch in range(training_epochs):

        avg_cost_sq = 0.
        num_train = X_training.shape[0]
        total_batch = int(num_train/batch_size)

        for i in range(total_batch):
            
            _, c = sess.run([optimizer, cost], feed_dict={X: X_training[i*batch_size:(i+1)*batch_size,], 
                                                  Y: Y_training[i*batch_size:(i+1)*batch_size,]})

            avg_cost_sq += np.square(c) * batch_size #/ total_batch 
            
        # rest part of training dataset
        if total_batch * batch_size != num_train:
            _, c = sess.run([optimizer, cost], feed_dict={X: X_training[total_batch*batch_size:num_train,], 
                                      Y: Y_training[total_batch*batch_size:num_train,]})
            avg_cost_sq += np.square(c) * (num_train - total_batch*batch_size)
        
        avg_cost = np.sqrt(avg_cost_sq / num_train)

        # validation
        c_val, = sess.run([cost], feed_dict={X: X_val, Y: Y_val})
        
        if c_val < best_val:
            c_tes, preds = sess.run([cost, pred], feed_dict={X: X_test,Y: Y_test})
            best_val = c_val
            # save model
            #saver.save(sess, './bikesharing_gcnn_ddgf')
            test_error = c_tes
            traing_error = avg_cost
            early_stop_k = 0 # reset to 0

        # update early stopping patience
        if c_val >= best_val:
            early_stop_k += 1

        # threshold
        if early_stop_k == early_stop_th:
            pred_Y = scaler.inverse_transform(preds)
            Y_true = scaler.inverse_transform(Y_test)
            test_err = tf.sqrt(tf.reduce_mean(tf.pow(pred_Y - Y_true, 2)))
            break

        if epoch % display_step == 0:
            print ("Epoch:", '%04d' % (epoch+1), "Training RMSE: ","{:.9f}".format(avg_cost))
            print("Validation RMSE: ", c_val)
            print("Lowest test RMSE: ", test_error)
                    
    print("epoch is ", epoch)
    print("training RMSE is ", traing_error)
    print("Optimization Finished! the lowest validation RMSE is ", best_val)
    print("The scaled test RMSE is ", test_error)

return pred_Y, Y_true

def gcn_lstm(signal_in, weights_hidden, weights_A, biases, node_num, lstm_cell):

signal_in = tf.transpose(signal_in, [1, 0, 2]) # node_num, batch, feature_in
feature_len = signal_in.shape[2] # feature vector length at the node of the input graph
signal_in = tf.reshape(signal_in, [node_num, -1]) # node_num, batch*feature_in

Adj = 0.5*(weights_A['A1'] + tf.transpose(weights_A['A1'])) 
Adj = normalize_adj(Adj)
Z = tf.matmul(Adj, signal_in) # node_num, batch*feature_in 
Z = tf.reshape(Z, [node_num, -1, int(feature_len)]) # node_num, batch, feature_in
Z = tf.transpose(Z,[1,2,0]) # batch, feature_in, node_num
# init_state = cell.zero_state(batch_size, tf.float32)
_, Z = tf.nn.dynamic_rnn(lstm_cell, Z, dtype = tf.float32) # init_state?

dense_output = tf.add(tf.matmul(Z[1], weights_hidden['h1']), biases['h1'])
dense_output = tf.nn.relu(dense_output)
final_output = tf.add(tf.matmul(dense_output, weights_hidden['out']), biases['bout'])  # batch, node_num*horizon
    
return final_output

特别是,我是否应该担心 _, Z = tf.nn.dynamic_rnn(lstm_cell, Z, dtype = tf.float32) 导致我在别处定义的变量无法训练?

非常感谢您的帮助 :) [1]:https://i.stack.imgur.com/MAO2t.png [2]:https://i.stack.imgur.com/UDjHw.png

【问题讨论】:

    标签: python tensorflow lstm


    【解决方案1】:

    我解决了这个问题。 我有三年的自行车使用数据来进行预测,并使用〜最近三个月作为我的验证/测试集。过去几个月是冬天,自行车使用量较低。当我在分配到集合之前对训练数据进行洗牌(为 LSTM 保留序列)时,我得到了预期的结果(GCNN+LSTM 优于 GCNN,虽然不是很多)

    【讨论】:

      猜你喜欢
      • 2020-03-10
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 2022-10-03
      • 2018-12-17
      • 2018-11-17
      • 2020-01-10
      相关资源
      最近更新 更多