BETTER-NMA 1.0.0__py3-none-any.whl → 1.0.2__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.
- BETTER_NMA/explaination_score.py +52 -0
- BETTER_NMA/main.py +5 -0
- BETTER_NMA/utilss/classes/adversarial_dataset.py +4 -9
- BETTER_NMA/utilss/classes/preprocessing/batch_predictor.py +1 -1
- BETTER_NMA/utilss/classes/score_calculator.py +0 -1
- BETTER_NMA/utilss/photos_uitls.py +3 -3
- BETTER_NMA/utilss/photos_utils.py +3 -3
- BETTER_NMA-1.0.2.dist-info/METADATA +174 -0
- {BETTER_NMA-1.0.0.dist-info → BETTER_NMA-1.0.2.dist-info}/RECORD +11 -10
- BETTER_NMA-1.0.0.dist-info/METADATA +0 -11
- {BETTER_NMA-1.0.0.dist-info → BETTER_NMA-1.0.2.dist-info}/WHEEL +0 -0
- {BETTER_NMA-1.0.0.dist-info → BETTER_NMA-1.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
from .utilss.classes.score_calculator import ScoreCalculator
|
2
|
+
from itertools import combinations
|
3
|
+
|
4
|
+
def get_explaination_score(dendrogram, class_names, normalize=True):
|
5
|
+
"""
|
6
|
+
Get the score of the entire dendrogram based on pairwise LCA ancestor counts.
|
7
|
+
|
8
|
+
Parameters:
|
9
|
+
- dendrogram: The hierarchical clustering dendrogram
|
10
|
+
- class_names: List of class names corresponding to model outputs
|
11
|
+
|
12
|
+
Returns:
|
13
|
+
- score: The explanation score of the dendrogram
|
14
|
+
"""
|
15
|
+
score_calculator = ScoreCalculator(dendrogram.Z, class_names)
|
16
|
+
|
17
|
+
total_count = 0
|
18
|
+
num_classes = len(class_names)
|
19
|
+
|
20
|
+
# Get all combinations of 2 labels from class_names
|
21
|
+
for label1, label2 in combinations(class_names, 2):
|
22
|
+
try:
|
23
|
+
idx1 = class_names.index(label1)
|
24
|
+
idx2 = class_names.index(label2)
|
25
|
+
count, _ = score_calculator.count_ancestors_to_lca(idx1, idx2)
|
26
|
+
total_count += count
|
27
|
+
except ValueError as e:
|
28
|
+
print(f"Error processing pair ({label1}, {label2}): {e}")
|
29
|
+
continue
|
30
|
+
|
31
|
+
total_combinations = len(list(combinations(class_names, 2)))
|
32
|
+
print(f"Total combinations processed: {total_combinations}")
|
33
|
+
print(f"Total ancestor count sum: {total_count}")
|
34
|
+
|
35
|
+
if normalize:
|
36
|
+
# Maximum ancestors = height of dendrogram tree
|
37
|
+
max_ancestors_per_pair = num_classes - 1 # Maximum tree height
|
38
|
+
theoretical_max = total_combinations * max_ancestors_per_pair
|
39
|
+
|
40
|
+
if theoretical_max == 0:
|
41
|
+
normalized_score = 0
|
42
|
+
else:
|
43
|
+
# Invert the score so higher ancestor counts = lower explanation quality
|
44
|
+
# and normalize to 0-100%
|
45
|
+
normalized_score = max(0, (1 - (total_count / theoretical_max)) * 100)
|
46
|
+
|
47
|
+
print(f"Theoretical maximum: {theoretical_max}")
|
48
|
+
print(f"Normalized score: {normalized_score:.2f}%")
|
49
|
+
|
50
|
+
return normalized_score
|
51
|
+
else:
|
52
|
+
return total_count
|
BETTER_NMA/main.py
CHANGED
@@ -8,6 +8,7 @@ from .detect_attack import detect_adversarial_image
|
|
8
8
|
from .query_image import query_image
|
9
9
|
from .utilss.verbal_explanation import get_verbal_explanation
|
10
10
|
from .white_box_testing import analyze_white_box_results, get_white_box_analysis
|
11
|
+
from .explaination_score import get_explaination_score
|
11
12
|
from .adversarial_score import get_adversarial_score
|
12
13
|
from .find_lca import get_lca
|
13
14
|
|
@@ -212,6 +213,10 @@ class NMA:
|
|
212
213
|
score = get_adversarial_score(image, self.model, self.dendrogram_object.Z, self.labels, top_k=top_k)
|
213
214
|
return score
|
214
215
|
|
216
|
+
def explanation_score(self, normalize=True):
|
217
|
+
return get_explaination_score(self.dendrogram_object, self.labels, normalize=normalize)
|
218
|
+
|
219
|
+
|
215
220
|
## query and explanation functions: ##
|
216
221
|
|
217
222
|
def query_image(self, image, top_k=5):
|
@@ -13,32 +13,27 @@ class AdversarialDataset:
|
|
13
13
|
scores = []
|
14
14
|
labels = []
|
15
15
|
|
16
|
-
print("getting preprocess function...")
|
17
|
-
|
18
16
|
try:
|
19
17
|
for image in self.clear_images[:50]:
|
20
18
|
# Add batch dimension for model prediction
|
21
19
|
image_batch = np.expand_dims(image, axis=0)
|
22
|
-
score = self.score_calculator.calculate_adversarial_score(self.model.predict(image_batch))
|
20
|
+
score = self.score_calculator.calculate_adversarial_score(self.model.predict(image_batch, verbose=0))
|
23
21
|
scores.append(score)
|
24
22
|
labels.append(0)
|
25
23
|
except Exception as e:
|
26
|
-
print(f"Error processing clean
|
24
|
+
print(f"Error processing clean images: {e}")
|
27
25
|
|
28
26
|
# Generate features for PGD attacks
|
29
|
-
print("Generating attack features...")
|
30
27
|
try:
|
31
28
|
for adv_image in self.adversarial_images[:50]:
|
32
29
|
# Add batch dimension for model prediction
|
33
30
|
adv_image_batch = np.expand_dims(adv_image, axis=0)
|
34
|
-
score = self.score_calculator.calculate_adversarial_score(self.model.predict(adv_image_batch))
|
31
|
+
score = self.score_calculator.calculate_adversarial_score(self.model.predict(adv_image_batch, verbose=0))
|
35
32
|
scores.append(score)
|
36
33
|
labels.append(1)
|
37
34
|
except Exception as e:
|
38
|
-
print(f"Error processing
|
35
|
+
print(f"Error processing attacked images: {e}")
|
39
36
|
|
40
|
-
print("labels:", labels)
|
41
|
-
print("scores:", scores)
|
42
37
|
|
43
38
|
# Convert to numpy arrays
|
44
39
|
X = np.array(scores)
|
@@ -11,7 +11,7 @@ class BatchPredictor:
|
|
11
11
|
self.buffer_results = [] # To store batch results
|
12
12
|
|
13
13
|
def get_top_predictions(self, X, labels, top_k, graph_threshold):
|
14
|
-
batch_preds = self.model.predict(np.array(X))
|
14
|
+
batch_preds = self.model.predict(np.array(X), verbose=0)
|
15
15
|
batch_results = []
|
16
16
|
for pred in batch_preds:
|
17
17
|
top_indices = pred.argsort()[-top_k:][::-1]
|
@@ -134,7 +134,6 @@ class ScoreCalculator:
|
|
134
134
|
|
135
135
|
# Calculate semantic distance
|
136
136
|
rank_count, _ = self.count_ancestors_to_lca(idx1, idx2)
|
137
|
-
print(f"Rank Count for {label1} and {label2}: {rank_count}")
|
138
137
|
|
139
138
|
# Calculate product of probabilities and distance
|
140
139
|
prob_product = prob1 * prob2
|
@@ -24,10 +24,10 @@ def get_preprocess_function(model):
|
|
24
24
|
model_config = model.get_config()
|
25
25
|
if "name" in model_config:
|
26
26
|
model_name = model_config["name"].lower()
|
27
|
-
print(f"Model name: {model_name}")
|
27
|
+
# print(f"Model name: {model_name}")
|
28
28
|
for key in preprocess_map.keys():
|
29
29
|
if key in model_name:
|
30
|
-
print(f"Detected model type: {key}")
|
30
|
+
# print(f"Detected model type: {key}")
|
31
31
|
return preprocess_map[key]
|
32
32
|
|
33
33
|
for layer in model.layers:
|
@@ -35,7 +35,7 @@ def get_preprocess_function(model):
|
|
35
35
|
print(f"Checking layer: {layer_name}")
|
36
36
|
for model_name in preprocess_map.keys():
|
37
37
|
if model_name in layer_name:
|
38
|
-
print(f"Detected model type: {model_name}")
|
38
|
+
# print(f"Detected model type: {model_name}")
|
39
39
|
return preprocess_map[model_name]
|
40
40
|
|
41
41
|
print("No supported model type found in the configuration. Falling back to generic normalization.")
|
@@ -25,15 +25,15 @@ def get_preprocess_function(model):
|
|
25
25
|
model_config = model.get_config()
|
26
26
|
if "name" in model_config:
|
27
27
|
model_name = model_config["name"].lower()
|
28
|
-
print(f"Model name: {model_name}")
|
28
|
+
# print(f"Model name: {model_name}")
|
29
29
|
for key in preprocess_map.keys():
|
30
30
|
if key in model_name:
|
31
|
-
print(f"Detected model type: {key}")
|
31
|
+
# print(f"Detected model type: {key}")
|
32
32
|
return preprocess_map[key]
|
33
33
|
|
34
34
|
for layer in model.layers:
|
35
35
|
layer_name = layer.name.lower()
|
36
|
-
print(f"Checking layer: {layer_name}")
|
36
|
+
# print(f"Checking layer: {layer_name}")
|
37
37
|
for model_name in preprocess_map.keys():
|
38
38
|
if model_name in layer_name:
|
39
39
|
print(f"Detected model type: {model_name}")
|
@@ -0,0 +1,174 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: BETTER_NMA
|
3
|
+
Version: 1.0.2
|
4
|
+
Summary: NMA: Dendrogram-based model analysis, white-box testing, and adversarial detection
|
5
|
+
Author: BETTER_XAI
|
6
|
+
Author-email: BETTERXAI2025@gmail.com
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
8
|
+
Classifier: Intended Audience :: Developers
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
11
|
+
Classifier: Operating System :: OS Independent
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
19
|
+
Requires-Python: >=3.8
|
20
|
+
Description-Content-Type: text/markdown
|
21
|
+
Requires-Dist: tensorflow>=2.10.0
|
22
|
+
Requires-Dist: pandas>=1.3.0
|
23
|
+
Requires-Dist: python-igraph>=0.10.0
|
24
|
+
Requires-Dist: numpy>=1.21.0
|
25
|
+
Requires-Dist: scikit-learn>=1.0.0
|
26
|
+
Requires-Dist: matplotlib>=3.5.0
|
27
|
+
Requires-Dist: nltk>=3.7
|
28
|
+
Requires-Dist: keras>=2.10.0
|
29
|
+
Requires-Dist: Pillow>=8.0.0
|
30
|
+
|
31
|
+
|
32
|
+
---
|
33
|
+
|
34
|
+
# NMA – Near Misses Analysis
|
35
|
+
|
36
|
+
NMA (**Near Misses Analysis**) is a Python package for analyzing machine learning models through **dendrogram-based hierarchical clustering**, **white-box testing**, and **adversarial attack detection**.
|
37
|
+
|
38
|
+
It provides visualization, explanation, and diagnostic tools to help developers and researchers understand their models’ decision boundaries, identify vulnerabilities, and detect adversarial inputs.
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
## ✨ Features
|
43
|
+
|
44
|
+
* 📊 **Dendrogram construction & visualization**
|
45
|
+
|
46
|
+
* Build hierarchical trees from model predictions.
|
47
|
+
* Plot full dendrograms or **sub-dendrograms** for specific labels.
|
48
|
+
|
49
|
+
* 🧪 **White-box testing**
|
50
|
+
|
51
|
+
* Identify problematic training samples likely to cause misclassification.
|
52
|
+
* Run structured analysis across source/target label pairs.
|
53
|
+
|
54
|
+
* 🛡 **Adversarial attack detection**
|
55
|
+
|
56
|
+
* Train a logistic regression adversarial detector.
|
57
|
+
* Detect adversarial images and compute adversarial scores.
|
58
|
+
|
59
|
+
* 🔎 **Model querying & explanations**
|
60
|
+
|
61
|
+
* Query images for predictions with hierarchical context.
|
62
|
+
* Generate **verbal explanations** of model predictions.
|
63
|
+
|
64
|
+
* 🧩 **Cluster analysis tools**
|
65
|
+
|
66
|
+
* Find lowest common ancestors (LCA) in the dendrogram.
|
67
|
+
* Rename clusters for more meaningful interpretation.
|
68
|
+
|
69
|
+
---
|
70
|
+
|
71
|
+
## 📦 Installation
|
72
|
+
|
73
|
+
```bash
|
74
|
+
pip install BETTER_NMA
|
75
|
+
```
|
76
|
+
|
77
|
+
---
|
78
|
+
|
79
|
+
## 🚀 Quickstart
|
80
|
+
|
81
|
+
```python
|
82
|
+
from BETTER_NMA import NMA
|
83
|
+
import numpy as np
|
84
|
+
|
85
|
+
# Example data (replace with your dataset/model)
|
86
|
+
x_train = np.random.rand(100, 32, 32, 3)
|
87
|
+
y_train = np.random.randint(0, 2, size=100)
|
88
|
+
labels = ["cat", "dog"]
|
89
|
+
|
90
|
+
# Your pre-trained model (e.g., Keras, PyTorch wrapper with predict)
|
91
|
+
model = my_model
|
92
|
+
|
93
|
+
# Initialize NMA
|
94
|
+
nma = NMA(
|
95
|
+
x_train=x_train,
|
96
|
+
y_train=y_train,
|
97
|
+
labels=labels,
|
98
|
+
model=model,
|
99
|
+
explanation_method="similarity",
|
100
|
+
save_connections=True
|
101
|
+
)
|
102
|
+
|
103
|
+
# Plot dendrogram
|
104
|
+
nma.plot(title="Model Decision Hierarchy")
|
105
|
+
|
106
|
+
# Run white-box testing
|
107
|
+
issues = nma.white_box_testing(["cat"], ["dog"], analyze_results=True)
|
108
|
+
|
109
|
+
# Train adversarial detector
|
110
|
+
nma.train_adversarial_detector(authentic_images, adversarial_images)
|
111
|
+
|
112
|
+
# Detect if a new image is adversarial
|
113
|
+
result = nma.detect_attack(test_image)
|
114
|
+
|
115
|
+
# Get verbal explanation of an image
|
116
|
+
explanation = nma.verbal_explanation(test_image)
|
117
|
+
print(explanation)
|
118
|
+
```
|
119
|
+
|
120
|
+
---
|
121
|
+
|
122
|
+
## 📚 API Overview
|
123
|
+
|
124
|
+
### Dendrogram & Visualization
|
125
|
+
|
126
|
+
* `plot(sub_labels=None, ...)` – plot full or partial dendrogram.
|
127
|
+
* `plot_sub_dendrogram(sub_labels, ...)` – zoom into specific classes.
|
128
|
+
|
129
|
+
### White-box Testing
|
130
|
+
|
131
|
+
* `white_box_testing(source_labels, target_labels, ...)` – find problematic images.
|
132
|
+
* `get_white_box_analysis(source_labels, target_labels, ...)` – detailed analysis.
|
133
|
+
|
134
|
+
### Adversarial Detection
|
135
|
+
|
136
|
+
* `train_adversarial_detector(authentic_images, attacked_images)` – train detector.
|
137
|
+
* `detect_attack(image, plot_result=False)` – detect adversarial samples.
|
138
|
+
* `adversarial_score(image, top_k=5)` – compute adversarial score.
|
139
|
+
|
140
|
+
### Query & Explanation
|
141
|
+
|
142
|
+
* `query_image(image, top_k=5)` – get predictions & explanation.
|
143
|
+
* `verbal_explanation(image)` – generate natural language explanation.
|
144
|
+
|
145
|
+
### Cluster Analysis
|
146
|
+
|
147
|
+
* `find_lca(label1, label2)` – lowest common ancestor.
|
148
|
+
* `change_cluster_name(cluster_id, new_name)` – rename clusters.
|
149
|
+
|
150
|
+
---
|
151
|
+
|
152
|
+
## 🛠 Requirements
|
153
|
+
|
154
|
+
* Python ≥ 3.8
|
155
|
+
* NumPy, Pandas, Matplotlib, Scikit-learn
|
156
|
+
* (Optional) PyTorch / TensorFlow for model support
|
157
|
+
|
158
|
+
---
|
159
|
+
|
160
|
+
## 📖 Use Cases
|
161
|
+
|
162
|
+
* **Research** – interpret model predictions via hierarchical clustering.
|
163
|
+
* **Robustness testing** – identify adversarial vulnerabilities.
|
164
|
+
* **Explainability** – provide visual + verbal explanations.
|
165
|
+
* **Debugging** – detect mislabeled or problematic training samples.
|
166
|
+
|
167
|
+
---
|
168
|
+
|
169
|
+
## 📜 License
|
170
|
+
|
171
|
+
MIT License – free to use and modify.
|
172
|
+
|
173
|
+
---
|
174
|
+
|
@@ -2,8 +2,9 @@ BETTER_NMA/__init__.py,sha256=ePaQnto0n4hccz2490Z7bxwcbtONVAa6nWqg7SL4W1Y,428
|
|
2
2
|
BETTER_NMA/adversarial_score.py,sha256=qgScTqS-aJ2q4kFom505hBtonVzKK67fGS09J1_-G3o,875
|
3
3
|
BETTER_NMA/change_cluster_name.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
BETTER_NMA/detect_attack.py,sha256=s7YwTVMJFABSMt2aISR-zaIUxFaSWm9oODc9yF12KPY,4327
|
5
|
+
BETTER_NMA/explaination_score.py,sha256=GWtncYjIj8UF94g1UxtNRnyK7Cvh3PqVcShle_vLhUM,2003
|
5
6
|
BETTER_NMA/find_lca.py,sha256=UlyftOJmbSPuXzxvcheRb_IrdCqBsaSQHLchIRZIR-0,812
|
6
|
-
BETTER_NMA/main.py,sha256=
|
7
|
+
BETTER_NMA/main.py,sha256=2d3O8Nc6J9YTWXIsqIGIIWDkL1V3pWN1hhcDde873Nc,11525
|
7
8
|
BETTER_NMA/nma_creator.py,sha256=M-LlZGRkxhGYLHpaXTNoZj9AUH7uvev7hq7tbILWMLI,5137
|
8
9
|
BETTER_NMA/plot.py,sha256=nj2ca-ybzGMlo6HhCngyjGUNaJDmfsPxF5ad9xpxzvE,4383
|
9
10
|
BETTER_NMA/query_image.py,sha256=13AQ9-8QdzaIwH5-ELX3z3iJBP8nTDe-SMtwQve-1ek,906
|
@@ -11,19 +12,19 @@ BETTER_NMA/train_adversarial_detector.py,sha256=nMaQ-Pm2vP84qNR1GoKQiVPpmMC3rdor
|
|
11
12
|
BETTER_NMA/white_box_testing.py,sha256=zfhK8G-2cJH1AMevPywVnc05IhSqttf3YxQ6abdpM78,3524
|
12
13
|
BETTER_NMA/utilss/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
14
|
BETTER_NMA/utilss/models_utils.py,sha256=gBXY2LFH4iR-2GZmHeUnnB5n9t3VdjIc9sugHDrD3AM,671
|
14
|
-
BETTER_NMA/utilss/photos_uitls.py,sha256=
|
15
|
-
BETTER_NMA/utilss/photos_utils.py,sha256=
|
15
|
+
BETTER_NMA/utilss/photos_uitls.py,sha256=wxmIIKFgAKYkcYaK95UMjtY-LZS6NDVveKrHBQV8Q70,3166
|
16
|
+
BETTER_NMA/utilss/photos_utils.py,sha256=4EjDHbMjrJ8P9y-X4H05P4wez4uKNit60UGnu3sKsys,4412
|
16
17
|
BETTER_NMA/utilss/verbal_explanation.py,sha256=_hrYZUjBUYOfuGr7t5r-DACooR5d60dRtGfUj7FbeZw,549
|
17
18
|
BETTER_NMA/utilss/wordnet_utils.py,sha256=_A_gbdR7tf5tiyN2Oe5sB4vvBkWnr4KUl5e9iq5ft8c,5535
|
18
19
|
BETTER_NMA/utilss/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
BETTER_NMA/utilss/classes/adversarial_dataset.py,sha256=
|
20
|
+
BETTER_NMA/utilss/classes/adversarial_dataset.py,sha256=LKmyseQetyBdoKrl7Q4MaTc7EzMZcMgqNdtCsdAvKHA,2299
|
20
21
|
BETTER_NMA/utilss/classes/adversarial_detector.py,sha256=BE_SxNEwcvuHERBiefefOmk1k6NJSo6juehkAjkEHuQ,2331
|
21
22
|
BETTER_NMA/utilss/classes/dendrogram.py,sha256=vtKBFfwzcz8k01Goc83pZlWC2pO86endTJURlkUWVQI,5141
|
22
23
|
BETTER_NMA/utilss/classes/edges_dataframe.py,sha256=q-RQ6beOeZeIgdEzwi8T5Ag2NBFySv7-ITD5m989nl4,1896
|
23
|
-
BETTER_NMA/utilss/classes/score_calculator.py,sha256=
|
24
|
+
BETTER_NMA/utilss/classes/score_calculator.py,sha256=zgZaFgFJeok2RzXFm9OE5pOuXY3euIXEiLGI44q30JM,5927
|
24
25
|
BETTER_NMA/utilss/classes/whitebox_testing.py,sha256=4WSEjQ5gl6f8xzWADAagZ3WtMHE889rW-zcYld9REnw,1367
|
25
26
|
BETTER_NMA/utilss/classes/preprocessing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
-
BETTER_NMA/utilss/classes/preprocessing/batch_predictor.py,sha256=
|
27
|
+
BETTER_NMA/utilss/classes/preprocessing/batch_predictor.py,sha256=Cw5yzxLCPYGCTvOWclyCLT4qNgCCTSbyr-BNHapkwn0,957
|
27
28
|
BETTER_NMA/utilss/classes/preprocessing/graph_builder.py,sha256=ILumiBY9BUIOxrIvq8C-8n945pK-t94Et6gZwJB-364,1672
|
28
29
|
BETTER_NMA/utilss/classes/preprocessing/heap_processor.py,sha256=KblmkVWVfMYtpZa4Wy1Ry0lVfdSr6h8LySt4S-lvIGo,1064
|
29
30
|
BETTER_NMA/utilss/classes/preprocessing/hierarchical_clustering_builder.py,sha256=YAIElJS_fSffIb3D2N1OZu9U6z7RYrHQTfB6bH4-VPI,4027
|
@@ -32,7 +33,7 @@ BETTER_NMA/utilss/classes/preprocessing/z_builder.py,sha256=T8ETfL7mMOgEj7oYNsw6
|
|
32
33
|
BETTER_NMA/utilss/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
34
|
BETTER_NMA/utilss/enums/explanation_method.py,sha256=Ang-rjvxO4AJ1IH4mwS8sNpSwt9jn3PlqFbPPT-R9I8,150
|
34
35
|
BETTER_NMA/utilss/enums/heap_types.py,sha256=0z1d2qu1ZCbpWRXKD1dTopn3M4G1CxRQW9HWxVxyPIA,88
|
35
|
-
BETTER_NMA-1.0.
|
36
|
-
BETTER_NMA-1.0.
|
37
|
-
BETTER_NMA-1.0.
|
38
|
-
BETTER_NMA-1.0.
|
36
|
+
BETTER_NMA-1.0.2.dist-info/METADATA,sha256=9_3kUtQ3Cw2TL_3wq4l0ICWgJtNncp197lFQUrsCfas,5100
|
37
|
+
BETTER_NMA-1.0.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
38
|
+
BETTER_NMA-1.0.2.dist-info/top_level.txt,sha256=SVRNqWPvCnynWVyXNAYnf9CSQIvMAvE6iyyiGHodQgY,11
|
39
|
+
BETTER_NMA-1.0.2.dist-info/RECORD,,
|
@@ -1,11 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: BETTER_NMA
|
3
|
-
Version: 1.0.0
|
4
|
-
Requires-Dist: tensorflow
|
5
|
-
Requires-Dist: pandas
|
6
|
-
Requires-Dist: igraph
|
7
|
-
Requires-Dist: numpy
|
8
|
-
Requires-Dist: scikit-learn
|
9
|
-
Requires-Dist: matplotlib
|
10
|
-
Requires-Dist: nltk
|
11
|
-
Requires-Dist: keras
|
File without changes
|
File without changes
|