研究给定 DL 模型中特征的重要性和权重演变
Investigating the features' importance and weights evolution in given DL model
对于比平时更长的介绍,我深表歉意,但这对问题很重要:
我最近被分配到一个现有项目中工作,该项目使用 Keras+Tensorflow 创建一个全连接网络。
总体而言,该模型有 3 个全连接层和 500 个神经元,并有 2 个输出 类。第一层有 500 个神经元,连接到 82 个输入特征。该模型用于生产并每周使用外部来源生成的本周信息进行再培训。
设计模型的工程师已不在此处工作,我正在尝试进行逆向工程并了解模型的行为。
我为自己定义的几个目标是:
- 了解特征选择过程和特征重要性。
- 了解并控制每周的再培训过程。
为了尝试回答这两个问题,我实施了一个实验,我在代码中输入了两个模型:一个来自上周,另一个来自本周:
import pickle
import numpy as np
import matplotlib.pyplot as plt
from keras.models import model_from_json
path1 = 'C:/Model/20190114/'
path2 = 'C:/Model/20190107/'
model_name1 = '0_10.1'
model_name2 = '0_10.2'
models = [path1 + model_name1, path2 + model_name2]
features_cum_weight = {}
然后我获取每个特征并尝试将连接到第一个隐藏层的所有权重(它们的绝对值)相加。
通过这种方式,我创建了两个包含 82 个值的向量:
for model_name in models:
structure_filename = model_name + "_structure.json"
weights_filename = model_name + "_weights.h5"
with open(structure_filename, 'r') as model_json:
model = model_from_json(model_json.read())
model.load_weights(weights_filename)
in_layer_weights = model.layers[0].get_weights()[0]
in_layer_weights = abs(in_layer_weights)
features_cum_weight[model_name] = in_layer_weights.sum(axis=1)
然后我使用 MatplotLib 绘制它们:
# Plot the Evolvement of Input Neuron Weights:
keys = list(features_cum_weight.keys())
weights_1 = features_cum_weight[keys[0]]
weights_2 = features_cum_weight[keys[1]]
fig, ax = plt.subplots(nrows=2, ncols=2)
width = 0.35 # the width of the bars
n_plots = 4
batch = int(np.ceil(len(weights_1)/n_plots))
for i in range(n_plots):
start = i*(batch+1)
stop = min(len(weights_1), start + batch + 1)
cur_w1 = weights_1[start:stop]
cur_w2 = weights_2[start:stop]
ind = np.arange(len(cur_w1))
cur_ax = ax[i//2][i%2]
cur_ax.bar(ind - width/2, cur_w1, width, color='SkyBlue', label='Current Model')
cur_ax.bar(ind + width/2, cur_w2, width, color='IndianRed', label='Previous Model')
cur_ax.set_ylabel('Sum of Weights')
cur_ax.set_title('Sum of all weights connected by feature')
cur_ax.set_xticks(ind)
cur_ax.legend()
cur_ax.set_ylim(0, 30)
plt.show()
导致以下情节:
MatPlotLib plot
然后我尝试比较向量以推断:
- 如果向量发生了巨大变化 - 训练数据可能发生了一些重大变化,或者在重新训练模型时出现了一些问题。
- 如果某个值接近于零,模型可能认为该特征不重要。
我想听听您对以下内容的意见和见解:
- 这个实验的总体方法。
- 关于给定模型逆向工程的其他想法的建议。
- 关于我在此处提供的输出的见解。
谢谢大家,我愿意接受任何建议和批评!
这种推论并不完全正确。特征之间的组合不是线性的。诚然,如果严格为0无所谓,但也有可能是然后以另一种方式,在另一个深层重新组合。
如果您的模型是线性的,那将是正确的。事实上,这就是 PCA 分析的工作原理,它通过协方差矩阵搜索线性关系。特征值将指示每个特征的重要性。
我认为有几种方法可以证实你的怀疑:
去掉你认为不重要的特征重新训练看看结果。如果相似,那你的猜测是正确的。
应用当前模型,举一个例子(我们称之为枢轴)来评估和显着改变你认为不相关的特征,并创建许多例子。这适用于多个枢轴。如果结果相似,则该字段无关紧要。示例(我认为第一个特征无关紧要):
data = np.array([[0.5, 1, 0.5], [1, 2, 5]])
range_values = 50
new_data = []
for i in range(data.shape[0]):
sample = data[i]
# We create new samples
for i in range (1000):
noise = np.random.rand () * range_values
new_sample = sample.copy()
new_sample[0] += noise
new_data.append(new_sample)
对于比平时更长的介绍,我深表歉意,但这对问题很重要:
我最近被分配到一个现有项目中工作,该项目使用 Keras+Tensorflow 创建一个全连接网络。
总体而言,该模型有 3 个全连接层和 500 个神经元,并有 2 个输出 类。第一层有 500 个神经元,连接到 82 个输入特征。该模型用于生产并每周使用外部来源生成的本周信息进行再培训。
设计模型的工程师已不在此处工作,我正在尝试进行逆向工程并了解模型的行为。
我为自己定义的几个目标是:
- 了解特征选择过程和特征重要性。
- 了解并控制每周的再培训过程。
为了尝试回答这两个问题,我实施了一个实验,我在代码中输入了两个模型:一个来自上周,另一个来自本周:
import pickle
import numpy as np
import matplotlib.pyplot as plt
from keras.models import model_from_json
path1 = 'C:/Model/20190114/'
path2 = 'C:/Model/20190107/'
model_name1 = '0_10.1'
model_name2 = '0_10.2'
models = [path1 + model_name1, path2 + model_name2]
features_cum_weight = {}
然后我获取每个特征并尝试将连接到第一个隐藏层的所有权重(它们的绝对值)相加。 通过这种方式,我创建了两个包含 82 个值的向量:
for model_name in models:
structure_filename = model_name + "_structure.json"
weights_filename = model_name + "_weights.h5"
with open(structure_filename, 'r') as model_json:
model = model_from_json(model_json.read())
model.load_weights(weights_filename)
in_layer_weights = model.layers[0].get_weights()[0]
in_layer_weights = abs(in_layer_weights)
features_cum_weight[model_name] = in_layer_weights.sum(axis=1)
然后我使用 MatplotLib 绘制它们:
# Plot the Evolvement of Input Neuron Weights:
keys = list(features_cum_weight.keys())
weights_1 = features_cum_weight[keys[0]]
weights_2 = features_cum_weight[keys[1]]
fig, ax = plt.subplots(nrows=2, ncols=2)
width = 0.35 # the width of the bars
n_plots = 4
batch = int(np.ceil(len(weights_1)/n_plots))
for i in range(n_plots):
start = i*(batch+1)
stop = min(len(weights_1), start + batch + 1)
cur_w1 = weights_1[start:stop]
cur_w2 = weights_2[start:stop]
ind = np.arange(len(cur_w1))
cur_ax = ax[i//2][i%2]
cur_ax.bar(ind - width/2, cur_w1, width, color='SkyBlue', label='Current Model')
cur_ax.bar(ind + width/2, cur_w2, width, color='IndianRed', label='Previous Model')
cur_ax.set_ylabel('Sum of Weights')
cur_ax.set_title('Sum of all weights connected by feature')
cur_ax.set_xticks(ind)
cur_ax.legend()
cur_ax.set_ylim(0, 30)
plt.show()
导致以下情节:
MatPlotLib plot
然后我尝试比较向量以推断:
- 如果向量发生了巨大变化 - 训练数据可能发生了一些重大变化,或者在重新训练模型时出现了一些问题。
- 如果某个值接近于零,模型可能认为该特征不重要。
我想听听您对以下内容的意见和见解:
- 这个实验的总体方法。
- 关于给定模型逆向工程的其他想法的建议。
- 关于我在此处提供的输出的见解。
谢谢大家,我愿意接受任何建议和批评!
这种推论并不完全正确。特征之间的组合不是线性的。诚然,如果严格为0无所谓,但也有可能是然后以另一种方式,在另一个深层重新组合。
如果您的模型是线性的,那将是正确的。事实上,这就是 PCA 分析的工作原理,它通过协方差矩阵搜索线性关系。特征值将指示每个特征的重要性。
我认为有几种方法可以证实你的怀疑:
去掉你认为不重要的特征重新训练看看结果。如果相似,那你的猜测是正确的。
应用当前模型,举一个例子(我们称之为枢轴)来评估和显着改变你认为不相关的特征,并创建许多例子。这适用于多个枢轴。如果结果相似,则该字段无关紧要。示例(我认为第一个特征无关紧要):
data = np.array([[0.5, 1, 0.5], [1, 2, 5]]) range_values = 50 new_data = [] for i in range(data.shape[0]): sample = data[i] # We create new samples for i in range (1000): noise = np.random.rand () * range_values new_sample = sample.copy() new_sample[0] += noise new_data.append(new_sample)