2017-03-27 73 views
2

我有一個Tensorflow模型,它是一個使用長期短期記憶的遞歸神經網絡。狀態大小爲3000,每次輸入步驟有300個輸入,大約有500個時間步,每個時間步有1個輸出。我正在訓練一個序列到序列的模型。Tensorflow GPU在均方誤差期間耗盡的內存

它運行罰款輸入小於500層時的步驟,但地方約500個時間步長,它具有以下內存不足錯誤崩潰:

ResourceExhaustedError (see above for traceback): OOM when allocating tensor with shape[20375,20375] 
    [[Node: gradients/mean_squared_error/Mul_grad/mul_1 = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](mean_squared_error/Square, gradients/mean_squared_error/Sum_grad/Tile)]] 
    [[Node: gradients/MatMul_grad/tuple/control_dependency_1/_225 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_5086_gradients/MatMul_grad/tuple/control_dependency_1", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"]()]] 

,這是在GPU上運行帶有12GB內存。

我已經嘗試在我的筆記本電腦CPU上運行它,它似乎使用很少的內存(大約1到2 GB),但它太慢了,它從來沒有達到500個時間步。我正在進行一些更改,這會使其跳到500個時間步,以查看未在GPU上運行時使用的內存量。

我的問題是:Tensorflow可能想要分配張量形狀[20375,20375]?它似乎與tf.mean_squared_error函數有關,但這看起來不像是一個需要如此大量內存的操作。

我已經嘗試減少批量大小,但這只是將故障點推到更多的時間步驟,而且我將需要多達幾千個時間步驟,所以這看起來不像一個好長的期限的解決方案。我寧願找到問題的根源。

這裏是平均值的相關代碼誤差平方:

initial_state_tuple = tf.contrib.rnn.LSTMStateTuple(initial_state, initial_hidden_state) 


# Create the actual RNN 
with tf.variable_scope(VARIABLE_SCOPE, reuse=None): 
    cell = tf.contrib.rnn.BasicLSTMCell(STATE_SIZE) 
    rnn_outputs, finalstate = tf.nn.dynamic_rnn(cell=cell, inputs=networkinput, 
               initial_state=initial_state_tuple) 

with tf.variable_scope(VARIABLE_SCOPE, reuse=True): 
    weights = tf.get_variable(name=WEIGHTS_NAME, shape=[STATE_SIZE, 1], dtype=tf.float32) 
    biases = tf.get_variable(name=BIASES_NAME, shape=[1], dtype=tf.float32) 

# Build the output layers 
rnn_outputs_reshaped = tf.reshape(rnn_outputs, [-1, STATE_SIZE]) 
network_outputs = tf.sigmoid(tf.matmul(rnn_outputs_reshaped, weights) + biases) 
expected_outputs_reshaped = tf.reshape(expected_outputs, [-1, 1]) 

# Loss mask just cancels out the inputs that are padding characters, since not all inputs have the same number of time steps 
loss_mask_reshaped = tf.reshape(loss_mask, shape=[-1]) 

expected_outputs_reshaped = loss_mask_reshaped * expected_outputs_reshaped 
network_outputs = loss_mask_reshaped * network_outputs 

loss = tf.losses.mean_squared_error(labels=expected_outputs_reshaped, predictions=network_outputs) 

如果你想所有的代碼,可以發現here。相關的函數是buildtower()和buildgraph()。在具有GPU的機器上運行時,常量NUM_GPUS和BATCH_SIZE設置爲適當的值。

更新:我更換了線

loss = tf.losses.mean_squared_error(labels=expected_outputs_reshaped, predictions=network_outputs) 

error_squared = tf.pow(expected_outputs_reshaped - network_outputs, 2) 
loss = tf.reduce_mean(error_squared) 

和同樣的錯誤發生。我將狀態大小減少到了30,批量大小減少到了5,並且錯誤仍然發生,儘管它使它達到了大約3000個時間步長。

更新:在做了一些研究之後,我發現,當訓練一個具有大量時間步長的RNN時,經常會使用截斷後向傳播。這使我相信通過大量時間步驟的反向傳播本質上需要大量的內存,而我的問題不是我構建了錯誤的圖形,而是我對梯度計算的資源需求存在根本的誤解。爲此,我正在努力將我的代碼更改爲使用截斷後向傳播。我會報告結果。

回答

0

這個項目是我第一次使用機器學習和Tensorflow的經驗,經過一番研究,似乎我有一些根本性的誤解。

我以爲內存使用量會隨着我數據中的時間步數而線性縮放。因爲我的模型(批量大小,狀態大小)的每個其他維度都很小,所以我預計在內存不足之前可能需要幾個時間步驟。但是,計算梯度的內存使用率似乎與時間步數成指數關係,所以無論我如何縮小狀態大小和批量大小,由於大量的時間步長,它最終會耗盡我所有的內存。

爲了解決這個問題,我使用了truncated backpropagation,其中每個批次都被分成幾個固定數量的時間步長。這並不完美,因爲這意味着錯誤最多隻能傳播多次。但是,基於我在網上找到的內容,它似乎工作得很好,並且沒有太多其他方法可以解決內存使用問題。

正如我之前所說的,這是我第一次使用機器學習的經驗,所以如果在這裏有什麼是公然錯誤的,請告訴我。