已经设计了几种方法来访问或量化 MLP 神经网络模型中的变量重要性(即使只是相对于彼此):
- 连接权重
- 加森算法
- 偏导数
- 输入扰动
- 敏感性分析
- 正向逐步加法
- 向后逐步消除
- 改进的逐步选择 1
- 改进的逐步选择 2
(这些在http://dx.doi.org/10.1016/j.ecolmodel.2004.03.013中有描述)
是否有任何方法可以应用于 RNN 或 LSTM 神经网络?
已经设计了几种方法来访问或量化 MLP 神经网络模型中的变量重要性(即使只是相对于彼此):
(这些在http://dx.doi.org/10.1016/j.ecolmodel.2004.03.013中有描述)
是否有任何方法可以应用于 RNN 或 LSTM 神经网络?
简而言之,是的,您可以对基于 RNN 的模型的变量重要性进行一些度量。我不会遍历问题中列出的所有建议,但我将深入介绍敏感性分析的示例。
我的 RNN 的输入数据将由具有三个特征的时间序列组成,、、。每个特征都将从随机均匀分布中抽取。我的 RNN 的目标变量将是一个时间序列(我输入中每个时间步长的一个预测):
正如我们所见,目标仅依赖于前两个特征。因此,一个好的变量重要性度量应该显示前两个变量很重要,而第三个变量不重要。
该模型是一个简单的三层 LSTM,在最后一层有一个 sigmoid 激活。该模型将在 5 个 epoch 中进行训练,每个 epoch 有 1000 个批次。
为了衡量变量的重要性,我们将对数据进行大样本(250 个时间序列)并计算模型的预测。然后,对于每个变量,我们将通过以 0 为中心、尺度为 0.2 的随机正态分布扰动该变量(并且仅该变量)并计算预测。和扰动之间的均方根差来测量这种扰动的影响。较大的均方根差异意味着变量“更重要”。
显然,用于扰动数据的确切机制,以及如何测量扰动和未扰动输出之间的差异,将高度依赖于您的特定数据集。
完成上述所有操作后,我们看到以下重要性:
Variable 1, perturbation effect: 0.1162
Variable 2, perturbation effect: 0.1185
Variable 3, perturbation effect: 0.0077
正如我们所料,发现变量 1 和 2 比变量 3 更重要(大约 15 倍)!
from tensorflow import keras # tensorflow v1.14.0 was used
import numpy as np # numpy v1.17.1 was used
np.random.seed(2019)
def make_model():
inp = keras.layers.Input(shape=(10, 3))
x = keras.layers.LSTM(10, activation='relu', return_sequences=True)(inp)
x = keras.layers.LSTM(5, activation='relu', return_sequences=True)(x)
x = keras.layers.LSTM(1, activation='sigmoid', return_sequences=True)(x)
out = keras.layers.Flatten()(x)
return keras.models.Model(inp, out)
def data_gen():
while True:
x = np.random.rand(5, 10, 3) # batch x time x features
yield x, x[:, :, 0] * x[:, :, 1] < 0.25
def var_importance(model):
g = data_gen()
x = np.concatenate([next(g)[0] for _ in range(50)]) # Get a sample of data
orig_out = model.predict(x)
for i in range(3): # iterate over the three features
new_x = x.copy()
perturbation = np.random.normal(0.0, 0.2, size=new_x.shape[:2])
new_x[:, :, i] = new_x[:, :, i] + perturbation
perturbed_out = model.predict(new_x)
effect = ((orig_out - perturbed_out) ** 2).mean() ** 0.5
print(f'Variable {i+1}, perturbation effect: {effect:.4f}')
def main():
model = make_model()
model.compile('adam', 'binary_crossentropy')
print(model.summary())
model.fit_generator(data_gen(), steps_per_epoch=500, epochs=10)
var_importance(model)
if __name__ == "__main__":
main()
代码的输出:
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 10, 3)] 0
_________________________________________________________________
lstm (LSTM) (None, 10, 10) 560
_________________________________________________________________
lstm_1 (LSTM) (None, 10, 5) 320
_________________________________________________________________
lstm_2 (LSTM) (None, 10, 1) 28
_________________________________________________________________
flatten (Flatten) (None, 10) 0
=================================================================
Total params: 908
Trainable params: 908
Non-trainable params: 0
_________________________________________________________________
Epoch 1/5
1000/1000 [==============================] - 14s 14ms/step - loss: 0.6261
Epoch 2/5
1000/1000 [==============================] - 12s 12ms/step - loss: 0.4901
Epoch 3/5
1000/1000 [==============================] - 13s 13ms/step - loss: 0.4631
Epoch 4/5
1000/1000 [==============================] - 14s 14ms/step - loss: 0.4480
Epoch 5/5
1000/1000 [==============================] - 14s 14ms/step - loss: 0.4440
Variable 1, perturbation effect: 0.1162
Variable 2, perturbation effect: 0.1185
Variable 3, perturbation effect: 0.0077