星期二, 08. 十月 2019 03:27下午
注:論文實現(xiàn)代碼和論文.pdf都在git 賬號下,歡迎交流討論
論文題目:
- Learning to Monitor Machine Health with Convolutional Bi-Directional LSTM Networks
- Machine health monitoring using local feature-based gated recurrent unit networks
1.第一篇文章基本框架
論文主要內(nèi)容:通過論文提出的模型實現(xiàn)對故障的診斷(分類回歸都可以實現(xiàn))
論文的框架主要分為四個部分:
1占键、原始數(shù)據(jù)(可以是多個傳感器數(shù)據(jù))通過滑窗提取時頻域特征,假設(shè)傳感器數(shù)目為m贩绕,窗口數(shù)目為k,每個傳感器提取的特征數(shù)目為n,則原始數(shù)據(jù)提過特征提取后的輸入為[-1, k, m*n],其中-1表示batch數(shù)目陶舞。
住:這一部分在框圖和代碼中沒有體現(xiàn)绪励,但是在論文中可以看出來肿孵。如果讀者需要套用這個模型,需要自己實現(xiàn)這一部分的功能疏魏,如果在用原始數(shù)據(jù)輸入(不經(jīng)過特征提韧W觥)也可以取得很好效果,則這一部分可以省略
2大莫、卷積部分實現(xiàn)空間特征提取蛉腌,保留時間信息,代碼如下:
@staticmethod
def cnn_layer(cnn_input=None, k=None, m=None, s=None, d=None):
cnn1 = tf.contrib.layers.conv2d(cnn_input,
num_outputs=k,
kernel_size=[m, d],
stride=[1, d],
padding='VALID', )
cnn1_pool = tf.nn.max_pool(cnn1,
ksize=[1, s, 1, 1],
strides=[1, s, 1, 1],
padding='SAME',
name='cnn1_max_pool')
cnn1_shape = cnn1_pool.get_shape()
cnn_out = tf.reshape(cnn1_pool, shape=[-1, cnn1_shape[1], cnn1_shape[-1]])
return cnn_out
可以參考圖3結(jié)合代碼的實現(xiàn)理解只厘,注意理解卷積層池化層的kernel_size和ksize眉抬,其中d表示數(shù)據(jù)的長度,即m*n的值:
3懈凹、兩層雙向LSTM的堆疊蜀变,主要用于在cnn輸出的基礎(chǔ)上提取時間信息,代碼如下:
@staticmethod
def bilstm_layer(bilstm_input=None, num_units=None):
# first bi-lstm cell
with tf.variable_scope('1st-bi-lstm-layer', reuse=tf.AUTO_REUSE):
cell_fw_1 = tf.nn.rnn_cell.LSTMCell(num_units=num_units[0], state_is_tuple=True)
cell_bw_1 = tf.nn.rnn_cell.LSTMCell(num_units=num_units[0], state_is_tuple=True)
outputs_1, states_1 = tf.nn.bidirectional_dynamic_rnn(cell_fw_1, cell_bw_1, inputs=bilstm_input,
dtype=tf.float32)
# second bi-lstm cell
with tf.variable_scope('2nd-bi-lstm-layer', reuse=tf.AUTO_REUSE):
# input_2 = tf.add(outputs_1[0], outputs_1[1])
input_2 = tf.concat([outputs_1[0], outputs_1[1]], axis=2)
cell_fw_2 = tf.nn.rnn_cell.LSTMCell(num_units=num_units[1], state_is_tuple=True)
cell_bw_2 = tf.nn.rnn_cell.LSTMCell(num_units=num_units[1], state_is_tuple=True)
outputs_2, states_2 = tf.nn.bidirectional_dynamic_rnn(cell_fw_2, cell_bw_2, inputs=input_2,
dtype=tf.float32)
# bilstm output
with tf.variable_scope('bi-lstm-layer-output', reuse=tf.AUTO_REUSE):
bilstm_out = tf.concat([states_2[0].h, states_2[1].h], axis=1)
return bilstm_out
可以參考圖c結(jié)合代碼的實現(xiàn)理解介评,注意理解兩個雙向lstm層的拼接(關(guān)于該部分的實現(xiàn)也是根據(jù)論文原文實現(xiàn)的库北,如果有問題還請討論交流):
4爬舰、全連接層實現(xiàn)最終結(jié)果輸出,這一部分的實現(xiàn)相對簡單寒瓦,主要對上一層最后在timestep輸出的隱層特征作為輸入得到最終的結(jié)果情屹,代碼如下所示:
@staticmethod
def fc_layer(fc_input=None, num_units=None, keep_prob=None):
fc_input_ = tf.nn.dropout(fc_input, keep_prob=keep_prob)
fc1 = tf.layers.dense(fc_input_, num_units[0], activation=tf.nn.relu,
kernel_initializer=tf.glorot_uniform_initializer())
fc1_ = tf.nn.dropout(fc1, keep_prob=keep_prob)
fc_out = tf.layers.dense(fc1_, num_units[1], activation=tf.nn.relu,
kernel_initializer=tf.glorot_uniform_initializer())
# fc_out = tf.layers.dense(fc_out, 1, activation=None, use_bias=False,
# kernel_initializer=tf.glorot_normal_initializer())
return fc_out
所有代碼實現(xiàn)請參考本人git.
2.第二篇文章基本框架
論文主要內(nèi)容:通過論文提出的模型實現(xiàn)對故障的診斷(分類回歸都可以實現(xiàn))
論文的框架主要分為四個部分:
1、原始數(shù)據(jù)(可以是多個傳感器數(shù)據(jù))通過滑窗提取時頻域特征杂腰,假設(shè)傳感器數(shù)目為m垃你,窗口數(shù)目為k,每個傳感器提取的特征數(shù)目為n喂很,則原始數(shù)據(jù)提過特征提取后的輸入為[-1, k, m*n]惜颇,其中-1表示batch數(shù)目。(這與論文1中提到的是一樣的少辣,而且可以從下圖中看出來)凌摄,這一部分的內(nèi)容同樣需要讀者自己實現(xiàn)。
2漓帅、雙向GRU實現(xiàn)時間特征提取锨亏,這一部分也相對簡單,代碼如下:
@staticmethod
def bigru_layer(bilstm_input=None, num_units=None):
cell_fw = tf.nn.rnn_cell.GRUCell(num_units=num_units, name='fw')
cell_bw = tf.nn.rnn_cell.GRUCell(num_units=num_units, name='bw')
outputs, states = tf.nn.bidirectional_dynamic_rnn(cell_fw, cell_bw, inputs=bilstm_input, dtype=tf.float32)
bigru_out = tf.concat([states[0], states[1]], axis=1)
return bigru_out
3忙干、權(quán)重平均化部分器予,這一部分主要通過fc實現(xiàn),但是需要先對輸入到gru的數(shù)據(jù)進行處理捐迫,參考原文公式和代碼劣摇,由于原文公式較長,該部分只粘貼代碼弓乙,其主要思想是實現(xiàn)不同窗口在同一個time step上做類似指數(shù)的平均末融,參考代碼如下:
@staticmethod
def get_weight_average_layer(weight_average_input=None):
_arr_weight_average_input = np.array(weight_average_input)
_, T, _ = _arr_weight_average_input.shape
_arr = []
for ck in _arr_weight_average_input: # every batch
qk = np.array([np.exp(np.min([k - 1, T - k])) for k in range(1, T+1)])
sigma_qk = np.sum(qk, dtype=np.float32)
wk = np.array([qj * 1.0 / sigma_qk for qj in qk])
c = np.array([wk[k]*ck[k] for k in range(T)]).sum(axis=0)
_arr.append(c)
return np.array(_arr)
4、這一部分相對簡單暇韧,就是將第2和第3部分的結(jié)果進行concat再通過一個fc學(xué)習(xí)勾习,代碼如下:
@staticmethod
def fc_layer_2(fc_input=None, num_units=None, keep_prob=None):
fc_input_ = tf.nn.dropout(fc_input, keep_prob=keep_prob)
fc_out = tf.layers.dense(fc_input_, num_units, activation=tf.nn.relu,
kernel_initializer=tf.glorot_uniform_initializer())
# fc_out = tf.nn.dropout(fc, keep_prob=keep_prob)
return fc_out
所有代碼實現(xiàn)請參考本人git.