4種除錯深度神經網路的方法

dicksonjyl560101發表於2019-01-12

https://www.toutiao.com/a6645209884650373639/


深度學習通常被視為一個 Blackbox 。但是 Blackbox 檢視對於機器學習從業者來說是一個明顯的問題: 如何除錯模型?

在本文中,我將介紹我們在心電圖中使用的一些技術來除錯DeepHeart,這是一個深度神經網路,使用來自Apple Watch,Garmin和WearOS裝置的資料來預測疾病。

在心電圖上,我們認為構建DNN架構是工程學。

4種除錯深度神經網路的方法

心電圖很能說明你的一切問題。DeepHeart使用來自Apple Watch、Garmin和Wear

一:預測合成輸出

通過預測從輸入資料構建的合成輸出任務來測試模型的能力。

我們在構建睡眠呼吸暫停檢測模型時應用了這一技術。現有的關於睡眠呼吸暫停篩查的文獻使用白天和夜間心率標準差的差異作為篩查機制。因此,我們為每週的輸入資料建立了一個合成輸出任務:

std(白天HRs) - std(夜間HRs)

為了學習這個函式,模型需要能夠完成:

  1. 區分白天和黑夜
  2. 記住過去幾天的資料

這兩個都是預測睡眠呼吸暫停的先決條件,因此我們嘗試新架構的第一步是檢查它是否能夠學習這個合成任務。

您還可以通過在合成任務上預先訓練網路,以半監督訓練的形式使用此類綜合任務。這種方法最適合的是當有很多沒有標籤的資料時,這個方法是很有用的。

二、視覺化啟用

很難理解訓練模型的內部結構。你如何理解成千上萬的矩陣乘法?

我們檢查了網路的幾個層的啟用情況,希望找到一些語義屬性,例如在使用者睡覺、鍛鍊或焦慮時細胞的啟用情況。

在Keras中,從模型中提取啟用的程式碼很簡單。下面的程式碼片段建立了一個Keras函式last_output_fn,該函式在給定一些輸入資料的情況下獲得一個層的輸出(啟用細胞)。

from keras import backend as K
def extract_layer_output(model, layer_name, input_data):
 layer_output_fn = K.function([model.layers[0].input],
 [model.get_layer(layer_name).output])
 layer_output = layer_output_fn([input_data])
 # layer_output.shape is (num_units, num_timesteps)
 return layer_output[0]
4種除錯深度神經網路的方法

我們視覺化網路的幾個啟用層。當我們檢查第二層卷積層(一個128寬的時間卷積層)的啟用時,我們注意到一些奇怪的事情:

4種除錯深度神經網路的方法

在每個時間步上啟用卷積層的每個單元。藍色陰影表示啟用值。

啟用不會隨時間而改變!它們不受輸入值的影響,被稱為“dead neurons”。

4種除錯深度神經網路的方法

ReLU啟用函式,f(x)= max(0,x)

該架構使用ReLU啟用函式,當輸入為負時輸出零。

在訓練的某一時刻,較大的梯度使得一個層的所有偏差項都變得非常負,使得ReLU函式的輸入非常負。因此,這一層發出了所有的零,並且由於ReLU的梯度在輸入小於零的情況下為零,因此不能通過梯度下降來解決這個問題。

當一個卷積層發出所有0時,後續層中的單元格輸出它們的偏差項的值。這就是為什麼這一層的每個單元輸出不同的值——它們的偏差項不同。

我們通過用Leaky ReLU替換ReLU來解決這個問題,即使輸入為負,也允許梯度傳播。

我們沒想到會在這個分析中會發現dead neurons,但當然最難發現的是你沒有在尋找的那些。

三、梯度分析

梯度不僅可用於優化損失函式。在梯度下降中,我們計算Δ損失遵循於Δ引數。一般來說,梯度計算的是改變一個變數對另一個變數的影響。由於梯度下降需要梯度計算,像TensorFlow這樣的框架包含計算梯度的函式。

