dl-backtrace 0.0.12__py3-none-any.whl → 0.0.16__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.

Files changed (27) hide show
  1. dl_backtrace/pytorch_backtrace/backtrace/backtrace.py +173 -44
  2. dl_backtrace/pytorch_backtrace/backtrace/utils/__init__.py +3 -0
  3. dl_backtrace/pytorch_backtrace/backtrace/utils/encoder.py +183 -0
  4. dl_backtrace/pytorch_backtrace/backtrace/utils/encoder_decoder.py +489 -0
  5. dl_backtrace/pytorch_backtrace/backtrace/utils/helper.py +95 -0
  6. dl_backtrace/pytorch_backtrace/backtrace/utils/prop.py +481 -0
  7. dl_backtrace/tf_backtrace/backtrace/__init__.py +1 -2
  8. dl_backtrace/tf_backtrace/backtrace/activation_info.py +33 -0
  9. dl_backtrace/tf_backtrace/backtrace/backtrace.py +506 -279
  10. dl_backtrace/tf_backtrace/backtrace/models.py +25 -0
  11. dl_backtrace/tf_backtrace/backtrace/server.py +27 -0
  12. dl_backtrace/tf_backtrace/backtrace/utils/__init__.py +5 -2
  13. dl_backtrace/tf_backtrace/backtrace/utils/encoder.py +206 -0
  14. dl_backtrace/tf_backtrace/backtrace/utils/encoder_decoder.py +501 -0
  15. dl_backtrace/tf_backtrace/backtrace/utils/helper.py +99 -0
  16. dl_backtrace/tf_backtrace/backtrace/utils/utils_contrast.py +1132 -0
  17. dl_backtrace/tf_backtrace/backtrace/utils/utils_prop.py +1582 -0
  18. dl_backtrace/version.py +2 -2
  19. {dl_backtrace-0.0.12.dist-info → dl_backtrace-0.0.16.dist-info}/METADATA +3 -2
  20. dl_backtrace-0.0.16.dist-info/RECORD +29 -0
  21. {dl_backtrace-0.0.12.dist-info → dl_backtrace-0.0.16.dist-info}/WHEEL +1 -1
  22. dl_backtrace/tf_backtrace/backtrace/config.py +0 -41
  23. dl_backtrace/tf_backtrace/backtrace/utils/contrast.py +0 -834
  24. dl_backtrace/tf_backtrace/backtrace/utils/prop.py +0 -725
  25. dl_backtrace-0.0.12.dist-info/RECORD +0 -21
  26. {dl_backtrace-0.0.12.dist-info → dl_backtrace-0.0.16.dist-info}/LICENSE +0 -0
  27. {dl_backtrace-0.0.12.dist-info → dl_backtrace-0.0.16.dist-info}/top_level.txt +0 -0
@@ -1,84 +1,111 @@
1
- import numpy as np
2
- from tensorflow.keras import Model
1
+ import gc
2
+ from datetime import datetime
3
+ from tqdm import tqdm
4
+ import tensorflow.keras as keras
5
+ import numpy as np
6
+ import tensorflow as tf
7
+ from dl_backtrace.tf_backtrace.backtrace.utils import utils_prop as UP
8
+ from dl_backtrace.tf_backtrace.backtrace.utils import utils_contrast as UC
9
+ from dl_backtrace.tf_backtrace.backtrace.activation_info import activation_master
10
+ from dl_backtrace.tf_backtrace.backtrace.utils import encoder as EN
11
+ from dl_backtrace.tf_backtrace.backtrace.utils import encoder_decoder as ED
12
+ from dl_backtrace.tf_backtrace.backtrace.utils import helper as HP
3
13
 
4
- from dl_backtrace.tf_backtrace.backtrace.config import activation_master
5
- from dl_backtrace.tf_backtrace.backtrace.utils import contrast as UC
6
- from dl_backtrace.tf_backtrace.backtrace.utils import prop as UP
14
+ from tensorflow.keras import backend as K
15
+ from tensorflow.keras import losses
16
+ from tensorflow.keras.backend import sigmoid
17
+ from tensorflow.keras.layers import (
18
+ LSTM,
19
+ Activation,
20
+ Add,
21
+ AveragePooling2D,
22
+ BatchNormalization,
23
+ Concatenate,
24
+ Conv2D,
25
+ Dense,
26
+ Dropout,
27
+ Flatten,
28
+ GlobalAveragePooling2D,
29
+ GlobalMaxPooling2D,
30
+ Input,
31
+ MaxPooling2D,
32
+ Reshape,
33
+ )
34
+ from tensorflow.keras.models import Model, Sequential
35
+ from tensorflow.keras.optimizers import SGD, Adadelta, Adagrad, Adam, Adamax, Nadam, RMSprop
36
+ from tensorflow.keras.regularizers import l2
37
+ from tensorflow.keras.utils import get_custom_objects
38
+ from numpy.lib.stride_tricks import as_strided
7
39
 
8
40
 
9
41
  class Backtrace(object):
