dl-backtrace 0.0.16__py3-none-any.whl → 0.0.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dl-backtrace might be problematic. Click here for more details.
- dl_backtrace/old_backtrace/__init__.py +1 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/__init__.py +1 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/backtrace/__init__.py +4 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/backtrace/backtrace.py +639 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/backtrace/config.py +41 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/backtrace/utils/__init__.py +2 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/backtrace/utils/contrast.py +840 -0
- dl_backtrace/old_backtrace/pytorch_backtrace/backtrace/utils/prop.py +746 -0
- dl_backtrace/old_backtrace/tf_backtrace/__init__.py +1 -0
- dl_backtrace/old_backtrace/tf_backtrace/backtrace/__init__.py +4 -0
- dl_backtrace/old_backtrace/tf_backtrace/backtrace/backtrace.py +527 -0
- dl_backtrace/old_backtrace/tf_backtrace/backtrace/config.py +41 -0
- dl_backtrace/old_backtrace/tf_backtrace/backtrace/utils/__init__.py +2 -0
- dl_backtrace/old_backtrace/tf_backtrace/backtrace/utils/contrast.py +834 -0
- dl_backtrace/old_backtrace/tf_backtrace/backtrace/utils/prop.py +725 -0
- dl_backtrace/tf_backtrace/backtrace/backtrace.py +5 -3
- dl_backtrace/tf_backtrace/backtrace/utils/utils_prop.py +53 -0
- dl_backtrace/version.py +2 -2
- dl_backtrace-0.0.17.dist-info/METADATA +164 -0
- dl_backtrace-0.0.17.dist-info/RECORD +44 -0
- dl_backtrace-0.0.16.dist-info/METADATA +0 -102
- dl_backtrace-0.0.16.dist-info/RECORD +0 -29
- {dl_backtrace-0.0.16.dist-info → dl_backtrace-0.0.17.dist-info}/LICENSE +0 -0
- {dl_backtrace-0.0.16.dist-info → dl_backtrace-0.0.17.dist-info}/WHEEL +0 -0
- {dl_backtrace-0.0.16.dist-info → dl_backtrace-0.0.17.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .backtrace import *
|
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import torch
|
|
3
|
+
import torch.nn as nn
|
|
4
|
+
from dl_backtrace.pytorch_backtrace.backtrace.utils import contrast as UC
|
|
5
|
+
from dl_backtrace.pytorch_backtrace.backtrace.utils import prop as UP
|
|
6
|
+
from dl_backtrace.pytorch_backtrace.backtrace.config import activation_master
|
|
7
|
+
|
|
8
|
+
class Backtrace(object):
|
|
9
|
+
"""
|
|
10
|
+
This is the constructor method for the Backtrace class. It initializes an instance of the class.
|
|
11
|
+
It takes two optional parameters: model (a neural network model) and activation_dict (a dictionary that maps layer names to activation functions).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, model=None, activation_dict={}):
|
|
15
|
+
|
|
16
|
+
# create a tree-like structure that represents the layers of the neural network model
|
|
17
|
+
self.create_tree(model)
|
|
18
|
+
|
|
19
|
+
# create a new model (an instance of tf.keras.Model) that produces the output of each layer in the neural network.
|
|
20
|
+
self.create_model_output(model)
|
|
21
|
+
|
|
22
|
+
# create a new model (an instance of tf.keras.Model) that produces the output of each layer in the neural network.
|
|
23
|
+
self.create_every_model_output(model)
|
|
24
|
+
|
|
25
|
+
# create a layer stack that defines the order in which layers should be processed during backpropagation.
|
|
26
|
+
self.create_layer_stack()
|
|
27
|
+
|
|
28
|
+
# checks if the model is sequential or not. If it's sequential, it adds the input layer to the layer stack.
|
|
29
|
+
# identity
|
|
30
|
+
|
|
31
|
+
inp_name = 'identity'
|
|
32
|
+
self.layer_stack.append(inp_name)
|
|
33
|
+
self.model_resource[1][inp_name] = {}
|
|
34
|
+
self.model_resource[1][inp_name]["name"] = inp_name
|
|
35
|
+
self.model_resource[1][inp_name]["type"] = "input"
|
|
36
|
+
self.model_resource[1][inp_name]["parent"] = []
|
|
37
|
+
self.model_resource[1][inp_name]["child"] = None
|
|
38
|
+
self.model_resource[3].append(inp_name)
|
|
39
|
+
self.sequential = True
|
|
40
|
+
try:
|
|
41
|
+
|
|
42
|
+
# calls the build_activation_dict method to build a dictionary that maps layer names to activation functions.
|
|
43
|
+
# If that fails, it creates a temporary dictionary with default activation functions.
|
|
44
|
+
if len(activation_dict) == 0:
|
|
45
|
+
self.build_activation_dict(model)
|
|
46
|
+
else:
|
|
47
|
+
self.activation_dict = activation_dict
|
|
48
|
+
|
|
49
|
+
except Exception as e:
|
|
50
|
+
print(e)
|
|
51
|
+
temp_dict = {}
|
|
52
|
+
for l in model.layers:
|
|
53
|
+
temp_dict[l.name] = activation_master["None"]
|
|
54
|
+
self.activation_dict = temp_dict
|
|
55
|
+
|
|
56
|
+
def build_activation_dict(self, model):
|
|
57
|
+
model_resource = self.model_resource
|
|
58
|
+
layer_list = list(model_resource[0].keys())
|
|
59
|
+
activation_dict = {}
|
|
60
|
+
activation_functions = ['relu', 'sigmoid', 'tanh', 'softmax'] # You can add more activation functions
|
|
61
|
+
|
|
62
|
+
for l in layer_list:
|
|
63
|
+
activation_found = False
|
|
64
|
+
|
|
65
|
+
try: # could be activation for that layer
|
|
66
|
+
for activation in activation_functions:
|
|
67
|
+
if activation in l.split('/')[1]:
|
|
68
|
+
activation_dict[l.split('/')[0]] = activation
|
|
69
|
+
activation_found = True
|
|
70
|
+
except:
|
|
71
|
+
activation_dict[l] = 'None'
|
|
72
|
+
|
|
73
|
+
# activation_master :
|
|
74
|
+
for key, value in activation_dict.items():
|
|
75
|
+
activation_dict[key] = activation_master.get(value)
|
|
76
|
+
self.activation_dict = activation_dict
|
|
77
|
+
|
|
78
|
+
def create_tree(self, model):
|
|
79
|
+
# create new layers same as tf version
|
|
80
|
+
layers = list(model.named_children())
|
|
81
|
+
|
|
82
|
+
activation_functions = ['relu', 'sigmoid', 'tanh', 'softmax']
|
|
83
|
+
layer_sequence = []
|
|
84
|
+
|
|
85
|
+
for i in range(len(layers) - 1):
|
|
86
|
+
current_layer, current_layer_obj = layers[i]
|
|
87
|
+
next_layer, next_layer_obj = layers[i + 1]
|
|
88
|
+
current_layer_name = current_layer
|
|
89
|
+
next_layer_name = next_layer
|
|
90
|
+
|
|
91
|
+
next_layer_type = next_layer_name.lower()
|
|
92
|
+
if any(af in next_layer_type for af in activation_functions):
|
|
93
|
+
layer_sequence.append((f"{current_layer_name}/{next_layer_name}", current_layer_obj))
|
|
94
|
+
i += 1
|
|
95
|
+
else:
|
|
96
|
+
if any(af in current_layer_name for af in activation_functions) is False:
|
|
97
|
+
layer_sequence.append((current_layer_name, current_layer_obj))
|
|
98
|
+
|
|
99
|
+
# creating model_resource variable
|
|
100
|
+
layer_sequence
|
|
101
|
+
ltree = {}
|
|
102
|
+
layer_tree = {}
|
|
103
|
+
inputs = []
|
|
104
|
+
outputs = []
|
|
105
|
+
intermediates = []
|
|
106
|
+
|
|
107
|
+
prev_layer_id = None
|
|
108
|
+
|
|
109
|
+
num_layers = len(layer_sequence)
|
|
110
|
+
|
|
111
|
+
for i, (layer_name, layer) in enumerate(layer_sequence):
|
|
112
|
+
layer_id = layer_name
|
|
113
|
+
ltree[layer_id] = {}
|
|
114
|
+
layer_tree[layer_id] = layer
|
|
115
|
+
|
|
116
|
+
layer_type = layer.__class__.__name__
|
|
117
|
+
ltree[layer_id]["name"] = layer_id.split("/")[0]
|
|
118
|
+
ltree[layer_id]["class"] = layer_type
|
|
119
|
+
|
|
120
|
+
if i < num_layers - 1:
|
|
121
|
+
ltree[layer_id]["type"] = "intermediate"
|
|
122
|
+
intermediates.append(layer_id)
|
|
123
|
+
else:
|
|
124
|
+
ltree[layer_id]["type"] = "output"
|
|
125
|
+
outputs.append(layer_id)
|
|
126
|
+
|
|
127
|
+
if prev_layer_id is not None:
|
|
128
|
+
ltree[layer_id]["child"] = [prev_layer_id]
|
|
129
|
+
ltree[prev_layer_id]["parent"] = [layer_id]
|
|
130
|
+
|
|
131
|
+
prev_layer_id = layer_id
|
|
132
|
+
|
|
133
|
+
# Set child of the last layer as an empty list
|
|
134
|
+
if prev_layer_id is not None:
|
|
135
|
+
ltree[prev_layer_id]["parent"] = []
|
|
136
|
+
|
|
137
|
+
layer_tree.pop('identity')
|
|
138
|
+
ltree.pop('identity')
|
|
139
|
+
self.model_resource = (layer_tree, ltree, outputs, inputs)
|
|
140
|
+
|
|
141
|
+
def create_layer_stack(self):
|
|
142
|
+
model_resource = self.model_resource
|
|
143
|
+
start_layer = model_resource[2][0]
|
|
144
|
+
layer_stack = [start_layer]
|
|
145
|
+
temp_stack = [start_layer]
|
|
146
|
+
while len(layer_stack) < len(model_resource[0]):
|
|
147
|
+
start_layer = temp_stack.pop(0)
|
|
148
|
+
if model_resource[1][start_layer]["child"]:
|
|
149
|
+
child_nodes = model_resource[1][start_layer]["child"]
|
|
150
|
+
for ch in child_nodes:
|
|
151
|
+
node_check = True
|
|
152
|
+
for pa in model_resource[1][ch]["parent"]:
|
|
153
|
+
if pa not in layer_stack:
|
|
154
|
+
node_check = False
|
|
155
|
+
break
|
|
156
|
+
if node_check:
|
|
157
|
+
if ch not in layer_stack:
|
|
158
|
+
layer_stack.append(ch)
|
|
159
|
+
temp_stack.append(ch)
|
|
160
|
+
self.layer_stack = layer_stack
|
|
161
|
+
|
|
162
|
+
def create_every_model_output(self, model):
|
|
163
|
+
class ModelWithEveryOutputs(nn.Module):
|
|
164
|
+
def __init__(self, base_model):
|
|
165
|
+
super(ModelWithEveryOutputs, self).__init__()
|
|
166
|
+
self.base_model = base_model
|
|
167
|
+
|
|
168
|
+
def forward(self, x):
|
|
169
|
+
outputs = []
|
|
170
|
+
for layer_name, layer in self.base_model._modules.items():
|
|
171
|
+
if isinstance(x, tuple):
|
|
172
|
+
if isinstance(layer, nn.LSTM):
|
|
173
|
+
# Assuming you want to take the last LSTM output
|
|
174
|
+
x, _ = layer(x[0]) # Pass the first element of the tuple (assumes one LSTM layer)
|
|
175
|
+
else:
|
|
176
|
+
x = layer(x[0]) # Pass the first element of the tuple
|
|
177
|
+
else:
|
|
178
|
+
x = layer(x)
|
|
179
|
+
outputs.append((layer_name, x))
|
|
180
|
+
return outputs
|
|
181
|
+
|
|
182
|
+
self.every_out_model = ModelWithEveryOutputs(model)
|
|
183
|
+
|
|
184
|
+
def create_model_output(self, model):
|
|
185
|
+
class ModelWithOutputs(nn.Module):
|
|
186
|
+
def __init__(self, base_model):
|
|
187
|
+
super(ModelWithOutputs, self).__init__()
|
|
188
|
+
self.base_model = base_model
|
|
189
|
+
|
|
190
|
+
def forward(self, x):
|
|
191
|
+
outputs = []
|
|
192
|
+
for layer_name, layer in self.base_model._modules.items():
|
|
193
|
+
if isinstance(layer, nn.LSTM):
|
|
194
|
+
lstm_output, _ = layer(x)
|
|
195
|
+
if lstm_output.dim() == 3:
|
|
196
|
+
x = lstm_output[:, -1, :] # Take the output of the last time step
|
|
197
|
+
else:
|
|
198
|
+
x = lstm_output
|
|
199
|
+
else:
|
|
200
|
+
x = layer(x)
|
|
201
|
+
outputs.append((layer_name, x))
|
|
202
|
+
return outputs
|
|
203
|
+
|
|
204
|
+
# all_out_model = ModelWithOutputs(model)
|
|
205
|
+
self.all_out_model = ModelWithOutputs(model)
|
|
206
|
+
model.eval()
|
|
207
|
+
model_resource = self.model_resource
|
|
208
|
+
self.layers = [[], []]
|
|
209
|
+
for l in model_resource[0]:
|
|
210
|
+
self.layers[0].append(l)
|
|
211
|
+
self.layers[1].append(model_resource[0][l])
|
|
212
|
+
|
|
213
|
+
def predict_every(self, inputs):
|
|
214
|
+
every_out = self.every_out_model(inputs)
|
|
215
|
+
activation_functions = ['relu', 'sigmoid', 'tanh', 'softmax']
|
|
216
|
+
every_temp_out = {}
|
|
217
|
+
|
|
218
|
+
for i in range(len(every_out)):
|
|
219
|
+
|
|
220
|
+
current_layer, current_layer_obj = every_out[i]
|
|
221
|
+
try:
|
|
222
|
+
next_layer, next_layer_obj = every_out[i + 1]
|
|
223
|
+
|
|
224
|
+
current_layer_name = current_layer
|
|
225
|
+
next_layer_name = next_layer
|
|
226
|
+
|
|
227
|
+
next_layer_type = next_layer_name.lower()
|
|
228
|
+
if any(af in next_layer_type for af in activation_functions):
|
|
229
|
+
if isinstance(next_layer_obj, tuple):
|
|
230
|
+
# Assuming you want the first tensor from the tuple
|
|
231
|
+
next_layer_tensor = next_layer_obj[0]
|
|
232
|
+
else:
|
|
233
|
+
next_layer_tensor = next_layer_obj
|
|
234
|
+
|
|
235
|
+
every_temp_out[
|
|
236
|
+
f"{current_layer_name}/{next_layer_name}"] = next_layer_tensor.detach().numpy().astype(
|
|
237
|
+
np.float32)
|
|
238
|
+
i += 1
|
|
239
|
+
|
|
240
|
+
else:
|
|
241
|
+
if any(af in current_layer_name for af in activation_functions) is False:
|
|
242
|
+
if isinstance(current_layer_obj, tuple):
|
|
243
|
+
# Assuming you want the first tensor from the tuple
|
|
244
|
+
current_layer_tensor = current_layer_obj[0]
|
|
245
|
+
else:
|
|
246
|
+
current_layer_tensor = current_layer_obj
|
|
247
|
+
|
|
248
|
+
every_temp_out[current_layer_name] = current_layer_tensor.detach().numpy().astype(np.float32)
|
|
249
|
+
except:
|
|
250
|
+
if any(af in next_layer_type for af in activation_functions):
|
|
251
|
+
pass
|
|
252
|
+
|
|
253
|
+
else:
|
|
254
|
+
if any(af in current_layer for af in activation_functions) is False:
|
|
255
|
+
if isinstance(current_layer_obj, tuple):
|
|
256
|
+
# Assuming you want the first tensor from the tuple
|
|
257
|
+
current_layer_tensor = current_layer_obj[0]
|
|
258
|
+
else:
|
|
259
|
+
current_layer_tensor = current_layer_obj
|
|
260
|
+
|
|
261
|
+
every_temp_out[current_layer] = current_layer_tensor.detach().cpu().numpy().astype(np.float32)
|
|
262
|
+
return every_temp_out
|
|
263
|
+
|
|
264
|
+
def predict(self, inputs):
|
|
265
|
+
all_out = self.all_out_model(inputs)
|
|
266
|
+
activation_functions = ['relu', 'sigmoid', 'tanh', 'softmax']
|
|
267
|
+
temp_out = {}
|
|
268
|
+
|
|
269
|
+
for i in range(len(all_out)):
|
|
270
|
+
|
|
271
|
+
current_layer, current_layer_obj = all_out[i]
|
|
272
|
+
try:
|
|
273
|
+
next_layer, next_layer_obj = all_out[i + 1]
|
|
274
|
+
|
|
275
|
+
current_layer_name = current_layer
|
|
276
|
+
next_layer_name = next_layer
|
|
277
|
+
|
|
278
|
+
next_layer_type = next_layer_name.lower()
|
|
279
|
+
if any(af in next_layer_type for af in activation_functions):
|
|
280
|
+
if isinstance(next_layer_obj, tuple):
|
|
281
|
+
# Assuming you want the first tensor from the tuple
|
|
282
|
+
next_layer_tensor = next_layer_obj[0]
|
|
283
|
+
else:
|
|
284
|
+
next_layer_tensor = next_layer_obj
|
|
285
|
+
|
|
286
|
+
temp_out[
|
|
287
|
+
f"{current_layer_name}/{next_layer_name}"] = next_layer_tensor.detach().cpu().numpy().astype(
|
|
288
|
+
np.float32)
|
|
289
|
+
i += 1
|
|
290
|
+
|
|
291
|
+
else:
|
|
292
|
+
if any(af in current_layer_name for af in activation_functions) is False:
|
|
293
|
+
if isinstance(current_layer_obj, tuple):
|
|
294
|
+
# Assuming you want the first tensor from the tuple
|
|
295
|
+
current_layer_tensor = current_layer_obj[0]
|
|
296
|
+
else:
|
|
297
|
+
current_layer_tensor = current_layer_obj
|
|
298
|
+
|
|
299
|
+
temp_out[current_layer_name] = current_layer_tensor.detach().numpy().astype(np.float32)
|
|
300
|
+
except:
|
|
301
|
+
if any(af in next_layer_type for af in activation_functions):
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
else:
|
|
305
|
+
if any(af in current_layer for af in activation_functions) is False:
|
|
306
|
+
if isinstance(current_layer_obj, tuple):
|
|
307
|
+
# Assuming you want the first tensor from the tuple
|
|
308
|
+
current_layer_tensor = current_layer_obj[0]
|
|
309
|
+
else:
|
|
310
|
+
current_layer_tensor = current_layer_obj
|
|
311
|
+
|
|
312
|
+
temp_out[current_layer] = current_layer_tensor.detach().cpu().numpy().astype(np.float32)
|
|
313
|
+
|
|
314
|
+
return temp_out
|
|
315
|
+
|
|
316
|
+
def eval(
|
|
317
|
+
self,
|
|
318
|
+
all_out,
|
|
319
|
+
mode,
|
|
320
|
+
start_wt=[],
|
|
321
|
+
multiplier=100.0,
|
|
322
|
+
scaler=0,
|
|
323
|
+
max_unit=0,
|
|
324
|
+
):
|
|
325
|
+
# This method is used for evaluating layer-wise relevance based on different modes.
|
|
326
|
+
if mode == "default":
|
|
327
|
+
output = self.proportional_eval(
|
|
328
|
+
all_out=all_out,
|
|
329
|
+
start_wt=start_wt,
|
|
330
|
+
multiplier=multiplier,
|
|
331
|
+
scaler=0,
|
|
332
|
+
max_unit=0,
|
|
333
|
+
)
|
|
334
|
+
return output
|
|
335
|
+
elif mode == "contrast":
|
|
336
|
+
temp_output = self.contrast_eval(all_out=all_out, multiplier=multiplier)
|
|
337
|
+
output = {}
|
|
338
|
+
for k in temp_output[0].keys():
|
|
339
|
+
output[k] = {}
|
|
340
|
+
output[k]["Positive"] = temp_output[0][k]
|
|
341
|
+
output[k]["Negative"] = temp_output[1][k]
|
|
342
|
+
return output
|
|
343
|
+
|
|
344
|
+
def proportional_eval(
|
|
345
|
+
self, all_out, start_wt=[], multiplier=100.0, scaler=0, max_unit=0
|
|
346
|
+
):
|
|
347
|
+
model_resource = self.model_resource
|
|
348
|
+
activation_dict = self.activation_dict
|
|
349
|
+
inputcheck = False
|
|
350
|
+
out_layer = model_resource[2][0]
|
|
351
|
+
all_wt = {}
|
|
352
|
+
if len(start_wt) == 0:
|
|
353
|
+
start_wt = UP.calculate_start_wt(all_out[out_layer])
|
|
354
|
+
all_wt[out_layer] = start_wt * multiplier
|
|
355
|
+
layer_stack = self.layer_stack
|
|
356
|
+
|
|
357
|
+
for start_layer in layer_stack:
|
|
358
|
+
if model_resource[1][start_layer]["child"]:
|
|
359
|
+
child_nodes = model_resource[1][start_layer]["child"]
|
|
360
|
+
for ch in child_nodes:
|
|
361
|
+
if ch not in all_wt:
|
|
362
|
+
if model_resource[1][start_layer]["class"] == 'LSTM':
|
|
363
|
+
all_wt[ch] = np.zeros_like(every_temp_out[ch][0])
|
|
364
|
+
else:
|
|
365
|
+
all_wt[ch] = np.zeros_like(all_out[ch][0])
|
|
366
|
+
|
|
367
|
+
if model_resource[1][start_layer]["class"] == "Linear":
|
|
368
|
+
l1 = model_resource[0][start_layer]
|
|
369
|
+
w1 = l1.state_dict()['weight']
|
|
370
|
+
b1 = l1.state_dict()['bias']
|
|
371
|
+
temp_wt = UP.calculate_wt_fc(
|
|
372
|
+
all_wt[start_layer],
|
|
373
|
+
all_out[child_nodes[0]][0],
|
|
374
|
+
w1,
|
|
375
|
+
b1,
|
|
376
|
+
activation_dict[model_resource[1][start_layer]["name"]],
|
|
377
|
+
)
|
|
378
|
+
all_wt[child_nodes[0]] += temp_wt
|
|
379
|
+
elif model_resource[1][start_layer]["class"] == "Conv2d":
|
|
380
|
+
l1 = model_resource[0][start_layer]
|
|
381
|
+
w1 = l1.state_dict()['weight']
|
|
382
|
+
b1 = l1.state_dict()['bias']
|
|
383
|
+
temp_wt = UP.calculate_wt_conv(
|
|
384
|
+
all_wt[start_layer],
|
|
385
|
+
all_out[child_nodes[0]][0],
|
|
386
|
+
w1,
|
|
387
|
+
b1,
|
|
388
|
+
activation_dict[model_resource[1][start_layer]["name"]],
|
|
389
|
+
)
|
|
390
|
+
all_wt[child_nodes[0]] += temp_wt.T
|
|
391
|
+
elif model_resource[1][start_layer]["class"] == "Reshape":
|
|
392
|
+
temp_wt = UP.calculate_wt_rshp(
|
|
393
|
+
all_wt[start_layer], all_out[child_nodes[0]][0]
|
|
394
|
+
)
|
|
395
|
+
all_wt[child_nodes[0]] += temp_wt
|
|
396
|
+
elif model_resource[1][start_layer]["class"] == "Flatten":
|
|
397
|
+
temp_wt = UP.calculate_wt_rshp(
|
|
398
|
+
all_wt[start_layer], all_out[child_nodes[0]][0]
|
|
399
|
+
)
|
|
400
|
+
all_wt[child_nodes[0]] += temp_wt
|
|
401
|
+
elif (
|
|
402
|
+
model_resource[1][start_layer]["class"] == "AdaptiveAvgPool2d"
|
|
403
|
+
):
|
|
404
|
+
temp_wt = UP.calculate_wt_gavgpool(
|
|
405
|
+
all_wt[start_layer], all_out[child_nodes[0]][0]
|
|
406
|
+
)
|
|
407
|
+
all_wt[child_nodes[0]] += temp_wt.T
|
|
408
|
+
elif model_resource[1][start_layer]["class"] == "MaxPool2d":
|
|
409
|
+
l1 = model_resource[0][start_layer]
|
|
410
|
+
temp_wt = UP.calculate_wt_maxpool(
|
|
411
|
+
all_wt[start_layer], all_out[child_nodes[0]][0], (l1.kernel_size, l1.kernel_size)
|
|
412
|
+
)
|
|
413
|
+
all_wt[child_nodes[0]] += temp_wt.T
|
|
414
|
+
elif model_resource[1][start_layer]["class"] == "AvgPool2d":
|
|
415
|
+
l1 = model_resource[0][start_layer]
|
|
416
|
+
temp_wt = UP.calculate_wt_avgpool(
|
|
417
|
+
all_wt[start_layer], all_out[child_nodes[0]][0], (l1.kernel_size, l1.kernel_size)
|
|
418
|
+
)
|
|
419
|
+
all_wt[child_nodes[0]] += temp_wt.T
|
|
420
|
+
elif model_resource[1][start_layer]["class"] == "Concatenate":
|
|
421
|
+
temp_wt = UP.calculate_wt_concat(
|
|
422
|
+
all_wt[start_layer],
|
|
423
|
+
[all_out[ch] for ch in child_nodes],
|
|
424
|
+
model_resource[0][start_layer].axis,
|
|
425
|
+
)
|
|
426
|
+
for ind, ch in enumerate(child_nodes):
|
|
427
|
+
all_wt[ch] += temp_wt[ind]
|
|
428
|
+
elif model_resource[1][start_layer]["class"] == "Add":
|
|
429
|
+
temp_wt = UP.calculate_wt_add(
|
|
430
|
+
all_wt[start_layer], [all_out[ch] for ch in child_nodes]
|
|
431
|
+
)
|
|
432
|
+
for ind, ch in enumerate(child_nodes):
|
|
433
|
+
all_wt[ch] += temp_wt[ind]
|
|
434
|
+
elif model_resource[1][start_layer]["class"] == "LSTM":
|
|
435
|
+
l1 = model_resource[0][start_layer]
|
|
436
|
+
return_sequence = l1.return_sequences
|
|
437
|
+
units = l1.units
|
|
438
|
+
num_of_cells = l1.input_shape[1]
|
|
439
|
+
lstm_obj_f = UP.LSTM_forward(
|
|
440
|
+
num_of_cells, units, l1.weights, return_sequence, False
|
|
441
|
+
)
|
|
442
|
+
lstm_obj_b = UP.LSTM_backtrace(
|
|
443
|
+
num_of_cells,
|
|
444
|
+
units,
|
|
445
|
+
[i.numpy() for i in l1.weights],
|
|
446
|
+
return_sequence,
|
|
447
|
+
False,
|
|
448
|
+
)
|
|
449
|
+
temp_out_f = lstm_obj_f.calculate_lstm_wt(
|
|
450
|
+
every_temp_out[child_nodes[0]][0]
|
|
451
|
+
)
|
|
452
|
+
temp_wt = lstm_obj_b.calculate_lstm_wt(
|
|
453
|
+
all_wt[start_layer], lstm_obj_f.compute_log
|
|
454
|
+
)
|
|
455
|
+
all_wt[child_nodes[0]] += temp_wt
|
|
456
|
+
else:
|
|
457
|
+
temp_wt = all_wt[start_layer]
|
|
458
|
+
all_wt[child_nodes[0]] += temp_wt
|
|
459
|
+
if max_unit > 0 and scaler == 0:
|
|
460
|
+
temp_dict = {}
|
|
461
|
+
for k in all_wt.keys():
|
|
462
|
+
temp_dict[k] = UC.weight_normalize(all_wt[k], max_val=max_unit)
|
|
463
|
+
all_wt = temp_dict
|
|
464
|
+
elif scaler > 0:
|
|
465
|
+
temp_dict = {}
|
|
466
|
+
for k in all_wt.keys():
|
|
467
|
+
temp_dict[k] = UC.weight_scaler(all_wt[k], scaler=scaler)
|
|
468
|
+
all_wt = temp_dict
|
|
469
|
+
|
|
470
|
+
return all_wt
|
|
471
|
+
|
|
472
|
+
def contrast_eval(self, all_out, multiplier=100.0):
|
|
473
|
+
model_resource = self.model_resource
|
|
474
|
+
activation_dict = self.activation_dict
|
|
475
|
+
inputcheck = False
|
|
476
|
+
out_layer = model_resource[2][0]
|
|
477
|
+
all_wt_pos = {}
|
|
478
|
+
all_wt_neg = {}
|
|
479
|
+
start_wt_pos, start_wt_neg = UC.calculate_start_wt(all_out[out_layer])
|
|
480
|
+
all_wt_pos[out_layer] = start_wt_pos * multiplier
|
|
481
|
+
all_wt_neg[out_layer] = start_wt_neg * multiplier
|
|
482
|
+
layer_stack = [out_layer]
|
|
483
|
+
|
|
484
|
+
while len(layer_stack) > 0:
|
|
485
|
+
start_layer = layer_stack.pop(0)
|
|
486
|
+
if model_resource[1][start_layer]["child"]:
|
|
487
|
+
child_nodes = model_resource[1][start_layer]["child"]
|
|
488
|
+
for ch in child_nodes:
|
|
489
|
+
if ch not in all_wt_pos:
|
|
490
|
+
all_wt_pos[ch] = np.zeros_like(all_out[ch][0])
|
|
491
|
+
all_wt_neg[ch] = np.zeros_like(all_out[ch][0])
|
|
492
|
+
if model_resource[1][start_layer]["class"] == "Linear":
|
|
493
|
+
l1 = model_resource[0][start_layer]
|
|
494
|
+
w1 = l1.state_dict()['weight']
|
|
495
|
+
b1 = l1.state_dict()['bias']
|
|
496
|
+
temp_wt_pos, temp_wt_neg = UC.calculate_wt_fc(
|
|
497
|
+
all_wt_pos[start_layer],
|
|
498
|
+
all_wt_neg[start_layer],
|
|
499
|
+
all_out[child_nodes[0]][0],
|
|
500
|
+
w1,
|
|
501
|
+
b1,
|
|
502
|
+
activation_dict[model_resource[1][start_layer]["name"]],
|
|
503
|
+
)
|
|
504
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos
|
|
505
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg
|
|
506
|
+
elif model_resource[1][start_layer]["class"] == "Conv2d":
|
|
507
|
+
l1 = model_resource[0][start_layer]
|
|
508
|
+
w1 = l1.state_dict()['weight']
|
|
509
|
+
b1 = l1.state_dict()['bias']
|
|
510
|
+
temp_wt_pos, temp_wt_neg = UC.calculate_wt_conv(
|
|
511
|
+
all_wt_pos[start_layer],
|
|
512
|
+
all_wt_neg[start_layer],
|
|
513
|
+
all_out[child_nodes[0]][0],
|
|
514
|
+
w1,
|
|
515
|
+
b1,
|
|
516
|
+
activation_dict[model_resource[1][start_layer]["name"]],
|
|
517
|
+
)
|
|
518
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos.T
|
|
519
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg.T
|
|
520
|
+
elif model_resource[1][start_layer]["class"] == "Reshape":
|
|
521
|
+
temp_wt_pos = UC.calculate_wt_rshp(
|
|
522
|
+
all_wt_pos[start_layer], all_out[child_nodes[0]][0]
|
|
523
|
+
)
|
|
524
|
+
temp_wt_neg = UC.calculate_wt_rshp(
|
|
525
|
+
all_wt_neg[start_layer], all_out[child_nodes[0]][0]
|
|
526
|
+
)
|
|
527
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos
|
|
528
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg
|
|
529
|
+
elif (
|
|
530
|
+
model_resource[1][start_layer]["class"] == "AdaptiveAvgPool2d"
|
|
531
|
+
):
|
|
532
|
+
temp_wt_pos, temp_wt_neg = UC.calculate_wt_gavgpool(
|
|
533
|
+
all_wt_pos[start_layer],
|
|
534
|
+
all_wt_neg[start_layer],
|
|
535
|
+
all_out[child_nodes[0]][0],
|
|
536
|
+
)
|
|
537
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos.T
|
|
538
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg.T
|
|
539
|
+
elif model_resource[1][start_layer]["class"] == "Flatten":
|
|
540
|
+
temp_wt = UC.calculate_wt_rshp(
|
|
541
|
+
all_wt_pos[start_layer], all_out[child_nodes[0]][0]
|
|
542
|
+
)
|
|
543
|
+
all_wt_pos[child_nodes[0]] += temp_wt
|
|
544
|
+
temp_wt = UC.calculate_wt_rshp(
|
|
545
|
+
all_wt_neg[start_layer], all_out[child_nodes[0]][0]
|
|
546
|
+
)
|
|
547
|
+
all_wt_neg[child_nodes[0]] += temp_wt
|
|
548
|
+
elif (
|
|
549
|
+
model_resource[1][start_layer]["class"] == "AdaptiveAvgPool2d"
|
|
550
|
+
):
|
|
551
|
+
temp_wt_pos, temp_wt_neg = UC.calculate_wt_gavgpool(
|
|
552
|
+
all_wt_pos[start_layer],
|
|
553
|
+
all_wt_neg[start_layer],
|
|
554
|
+
all_out[child_nodes[0]][0],
|
|
555
|
+
)
|
|
556
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos.T
|
|
557
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg.T
|
|
558
|
+
elif model_resource[1][start_layer]["class"] == "MaxPool2d":
|
|
559
|
+
l1 = model_resource[0][start_layer]
|
|
560
|
+
temp_wt = UC.calculate_wt_maxpool(
|
|
561
|
+
all_wt_pos[start_layer],
|
|
562
|
+
all_out[child_nodes[0]][0],
|
|
563
|
+
(l1.kernel_size, l1.kernel_size),
|
|
564
|
+
)
|
|
565
|
+
all_wt_pos[child_nodes[0]] += temp_wt.T
|
|
566
|
+
temp_wt = UC.calculate_wt_maxpool(
|
|
567
|
+
all_wt_neg[start_layer],
|
|
568
|
+
all_out[child_nodes[0]][0],
|
|
569
|
+
(l1.kernel_size, l1.kernel_size),
|
|
570
|
+
)
|
|
571
|
+
all_wt_neg[child_nodes[0]] += temp_wt.T
|
|
572
|
+
elif model_resource[1][start_layer]["class"] == "AvgPool2d":
|
|
573
|
+
l1 = model_resource[0][start_layer]
|
|
574
|
+
temp_wt_pos, temp_wt_neg = UC.calculate_wt_avgpool(
|
|
575
|
+
all_wt_pos[start_layer],
|
|
576
|
+
all_wt_neg[start_layer],
|
|
577
|
+
all_out[child_nodes[0]][0],
|
|
578
|
+
(l1.kernel_size, l1.kernel_size),
|
|
579
|
+
)
|
|
580
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos.T
|
|
581
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg.T
|
|
582
|
+
elif model_resource[1][start_layer]["class"] == "Concatenate":
|
|
583
|
+
temp_wt = UC.calculate_wt_concat(
|
|
584
|
+
all_wt_pos[start_layer],
|
|
585
|
+
[all_out[ch] for ch in child_nodes],
|
|
586
|
+
model_resource[0][start_layer].axis,
|
|
587
|
+
)
|
|
588
|
+
for ind, ch in enumerate(child_nodes):
|
|
589
|
+
all_wt_pos[ch] += temp_wt[ind]
|
|
590
|
+
temp_wt = UC.calculate_wt_concat(
|
|
591
|
+
all_wt_neg[start_layer],
|
|
592
|
+
[all_out[ch] for ch in child_nodes],
|
|
593
|
+
model_resource[0][start_layer].axis,
|
|
594
|
+
)
|
|
595
|
+
for ind, ch in enumerate(child_nodes):
|
|
596
|
+
all_wt_neg[ch] += temp_wt[ind]
|
|
597
|
+
elif model_resource[1][start_layer]["class"] == "Add":
|
|
598
|
+
temp_wt = UC.calculate_wt_add(
|
|
599
|
+
all_wt_pos[start_layer],
|
|
600
|
+
all_wt_neg[start_layer],
|
|
601
|
+
[all_out[ch] for ch in child_nodes],
|
|
602
|
+
)
|
|
603
|
+
for ind, ch in enumerate(child_nodes):
|
|
604
|
+
all_wt_pos[ch] += temp_wt[ind][0]
|
|
605
|
+
all_wt_neg[ch] += temp_wt[ind][1]
|
|
606
|
+
elif model_resource[1][start_layer]["class"] == "LSTM":
|
|
607
|
+
l1 = model_resource[0][start_layer]
|
|
608
|
+
return_sequence = l1.return_sequences
|
|
609
|
+
units = l1.units
|
|
610
|
+
num_of_cells = l1.input_shape[1]
|
|
611
|
+
lstm_obj_f = UC.LSTM_forward(
|
|
612
|
+
num_of_cells, units, l1.weights, return_sequence, False
|
|
613
|
+
)
|
|
614
|
+
lstm_obj_b = UC.LSTM_backtrace(
|
|
615
|
+
num_of_cells,
|
|
616
|
+
units,
|
|
617
|
+
[i.numpy() for i in l1.weights],
|
|
618
|
+
return_sequence,
|
|
619
|
+
False,
|
|
620
|
+
)
|
|
621
|
+
temp_out_f = lstm_obj_f.calculate_lstm_wt(
|
|
622
|
+
all_out[child_nodes[0]][0]
|
|
623
|
+
)
|
|
624
|
+
temp_wt_pos, temp_wt_neg = lstm_obj_b.calculate_lstm_wt(
|
|
625
|
+
all_wt_pos[start_layer],
|
|
626
|
+
all_wt_neg[start_layer],
|
|
627
|
+
lstm_obj_f.compute_log,
|
|
628
|
+
)
|
|
629
|
+
all_wt_pos[child_nodes[0]] = temp_wt_pos
|
|
630
|
+
all_wt_neg[child_nodes[0]] = temp_wt_neg
|
|
631
|
+
else:
|
|
632
|
+
temp_wt_pos = all_wt_pos[start_layer]
|
|
633
|
+
temp_wt_neg = all_wt_neg[start_layer]
|
|
634
|
+
all_wt_pos[child_nodes[0]] += temp_wt_pos
|
|
635
|
+
all_wt_neg[child_nodes[0]] += temp_wt_neg
|
|
636
|
+
for ch in child_nodes:
|
|
637
|
+
if not (ch in layer_stack):
|
|
638
|
+
layer_stack.append(ch)
|
|
639
|
+
return all_wt_pos, all_wt_neg
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from dl_backtrace.pytorch_backtrace.backtrace.utils.prop import np_swish
|
|
2
|
+
|
|
3
|
+
activation_master = {
|
|
4
|
+
"None": {
|
|
5
|
+
"name": None,
|
|
6
|
+
"range": {"l": None, "u": None},
|
|
7
|
+
"type": "null",
|
|
8
|
+
"func": None,
|
|
9
|
+
},
|
|
10
|
+
"linear": {
|
|
11
|
+
"name": None,
|
|
12
|
+
"range": {"l": None, "u": None},
|
|
13
|
+
"type": "mono",
|
|
14
|
+
"func": None,
|
|
15
|
+
},
|
|
16
|
+
"tanh": {"name": "tanh", "range": {"l": -2, "u": 2}, "type": "mono", "func": None},
|
|
17
|
+
"sigmoid": {
|
|
18
|
+
"name": "sigmoid",
|
|
19
|
+
"range": {"l": -4, "u": 4},
|
|
20
|
+
"type": "mono",
|
|
21
|
+
"func": None,
|
|
22
|
+
},
|
|
23
|
+
"relu": {
|
|
24
|
+
"name": "relu",
|
|
25
|
+
"range": {"l": 0, "u": None},
|
|
26
|
+
"type": "mono",
|
|
27
|
+
"func": None,
|
|
28
|
+
},
|
|
29
|
+
"swish": {
|
|
30
|
+
"name": "swish",
|
|
31
|
+
"range": {"l": -6, "u": None},
|
|
32
|
+
"type": "non_mono",
|
|
33
|
+
"func": np_swish,
|
|
34
|
+
},
|
|
35
|
+
"softmax": {
|
|
36
|
+
"name": "softmax",
|
|
37
|
+
"range": {"l": -1, "u": 2},
|
|
38
|
+
"type": "mono",
|
|
39
|
+
"func": None,
|
|
40
|
+
},
|
|
41
|
+
}
|