patra-toolkit 0.1.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.
- patra_toolkit-0.1.1/LICENSE +28 -0
- patra_toolkit-0.1.1/PKG-INFO +15 -0
- patra_toolkit-0.1.1/README.md +129 -0
- patra_toolkit-0.1.1/patra_toolkit/__init__.py +3 -0
- patra_toolkit-0.1.1/patra_toolkit/fairlearn_bias.py +32 -0
- patra_toolkit-0.1.1/patra_toolkit/patra_model_card.py +376 -0
- patra_toolkit-0.1.1/patra_toolkit/schema/schema.json +274 -0
- patra_toolkit-0.1.1/patra_toolkit/shap_xai.py +37 -0
- patra_toolkit-0.1.1/patra_toolkit.egg-info/PKG-INFO +15 -0
- patra_toolkit-0.1.1/patra_toolkit.egg-info/SOURCES.txt +17 -0
- patra_toolkit-0.1.1/patra_toolkit.egg-info/dependency_links.txt +1 -0
- patra_toolkit-0.1.1/patra_toolkit.egg-info/requires.txt +6 -0
- patra_toolkit-0.1.1/patra_toolkit.egg-info/top_level.txt +2 -0
- patra_toolkit-0.1.1/setup.cfg +4 -0
- patra_toolkit-0.1.1/setup.py +23 -0
- patra_toolkit-0.1.1/tests/__init__.py +0 -0
- patra_toolkit-0.1.1/tests/test_patra_hash_id.py +116 -0
- patra_toolkit-0.1.1/tests/test_patra_inout_data.py +112 -0
- patra_toolkit-0.1.1/tests/test_patra_mc.py +159 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, Indiana University Board of Trustees.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: patra-toolkit
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Toolkit for semi-automated modelcard creation for AI/ML models.
|
|
5
|
+
Home-page: https://github.com/Data-to-Insight-Center/patra-toolkit.git
|
|
6
|
+
Author: Data to Insight Center
|
|
7
|
+
Author-email: d2i@iu.edu
|
|
8
|
+
License: BSD-3-Clause
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: jsonschema>4.18.5
|
|
11
|
+
Requires-Dist: fairlearn~=0.11.0
|
|
12
|
+
Requires-Dist: shap~=0.46.0
|
|
13
|
+
Requires-Dist: pandas>=2.0.0
|
|
14
|
+
Requires-Dist: numpy>2.0.0
|
|
15
|
+
Requires-Dist: requests>2.32.2
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Patra Model Card Toolkit
|
|
2
|
+
|
|
3
|
+
[](https://patra-toolkit.readthedocs.io/en/latest/)
|
|
4
|
+
[](https://github.com/Data-to-Insight-Center/patra-toolkit/actions)
|
|
5
|
+
[](https://pypi.org/project/patra-model-card/)
|
|
6
|
+
|
|
7
|
+
The Patra Toolkit is a component of the Patra ModelCards framework designed to simplify the process of creating and documenting AI/ML models. It provides a structured schema that guides users in providing essential information about their models, including details about the model's purpose, development process, and performance. The toolkit also includes features for semi-automating the capture of key information, such as fairness and explainability metrics, through integrated analysis tools. By reducing the manual effort involved in creating model cards, the Patra Toolkit encourages researchers and developers to adopt best practices for documenting their models, ultimately contributing to greater transparency and accountability in AI/ML development.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Structured Schema:** The Patra Toolkit offers a structured schema to guide users in providing crucial model information. This includes details such as the model's intended use, development process, and performance metrics.
|
|
12
|
+
|
|
13
|
+
- **Semi-Automated Information Capture:** The toolkit supports semi-automatic capture of certain descriptive fields. It achieves this by running a variety of automated scanners, with the results incorporated into the Model Card. These include,
|
|
14
|
+
- **Fairness Scanner** evaluates the model's fairness by examining its predictions across different groups.
|
|
15
|
+
- **Explainability Scanner** generates explainability metrics to help understand the model's decision-making process.
|
|
16
|
+
- **Model Requirements Scanner** captures the Python packages and versions required to run the model.
|
|
17
|
+
|
|
18
|
+
- **Validation and JSON Generation:** Once a Model Card is created using the Toolkit, it validates the data against the defined schema to ensure completeness and accuracy. It then generates the Model Card as a JSON file, ready for integration into the Patra Knowledge Base.
|
|
19
|
+
|
|
20
|
+
- **Integration with Patra Knowledge Base:** The Model Cards created using the Patra Toolkit are designed to be added to the [Patra Knowledge Base](https://github.com/Data-to-Insight-Center/patra-kg), which is a graph database that stores and manages these cards.
|
|
21
|
+
|
|
22
|
+
The Patra Toolkit plays a crucial role in promoting transparency and accountability in AI/ML development by making it easier for developers to create comprehensive and informative Model Cards. By automating certain aspects of the documentation process and providing a structured schema, the Toolkit reduces the barriers to entry for creating high-quality model documentation.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to the [Patra ModelCards paper](https://ieeexplore.ieee.org/document/10678710).
|
|
25
|
+
|
|
26
|
+
## Getting Started
|
|
27
|
+
|
|
28
|
+
#### (Optional) Create a virtual environment for using Patra Model Card Toolkit
|
|
29
|
+
We recommend creating a new virtual environment using venv before installing patra-model-card. To do so, please follow instructions [here](https://docs.python.org/3/library/venv.html).
|
|
30
|
+
|
|
31
|
+
#### Installing Patra Model Card
|
|
32
|
+
The latest version can be installed from PyPI:
|
|
33
|
+
```shell
|
|
34
|
+
pip install patra-toolkit
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For local installation, clone the repository and install using:
|
|
38
|
+
```shell
|
|
39
|
+
pip install -e <local_git_dir>/patra_toolkit
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
### Create a Model Card
|
|
44
|
+
Find the descriptions of the Model Card parameters in the [schema descriptions document](https://github.com/Data-to-Insight-Center/patra-toolkit/blob/main/Schema_Descriptions.md).
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from patra_toolkit import ModelCard
|
|
48
|
+
|
|
49
|
+
mc = ModelCard(
|
|
50
|
+
name="UCI Adult Data Analysis model using Tensorflow",
|
|
51
|
+
version="0.1",
|
|
52
|
+
short_description="UCI Adult Data analysis using Tensorflow for demonstration of Patra Model Cards.",
|
|
53
|
+
full_description="We have trained a ML model using the tensorflow framework to predict income for the UCI Adult Dataset. We leverage this data to run the Patra model cards to capture metadata about the model as well as fairness and explainability metrics.",
|
|
54
|
+
keywords="uci adult, tensorflow, explainability, fairness, patra",
|
|
55
|
+
author="Sachith Withana",
|
|
56
|
+
input_type="Tabular",
|
|
57
|
+
category="classification",
|
|
58
|
+
foundational_model="None"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Add Model Metadata
|
|
62
|
+
mc.input_data = 'https://archive.ics.uci.edu/dataset/2/adult'
|
|
63
|
+
mc.output_data = 'https://github.iu.edu/swithana/mcwork/rf_sklearn/adult_model.pkl'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Initialize an AI/ML Model
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from patra_toolkit import AIModel
|
|
70
|
+
|
|
71
|
+
ai_model = AIModel(
|
|
72
|
+
name="UCI Adult Random Forest model",
|
|
73
|
+
version="0.1",
|
|
74
|
+
description="Census classification problem using Random Forest",
|
|
75
|
+
owner="Sachith Withana",
|
|
76
|
+
location="https://github.iu.edu/swithana/mcwork/randomforest/adult_model.pkl",
|
|
77
|
+
license="BSD-3 Clause",
|
|
78
|
+
framework="sklearn",
|
|
79
|
+
model_type="random_forest",
|
|
80
|
+
test_accuracy=accuracy
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Populate Model Structure
|
|
84
|
+
ai_model.populate_model_structure(trained_model)
|
|
85
|
+
mc.ai_model = ai_model
|
|
86
|
+
|
|
87
|
+
# Add Custom Metrics
|
|
88
|
+
ai_model.add_metric("Test loss", loss)
|
|
89
|
+
ai_model.add_metric("Epochs", 100)
|
|
90
|
+
ai_model.add_metric("Batch Size", 32)
|
|
91
|
+
ai_model.add_metric("Optimizer", "Adam")
|
|
92
|
+
ai_model.add_metric("Learning Rate", 0.0001)
|
|
93
|
+
ai_model.add_metric("Input Shape", "(26048, 100)")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Run Fairness and Explainability Scanners
|
|
97
|
+
```python
|
|
98
|
+
# To assess fairness, provide the sensitive feature, test data, labels, and predictions
|
|
99
|
+
mc.populate_bias(X_test, y_test, predictions, "gender", X_test['sex'], clf)
|
|
100
|
+
|
|
101
|
+
# To generate explainability metrics, specify the dataset, column names, model, and number of features
|
|
102
|
+
mc.populate_xai(X_test, x_columns, model, top_n=10)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Validate and Save the Model Card
|
|
106
|
+
```python
|
|
107
|
+
# Verify the model card content against the schema
|
|
108
|
+
mc.validate()
|
|
109
|
+
mc.save(<file_path>)
|
|
110
|
+
|
|
111
|
+
# Capture Python package dependencies and versions
|
|
112
|
+
mc.populate_requirements()
|
|
113
|
+
|
|
114
|
+
# Upload the model card to the Patra server
|
|
115
|
+
mc.submit(<patra_server_url>)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
## Examples
|
|
120
|
+
Explore the following example notebooks and model cards to learn more about how to use the Patra Model Card Toolkit:
|
|
121
|
+
[Notebook Examples](./examples/notebooks), [Model Card Examples](./examples/model_cards)
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
The Patra Model Card toolkit is developed by Indiana University and distributed under the BSD 3-Clause License. See `LICENSE.txt` for more details.
|
|
127
|
+
|
|
128
|
+
## Reference
|
|
129
|
+
S. Withana and B. Plale, "Patra ModelCards: AI/ML Accountability in the Edge-Cloud Continuum," 2024 IEEE 20th International Conference on e-Science (e-Science), Osaka, Japan, 2024, pp. 1-10, doi: 10.1109/e-Science62913.2024.10678710. Keywords: Analytical models, Vectors, Edge-cloud continuum, Model cards, AI/ML accountability, Provenance
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from fairlearn.metrics import demographic_parity_difference, equalized_odds_difference
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BiasAnalyzer:
|
|
5
|
+
"""
|
|
6
|
+
Provides automated capture of fairness metrics in a given AI workflow.
|
|
7
|
+
"""
|
|
8
|
+
def __init__(self, dataset, true_labels, predicted_labels, sensitive_feature_name, sensitive_feature_data, model):
|
|
9
|
+
self.dataset = dataset
|
|
10
|
+
self.true_labels = true_labels
|
|
11
|
+
self.predicted_labels = predicted_labels
|
|
12
|
+
self.sensitive_feature = sensitive_feature_name
|
|
13
|
+
self.sensitive_data = sensitive_feature_data
|
|
14
|
+
self.model = model
|
|
15
|
+
|
|
16
|
+
def calculate_bias_metrics(self):
|
|
17
|
+
"""
|
|
18
|
+
Calculate bias metrics.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
None
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
dict: A dictionary of bias
|
|
25
|
+
"""
|
|
26
|
+
demographic_parity = demographic_parity_difference(self.true_labels, self.predicted_labels,
|
|
27
|
+
sensitive_features=self.sensitive_data)
|
|
28
|
+
equal_odds_diff = equalized_odds_difference(self.true_labels, self.predicted_labels,
|
|
29
|
+
sensitive_features=self.sensitive_data)
|
|
30
|
+
|
|
31
|
+
return {"demographic_parity_diff": demographic_parity,
|
|
32
|
+
"equal_odds_difference": equal_odds_diff}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import os.path
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from json import JSONEncoder
|
|
6
|
+
from typing import List, Optional, Dict
|
|
7
|
+
|
|
8
|
+
import jsonschema
|
|
9
|
+
import pkg_resources
|
|
10
|
+
import requests
|
|
11
|
+
|
|
12
|
+
from .fairlearn_bias import BiasAnalyzer
|
|
13
|
+
from .shap_xai import ExplainabilityAnalyser
|
|
14
|
+
|
|
15
|
+
SCHEMA_JSON = os.path.join(os.path.dirname(__file__), 'schema', 'schema.json')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class Metric:
|
|
20
|
+
"""
|
|
21
|
+
Data class for storing metric key-value pairs.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
key (str): The name of the metric.
|
|
25
|
+
value (str): The value of the metric.
|
|
26
|
+
"""
|
|
27
|
+
key: str
|
|
28
|
+
value: str
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class AIModel:
|
|
32
|
+
"""
|
|
33
|
+
Represents and stores AI model metadata and its performance metrics.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
name (str): The name of the model.
|
|
37
|
+
version (str): The version identifier of the model.
|
|
38
|
+
description (str): A detailed description of the model.
|
|
39
|
+
owner (str): The owner of the model.
|
|
40
|
+
location (str): The file path or URL where the model is stored.
|
|
41
|
+
license (str): The license under which the model is distributed.
|
|
42
|
+
framework (str): The framework used to build the model (e.g., TensorFlow, PyTorch).
|
|
43
|
+
model_type (str): The type of model (e.g., classifier, regressor).
|
|
44
|
+
test_accuracy (str): The accuracy of the model on a test dataset.
|
|
45
|
+
model_structure (str): The structure of the model as a dictionary (optional).
|
|
46
|
+
metrics (str): A dictionary storing performance metrics for the model.
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
.. code-block:: python
|
|
50
|
+
|
|
51
|
+
ai_model = AIModel(
|
|
52
|
+
name="Model Name",
|
|
53
|
+
version="1.0",
|
|
54
|
+
description="Model description",
|
|
55
|
+
owner="Model owner",
|
|
56
|
+
location="Model location",
|
|
57
|
+
license="Model license",
|
|
58
|
+
framework="Model framework",
|
|
59
|
+
model_type="Model type",
|
|
60
|
+
test_accuracy=0.95,
|
|
61
|
+
model_structure={},
|
|
62
|
+
metrics={"accuracy": "0.95"}
|
|
63
|
+
)
|
|
64
|
+
"""
|
|
65
|
+
name: str
|
|
66
|
+
version: str
|
|
67
|
+
description: str
|
|
68
|
+
owner: str
|
|
69
|
+
location: str
|
|
70
|
+
license: str
|
|
71
|
+
framework: str
|
|
72
|
+
model_type: str
|
|
73
|
+
test_accuracy: float
|
|
74
|
+
model_structure: Optional[object] = field(default_factory=dict)
|
|
75
|
+
metrics: Dict[str, str] = field(default_factory=dict)
|
|
76
|
+
|
|
77
|
+
def add_metric(self, key: str, value: str) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Adds a performance metric to the model's metrics.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
key (str): The name of the metric.
|
|
83
|
+
value (str): The value of the metric.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
None
|
|
87
|
+
"""
|
|
88
|
+
self.metrics[key] = value
|
|
89
|
+
|
|
90
|
+
def remove_nulls(self, model_structure):
|
|
91
|
+
"""
|
|
92
|
+
Recursively removes null values from the model structure.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
model_structure (object): The model structure as a dictionary or list.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
object: Model structure with null values removed.
|
|
99
|
+
"""
|
|
100
|
+
if isinstance(model_structure, dict):
|
|
101
|
+
return {k: self.remove_nulls(v) for k, v in model_structure.items() if v is not None}
|
|
102
|
+
elif isinstance(model_structure, list):
|
|
103
|
+
return [self.remove_nulls(v) for v in model_structure if v is not None]
|
|
104
|
+
return model_structure
|
|
105
|
+
|
|
106
|
+
def populate_model_structure(self, trained_model):
|
|
107
|
+
"""
|
|
108
|
+
Populates the `model_structure` attribute from a trained model object.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
trained_model (object): A trained machine learning model object.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
None
|
|
115
|
+
"""
|
|
116
|
+
if self.framework == 'tensorflow':
|
|
117
|
+
json_structure = json.loads(trained_model.to_json())
|
|
118
|
+
self.model_structure = self.remove_nulls(json_structure)
|
|
119
|
+
else:
|
|
120
|
+
self.model_structure = {}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@dataclass
|
|
124
|
+
class BiasAnalysis:
|
|
125
|
+
"""
|
|
126
|
+
Class to store results from bias analysis.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
demographic_parity_difference (float): The difference in demographic parity between groups.
|
|
130
|
+
equal_odds_difference (float): The difference in equal odds between groups.
|
|
131
|
+
"""
|
|
132
|
+
demographic_parity_difference: float
|
|
133
|
+
equal_odds_difference: float
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass
|
|
137
|
+
class ExplainabilityAnalysis:
|
|
138
|
+
"""
|
|
139
|
+
Class to store explainability metrics.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
name (str): Name of the explainability method used.
|
|
143
|
+
metrics (List[Metric]): List of metrics related to explainability analysis.
|
|
144
|
+
"""
|
|
145
|
+
name: str
|
|
146
|
+
metrics: List[Metric] = field(default_factory=list)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@dataclass
|
|
150
|
+
class ModelCard:
|
|
151
|
+
"""
|
|
152
|
+
Represents an AI model card to document model metadata, analyses, and requirements.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
name (str): The name of the model.
|
|
156
|
+
version (str): The model's version.
|
|
157
|
+
short_description (str): A brief description of the model.
|
|
158
|
+
full_description (str): A detailed description of the model.
|
|
159
|
+
keywords (str): Comma-separated keywords for searchability.
|
|
160
|
+
author (str): The model's creator or owner.
|
|
161
|
+
input_type (str): Type of input data (e.g., "Image", "Text").
|
|
162
|
+
category (str): The category of the model (e.g., "Classification", "Regression").
|
|
163
|
+
input_data (Optional[str]): Description of the model's input data.
|
|
164
|
+
output_data (Optional[str]): Description of the model's output data.
|
|
165
|
+
foundational_model (Optional[str]): Reference to any foundational model used.
|
|
166
|
+
ai_model (Optional[AIModel]): An instance of `AIModel` containing model details.
|
|
167
|
+
bias_analysis (Optional[BiasAnalysis]): Instance of `BiasAnalysis` containing bias metrics.
|
|
168
|
+
xai_analysis (Optional[ExplainabilityAnalysis]): Instance of `ExplainabilityAnalysis` with interpretability metrics.
|
|
169
|
+
model_requirements (Optional[List[str]]): List of required packages and dependencies.
|
|
170
|
+
id (Optional[str]): Unique identifier for the model card, generated upon submission.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
.. code-block:: python
|
|
174
|
+
|
|
175
|
+
model_card = ModelCard(
|
|
176
|
+
name="Model Name",
|
|
177
|
+
version="1.0",
|
|
178
|
+
short_description="A brief description",
|
|
179
|
+
full_description="A detailed description of the model's purpose and usage.",
|
|
180
|
+
keywords="classification, AI, image processing",
|
|
181
|
+
author="Author Name",
|
|
182
|
+
input_type="Image",
|
|
183
|
+
category="Classification",
|
|
184
|
+
input_data="Images of size 28x28.",
|
|
185
|
+
output_data="Prediction probabilities for classes.",
|
|
186
|
+
foundational_model="Base Model Reference",
|
|
187
|
+
ai_model=AIModel(
|
|
188
|
+
name="Model Name",
|
|
189
|
+
version="1.0",
|
|
190
|
+
description="Detailed model description",
|
|
191
|
+
owner="Model owner",
|
|
192
|
+
location="Storage location",
|
|
193
|
+
license="MIT",
|
|
194
|
+
framework="TensorFlow",
|
|
195
|
+
model_type="Classifier",
|
|
196
|
+
test_accuracy=0.95,
|
|
197
|
+
model_structure={},
|
|
198
|
+
metrics={"accuracy": "0.95"}
|
|
199
|
+
),
|
|
200
|
+
bias_analysis=BiasAnalysis(
|
|
201
|
+
demographic_parity_difference=0.05,
|
|
202
|
+
equal_odds_difference=0.1
|
|
203
|
+
),
|
|
204
|
+
xai_analysis=ExplainabilityAnalysis(
|
|
205
|
+
name="SHAP",
|
|
206
|
+
metrics=[Metric(key="Feature A", value="0.1")]
|
|
207
|
+
),
|
|
208
|
+
model_requirements=["numpy>=1.19.2", "tensorflow>=2.4.1"]
|
|
209
|
+
)
|
|
210
|
+
"""
|
|
211
|
+
name: str
|
|
212
|
+
version: str
|
|
213
|
+
short_description: str
|
|
214
|
+
full_description: str
|
|
215
|
+
keywords: str
|
|
216
|
+
author: str
|
|
217
|
+
input_type: str
|
|
218
|
+
category: str
|
|
219
|
+
input_data: Optional[str] = ""
|
|
220
|
+
output_data: Optional[str] = ""
|
|
221
|
+
foundational_model: Optional[str] = ""
|
|
222
|
+
ai_model: Optional[AIModel] = None
|
|
223
|
+
bias_analysis: Optional[BiasAnalysis] = None
|
|
224
|
+
xai_analysis: Optional[ExplainabilityAnalysis] = None
|
|
225
|
+
model_requirements: Optional[List] = None
|
|
226
|
+
id: Optional[str] = field(init=False, default=None)
|
|
227
|
+
|
|
228
|
+
def __str__(self):
|
|
229
|
+
"""
|
|
230
|
+
Returns a JSON string representation of the model card.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
str: A JSON-formatted string representing the model card.
|
|
234
|
+
"""
|
|
235
|
+
return json.dumps(self.__dict__, cls=ModelCardJSONEncoder, indent=4, separators=(',', ': '))
|
|
236
|
+
|
|
237
|
+
def populate_bias(self, dataset, true_labels, predicted_labels, sensitive_feature_name, sensitive_feature_data, model):
|
|
238
|
+
"""
|
|
239
|
+
Calculates and stores fairness metrics.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
dataset (object): The dataset used for bias analysis.
|
|
243
|
+
true_labels (list): The ground truth labels.
|
|
244
|
+
predicted_labels (list): Model's predictions.
|
|
245
|
+
sensitive_feature_name (str): The name of the sensitive attribute.
|
|
246
|
+
sensitive_feature_data (list): Values for the sensitive feature.
|
|
247
|
+
model (object): The model being analyzed.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
None
|
|
251
|
+
"""
|
|
252
|
+
bias_analyzer = BiasAnalyzer(dataset, true_labels, predicted_labels, sensitive_feature_name,
|
|
253
|
+
sensitive_feature_data, model)
|
|
254
|
+
self.bias_analysis = bias_analyzer.calculate_bias_metrics()
|
|
255
|
+
|
|
256
|
+
def populate_xai(self, train_dataset, column_names, model, n_features=10):
|
|
257
|
+
"""
|
|
258
|
+
Computes and stores feature importance metrics.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
train_dataset (object): Training dataset used in the analysis.
|
|
262
|
+
column_names (list): Names of the features.
|
|
263
|
+
model (object): The model being explained.
|
|
264
|
+
n_features (int, optional): Number of features to analyze. Default is 10.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
None
|
|
268
|
+
"""
|
|
269
|
+
xai_analyzer = ExplainabilityAnalyser(train_dataset, column_names, model)
|
|
270
|
+
self.xai_analysis = xai_analyzer.calculate_xai_features(n_features)
|
|
271
|
+
|
|
272
|
+
def populate_requirements(self):
|
|
273
|
+
"""
|
|
274
|
+
Collects package requirements for the model card, excluding specific dependencies.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
None
|
|
278
|
+
"""
|
|
279
|
+
exclude_packages = {"shap", "fairlearn"}
|
|
280
|
+
installed_packages = pkg_resources.working_set
|
|
281
|
+
packages_list = sorted(["%s==%s" % (i.key, i.version) for i in installed_packages])
|
|
282
|
+
self.model_requirements = [pkg for pkg in packages_list if pkg.split("==")[0] not in exclude_packages]
|
|
283
|
+
|
|
284
|
+
def validate(self):
|
|
285
|
+
"""
|
|
286
|
+
Validates the model card against a predefined JSON schema.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
bool: True if the model card is valid according to the schema, False otherwise.
|
|
290
|
+
"""
|
|
291
|
+
mc_json = self.__str__()
|
|
292
|
+
try:
|
|
293
|
+
with open(SCHEMA_JSON, 'r') as schema_file:
|
|
294
|
+
schema = json.load(schema_file)
|
|
295
|
+
jsonschema.validate(instance=json.loads(mc_json), schema=schema)
|
|
296
|
+
return True
|
|
297
|
+
except jsonschema.ValidationError as e:
|
|
298
|
+
print(e.message)
|
|
299
|
+
return False
|
|
300
|
+
except Exception as e:
|
|
301
|
+
print(f"An unexpected error occurred: {e}")
|
|
302
|
+
return False
|
|
303
|
+
|
|
304
|
+
def submit(self, patra_server_url):
|
|
305
|
+
"""
|
|
306
|
+
Validates and submits the model card to the specified Patra server.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
patra_server_url (str): The Patra server URL where the model card should be submitted.
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
dict: The server's response as a JSON object.
|
|
313
|
+
"""
|
|
314
|
+
if self.validate():
|
|
315
|
+
try:
|
|
316
|
+
self.id = self._get_hash_id(patra_server_url)
|
|
317
|
+
patra_submit_url = f"{patra_server_url}/upload_mc"
|
|
318
|
+
headers = {'Content-Type': 'application/json'}
|
|
319
|
+
response = requests.post(patra_submit_url, json=json.loads(str(self)), headers=headers)
|
|
320
|
+
response.raise_for_status()
|
|
321
|
+
return response.json()
|
|
322
|
+
except requests.exceptions.RequestException as e:
|
|
323
|
+
print("The Patra Server cannot be reached. Please try again.")
|
|
324
|
+
return None
|
|
325
|
+
return {"An error occurred: valid patra_server_url not provided. Unable to upload."}
|
|
326
|
+
|
|
327
|
+
def _get_hash_id(self, patra_server_url):
|
|
328
|
+
"""
|
|
329
|
+
Generates a unique identifier for the model card based on its metadata.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
patra_server_url (str): The Patra server URL used to generate the ID.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
str: A unique hash identifier for the model card.
|
|
336
|
+
"""
|
|
337
|
+
combined_string = f"{self.name}:{self.version}:{self.author}"
|
|
338
|
+
try:
|
|
339
|
+
if patra_server_url:
|
|
340
|
+
patra_hash_url = f"{patra_server_url}/get_hash_id"
|
|
341
|
+
headers = {'Content-Type': 'application/json'}
|
|
342
|
+
response = requests.get(patra_hash_url, params={"combined_string": combined_string}, headers=headers)
|
|
343
|
+
response.raise_for_status()
|
|
344
|
+
return response.json()
|
|
345
|
+
else:
|
|
346
|
+
return hashlib.sha256(combined_string.encode()).hexdigest()
|
|
347
|
+
except requests.exceptions.RequestException as e:
|
|
348
|
+
print("Could not connect to the Patra Server, generating the ID locally")
|
|
349
|
+
return hashlib.sha256(combined_string.encode()).hexdigest()
|
|
350
|
+
|
|
351
|
+
def save(self, file_location):
|
|
352
|
+
"""
|
|
353
|
+
Saves the model card as a JSON file to the specified location.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
file_location (str): The path where the model card JSON file will be saved.
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
None
|
|
360
|
+
"""
|
|
361
|
+
with open(file_location, 'w') as json_file:
|
|
362
|
+
json_file.write(str(self))
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class ModelCardJSONEncoder(JSONEncoder):
|
|
366
|
+
"""
|
|
367
|
+
Custom JSON Encoder for ModelCard to handle complex objects.
|
|
368
|
+
|
|
369
|
+
Methods:
|
|
370
|
+
default: Serializes non-serializable fields.
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
def default(self, obj):
|
|
374
|
+
if isinstance(obj, (ModelCard, Metric, AIModel, ExplainabilityAnalysis, BiasAnalysis)):
|
|
375
|
+
return obj.__dict__
|
|
376
|
+
return super().default(obj)
|