我們使用梯度分析來確定我們的DNN是否可以獲取資料中的長期依賴性。DNN的輸入非常長:心率的4096個時間步長。我們的架構能夠獲取這些資料中的長期依賴關係是非常重要的。例如,心率恢復時間可以預測糖尿病。這是運動後恢復靜息心率所需的時間。為了計算這個,DNN必須能夠計算你的靜息心率,並記住你結束鍛鍊的時間。

模型是否可以跟蹤長期依賴關係的簡單度量是檢查輸入資料的每個時間步對輸出預測的影響。如果對後來的時間步長具有很大的影響,則該模型可能無法有效地使用之前的資料。

對於所有時間步長t,我們想要計算的梯度是相對於Δinput_t的Δoutput。以下是使用Keras和TensorFlow計算此示例的示例程式碼:

def gradient_output_wrt_input(model, data):
 # [:, 2048, 0] means all users in batch, midpoint timestep, 0th task (diabetes)
 output_tensor = model.model.get_layer('raw_output').output[:, 2048, 0]
 # output_tensor.shape == (num_users)
 # Average output over all users. Result is a scalar.
 output_tensor_sum = tf.reduce_mean(output_tensor)
 inputs = model.model.inputs # (num_users x num_timesteps x num_input_channels)
 gradient_tensors = tf.gradients(output_tensor_sum, inputs)
 # gradient_tensors.shape == (num_users x num_timesteps x num_input_channels)
 # Average over users
 gradient_tensors = tf.reduce_mean(gradient_tensors, axis=0)
 # gradient_tensors.shape == (num_timesteps x num_input_channels)
 # eg gradient_tensor[10, 0] is deriv of last output wrt 10th input heart rate
 # Convert to Keras function
 k_gradients = K.function(inputs=inputs, outputs=gradient_tensors)
 # Apply function to dataset
 return k_gradients([data.X])
4種除錯深度神經網路的方法

在上面的程式碼中,我們在平均池化之前以及在中點時間步2048處測量了輸出。我們使用中點而不是最後一個時間步長,因為我們的LSTM單元是雙向的,這意味著對於一半的單元來說,時間步長4095實際上是第一個時間步長。我們繪製出了梯度影像。

4種除錯深度神經網路的方法

Δoutput_2048/Δinput_t

注意y軸是log-scale。在時間步長2048處輸出相對於輸入的梯度是0.001。但是相對於輸入時間步長2500的梯度要小一百萬倍!通過梯度分析,我們發現這種架構無法獲得長期依賴關係。

四、分析模型預測

您可能已經在分析模型預測,至少通過檢視AUROC和平均絕對誤差等指標,也可以執行更多分析來了解模型的行為。

例如,我們很好奇我們的DNN是否真的使用心率輸入來生成預測,或者它是否嚴重依賴於提供的後設資料——我們使用使用者後設資料(如:年齡和性別)初始化LSTM狀態。為了理解這一點,我們將模型輸出與在後設資料上訓練的邏輯迴歸模型進行了比較。

DNN需要收集一週的使用者資料,因此在下面的散點圖中,每個點都是一個使用者周。

4種除錯深度神經網路的方法

這個圖推翻了我們的假設,因為這些預測並不是高度相關的。

除了綜合分析之外,檢視最佳贏利和虧損的例子也很有啟發性。對於二元分類任務,您需要檢視假陽性和假陰性(即預測離標籤最遠的情況)。嘗試識別損失模型,然後過濾掉那些也出現在真陽性和真陰性中的模式。

一旦對損失模式有了一個假設,通過分層分析進行測試。例如,如果最大的損失都來自第一代Apple Watch,那麼我們可以計算第一代Apple Watch調優集的使用者集的準確性指標,並將這些指標與調優集其餘部分計算的指標進行比較。

我希望這些技巧能夠幫助您除錯您的模型


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29829936/viewspace-2386018/,如需轉載,請註明出處,否則將追究法律責任。

相關文章