compositional-explanations 0.0.2__tar.gz → 0.0.3.1__tar.gz
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.
- {compositional_explanations-0.0.2/src/compositional_explanations.egg-info → compositional_explanations-0.0.3.1}/PKG-INFO +1 -1
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/pyproject.toml +1 -1
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/metrics.py +1 -1
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/optimal.py +3 -3
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/optimal_sample_heuristic.py +46 -3
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/optimal_sum_heuristic.py +19 -3
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1/src/compositional_explanations.egg-info}/PKG-INFO +1 -1
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations.egg-info/SOURCES.txt +4 -4
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations.egg-info/top_level.txt +1 -1
- {compositional_explanations-0.0.2/src/utils → compositional_explanations-0.0.3.1/src/package_utils}/mask_utils.py +2 -1
- {compositional_explanations-0.0.2/src/utils → compositional_explanations-0.0.3.1/src/package_utils}/optimal_utils.py +2 -2
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/LICENSE +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/README.md +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/setup.cfg +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/beam.py +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/formula.py +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations/path_heuristic.py +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations.egg-info/dependency_links.txt +0 -0
- {compositional_explanations-0.0.2 → compositional_explanations-0.0.3.1}/src/compositional_explanations.egg-info/requires.txt +0 -0
- {compositional_explanations-0.0.2/src/utils → compositional_explanations-0.0.3.1/src/package_utils}/constants.py +0 -0
- {compositional_explanations-0.0.2/src/utils → compositional_explanations-0.0.3.1/src/package_utils}/general_utils.py +0 -0
|
@@ -8,8 +8,8 @@ import torch
|
|
|
8
8
|
|
|
9
9
|
from compositional_explanations import formula as F
|
|
10
10
|
from compositional_explanations import path_heuristic
|
|
11
|
-
from
|
|
12
|
-
from
|
|
11
|
+
from package_utils import optimal_utils, mask_utils, general_utils
|
|
12
|
+
from package_utils.constants import INDEX_OR, INDEX_AND, INDEX_NOT
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def update_frontier_by_ancestors(
|
|
@@ -924,7 +924,7 @@ def compute_optimal_explanations(*, masks, bitmaps, disjoint_info, length, devic
|
|
|
924
924
|
bitmaps = bitmaps.to(device)
|
|
925
925
|
|
|
926
926
|
masks_info = mask_utils.get_dataset_info(masks, cache_dir)
|
|
927
|
-
max_size_mask = torch.numel(masks[0])
|
|
927
|
+
max_size_mask = torch.numel(general_utils.parse_mask_by_type(masks[0]))
|
|
928
928
|
|
|
929
929
|
# Get quantities
|
|
930
930
|
neuron_quantities, concept_quantities = optimal_utils.get_optimal_heuristic_info(
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from package_utils import optimal_utils
|
|
7
7
|
from compositional_explanations import formula as F
|
|
8
|
-
from
|
|
8
|
+
from package_utils.constants import (
|
|
9
9
|
TOP_INDEX_SAMPLE,
|
|
10
10
|
BOTTOM_INDEX_SAMPLE,
|
|
11
11
|
BOTTOM_INDEX_SUM,
|
|
@@ -227,7 +227,7 @@ def estimate_label_info(label, left_quantities, right_quantities, neuron_quantit
|
|
|
227
227
|
|
|
228
228
|
# Quantities used by all the operators
|
|
229
229
|
_, neuron_common_tuple, _, _, common_space_extras_tuple, _ = neuron_quantities
|
|
230
|
-
neuron_common,
|
|
230
|
+
neuron_common, neuron_common_sum = neuron_common_tuple
|
|
231
231
|
common_space_extras, _ = common_space_extras_tuple
|
|
232
232
|
max_left_common_intersection = optimal_utils.get_quantity(
|
|
233
233
|
label_info=left_quantities,
|
|
@@ -308,6 +308,18 @@ def estimate_label_info(label, left_quantities, right_quantities, neuron_quantit
|
|
|
308
308
|
)
|
|
309
309
|
|
|
310
310
|
if isinstance(label, F.Or):
|
|
311
|
+
max_right_common_intersection_sum = optimal_utils.get_quantity(
|
|
312
|
+
label_info=right_quantities,
|
|
313
|
+
quantity_name="common_intersection",
|
|
314
|
+
quantity_type="max",
|
|
315
|
+
quantity_scope="sum",
|
|
316
|
+
)
|
|
317
|
+
max_left_common_intersection_sum = optimal_utils.get_quantity(
|
|
318
|
+
label_info=left_quantities,
|
|
319
|
+
quantity_name="common_intersection",
|
|
320
|
+
quantity_type="max",
|
|
321
|
+
quantity_scope="sum",
|
|
322
|
+
)
|
|
311
323
|
# Auxiliary info: Sum of the right quantities, right unique extras and intersection
|
|
312
324
|
right_unique_intersection_sum = optimal_utils.get_quantity(
|
|
313
325
|
label_info=right_quantities,
|
|
@@ -315,6 +327,19 @@ def estimate_label_info(label, left_quantities, right_quantities, neuron_quantit
|
|
|
315
327
|
quantity_type="max",
|
|
316
328
|
quantity_scope="sum",
|
|
317
329
|
)
|
|
330
|
+
|
|
331
|
+
min_left_common_intersection_sum = optimal_utils.get_quantity(
|
|
332
|
+
label_info=left_quantities,
|
|
333
|
+
quantity_name="common_intersection",
|
|
334
|
+
quantity_type="min",
|
|
335
|
+
quantity_scope="sum",
|
|
336
|
+
)
|
|
337
|
+
min_right_common_intersection_sum = optimal_utils.get_quantity(
|
|
338
|
+
label_info=right_quantities,
|
|
339
|
+
quantity_name="common_intersection",
|
|
340
|
+
quantity_type="min",
|
|
341
|
+
quantity_scope="sum",
|
|
342
|
+
)
|
|
318
343
|
right_unique_extras_sum = optimal_utils.get_quantity(
|
|
319
344
|
label_info=right_quantities,
|
|
320
345
|
quantity_name="unique_extras",
|
|
@@ -334,6 +359,24 @@ def estimate_label_info(label, left_quantities, right_quantities, neuron_quantit
|
|
|
334
359
|
quantity_scope="sample",
|
|
335
360
|
)
|
|
336
361
|
|
|
362
|
+
if (right_unique_intersection_sum == 0 and max_right_common_intersection_sum == 0) or (
|
|
363
|
+
left_unique_intersection_sum == 0 and max_left_common_intersection_sum == 0) or (
|
|
364
|
+
right_unique_intersection_sum == 0 and min_left_common_intersection_sum == neuron_common_sum
|
|
365
|
+
) or (
|
|
366
|
+
left_unique_intersection_sum == 0 and min_right_common_intersection_sum == neuron_common_sum):
|
|
367
|
+
# If one of the two side does not change to the intersection, we can discard this formula because
|
|
368
|
+
# OR can't reduce the extras
|
|
369
|
+
return None
|
|
370
|
+
|
|
371
|
+
left_can_be_improved = np.where(min_left_common_intersection < neuron_common, True, False) & np.where(min_right_common_intersection > 0, True, False)
|
|
372
|
+
right_can_be_improved = np.where(min_right_common_intersection < neuron_common, True, False) & np.where(min_left_common_intersection > 0, True, False)
|
|
373
|
+
if (right_unique_intersection_sum == 0 and not left_can_be_improved.any()) or (left_unique_intersection_sum == 0 and not right_can_be_improved.any()):
|
|
374
|
+
# If for a sample the min left intersection is already maximum, the right component cannot improve the score
|
|
375
|
+
# Similarly, if the minimum common intersection of the right element is 0, it cannot improve the score for that sample
|
|
376
|
+
return None
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
337
380
|
# OR simply sums the unique elements
|
|
338
381
|
unique_intersection = left_unique_intersection + right_unique_intersection # I^u(L) + I^u(c)
|
|
339
382
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from package_utils import optimal_utils
|
|
6
6
|
from compositional_explanations import formula as F
|
|
7
|
-
from
|
|
7
|
+
from package_utils.constants import TOP_INDEX_SUM, BOTTOM_INDEX_SUM
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def estimate_disjoint_label_info(label, *, left_quantities, right_quantities):
|
|
@@ -245,9 +245,25 @@ def estimate_label_info(label, *, left_quantities, right_quantities, neuron_quan
|
|
|
245
245
|
quantity_type="max",
|
|
246
246
|
quantity_scope="sum",
|
|
247
247
|
)
|
|
248
|
+
min_left_common_intersection_sum = optimal_utils.get_quantity(
|
|
249
|
+
label_info=left_quantities,
|
|
250
|
+
quantity_name="common_intersection",
|
|
251
|
+
quantity_type="min",
|
|
252
|
+
quantity_scope="sum",
|
|
253
|
+
)
|
|
248
254
|
|
|
249
|
-
if isinstance(label, F.Or):
|
|
250
255
|
|
|
256
|
+
if isinstance(label, F.Or):
|
|
257
|
+
if (right_unique_intersection_sum == 0 and max_right_common_intersection_sum == 0) or (
|
|
258
|
+
left_unique_intersection_sum == 0 and max_left_common_intersection_sum == 0) or (
|
|
259
|
+
right_unique_intersection_sum == 0 and min_left_common_intersection_sum == neuron_common_sum
|
|
260
|
+
) or (
|
|
261
|
+
left_unique_intersection_sum == 0 and min_right_common_intersection_sum == neuron_common_sum):
|
|
262
|
+
# If one of the two side does not change to the intersection, we can discard this formula because
|
|
263
|
+
# OR can't reduce the extras
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
|
|
251
267
|
# Unique elements are additive since they are disjoint
|
|
252
268
|
unique_intersection_sum = left_unique_intersection_sum + right_unique_intersection_sum
|
|
253
269
|
unique_extras_sum = left_unique_extras_sum + right_unique_extras_sum
|
|
@@ -13,7 +13,7 @@ src/compositional_explanations.egg-info/SOURCES.txt
|
|
|
13
13
|
src/compositional_explanations.egg-info/dependency_links.txt
|
|
14
14
|
src/compositional_explanations.egg-info/requires.txt
|
|
15
15
|
src/compositional_explanations.egg-info/top_level.txt
|
|
16
|
-
src/
|
|
17
|
-
src/
|
|
18
|
-
src/
|
|
19
|
-
src/
|
|
16
|
+
src/package_utils/constants.py
|
|
17
|
+
src/package_utils/general_utils.py
|
|
18
|
+
src/package_utils/mask_utils.py
|
|
19
|
+
src/package_utils/optimal_utils.py
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
compositional_explanations
|
|
2
|
-
|
|
2
|
+
package_utils
|
|
@@ -4,7 +4,7 @@ import pickle
|
|
|
4
4
|
|
|
5
5
|
import torch
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from package_utils import general_utils
|
|
8
8
|
from compositional_explanations import formula as F
|
|
9
9
|
|
|
10
10
|
|
|
@@ -24,6 +24,7 @@ def get_dataset_info(masks, info_directory):
|
|
|
24
24
|
print("Loading dataset info from cache...")
|
|
25
25
|
common_elements, unique_elements, uncoverable_elements = pickle.load(file)
|
|
26
26
|
else:
|
|
27
|
+
print("Computing dataset info...")
|
|
27
28
|
# Compute unique elements
|
|
28
29
|
sum_elements = torch.zeros_like(
|
|
29
30
|
general_utils.parse_mask_by_type(masks[1]), dtype=torch.int32
|
|
@@ -7,8 +7,8 @@ import torch
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
9
9
|
from compositional_explanations import formula as F
|
|
10
|
-
from
|
|
11
|
-
from
|
|
10
|
+
from package_utils import general_utils
|
|
11
|
+
from package_utils.constants import (
|
|
12
12
|
QUANTITIES,
|
|
13
13
|
INDEX_TUPLE_MAX,
|
|
14
14
|
INDEX_TUPLE_MIN,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|