10
- """
11
- This is the constructor method for the Backtrace class. It initializes an instance of the class.
12
- It takes two optional parameters: model (a neural network model) and activation_dict (a dictionary that maps layer names to activation functions).
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.layers)
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 layer stack that defines the order in which layers should be processed during backpropagation.
23
- self.create_layer_stack()
24
-
25
- #checks if the model is sequential or not. If it's sequential, it adds the input layer to the layer stack.
26
- if (
27
- len(self.model_resource[3]) == 0
28
- or model.__module__.split(".")[-1] == "sequential"
29
- ):
30
- inp_name = model.input.name
31
- self.layer_stack.append(inp_name)
32
- self.model_resource[1][inp_name] = {}
33
- self.model_resource[1][inp_name]["name"] = inp_name
34
- self.model_resource[1][inp_name]["type"] = "input"
35
- self.model_resource[1][inp_name]["parent"] = []
36
- self.model_resource[1][inp_name]["child"] = None
37
- self.model_resource[3].append(inp_name)
38
- self.sequential = True
42
+ def __init__(self, model=None, activation_dict={}, model_type=None):
43
+ self.model = model
44
+ self.model_type = model_type
45
+ if model_type == 'encoder':
46
+ # create a tree-like structure for encoder model
47
+ self.model_resource = EN.build_encoder_tree(model)
48
+ # create a layer stack for encoder model
49
+ self.create_layer_stack()
50
+ # extract the encoder model weights
51
+ self.model_weights = EN.extract_encoder_weights(model)
52
+ # # calculate the output of each submodule of the encoder model
53
+ # self.all_out_model = EN.create_encoder_output(model)
54
+ elif model_type == 'encoder_decoder':
55
+ # create a tree-like structure and layer_stack for encoder-decoder model
56
+ self.model_resource, self.layer_stack = ED.build_enc_dec_tree(model)
57
+ # extract the encoder-decoder model weights
58
+ self.model_weights = ED.extract_encoder_decoder_weights(model)
59
+ # # calculate the output of each submodule of the encoder-decoder model
60
+ # self.all_out_model = ED.calculate_encoder_decoder_output(model)
61
+
39
62
  else:
40
- self.sequential = False
41
- try:
63
+ self.create_tree(model.layers)
64
+ self.create_model_output(model)
65
+ self.create_layer_stack()
42
66
 
43
- #calls the build_activation_dict method to build a dictionary that maps layer names to activation functions.
44
- #If that fails, it creates a temporary dictionary with default activation functions.
45
- if len(activation_dict) == 0:
46
- self.build_activation_dict(model)
67
+ if len(self.model_resource["inputs"])==0 or model.__module__.split(".")[-1]=='sequential':
68
+ inp_name = model.input.name
69
+ self.layer_stack.append(inp_name)
70
+ self.model_resource["graph"][inp_name] = {}
71
+ self.model_resource["graph"][inp_name]["name"] = inp_name
72
+ self.model_resource["graph"][inp_name]["type"] = "input"
73
+ self.model_resource["graph"][inp_name]["parent"] = []
74
+ self.model_resource["graph"][inp_name]["child"] = None
75
+ self.model_resource["inputs"].append(inp_name)
76
+ self.sequential = True
47
77
  else:
48
- self.activation_dict = activation_dict
49
-
50
- except Exception as e:
51
- print(e)
52
- temp_dict = {}
53
- for l in model.layers:
54
- temp_dict[l.name] = activation_master["None"]
55
- self.activation_dict = temp_dict
78
+ self.sequential = False
79
+ try:
80
+ if len(activation_dict) == 0:
81
+ self.build_activation_dict(model)
82
+ else:
83
+ self.activation_dict = activation_dict
84
+ except Exception as e:
85
+ print(e)
86
+ temp_dict = {}
87
+ for l in model.layers:
88
+ temp_dict[l.name] = activation_master["None"]
89
+ self.activation_dict = temp_dict
56
90
 
57
- def build_activation_dict(self, model):
58
- # Builds an activation dictionary by inspecting the activation functions of the layers in the model.
91
+ def build_activation_dict(self,model):
59
92
  activation_dict = {}
60
93
  for l in model.layers:
61
- if not hasattr(l, "activation"):
94
+ if not hasattr(l,"activation"):
62
95
  activation_dict[l.name] = activation_master["None"]
63
96
  continue
64
97
  a1 = l.activation
65
98
  func_name = str(a1).split(" ")
66
99
  if func_name[0] == "<function":
67
- activation_dict[l.name] = activation_master.get(
68
- func_name[1], activation_master["None"]
69
- )
100
+ activation_dict[l.name] = activation_master.get(func_name[1],activation_master["None"])
70
101
  else:
71
102
  a2 = a1.activation
72
103
  func_name = str(a2).split(" ")
73
104
  if func_name[0] == "<function":
74
- activation_dict[l.name] = activation_master.get(
75
- func_name[1], activation_master["None"]
76
- )
105
+ activation_dict[l.name] = activation_master.get(func_name[1],activation_master["None"])
77
106
  self.activation_dict = activation_dict
78
107
 
79
108
  def create_tree(self, layers):
80
- #Creates a tree structure representing the layers of the model.
81
- #categorizes layers as input, output, or intermediate layers and establishes parent-child relationships between layers.
82
109
  ltree = {}
83
110
  layer_tree = {}
84
111
  inputs = []
@@ -120,21 +147,20 @@ class Backtrace(object):
120
147
  intermediates.append(i.name)
121
148
 
122
149
  outputs = list(set(outputs) - set(intermediates))
123
- self.model_resource = (layer_tree, ltree, outputs, inputs)
150
+ self.model_resource = {"layers":layer_tree, "graph":ltree, "outputs":outputs, "inputs":inputs}
124
151
 
125
152
  def create_layer_stack(self):
126
- #Creates a layer stack that defines the order in which layers should be processed during backpropagation.
127
153
  model_resource = self.model_resource
128
- start_layer = model_resource[2][0]
154
+ start_layer = model_resource["outputs"][0]
129
155
  layer_stack = [start_layer]
130
156
  temp_stack = [start_layer]
131
- while len(layer_stack) < len(model_resource[0]):
157
+ while len(layer_stack) < len(model_resource["layers"]):
132
158
  start_layer = temp_stack.pop(0)
133
- if model_resource[1][start_layer]["child"]:
134
- child_nodes = model_resource[1][start_layer]["child"]
159
+ if model_resource["graph"][start_layer]["child"]:
160
+ child_nodes = model_resource["graph"][start_layer]["child"]
135
161
  for ch in child_nodes:
136
162
  node_check = True
137
- for pa in model_resource[1][ch]["parent"]:
163
+ for pa in model_resource["graph"][ch]["parent"]:
138
164
  if pa not in layer_stack:
139
165
  node_check = False
140
166
  break
@@ -145,20 +171,16 @@ class Backtrace(object):
145
171
  self.layer_stack = layer_stack
146
172
 
147
173
  def create_model_output(self, model):
148
- #Creates a new model that produces the output of each layer in the neural network.
149
174
  self.layers = [[], []]
150
- for l in self.model_resource[0]:
151
- # if l not in model_resource[3]:
175
+ for l in self.model_resource["layers"]:
152
176
  self.layers[0].append(l)
153
- self.layers[1].append(self.model_resource[0][l])
177
+ self.layers[1].append(self.model_resource["layers"][l])
154
178
 
155
179
  self.all_out_model = Model(
156
180
  inputs=model.input, outputs=[layer.output for layer in self.layers[1]]
157
181
  )
158
182
 
159
183
  def predict(self, inputs):
160
- #takes input data inputs and performs a forward pass through the neural network model to compute the output of each layer.
161
- #returns a dictionary that maps layer names to their corresponding outputs.
162
184
  all_out = self.all_out_model(inputs, training=False)
163
185
  temp_out = {}
164
186
  for i, v in enumerate(self.layers[0]):
@@ -166,28 +188,27 @@ class Backtrace(object):
166
188
  if self.sequential:
167
189
  temp_out[self.layer_stack[-1]] = inputs
168
190
  return temp_out
191
+
192
+ def eval(self, all_out, start_wt=[], mode="default",multiplier=100.0,
193
+ scaler=None, max_unit=0,thresholding=0.5,
194
+ task="binary-classification",predicted_token=None):
169
195
 
170
- def eval(
171
- self,
172
- all_out,
173
- mode,
174
- start_wt=[],
175
- multiplier=100.0,
176
- scaler=0,
177
- max_unit=0,
178
- ):
179
- #This method is used for evaluating layer-wise relevance based on different modes.
180
- if mode == "default":
181
- output = self.proportional_eval(
182
- all_out=all_out,
183
- start_wt=start_wt,
184
- multiplier=multiplier,
185
- scaler=0,
186
- max_unit=0,
187
- )
196
+ if mode=="default":
197
+ output = self.proportional_eval(all_out=all_out,
198
+ start_wt=start_wt ,
199
+ multiplier=multiplier,
200
+ scaler=scaler,
201
+ max_unit=max_unit,
202
+ thresholding=thresholding,
203
+ task=task,
204
+ predicted_token=predicted_token)
188
205
  return output
189
- elif mode == "contrast":
190
- temp_output = self.contrast_eval(all_out=all_out, multiplier=multiplier)
206
+ elif mode=="contrast":
207
+ temp_output = self.contrast_eval(all_out=all_out,
208
+ multiplier=multiplier,
209
+ scaler=scaler,
210
+ thresholding=thresholding,
211
+ task=task)
191
212
  output = {}
192
213
  for k in temp_output[0].keys():
193
214
  output[k] = {}
@@ -195,34 +216,41 @@ class Backtrace(object):
195
216
  output[k]["Negative"] = temp_output[1][k]
196
217
  return output
197
218
 
198
- def proportional_eval(
199
- self, all_out, start_wt=[], multiplier=100.0, scaler=0, max_unit=0
200
- ):
201
- #This method computes layer-wise relevance in the "default" mode.
202
- #iteratively calculates relevance for each layer based on the layer's type (e.g., Dense, Conv2D, LSTM) and activation function.
203
- #returns a dictionary mapping layer names to their relevance scores.
219
+ def proportional_eval(self, all_out, start_wt=[] ,
220
+ multiplier=100.0, scaler=None, max_unit=0,
221
+ predicted_token=None, thresholding=0.5,
222
+ task="binary-classification"):
204
223
  model_resource = self.model_resource
205
224
  activation_dict = self.activation_dict
206
225
  inputcheck = False
207
- out_layer = model_resource[2][0]
226
+ out_layer = model_resource["outputs"][0]
208
227
  all_wt = {}
209
228
  if len(start_wt) == 0:
210
- start_wt = UP.calculate_start_wt(all_out[out_layer])
211
- all_wt[out_layer] = start_wt * multiplier
212
- layer_stack = self.layer_stack
229
+ if self.model_type == 'encoder':
230
+ start_wt = UP.calculate_start_wt_UP(all_out[out_layer])
231
+ all_wt[out_layer] = start_wt * multiplier
232
+ layer_stack = self.layer_stack
233
+ all_wts = self.model_weights
213
234
 
214
- for start_layer in layer_stack:
215
- # print("===========================================")
216
- # print(layer_stack)
217
- if model_resource[1][start_layer]["child"]:
218
- child_nodes = model_resource[1][start_layer]["child"]
235
+ elif self.model_type == 'encoder_decoder':
236
+ start_wt = UP.calculate_enc_dec_start_wt(all_out[out_layer][0], predicted_token)
237
+ all_wt[out_layer] = start_wt * multiplier
238
+ layer_stack = self.layer_stack
239
+ all_wts = self.model_weights
240
+
241
+ else:
242
+ start_wt = UP.calculate_start_wt(all_out[out_layer],scaler,thresholding,task=task)
243
+ all_wt[out_layer] = start_wt * multiplier
244
+ layer_stack = self.layer_stack
245
+
246
+ for start_layer in tqdm(layer_stack):
247
+ if model_resource["graph"][start_layer]["child"]:
248
+ child_nodes = model_resource["graph"][start_layer]["child"]
219
249
  for ch in child_nodes:
220
250
  if ch not in all_wt:
221
251
  all_wt[ch] = np.zeros_like(all_out[ch][0])
222
- # print(start_layer, child_nodes,all_out[start_layer].shape)
223
- if model_resource[1][start_layer]["class"] == "Dense":
224
- print('dense')
225
- l1 = model_resource[0][start_layer]
252
+ if model_resource["graph"][start_layer]["class"] == "Dense":
253
+ l1 = model_resource["layers"][start_layer]
226
254
  w1 = l1.weights[0]
227
255
  b1 = l1.weights[1]
228
256
  temp_wt = UP.calculate_wt_fc(
@@ -230,68 +258,158 @@ class Backtrace(object):
230
258
  all_out[child_nodes[0]][0],
231
259
  w1,
232
260
  b1,
233
- activation_dict[model_resource[1][start_layer]["name"]],
261
+ activation_dict[model_resource["graph"][start_layer]["name"]],
234
262
  )
235
263
  all_wt[child_nodes[0]] += temp_wt
236
-
237
- elif model_resource[1][start_layer]["class"] == "Conv2D":
238
- l1 = model_resource[0][start_layer]
264
+ elif model_resource["graph"][start_layer]["class"] == "Conv2D":
265
+ l1 = model_resource["layers"][start_layer]
239
266
  w1 = l1.weights[0]
240
267
  b1 = l1.weights[1]
268
+ pad1 = l1.padding
269
+ strides1 = l1.strides
241
270
  temp_wt = UP.calculate_wt_conv(
242
271
  all_wt[start_layer],
243
272
  all_out[child_nodes[0]][0],
244
273
  w1,
245
274
  b1,
246
- activation_dict[model_resource[1][start_layer]["name"]],
275
+ pad1,
276
+ strides1,
277
+ activation_dict[model_resource["graph"][start_layer]["name"]],
278
+ )
279
+ all_wt[child_nodes[0]] += temp_wt
280
+ elif model_resource["graph"][start_layer]["class"] == "Conv2DTranspose":
281
+ l1 = model_resource["layers"][start_layer]
282
+ w1 = l1.weights[0]
283
+ b1 = l1.weights[1]
284
+ pad1 = l1.padding
285
+ strides1 = l1.strides
286
+ temp_wt = UP.calculate_wt_conv2d_transpose(
287
+ all_wt[start_layer],
288
+ all_out[child_nodes[0]][0],
289
+ w1,
290
+ b1,
291
+ pad1,
292
+ strides1,
293
+ activation_dict[model_resource["graph"][start_layer]["name"]],
247
294
  )
248
295
  all_wt[child_nodes[0]] += temp_wt
249
- elif model_resource[1][start_layer]["class"] == "Reshape":
296
+ elif model_resource["graph"][start_layer]["class"] == "Conv1D":
297
+ l1 = model_resource["layers"][start_layer]
298
+ w1 = l1.weights[0]
299
+ b1 = l1.weights[1]
300
+ pad1 = l1.padding
301
+ strides1 = l1.strides[0]
302
+ temp_wt = UP.calculate_wt_conv_1d(
303
+ all_wt[start_layer],
304
+ all_out[child_nodes[0]][0],
305
+ w1,
306
+ b1,
307
+ pad1,
308
+ strides1,
309
+ activation_dict[model_resource["graph"][start_layer]["name"]],
310
+ )
311
+ all_wt[child_nodes[0]] += temp_wt
312
+ elif model_resource["graph"][start_layer]["class"] == "Conv1DTranspose":
313
+ l1 = model_resource["layers"][start_layer]
314
+ w1 = l1.weights[0]
315
+ b1 = l1.weights[1]
316
+ pad1 = l1.padding
317
+ strides1 = l1.strides[0]
318
+ temp_wt = UP.calculate_wt_conv1d_transpose(
319
+ all_wt[start_layer],
320
+ all_out[child_nodes[0]][0],
321
+ w1,
322
+ b1,
323
+ pad1,
324
+ strides1,
325
+ activation_dict[model_resource["graph"][start_layer]["name"]],
326
+ )
327
+ all_wt[child_nodes[0]] += temp_wt
328
+ elif model_resource["graph"][start_layer]["class"] == "Reshape":
250
329
  temp_wt = UP.calculate_wt_rshp(
251
330
  all_wt[start_layer], all_out[child_nodes[0]][0]
252
331
  )
253
332
  all_wt[child_nodes[0]] += temp_wt
254
- elif model_resource[1][start_layer]["class"] == "Flatten":
333
+ elif model_resource["graph"][start_layer]["class"] == "Flatten":
255
334
  temp_wt = UP.calculate_wt_rshp(
256
335
  all_wt[start_layer], all_out[child_nodes[0]][0]
257
336
  )
258
337
  all_wt[child_nodes[0]] += temp_wt
259
- elif (
260
- model_resource[1][start_layer]["class"] == "GlobalAveragePooling2D"
261
- ):
338
+ elif model_resource["graph"][start_layer]["class"] == "GlobalAveragePooling2D":
262
339
  temp_wt = UP.calculate_wt_gavgpool(
263
340
  all_wt[start_layer], all_out[child_nodes[0]][0]
264
341
  )
265
342
  all_wt[child_nodes[0]] += temp_wt
266
- elif model_resource[1][start_layer]["class"] == "MaxPooling2D":
267
- l1 = model_resource[0][start_layer]
268
- temp_wt = UP.calculate_wt_maxpool(
269
- all_wt[start_layer], all_out[child_nodes[0]][0], l1.pool_size
343
+ elif model_resource["graph"][start_layer]["class"] == "GlobalAveragePooling1D":
344
+ temp_wt = UP.calculate_wt_gavgpool_1d(
345
+ all_wt[start_layer], all_out[child_nodes[0]][0]
270
346
  )
271
347
  all_wt[child_nodes[0]] += temp_wt
272
- elif model_resource[1][start_layer]["class"] == "AveragePooling2D":
273
- l1 = model_resource[0][start_layer]
274
- temp_wt = UP.calculate_wt_avgpool(
275
- all_wt[start_layer], all_out[child_nodes[0]][0], l1.pool_size
348
+ elif model_resource["graph"][start_layer]["class"] == "GlobalMaxPooling2D":
349
+ temp_wt = UP.calculate_wt_gmaxpool_2d(
350
+ all_wt[start_layer], all_out[child_nodes[0]][0]
276
351
  )
277
352
  all_wt[child_nodes[0]] += temp_wt
278
- elif model_resource[1][start_layer]["class"] == "Concatenate":
353
+ elif model_resource["graph"][start_layer]["class"] == "GlobalMaxPooling1D":
354
+ temp_wt = UP.calculate_wt_gmaxpool_1d(
355
+ all_wt[start_layer], all_out[child_nodes[0]][0]
356
+ )
357
+ all_wt[child_nodes[0]] += temp_wt
358
+ elif model_resource["graph"][start_layer]["class"] == 'ZeroPadding2D':
359
+ l1 = model_resource["layers"][start_layer]
360
+ pad1 = l1.padding
361
+ temp_wt = UP.calculate_wt_zero_pad(all_wt[start_layer],
362
+ all_out[child_nodes[0]][0],
363
+ pad1)
364
+ all_wt[child_nodes[0]] += temp_wt
365
+ elif model_resource["graph"][start_layer]["class"] == 'MaxPooling2D':
366
+ l1 = model_resource["layers"][start_layer]
367
+ pad1 = l1.padding
368
+ strides1 = l1.strides
369
+ temp_wt = UP.calculate_wt_maxpool(all_wt[start_layer],
370
+ all_out[child_nodes[0]][0],
371
+ l1.pool_size, pad1, strides1)
372
+ all_wt[child_nodes[0]] += temp_wt
373
+ elif model_resource["graph"][start_layer]["class"] == 'MaxPooling1D':
374
+ l1 = model_resource["layers"][start_layer]
375
+ pad1 = l1.padding
376
+ strides1 = l1.strides
377
+ temp_wt = UP.calculate_wt_maxpool_1d(all_wt[start_layer],
378
+ all_out[child_nodes[0]][0],
379
+ l1.pool_size, pad1, strides1)
380
+ all_wt[child_nodes[0]] += temp_wt
381
+ elif model_resource["graph"][start_layer]["class"] == 'AveragePooling2D':
382
+ l1 = model_resource["layers"][start_layer]
383
+ pad1 = l1.padding
384
+ strides1 = l1.strides
385
+ temp_wt = UP.calculate_wt_avgpool(all_wt[start_layer],
386
+ all_out[child_nodes[0]][0],
387
+ l1.pool_size, pad1, strides1)
388
+ all_wt[child_nodes[0]] += temp_wt
389
+ elif model_resource["graph"][start_layer]["class"] == 'AveragePooling1D':
390
+ l1 = model_resource["layers"][start_layer]
391
+ pad1 = l1.padding
392
+ strides1 = l1.strides
393
+ temp_wt = UP.calculate_wt_avgpool_1d(all_wt[start_layer],
394
+ all_out[child_nodes[0]][0],
395
+ l1.pool_size, pad1, strides1)
396
+ all_wt[child_nodes[0]] += temp_wt
397
+ elif model_resource["graph"][start_layer]["class"] == "Concatenate":
279
398
  temp_wt = UP.calculate_wt_concat(
280
399
  all_wt[start_layer],
281
400
  [all_out[ch] for ch in child_nodes],
282
- model_resource[0][start_layer].axis,
401
+ model_resource["layers"][start_layer].axis,
283
402
  )
284
403
  for ind, ch in enumerate(child_nodes):
285
404
  all_wt[ch] += temp_wt[ind]
286
- elif model_resource[1][start_layer]["class"] == "Add":
405
+ elif model_resource["graph"][start_layer]["class"] == "Add":
287
406
  temp_wt = UP.calculate_wt_add(
288
407
  all_wt[start_layer], [all_out[ch] for ch in child_nodes]
289
408
  )
290
409
  for ind, ch in enumerate(child_nodes):
291
410
  all_wt[ch] += temp_wt[ind]
292
- elif model_resource[1][start_layer]["class"] == "LSTM":
293
- print('lstm')
294
- l1 = model_resource[0][start_layer]
411
+ elif model_resource["graph"][start_layer]["class"] == "LSTM":
412
+ l1 = model_resource["layers"][start_layer]
295
413
  return_sequence = l1.return_sequences
296
414
  units = l1.units
297
415
  num_of_cells = l1.input_shape[1]
@@ -312,199 +430,307 @@ class Backtrace(object):
312
430
  all_wt[start_layer], lstm_obj_f.compute_log
313
431
  )
314
432
  all_wt[child_nodes[0]] += temp_wt
315
-
316
- elif model_resource[1][start_layer]["class"] == "Embedding":
317
- print('embedding')
433
+ elif model_resource["graph"][start_layer]["class"] == "Embedding":
318
434
  temp_wt = all_wt[start_layer]
319
435
  temp_wt = np.mean(temp_wt,axis=1)
320
-
321
436
  all_wt[child_nodes[0]] = all_wt[child_nodes[0]] + temp_wt
437
+ elif model_resource["graph"][start_layer]["class"] == "TextVectorization":
438
+ temp_wt = all_wt[start_layer]
439
+ all_wt[child_nodes[0]] = all_wt[child_nodes[0]] + temp_wt.sum()
440
+ elif model_resource["graph"][start_layer]["class"] == "Self_Attention":
441
+ weights = all_wts[start_layer]
442
+ self_attention_weights = HP.rename_attention_keys(weights)
443
+ temp_wt = UP.calculate_wt_self_attention(
444
+ all_wt[start_layer],
445
+ all_out[child_nodes[0]][0],
446
+ self_attention_weights,
447
+ )
448
+ all_wt[child_nodes[0]] += temp_wt
449
+ elif model_resource["graph"][start_layer]["class"] == 'Residual':
450
+ temp_wt = UP.calculate_wt_add(
451
+ all_wt[start_layer],
452
+ [all_out[ch] for ch in child_nodes],
453
+ )
454
+ for ind, ch in enumerate(child_nodes):
455
+ all_wt[ch] += temp_wt[ind]
456
+ elif model_resource["graph"][start_layer]["class"] == 'Feed_Forward':
457
+ weights = all_wts[start_layer]
458
+ feed_forward_weights = HP.rename_feed_forward_keys(weights)
459
+ temp_wt = UP.calculate_wt_feed_forward(
460
+ all_wt[start_layer],
461
+ all_out[child_nodes[0]][0],
462
+ feed_forward_weights
463
+ )
464
+ all_wt[child_nodes[0]] += temp_wt
465
+ elif model_resource["graph"][start_layer]["class"] == "Pooler":
466
+ weights = all_wts[start_layer]
467
+ pooler_weights = HP.rename_pooler_keys(weights)
468
+ temp_wt = UP.calculate_wt_pooler(
469
+ all_wt[start_layer],
470
+ all_out[child_nodes[0]][0],
471
+ pooler_weights
472
+ )
473
+ all_wt[child_nodes[0]] += temp_wt
474
+ elif model_resource["graph"][start_layer]["class"] == "Classifier":
475
+ weights = all_wts[start_layer]
476
+ classifier_weights = HP.rename_classifier_keys(weights)
477
+ temp_wt = UP.calculate_wt_classifier(
478
+ all_wt[start_layer],
479
+ all_out[child_nodes[0]][0],
480
+ classifier_weights
481
+ )
482
+ all_wt[child_nodes[0]] += temp_wt
483
+ elif model_resource["graph"][start_layer]["class"] == "LM_Head":
484
+ weights = all_wts[start_layer]
485
+ lm_head_weights = HP.rename_decoder_lm_head(weights)
322
486
 
487
+ temp_wt = UP.calculate_wt_lm_head(
488
+ all_wt[start_layer],
489
+ all_out[child_nodes[0]][0], #.detach().numpy(),
490
+ lm_head_weights
491
+ )
492
+ all_wt[child_nodes[0]] += temp_wt
493
+ elif model_resource["graph"][start_layer]["class"] == 'Layer_Norm':
494
+ temp_wt = all_wt[start_layer]
495
+ child_shape = all_wt[child_nodes[0]].shape
496
+ # Ensure temp_wt has the same shape as all_wt[child_nodes[0]]
497
+ if all_wt[child_nodes[0]].shape != temp_wt.shape:
498
+ temp_wt = np.squeeze(temp_wt, axis=0) if len(temp_wt.shape) == 3 else temp_wt
499
+ all_wt[child_nodes[0]] += temp_wt
500
+ elif model_resource["graph"][start_layer]["class"] == 'Cross_Attention':
501
+ weights = all_wts[start_layer]
502
+ cross_attention_weights = HP.rename_cross_attention_keys(weights)
503
+ temp_wt = UP.calculate_wt_cross_attention(
504
+ all_wt[start_layer],
505
+ [all_out[ch][0] for ch in child_nodes],
506
+ cross_attention_weights,
507
+ )
508
+ for ind, ch in enumerate(child_nodes):
509
+ all_wt[ch] += temp_wt[ind]
323
510
  else:
324
- print('else')
325
511
  temp_wt = all_wt[start_layer]
326
- all_wt[child_nodes[0]] += temp_wt.astype('float64')
327
-
328
- if max_unit > 0 and scaler == 0:
329
- temp_dict = {}
330
- for k in all_wt.keys():
331
- temp_dict[k] = UC.weight_normalize(all_wt[k], max_val=max_unit)
332
- all_wt = temp_dict
333
- elif scaler > 0:
512
+ all_wt[child_nodes[0]] += temp_wt
513
+ if max_unit>0:
334
514
  temp_dict = {}
335
515
  for k in all_wt.keys():
336
- temp_dict[k] = UC.weight_scaler(all_wt[k], scaler=scaler)
516
+ temp_dict[k] = UC.weight_normalize(all_wt[k],max_val=max_unit)
337
517
  all_wt = temp_dict
338
518
  return all_wt
339
519
 
340
- def contrast_eval(self, all_out, multiplier=100.0):
341
- #This method computes layer-wise relevance in the "contrast" mode.
342
- #calculates positive and negative relevance scores for each layer
343
- #returns a dictionary that maps layer names to dictionaries containing positive and negative relevance values.
520
+ def contrast_eval(self, all_out ,
521
+ multiplier=100.0, scaler=None,
522
+ thresholding=0.5,task="binary-classification"):
344
523
  model_resource = self.model_resource
345
- print(model_resource)
346
524
  activation_dict = self.activation_dict
347
525
  inputcheck = False
348
- out_layer = model_resource[2][0]
526
+ out_layer = model_resource["outputs"][0]
349
527
  all_wt_pos = {}
350
528
  all_wt_neg = {}
351
- start_wt_pos, start_wt_neg = UC.calculate_start_wt(all_out[out_layer])
352
- all_wt_pos[out_layer] = start_wt_pos * multiplier
353
- all_wt_neg[out_layer] = start_wt_neg * multiplier
354
- layer_stack = [out_layer]
355
- while len(layer_stack) > 0:
356
- start_layer = layer_stack.pop(0)
357
- if model_resource[1][start_layer]["child"]:
358
- child_nodes = model_resource[1][start_layer]["child"]
529
+ start_wt_pos,start_wt_neg = UC.calculate_start_wt(all_out[out_layer], scaler,thresholding,task)
530
+ all_wt_pos[out_layer] = start_wt_pos*multiplier
531
+ all_wt_neg[out_layer] = start_wt_neg*multiplier
532
+ layer_stack = self.layer_stack
533
+ for start_layer in tqdm(layer_stack):
534
+ if model_resource["graph"][start_layer]["child"]:
535
+ child_nodes = model_resource["graph"][start_layer]["child"]
359
536
  for ch in child_nodes:
360
537
  if ch not in all_wt_pos:
361
538
  all_wt_pos[ch] = np.zeros_like(all_out[ch][0])
362
539
  all_wt_neg[ch] = np.zeros_like(all_out[ch][0])
363
- if model_resource[1][start_layer]["class"] == "Dense":
364
- print('dense')
365
- l1 = model_resource[0][start_layer]
540
+ if model_resource["graph"][start_layer]["class"] == 'Dense':
541
+ l1 = model_resource["layers"][start_layer]
366
542
  w1 = l1.weights[0]
367
543
  b1 = l1.weights[1]
368
- temp_wt_pos, temp_wt_neg = UC.calculate_wt_fc(
369
- all_wt_pos[start_layer],
370
- all_wt_neg[start_layer],
371
- all_out[child_nodes[0]][0],
372
- w1,
373
- b1,
374
- activation_dict[model_resource[1][start_layer]["name"]],
375
- )
544
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_fc(all_wt_pos[start_layer],
545
+ all_wt_neg[start_layer],
546
+ all_out[child_nodes[0]][0],
547
+ w1,b1,
548
+ activation_dict[model_resource["graph"][start_layer]['name']])
376
549
  all_wt_pos[child_nodes[0]] += temp_wt_pos
377
550
  all_wt_neg[child_nodes[0]] += temp_wt_neg
378
- elif model_resource[1][start_layer]["class"] == "Conv2D":
379
- l1 = model_resource[0][start_layer]
551
+ elif model_resource["graph"][start_layer]["class"] == 'Conv2D':
552
+ l1 = model_resource["layers"][start_layer]
380
553
  w1 = l1.weights[0]
381
554
  b1 = l1.weights[1]
382
- temp_wt_pos, temp_wt_neg = UC.calculate_wt_conv(
555
+ pad1 = l1.padding
556
+ strides1 = l1.strides
557
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_conv(all_wt_pos[start_layer],
558
+ all_wt_neg[start_layer],
559
+ all_out[child_nodes[0]][0],
560
+ w1,b1, pad1, strides1,
561
+ activation_dict[model_resource["graph"][start_layer]['name']])
562
+ all_wt_pos[child_nodes[0]] += temp_wt_pos
563
+ all_wt_neg[child_nodes[0]] += temp_wt_neg
564
+ elif model_resource["graph"][start_layer]["class"] == "Conv2DTranspose":
565
+ l1 = model_resource["layers"][start_layer]
566
+ w1 = l1.weights[0]
567
+ b1 = l1.weights[1]
568
+ pad1 = l1.padding
569
+ strides1 = l1.strides
570
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_conv2d_transpose(
383
571
  all_wt_pos[start_layer],
384
572
  all_wt_neg[start_layer],
385
573
  all_out[child_nodes[0]][0],
386
574
  w1,
387
575
  b1,
388
- activation_dict[model_resource[1][start_layer]["name"]],
576
+ pad1,
577
+ strides1,
578
+ activation_dict[model_resource["graph"][start_layer]["name"]],
389
579
  )
390
580
  all_wt_pos[child_nodes[0]] += temp_wt_pos
391
581
  all_wt_neg[child_nodes[0]] += temp_wt_neg
392
- elif model_resource[1][start_layer]["class"] == "Reshape":
393
- temp_wt_pos = UC.calculate_wt_rshp(
394
- all_wt_pos[start_layer], all_out[child_nodes[0]][0]
395
- )
396
- temp_wt_neg = UC.calculate_wt_rshp(
397
- all_wt_neg[start_layer], all_out[child_nodes[0]][0]
398
- )
582
+ elif model_resource["graph"][start_layer]["class"] == 'Conv1D':
583
+ l1 = model_resource["layers"][start_layer]
584
+ w1 = l1.weights[0]
585
+ b1 = l1.weights[1]
586
+ pad1 = l1.padding
587
+ strides1 = l1.strides[0]
588
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_conv_1d(all_wt_pos[start_layer],
589
+ all_wt_neg[start_layer],
590
+ all_out[child_nodes[0]][0],
591
+ w1,b1, pad1, strides1,
592
+ activation_dict[model_resource["graph"][start_layer]['name']])
399
593
  all_wt_pos[child_nodes[0]] += temp_wt_pos
400
594
  all_wt_neg[child_nodes[0]] += temp_wt_neg
401
- elif (
402
- model_resource[1][start_layer]["class"] == "GlobalAveragePooling2D"
403
- ):
404
- temp_wt_pos, temp_wt_neg = UC.calculate_wt_gavgpool(
405
- all_wt_pos[start_layer],
406
- all_wt_neg[start_layer],
407
- all_out[child_nodes[0]][0],
408
- )
595
+ elif model_resource["graph"][start_layer]["class"] == "Conv1DTranspose":
596
+ l1 = model_resource["layers"][start_layer]
597
+ w1 = l1.weights[0]
598
+ b1 = l1.weights[1]
599
+ pad1 = l1.padding
600
+ strides1 = l1.strides[0]
601
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_conv1d_transpose(all_wt_pos[start_layer],
602
+ all_wt_neg[start_layer],
603
+ all_out[child_nodes[0]][0],
604
+ w1,b1, pad1, strides1,
605
+ activation_dict[model_resource["graph"][start_layer]['name']])
409
606
  all_wt_pos[child_nodes[0]] += temp_wt_pos
410
607
  all_wt_neg[child_nodes[0]] += temp_wt_neg
411
- elif model_resource[1][start_layer]["class"] == "Flatten":
412
- temp_wt = UC.calculate_wt_rshp(
413
- all_wt_pos[start_layer], all_out[child_nodes[0]][0]
414
- )
608
+ elif model_resource["graph"][start_layer]["class"] == 'Reshape':
609
+ temp_wt_pos = UC.calculate_wt_rshp(all_wt_pos[start_layer],
610
+ all_out[child_nodes[0]][0])
611
+ temp_wt_neg = UC.calculate_wt_rshp(all_wt_neg[start_layer],
612
+ all_out[child_nodes[0]][0])
613
+ all_wt_pos[child_nodes[0]] += temp_wt_pos
614
+ all_wt_neg[child_nodes[0]] += temp_wt_neg
615
+ elif model_resource["graph"][start_layer]["class"] == 'GlobalAveragePooling2D':
616
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_gavgpool(all_wt_pos[start_layer],
617
+ all_wt_neg[start_layer],
618
+ all_out[child_nodes[0]][0])
619
+ all_wt_pos[child_nodes[0]] += temp_wt_pos
620
+ all_wt_neg[child_nodes[0]] += temp_wt_neg
621
+ elif model_resource["graph"][start_layer]["class"] == 'GlobalAveragePooling1D':
622
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_gavgpool_1d(all_wt_pos[start_layer],
623
+ all_wt_neg[start_layer],
624
+ all_out[child_nodes[0]][0])
625
+ all_wt_pos[child_nodes[0]] += temp_wt_pos
626
+ all_wt_neg[child_nodes[0]] += temp_wt_neg
627
+ elif model_resource["graph"][start_layer]["class"] == 'Flatten':
628
+ temp_wt = UC.calculate_wt_rshp(all_wt_pos[start_layer],
629
+ all_out[child_nodes[0]][0])
415
630
  all_wt_pos[child_nodes[0]] += temp_wt
416
- temp_wt = UC.calculate_wt_rshp(
417
- all_wt_neg[start_layer], all_out[child_nodes[0]][0]
418
- )
631
+ temp_wt = UC.calculate_wt_rshp(all_wt_neg[start_layer],
632
+ all_out[child_nodes[0]][0])
419
633
  all_wt_neg[child_nodes[0]] += temp_wt
420
- elif (
421
- model_resource[1][start_layer]["class"] == "GlobalAveragePooling2D"
422
- ):
423
- temp_wt_pos, temp_wt_neg = UC.calculate_wt_gavgpool(
424
- all_wt_pos[start_layer],
425
- all_wt_neg[start_layer],
426
- all_out[child_nodes[0]][0],
427
- )
634
+ elif model_resource["graph"][start_layer]["class"] == 'ZeroPadding2D':
635
+ l1 = model_resource["layers"][start_layer]
636
+ pad1 = l1.padding
637
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_zero_pad(all_wt_pos[start_layer],
638
+ all_wt_neg[start_layer],
639
+ all_out[child_nodes[0]][0],
640
+ pad1)
428
641
  all_wt_pos[child_nodes[0]] += temp_wt_pos
429
642
  all_wt_neg[child_nodes[0]] += temp_wt_neg
430
- elif model_resource[1][start_layer]["class"] == "MaxPooling2D":
431
- l1 = model_resource[0][start_layer]
432
- temp_wt = UC.calculate_wt_maxpool(
433
- all_wt_pos[start_layer],
434
- all_out[child_nodes[0]][0],
435
- l1.pool_size,
436
- )
643
+ elif model_resource["graph"][start_layer]["class"] == 'MaxPooling2D':
644
+ l1 = model_resource["layers"][start_layer]
645
+ pad1 = l1.padding
646
+ strides1 = l1.strides
647
+ temp_wt = UC.calculate_wt_maxpool(all_wt_pos[start_layer],
648
+ all_out[child_nodes[0]][0],
649
+ l1.pool_size, pad1, strides1)
437
650
  all_wt_pos[child_nodes[0]] += temp_wt
438
- temp_wt = UC.calculate_wt_maxpool(
439
- all_wt_neg[start_layer],
440
- all_out[child_nodes[0]][0],
441
- l1.pool_size,
442
- )
651
+ temp_wt = UC.calculate_wt_maxpool(all_wt_neg[start_layer],
652
+ all_out[child_nodes[0]][0],
653
+ l1.pool_size, pad1, strides1)
443
654
  all_wt_neg[child_nodes[0]] += temp_wt
444
- elif model_resource[1][start_layer]["class"] == "AveragePooling2D":
445
- l1 = model_resource[0][start_layer]
446
- temp_wt_pos, temp_wt_neg = UC.calculate_wt_avgpool(
447
- all_wt_pos[start_layer],
448
- all_wt_neg[start_layer],
449
- all_out[child_nodes[0]][0],
450
- l1.pool_size,
451
- )
655
+ elif model_resource["graph"][start_layer]["class"] == 'MaxPooling1D':
656
+ l1 = model_resource["layers"][start_layer]
657
+ pad1 = l1.padding
658
+ strides1 = l1.strides
659
+ temp_wt = UC.calculate_wt_maxpool_1d(all_wt_pos[start_layer],
660
+ all_out[child_nodes[0]][0],
661
+ l1.pool_size, pad1, strides1)
662
+ all_wt_pos[child_nodes[0]] += temp_wt
663
+ temp_wt = UC.calculate_wt_maxpool_1d(all_wt_neg[start_layer],
664
+ all_out[child_nodes[0]][0],
665
+ l1.pool_size, pad1, strides1)
666
+ all_wt_neg[child_nodes[0]] += temp_wt
667
+ elif model_resource["graph"][start_layer]["class"] == 'GlobalMaxPooling2D':
668
+ temp_wt = UC.calculate_wt_gmaxpool_2d(all_wt_pos[start_layer],
669
+ all_out[child_nodes[0]][0])
670
+ all_wt_pos[child_nodes[0]] += temp_wt
671
+ temp_wt = UC.calculate_wt_gmaxpool_2d(all_wt_neg[start_layer],
672
+ all_out[child_nodes[0]][0])
673
+ all_wt_neg[child_nodes[0]] += temp_wt
674
+ elif model_resource["graph"][start_layer]["class"] == 'GlobalMaxPooling1D':
675
+ temp_wt = UC.calculate_wt_gmaxpool_1d(all_wt_pos[start_layer],
676
+ all_out[child_nodes[0]][0])
677
+ all_wt_pos[child_nodes[0]] += temp_wt
678
+ temp_wt = UC.calculate_wt_gmaxpool_1d(all_wt_neg[start_layer],
679
+ all_out[child_nodes[0]][0])
680
+ all_wt_neg[child_nodes[0]] += temp_wt
681
+ elif model_resource["graph"][start_layer]["class"] == 'AveragePooling2D':
682
+ l1 = model_resource["layers"][start_layer]
683
+ pad1 = l1.padding
684
+ strides1 = l1.strides
685
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_avgpool(all_wt_pos[start_layer],
686
+ all_wt_neg[start_layer],
687
+ all_out[child_nodes[0]][0],
688
+ l1.pool_size, pad1, strides1)
452
689
  all_wt_pos[child_nodes[0]] += temp_wt_pos
453
690
  all_wt_neg[child_nodes[0]] += temp_wt_neg
454
- elif model_resource[1][start_layer]["class"] == "Concatenate":
455
- temp_wt = UC.calculate_wt_concat(
456
- all_wt_pos[start_layer],
457
- [all_out[ch] for ch in child_nodes],
458
- model_resource[0][start_layer].axis,
459
- )
691
+ elif model_resource["graph"][start_layer]["class"] == 'AveragePooling1D':
692
+ l1 = model_resource["layers"][start_layer]
693
+ pad1 = l1.padding
694
+ strides1 = l1.strides
695
+ temp_wt_pos,temp_wt_neg = UC.calculate_wt_avgpool_1d(all_wt_pos[start_layer],
696
+ all_wt_neg[start_layer],
697
+ all_out[child_nodes[0]][0],
698
+ l1.pool_size, pad1, strides1)
699
+ all_wt_pos[child_nodes[0]] += temp_wt_pos
700
+ all_wt_neg[child_nodes[0]] += temp_wt_neg
701
+ elif model_resource["graph"][start_layer]["class"] == "Concatenate":
702
+ temp_wt = UC.calculate_wt_concat(all_wt_pos[start_layer],
703
+ [all_out[ch] for ch in child_nodes],
704
+ model_resource["layers"][start_layer].axis)
460
705
  for ind, ch in enumerate(child_nodes):
461
- all_wt_pos[ch] += temp_wt[ind]
462
- temp_wt = UC.calculate_wt_concat(
463
- all_wt_neg[start_layer],
464
- [all_out[ch] for ch in child_nodes],
465
- model_resource[0][start_layer].axis,
466
- )
706
+ all_wt_pos[ch]+=temp_wt[ind]
707
+ temp_wt = UC.calculate_wt_concat(all_wt_neg[start_layer],
708
+ [all_out[ch] for ch in child_nodes],
709
+ model_resource["layers"][start_layer].axis)
467
710
  for ind, ch in enumerate(child_nodes):
468
- all_wt_neg[ch] += temp_wt[ind]
711
+ all_wt_neg[ch]+=temp_wt[ind]
469
712
 
470
- elif model_resource[1][start_layer]["class"] == "Add":
471
- temp_wt = UC.calculate_wt_add(
472
- all_wt_pos[start_layer],
473
- all_wt_neg[start_layer],
474
- [all_out[ch] for ch in child_nodes],
475
- )
713
+ elif model_resource["graph"][start_layer]["class"] == "Add":
714
+ temp_wt = UC.calculate_wt_add(all_wt_pos[start_layer],
715
+ all_wt_neg[start_layer],
716
+ [all_out[ch] for ch in child_nodes])
476
717
  for ind, ch in enumerate(child_nodes):
477
- all_wt_pos[ch] += temp_wt[ind][0]
478
- all_wt_neg[ch] += temp_wt[ind][1]
479
- elif model_resource[1][start_layer]["class"] == "LSTM":
480
- print('lstm')
481
- l1 = model_resource[0][start_layer]
718
+ all_wt_pos[ch]+=temp_wt[ind][0]
719
+ all_wt_neg[ch]+=temp_wt[ind][1]
720
+ elif model_resource["graph"][start_layer]["class"] == "LSTM":
721
+ l1 = model_resource["layers"][start_layer]
482
722
  return_sequence = l1.return_sequences
483
723
  units = l1.units
484
724
  num_of_cells = l1.input_shape[1]
485
- lstm_obj_f = UC.LSTM_forward(
486
- num_of_cells, units, l1.weights, return_sequence, False
487
- )
488
- lstm_obj_b = UC.LSTM_backtrace(
489
- num_of_cells,
490
- units,
491
- [i.numpy() for i in l1.weights],
492
- return_sequence,
493
- False,
494
- )
495
- temp_out_f = lstm_obj_f.calculate_lstm_wt(
496
- all_out[child_nodes[0]][0]
497
- )
498
- temp_wt_pos, temp_wt_neg = lstm_obj_b.calculate_lstm_wt(
499
- all_wt_pos[start_layer],
500
- all_wt_neg[start_layer],
501
- lstm_obj_f.compute_log,
502
- )
725
+ lstm_obj_f = UC.LSTM_forward(num_of_cells, units, l1.weights, return_sequence, False)
726
+ lstm_obj_b = UC.LSTM_backtrace(num_of_cells, units, [i.numpy() for i in l1.weights], return_sequence, False)
727
+ temp_out_f = lstm_obj_f.calculate_lstm_wt(all_out[child_nodes[0]][0])
728
+ temp_wt_pos,temp_wt_neg = lstm_obj_b.calculate_lstm_wt(all_wt_pos[start_layer],
729
+ all_wt_neg[start_layer],
730
+ lstm_obj_f.compute_log)
503
731
  all_wt_pos[child_nodes[0]] = temp_wt_pos
504
732
  all_wt_neg[child_nodes[0]] = temp_wt_neg
505
-
506
- elif model_resource[1][start_layer]["class"] == "Embedding":
507
- print('embedding layer')
733
+ elif model_resource["graph"][start_layer]["class"] == "Embedding":
508
734
  temp_wt_pos = all_wt_pos[start_layer]
509
735
  temp_wt_neg = all_wt_neg[start_layer]
510
736
 
@@ -513,15 +739,16 @@ class Backtrace(object):
513
739
 
514
740
  all_wt_pos[child_nodes[0]] = all_wt_pos[child_nodes[0]] + temp_wt_pos
515
741
  all_wt_neg[child_nodes[0]] = all_wt_neg[child_nodes[0]] + temp_wt_neg
742
+ elif model_resource["graph"][start_layer]["class"] == "TextVectorization":
743
+ temp_wt_pos = all_wt_pos[start_layer]
744
+ temp_wt_neg = all_wt_neg[start_layer]
516
745
 
517
-
746
+ all_wt_pos[child_nodes[0]] = all_wt_pos[child_nodes[0]] + temp_wt_pos.sum()
747
+ all_wt_neg[child_nodes[0]] = all_wt_neg[child_nodes[0]] + temp_wt_neg.sum()
518
748
  else:
519
- print('else')
520
749
  temp_wt_pos = all_wt_pos[start_layer]
521
750
  temp_wt_neg = all_wt_neg[start_layer]
522
751
  all_wt_pos[child_nodes[0]] += temp_wt_pos
523
752
  all_wt_neg[child_nodes[0]] += temp_wt_neg
524
- for ch in child_nodes:
525
- if not (ch in layer_stack):
526
- layer_stack.append(ch)
527
- return all_wt_pos, all_wt_neg
753
+
754
+ return all_wt_pos,all_wt_neg