├── .dockerignore ├── .gitignore ├── CODEOWNERS ├── DATASETS.md ├── LICENSE ├── MANIFEST.in ├── MODELS.md ├── Makefile ├── README.md ├── SECURITY.md ├── docker ├── Dockerfile.explainers ├── Dockerfile.mcg ├── README.md └── docker-compose.yaml ├── docs ├── .gitignore ├── Makefile ├── README.md ├── build.sh ├── conf.py ├── datasets.rst ├── explainer │ ├── attributions.md │ ├── cam.md │ ├── index.md │ └── metrics.md ├── index.md ├── install.rst ├── legal.rst ├── model_card_gen │ ├── api.rst │ ├── example.md │ └── index.md ├── models.rst ├── notebooks.rst ├── notebooks │ ├── ExplainingImageClassification.nblink │ ├── Multimodal_Cancer_Detection.nblink │ ├── PyTorch_Text_Classifier_fine_tuning_with_Attributions.nblink │ ├── TorchVision_CIFAR_Interpret.nblink │ ├── adult-pytorch-model-card.nblink │ ├── compas-model-card-tfx.nblink │ ├── heart_disease.nblink │ ├── huggingface-model-card.nblink │ ├── image-classification-model-card.nblink │ ├── mnist.nblink │ ├── multiclass-huggingface-model-card.nblink │ ├── multimodal-classification-model-card.nblink │ ├── partitionexplainer.nblink │ └── toxicity-tfma-model-card.nblink ├── overview.rst ├── requirements-docs.txt └── toc.yml ├── explainer ├── README.md ├── intel_ai_safety │ └── explainer │ │ ├── base_explainer.py │ │ ├── blackbox.py │ │ ├── context │ │ ├── __init__.py │ │ ├── agnostic │ │ │ ├── __init__.py │ │ │ └── attributions_explainer.py │ │ └── image │ │ │ └── gradcam_explainer.py │ │ ├── utils │ │ ├── graphics │ │ │ ├── __init__.py │ │ │ └── info.py │ │ ├── model │ │ │ ├── __init__.py │ │ │ └── model_framework.py │ │ └── types.py │ │ └── version.py ├── poetry.toml ├── pyproject.toml └── tests │ ├── __init__.py │ ├── conftest.py │ └── pytest.ini ├── fuzz ├── README.md ├── fuzz_dataset.py ├── fuzz_deep_explainer.py ├── fuzz_test.py └── requirements.txt ├── intel_ai_safety ├── common │ ├── constants.py │ ├── frameworks │ │ ├── __init__.py │ │ └── model_framework.py │ ├── plugins.py │ └── types.py └── version.py ├── model_card_gen ├── README.md ├── intel_ai_safety │ └── model_card_gen │ │ ├── __init__.py │ │ ├── base_model_card_field.py │ │ ├── docs │ │ └── examples │ │ │ ├── __init__.py │ │ │ ├── csv │ │ │ ├── metrics_by_group.csv │ │ │ ├── metrics_by_threshold.csv │ │ │ ├── multiclass_metrics_by_group.csv │ │ │ └── multiclass_metrics_by_threshold.csv │ │ │ ├── html │ │ │ └── compas_model_card.html │ │ │ └── json │ │ │ ├── model_card_compas.json │ │ │ └── model_card_example.json │ │ ├── graphics │ │ ├── __init__.py │ │ ├── add_graphics.py │ │ ├── graphics_data_transform.py │ │ ├── plotly_graphics.py │ │ └── plotly_utils.py │ │ ├── model_card.py │ │ ├── model_card_gen.py │ │ ├── schema │ │ └── v0.0.1 │ │ │ └── model_card.schema.json │ │ ├── template │ │ ├── html │ │ │ ├── default_template.html.jinja │ │ │ ├── js │ │ │ │ └── plotly_js_header.html.jinja │ │ │ ├── macros │ │ │ │ └── default_macros.html.jinja │ │ │ └── style │ │ │ │ └── default_style.html.jinja │ │ └── md │ │ │ ├── default_template.md.jinja │ │ │ └── macros │ │ │ └── default_macros.md.jinja │ │ ├── utils │ │ ├── __init__.py │ │ └── types.py │ │ ├── validation.py │ │ └── version.py ├── model_card_ui │ ├── .streamlit │ │ └── config.toml │ ├── README.md │ ├── generate_model_card_json.py │ ├── home.py │ ├── model_card_html_generator.py │ ├── pages │ │ ├── considerations.py │ │ ├── model_details.py │ │ ├── model_parameters.py │ │ ├── quantitative_analysis.py │ │ └── view_model_card.py │ ├── persist.py │ ├── read_json.py │ ├── requirements.txt │ ├── session_state_initializer.py │ └── utils.py ├── poetry.toml ├── pyproject.toml └── tests │ ├── __init__.py │ └── test_model_card.py ├── notebooks ├── README.md ├── explainer │ ├── README.ipynb │ ├── README.md │ ├── cifar_with_attributions │ │ ├── README.md │ │ └── TorchVision_CIFAR_Interpret.ipynb │ ├── gen_llm_with_attributions │ │ ├── HugingFace_Gen_LLM_Interpret.ipynb │ │ └── README.md │ ├── heart_disease_with_attributions │ │ ├── README.md │ │ └── heart_disease.ipynb │ ├── imagenet_with_cam │ │ ├── ExplainingImageClassification.ipynb │ │ ├── ExplainingObjectDetection.ipynb │ │ └── README.md │ ├── mnist_with_attributions_and_metrics │ │ ├── README.md │ │ └── mnist.ipynb │ ├── multimodal_cancer_detection │ │ ├── Multimodal_Cancer_Detection.ipynb │ │ ├── README.md │ │ ├── data_utils.py │ │ ├── prepare_nlp_data.py │ │ └── prepare_vision_data.py │ ├── newsgroups_with_attributions_and_metrics │ │ ├── README.md │ │ └── partitionexplainer.ipynb │ ├── requirements.txt │ └── transfer_learning_text_classification │ │ ├── PyTorch_Text_Classifier_fine_tuning_with_Attributions.ipynb │ │ └── README.md ├── model_card_gen │ ├── README.ipynb │ ├── README.md │ ├── compas_with_model_card_gen │ │ ├── README.md │ │ └── compas-model-card-tfx.ipynb │ ├── hugging_face_model_card │ │ ├── README.md │ │ └── hugging-face-model-card.ipynb │ ├── image_classification_model_card │ │ ├── README.md │ │ └── image-classification-model-card.ipynb │ ├── model_card_generation_with_pytorch │ │ ├── README.md │ │ └── adult-pytorch-model-card.ipynb │ ├── multiclass_classification │ │ ├── README.md │ │ └── multiclass-classification-model-card.ipynb │ ├── multimodal_classification_model_card │ │ ├── README.md │ │ └── multimodal-classification-model-card.ipynb │ └── toxic_comments_classification │ │ ├── README.md │ │ └── toxicity-tfma-model-card.ipynb └── performance │ ├── README.md │ ├── aitools_vs_stock.ipynb │ └── partition_image_bm.ipynb ├── plugins ├── benchmark │ └── classification_metrics │ │ ├── README.md │ │ ├── classification_metrics │ │ ├── scripts │ │ │ └── benchmark_classification_metrics.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ └── test_benchmark_classification.py │ │ ├── poetry.toml │ │ ├── pyproject.toml │ │ ├── requirements.txt │ │ └── version.py ├── explainers │ ├── attributions-hugging-face │ │ ├── README.md │ │ ├── intel_ai_safety │ │ │ └── explainer │ │ │ │ └── attributions │ │ │ │ └── hf_attributions.py │ │ ├── poetry.toml │ │ ├── pyproject.toml │ │ └── tests │ │ │ ├── conftest.py │ │ │ └── test_hf_attributions.py │ ├── attributions │ │ ├── README.md │ │ ├── intel_ai_safety │ │ │ └── explainer │ │ │ │ └── attributions │ │ │ │ ├── README.md │ │ │ │ ├── attributions.py │ │ │ │ ├── attributions_info.py │ │ │ │ ├── plots.py │ │ │ │ └── widgets.py │ │ ├── poetry.toml │ │ ├── pyproject.toml │ │ └── tests │ │ │ ├── conftest.py │ │ │ └── test_attributions.py │ ├── cam-pytorch │ │ ├── README.md │ │ ├── intel_ai_safety │ │ │ └── explainer │ │ │ │ └── cam │ │ │ │ └── pt_cam.py │ │ ├── poetry.toml │ │ ├── pyproject.toml │ │ └── tests │ │ │ ├── conftest.py │ │ │ └── test_cam.py │ ├── cam-tensorflow │ │ ├── README.md │ │ ├── intel_ai_safety │ │ │ └── explainer │ │ │ │ └── cam │ │ │ │ └── tf_cam.py │ │ ├── poetry.toml │ │ ├── pyproject.toml │ │ └── tests │ │ │ ├── conftest.py │ │ │ └── test_cam.py │ ├── captum │ │ ├── README.md │ │ ├── intel_ai_safety │ │ │ └── explainer │ │ │ │ └── attributions │ │ │ │ └── pt_attributions.py │ │ ├── poetry.toml │ │ └── pyproject.toml │ └── metrics │ │ ├── README.md │ │ ├── intel_ai_safety │ │ └── explainer │ │ │ └── metrics │ │ │ ├── __init__.py │ │ │ └── metrics.py │ │ ├── poetry.toml │ │ ├── pyproject.toml │ │ └── tests │ │ ├── conftest.py │ │ └── test_metrics.py ├── mlcommons │ └── modelgauge │ │ ├── README.md │ │ ├── config │ │ └── secrets.toml │ │ ├── modelgauge │ │ └── suts │ │ │ └── neuralchat_sut.py │ │ └── pyproject.toml └── model_card_gen │ └── generators │ └── tfma │ ├── intel_ai_safety │ └── model_card_gen │ │ ├── analyze │ │ ├── __init__.py │ │ ├── analyzer.py │ │ ├── analyzer_factory.py │ │ ├── pandas_analyzer.py │ │ ├── tf_analyzer.py │ │ └── torch_analyzer.py │ │ ├── datasets │ │ ├── __init__.py │ │ ├── datasets.py │ │ ├── tf_datasets.py │ │ └── torch_datasets.py │ │ └── model_card_gen.py │ └── tests │ ├── __init__.py │ ├── test_end_to_end_tf.py │ ├── test_end_to_end_torch.py │ ├── tf_model.py │ └── torch_model.py ├── poetry.toml ├── pyproject.toml ├── run_notebooks.sh └── tox.ini /.dockerignore: -------------------------------------------------------------------------------- 1 | **/*.venv 2 | **/.git** 3 | **/__pycache__ 4 | **/poetry.lock 5 | docker 6 | notebooks/explainer/README.md 7 | notebooks/model_card_gen/README.md 8 | fuzz 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore explainer pkz, zip, bin, vscode 2 | **/*.pkz 3 | **/*.zip 4 | **/*.bin 5 | **/*.vscode 6 | 7 | # VGG-16 Model ignore 8 | **/*.hdf5 9 | **/*.tar.gz 10 | **/*.png 11 | **/*whl 12 | train_logmel/ 13 | 14 | /docs/explainer/examples/data 15 | /docs/explainer/examples/models 16 | **/mcg_tests 17 | 18 | # ignore all plugin created directories 19 | /explainer/explainer/explainers/*/ 20 | 21 | # Byte-compiled / optimized / DLL files 22 | __pycache__/ 23 | *.py[cod] 24 | *$py.class 25 | 26 | # C extensions 27 | *.so 28 | 29 | # Distribution / packaging 30 | .Python 31 | build/ 32 | develop-eggs/ 33 | dist/ 34 | downloads/ 35 | eggs/ 36 | .eggs/ 37 | lib/ 38 | lib64/ 39 | parts/ 40 | sdist/ 41 | var/ 42 | wheels/ 43 | pip-wheel-metadata/ 44 | share/python-wheels/ 45 | *.egg-info/ 46 | .installed.cfg 47 | *.egg 48 | MANIFEST 49 | 50 | # PyInstaller 51 | # Usually these files are written by a python script from a template 52 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 53 | *.manifest 54 | *.spec 55 | 56 | # Installer logs 57 | pip-log.txt 58 | pip-delete-this-directory.txt 59 | 60 | # Unit test / coverage reports 61 | htmlcov/ 62 | .tox/ 63 | .nox/ 64 | .coverage 65 | .coverage.* 66 | .cache 67 | nosetests.xml 68 | coverage.xml 69 | *.cover 70 | *.py,cover 71 | .hypothesis/ 72 | .pytest_cache/ 73 | 74 | # Translations 75 | *.mo 76 | *.pot 77 | 78 | # Django stuff: 79 | *.log 80 | local_settings.py 81 | db.sqlite3 82 | db.sqlite3-journal 83 | 84 | # Flask stuff: 85 | instance/ 86 | .webassets-cache 87 | 88 | # Scrapy stuff: 89 | .scrapy 90 | 91 | # Sphinx documentation 92 | docs/_build/ 93 | 94 | # PyBuilder 95 | target/ 96 | 97 | # Jupyter Notebook 98 | .ipynb_checkpoints 99 | 100 | # Artifacts generated by notebooks 101 | notebooks/model_card_gen/*.pt 102 | notebooks/model_card_gen/*.html 103 | notebooks/model_card_gen/*.proto 104 | notebooks/model_card_gen/compas/ 105 | 106 | # IPython 107 | profile_default/ 108 | ipython_config.py 109 | 110 | # pyenv 111 | .python-version 112 | 113 | # pipenv 114 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 115 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 116 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 117 | # install all needed dependencies. 118 | #Pipfile.lock 119 | 120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 121 | __pypackages__/ 122 | 123 | # Celery stuff 124 | celerybeat-schedule 125 | celerybeat.pid 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Environments 131 | .env 132 | .venv 133 | env/ 134 | venv/ 135 | ENV/ 136 | env.bak/ 137 | venv.bak/ 138 | **test_env 139 | # Spyder project settings 140 | .spyderproject 141 | .spyproject 142 | 143 | # Rope project settings 144 | .ropeproject 145 | 146 | # mkdocs documentation 147 | /site 148 | 149 | # mypy 150 | .mypy_cache/ 151 | .dmypy.json 152 | dmypy.json 153 | 154 | # Pyre type checker 155 | .pyre/ 156 | 157 | # poetry lock files 158 | poetry.lock 159 | **/poetry.lock 160 | **/**/poetry.lock 161 | 162 | # Fuzzing crash reports 163 | **/**crash-** 164 | 165 | # Test data files 166 | mnist_data 167 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in 5 | # the repo. Unless a later match takes precedence, 6 | # @global-owner1 and @global-owner2 will be requested for 7 | # review when someone opens a pull request. 8 | * @ashahba @daniel-de-leon-user293 @mitalipo @qgao007 9 | 10 | # Order is important; the last matching pattern takes the most 11 | # precedence. When someone opens a pull request that only 12 | # modifies JS files, only @js-owner and not the global 13 | # owner(s) will be requested for a review. 14 | # *.js @js-owner #This is an inline comment. 15 | 16 | # You can also use email addresses if you prefer. They'll be 17 | # used to look up users just like we do for commit author 18 | # emails. 19 | # *.go docs@example.com 20 | 21 | # Teams can be specified as code owners as well. Teams should 22 | # be identified in the format @org/team-name. Teams must have 23 | # explicit write access to the repository. In this example, 24 | # the octocats team in the octo-org organization owns all .txt files. 25 | # *.txt @octo-org/octocats 26 | 27 | # In this example, @doctocat owns any files in the build/logs 28 | # directory at the root of the repository and any of its 29 | # subdirectories. 30 | # /build/logs/ @doctocat 31 | 32 | # The `docs/*` pattern will match files like 33 | # `docs/getting-started.md` but not further nested files like 34 | # `docs/build-app/troubleshooting.md`. 35 | # docs/* docs@example.com 36 | 37 | # In this example, @octocat owns any file in an apps directory 38 | # anywhere in your repository. 39 | # apps/ @octocat 40 | 41 | # In this example, @doctocat owns any file in the `/docs` 42 | # directory in the root of your repository and any of its 43 | # subdirectories. 44 | # /docs/ @doctocat 45 | 46 | # In this example, any change inside the `/scripts` directory 47 | # will require approval from @doctocat or @octocat. 48 | # /scripts/ @doctocat @octocat 49 | 50 | # In this example, @octocat owns any file in a `/logs` directory such as 51 | # `/build/logs`, `/scripts/logs`, and `/deeply/nested/logs`. Any changes 52 | # in a `/logs` directory will require approval from @octocat. 53 | # **/logs @octocat 54 | 55 | # In this example, @octocat owns any file in the `/apps` 56 | # directory in the root of your repository except for the `/apps/github` 57 | # subdirectory, as its owners are left empty. 58 | # /apps/ @octocat 59 | # /apps/github 60 | -------------------------------------------------------------------------------- /DATASETS.md: -------------------------------------------------------------------------------- 1 | # Datasets 2 | 3 | This is a comprehensive list of public datasets used by this repository. 4 | 5 | | Name (Link/Source) | Framework | Use Case | 6 | |--------------------| --------- | -------- | 7 | | [Adult Income Dataset ](https://archive.ics.uci.edu/dataset/2/adult) | PyTorch | Tabular Classification | 8 | | [CDD-CESM](https://wiki.cancerimagingarchive.net/pages/viewpage.action?pageId=109379611) | PyTorch | Image & Text Classification | 9 | | [CIFAR-10 (TorchVision)](https://pytorch.org/vision/main/generated/torchvision.datasets.CIFAR10.html) | Tensorflow | Text Classification | 10 | | [Civil Comments (TFDS)](https://www.tensorflow.org/datasets/catalog/civil_comments) | Tensorflow | Text Classification | 11 | | [COMPAS Recidivism Risk Score Data and Analysis](https://github.com/propublica/compas-analysis/) | TensorFlow | Tabular Classification | 12 | | [ImageNet (TorchVision)](https://pytorch.org/vision/main/generated/torchvision.datasets.ImageNet.html) | PyTorch | Image Classification | 13 | | [IMDB Reviews](https://ai.stanford.edu/~amaas/data/sentiment/) | PyTorch | Text Classification | 14 | | [MNIST (TorchVision)](https://pytorch.org/vision/main/generated/torchvision.datasets.MNIST.html) | PyTorch | Image Classification | 15 | | [SMS Spam Collection](https://archive.ics.uci.edu/dataset/228/sms+spam+collection) | PyTorch | Text Classification | 16 | | [ToxicChat](https://huggingface.co/datasets/lmsys/toxic-chat) | PyTorch | Toxicity Model Benchmarking | 17 | | [Jigsaw Unintended Bias](https://www.kaggle.com/c/jigsaw-unintended-bias-in-toxicity-classification) | PyTorch | Toxicity Model Benchmarking | 18 | | [OpenAI Moderation](https://github.com/openai/moderation-api-release/tree/main) | PyTorch | Toxicity Model Benchmarking | 19 | | [SurgeAI Toxicity](https://github.com/surge-ai/toxicity) | PyTorch | Toxicity Model Benchmarking | 20 | | [ToxiGen](https://huggingface.co/datasets/toxigen/toxigen-data) | PyTorch | Toxicity Model Benchmarking | 21 | | [XSTest](https://huggingface.co/datasets/walledai/XSTest) | PyTorch | Toxicity Model Benchmarking | 22 | | [BeaverTails](https://huggingface.co/datasets/PKU-Alignment/BeaverTails) | PyTorch | Toxicity Model Benchmarking | 23 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include explainer * 2 | recursive-include model_card_gen * 3 | -------------------------------------------------------------------------------- /MODELS.md: -------------------------------------------------------------------------------- 1 | # Models 2 | 3 | This is a comprehensive list of public models used by this repository. 4 | 5 | | Model Name (Link/Source) | Framework | Model Hub | 6 | |--------------------| --------- | -------- | 7 | | [ toxic-prompt-roberta ](https://huggingface.co/Intel/toxic-prompt-roberta) | PyTorch | Hugging Face | 8 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Report a Vulnerability 4 | 5 | Please report security issues or vulnerabilities to the [Intel® Security Center]. 6 | 7 | For more information on how Intel® works to resolve security issues, see 8 | [Vulnerability Handling Guidelines]. 9 | 10 | [Intel® Security Center]:https://www.intel.com/content/www/us/en/security-center/default.html 11 | 12 | [Vulnerability Handling Guidelines]:https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html 13 | -------------------------------------------------------------------------------- /docker/Dockerfile.explainers: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | ARG IMAGE_NAME=ubuntu 20 | ARG IMAGE_TAG=22.04 21 | 22 | # Clean base for Explainer 23 | FROM ${IMAGE_NAME}:${IMAGE_TAG} as base 24 | 25 | ARG PY_VER=3.10 26 | 27 | RUN apt-get update && \ 28 | apt-get upgrade -y && \ 29 | apt-get autoclean && \ 30 | apt-get autoremove -y && \ 31 | DEBIAN_FRONTEND=noninteractive \ 32 | apt-get install --no-install-recommends --fix-missing -y \ 33 | graphviz \ 34 | libgl1 \ 35 | libglib2.0.0 \ 36 | python${PY_VER} \ 37 | python3-pip \ 38 | tzdata 39 | 40 | RUN ln -sf $( which python${PY_VER} ) /usr/bin/python 41 | 42 | # Development Explainer image 43 | FROM base as builder 44 | 45 | ARG PY_VER=3.10 46 | ARG APP_DIR=/intel-xai 47 | 48 | ARG POETRY_NO_INTERACTION=1 \ 49 | POETRY_VIRTUALENVS_IN_PROJECT=1 \ 50 | POETRY_VIRTUALENVS_CREATE=1 51 | 52 | RUN apt-get update && \ 53 | apt-get upgrade -y && \ 54 | apt-get autoclean && \ 55 | apt-get autoremove -y && \ 56 | apt-get install --no-install-recommends --fix-missing -y \ 57 | g++ \ 58 | python${PY_VER}-dev 59 | 60 | RUN python${PY_VER} -m pip install --no-cache-dir \ 61 | 'poetry==2.1.1' 62 | 63 | COPY . ${APP_DIR} 64 | WORKDIR ${APP_DIR} 65 | 66 | RUN /usr/local/bin/poetry config virtualenvs.create false && \ 67 | poetry install --extras explainer --extras explainer-all && \ 68 | poetry run python -m pip install --no-cache-dir \ 69 | 'jupyter==1.1.1' && \ 70 | poetry run python -m pip install --no-cache-dir -r notebooks/explainer/requirements.txt && \ 71 | rm -rf ${HOME}/.cache/pypoetry ${HOME}/.cache/pip 72 | 73 | # Production Explainer image 74 | FROM base as runtime 75 | 76 | ARG APP_DIR=/intel-xai 77 | ARG UID=1000 78 | ARG GID=1000 79 | ARG NON_ROOT_USER=intelai 80 | 81 | SHELL ["/bin/bash", "-c"] 82 | 83 | # Create a non-root user 'intelai' 84 | RUN addgroup --gid ${GID} ${NON_ROOT_USER} && \ 85 | adduser --uid ${UID} --gid ${GID} --disabled-password --gecos "" ${NON_ROOT_USER} 86 | 87 | # Set the non-root user as the default user 88 | USER ${NON_ROOT_USER} 89 | 90 | COPY --from=builder --chown=${NON_ROOT_USER}:${NON_ROOT_USER} ${APP_DIR} ${APP_DIR} 91 | 92 | ENV VIRTUAL_ENV="${APP_DIR}/.venv" \ 93 | PATH="${APP_DIR}/.venv/bin:${PATH}" 94 | 95 | WORKDIR ${APP_DIR}/notebooks/explainer 96 | 97 | EXPOSE 8888 98 | 99 | RUN echo "source activate ${VIRTUAL_ENV}" >> ~/.bashrc 100 | 101 | CMD ["bash", "-c", "source activate ${VIRTUAL_ENV} && jupyter notebook --port 8888 --ip 0.0.0.0 --no-browser --allow-root"] 102 | 103 | HEALTHCHECK --interval=1m --timeout=5s --retries=5 \ 104 | CMD jupyter server list || exit 1 105 | -------------------------------------------------------------------------------- /docker/Dockerfile.mcg: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | ARG IMAGE_NAME=ubuntu 20 | ARG IMAGE_TAG=22.04 21 | 22 | # Clean base for MCG 23 | FROM ${IMAGE_NAME}:${IMAGE_TAG} as base 24 | 25 | ARG PY_VER=3.10 26 | 27 | RUN apt-get update && \ 28 | apt-get upgrade -y && \ 29 | apt-get autoclean && \ 30 | apt-get autoremove -y && \ 31 | DEBIAN_FRONTEND=noninteractive \ 32 | apt-get install --no-install-recommends --fix-missing -y \ 33 | python${PY_VER} \ 34 | python3-pip \ 35 | tzdata 36 | 37 | RUN ln -sf $( which python${PY_VER} ) /usr/bin/python 38 | 39 | # Development MCG image 40 | FROM base as builder 41 | 42 | ARG PY_VER=3.10 43 | ARG APP_DIR=/intel-xai 44 | 45 | ARG POETRY_NO_INTERACTION=1 \ 46 | POETRY_VIRTUALENVS_IN_PROJECT=1 \ 47 | POETRY_VIRTUALENVS_CREATE=1 48 | 49 | RUN apt-get update && \ 50 | apt-get upgrade -y && \ 51 | apt-get autoclean && \ 52 | apt-get autoremove -y && \ 53 | apt-get install --no-install-recommends --fix-missing -y \ 54 | g++ \ 55 | python${PY_VER}-dev 56 | 57 | RUN python${PY_VER} -m pip install --no-cache-dir \ 58 | 'poetry==2.1.1' 59 | 60 | COPY . ${APP_DIR} 61 | WORKDIR ${APP_DIR} 62 | 63 | RUN /usr/local/bin/poetry config virtualenvs.create false && \ 64 | poetry install --no-root --with test --extras model-card && \ 65 | poetry run python -m pip install --no-cache-dir \ 66 | 'jupyter==1.1.1' && \ 67 | rm -rf ${HOME}/.cache/pypoetry ${HOME}/.cache/pip 68 | 69 | # MCG base runtime image 70 | FROM base as runtime 71 | 72 | ARG APP_DIR=/intel-xai 73 | ARG UID=1000 74 | ARG GID=1000 75 | ARG NON_ROOT_USER=intelai 76 | 77 | SHELL ["/bin/bash", "-c"] 78 | 79 | # Create a non-root user 'intelai' 80 | RUN addgroup --gid ${GID} ${NON_ROOT_USER} && \ 81 | adduser --uid ${UID} --gid ${GID} --disabled-password --gecos "" ${NON_ROOT_USER} 82 | 83 | RUN apt-get update && apt-get install -y --no-install-recommends --fix-missing \ 84 | git 85 | 86 | # Set the non-root user as the default user 87 | USER ${NON_ROOT_USER} 88 | 89 | COPY --from=builder --chown=${NON_ROOT_USER}:${NON_ROOT_USER} ${APP_DIR} ${APP_DIR} 90 | 91 | ENV VIRTUAL_ENV="${APP_DIR}/.venv" \ 92 | PATH="${APP_DIR}/.venv/bin:${PATH}" 93 | 94 | RUN echo "source activate ${VIRTUAL_ENV}" >> ~/.bashrc 95 | 96 | # MCG runtime image 97 | FROM runtime as mcg 98 | 99 | WORKDIR ${APP_DIR}/notebooks/model_card_gen 100 | 101 | EXPOSE 8888 102 | 103 | CMD ["bash", "-c", "source activate ${VIRTUAL_ENV} && jupyter notebook --port 8888 --ip 0.0.0.0 --no-browser --allow-root"] 104 | 105 | HEALTHCHECK --interval=1m --timeout=5s --retries=5 \ 106 | CMD jupyter server list || exit 1 107 | 108 | # MCG UI runtime image 109 | FROM runtime as mcg_ui 110 | 111 | WORKDIR ${APP_DIR}/model_card_gen/model_card_ui 112 | 113 | RUN pip install --no-cache-dir -r requirements.txt 114 | 115 | EXPOSE 8501 116 | 117 | CMD ["streamlit", "run", "home.py", "--server.port=8501", "--server.address=0.0.0.0"] 118 | -------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | services: 20 | explainers: 21 | image: intel/ai-tools:intel-ai-safety-1.3.0-explainers 22 | pull_policy: always 23 | build: 24 | dockerfile: docker/Dockerfile.explainers 25 | context: ../ 26 | target: runtime 27 | args: 28 | IMAGE_NAME: ubuntu 29 | IMAGE_TAG: "22.04" 30 | PY_VER: "3.10" 31 | UID: "1000" 32 | GID: "1000" 33 | NON_ROOT_USER: "intelai" 34 | http_proxy: ${http_proxy} 35 | https_proxy: ${https_proxy} 36 | no_proxy: ${no_proxy} 37 | ports: 38 | - "8887:8888" 39 | environment: 40 | - VIRTUAL_ENV=/intel-xai/.venv 41 | command: bash -c "source activate ${VIRTUAL_ENV} && jupyter notebook --port 8888 --ip 0.0.0.0 --no-browser --allow-root" 42 | healthcheck: 43 | test: ["CMD-SHELL", "jupyter server list"] 44 | interval: 1m 45 | timeout: 5s 46 | retries: 5 47 | 48 | model_card_gen: 49 | image: intel/ai-tools:intel-ai-safety-1.3.0-mcg 50 | pull_policy: always 51 | build: 52 | dockerfile: docker/Dockerfile.mcg 53 | context: ../ 54 | target: mcg 55 | args: 56 | IMAGE_NAME: ubuntu 57 | IMAGE_TAG: "22.04" 58 | UID: "1000" 59 | GID: "1000" 60 | NON_ROOT_USER: "intelai" 61 | PY_VER: "3.10" 62 | http_proxy: ${http_proxy} 63 | https_proxy: ${https_proxy} 64 | no_proxy: ${no_proxy} 65 | ports: 66 | - "8889:8888" 67 | environment: 68 | - VIRTUAL_ENV=/intel-xai/.venv 69 | command: bash -c "source activate ${VIRTUAL_ENV} && jupyter notebook --port 8888 --ip 0.0.0.0 --no-browser --allow-root" 70 | healthcheck: 71 | test: ["CMD-SHELL", "jupyter server list"] 72 | interval: 1m 73 | timeout: 5s 74 | retries: 5 75 | 76 | model_card_gen_ui: 77 | image: intel/ai-tools:intel-ai-safety-1.3.0-mcg-ui 78 | pull_policy: always 79 | build: 80 | dockerfile: docker/Dockerfile.mcg 81 | context: ../ 82 | target: mcg_ui 83 | args: 84 | IMAGE_NAME: ubuntu 85 | IMAGE_TAG: "22.04" 86 | UID: "1000" 87 | GID: "1000" 88 | NON_ROOT_USER: "intelai" 89 | PY_VER: "3.10" 90 | http_proxy: ${http_proxy} 91 | https_proxy: ${https_proxy} 92 | no_proxy: ${no_proxy} 93 | ports: 94 | - "8501:8501" 95 | environment: 96 | - VIRTUAL_ENV=/intel-xai/.venv 97 | command: "streamlit run home.py --server.port=8501 --server.address=0.0.0.0" 98 | healthcheck: 99 | test: ["CMD-SHELL", "curl --fail http://localhost:8501 || exit 1"] 100 | interval: 1m 101 | timeout: 5s 102 | retries: 5 103 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints 2 | _build 3 | markdown 4 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | # Minimal makefile for Sphinx documentation 20 | # 21 | 22 | # You can set these variables from the command line, and also 23 | # from the environment for the first two. 24 | 25 | SPHINXOPTS ?= 26 | SPHINXBUILD ?= sphinx-build 27 | SOURCEDIR = . 28 | BUILDDIR = _build 29 | 30 | # Put it first so that "make" without argument is like "make help". 31 | help: 32 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 33 | 34 | .PHONY: help Makefile 35 | 36 | # Catch-all target: route all unknown targets to Sphinx using the new 37 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 38 | %: Makefile 39 | ./build.sh $@ 40 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 41 | 42 | LISTEN_IP ?= 127.0.0.1 43 | LISTEN_PORT ?= 9999 44 | serve: 45 | @python -m http.server --directory ./_build/html ${LISTEN_PORT} --bind ${LISTEN_IP} 46 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | ## Sphinx Documentation 4 | 5 | Install `intel-xai-tools` and its dependencies for developers as described [here](/README.md#developer-installation). 6 | ```bash 7 | # Run these commands from intel-xai-tools project folder 8 | python3 -m virtualenv xai_env 9 | source xai_env/bin/activate 10 | python -m pip install --editable . 11 | ``` 12 | 13 | Install Sphinx and a few other tools required to build docs 14 | ```bash 15 | pip install -r docs/requirements-docs.txt 16 | ``` 17 | 18 | Finally generate the html docs (from within `docs` directory): 19 | ```bash 20 | make clean html 21 | ``` 22 | 23 | The output HTML files will be located in `docs/_build/html`. 24 | 25 | To start a local HTTP server and view the docs locally, try: 26 | ```bash 27 | make serve 28 | Serving HTTP on 127.0.1.1 port 9999 (http://127.0.1.1:9999/) ... 29 | ``` 30 | 31 | If you need to view the docs from another machine, please try either port forwarding or 32 | provide appropriate values for `LISTEN_IP/LISTEN_PORT` arguments. 33 | For example: 34 | ```bash 35 | LISTEN_IP=0.0.0.0 make serve 36 | Serving HTTP on 0.0.0.0 port 9999 (http://0.0.0.0:9999/) ... 37 | ``` 38 | 39 | runs the docs server on the host while listening to all hosts. 40 | Now you can navigate to `HOSTNAME:9999` to view the docs. 41 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import sys, os 22 | from explainer.intel_ai_safety.explainer.version import __version__ 23 | from explainer.intel_ai_safety import explainer 24 | 25 | project = "Intel® Explainable AI Tools" 26 | author = "IntelAI" 27 | copyright = "2023, Intel" 28 | exclude_patterns = ["_build", "conf.py"] 29 | 30 | release = __version__ 31 | version = __version__ 32 | extensions = [ 33 | "myst_parser", 34 | "nbsphinx", 35 | "nbsphinx_link", 36 | "sphinx.ext.autodoc", 37 | "sphinx.ext.doctest", 38 | "sphinx.ext.intersphinx", 39 | "sphinx.ext.napoleon", 40 | "sphinx.ext.viewcode", 41 | "sphinx_design", 42 | "sphinx_external_toc", 43 | ] 44 | external_toc_path = "toc.yml" 45 | external_toc_exclude_missing = False 46 | html_theme = "sphinx_rtd_theme" 47 | nbsphinx_execute = "never" 48 | -------------------------------------------------------------------------------- /docs/datasets.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../DATASETS.md 2 | :parser: myst_parser.sphinx_ 3 | -------------------------------------------------------------------------------- /docs/explainer/attributions.md: -------------------------------------------------------------------------------- 1 | (attributions)= 2 | 3 | ```{include} ../../plugins/explainers/attributions/README.md 4 | ``` 5 | 6 | ```{eval-rst} 7 | 8 | .. automodule:: intel_ai_safety.explainer.attributions 9 | :members: 10 | 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/explainer/cam.md: -------------------------------------------------------------------------------- 1 | (cam)= 2 | 3 | ```{include} ../../plugins/explainers/cam-pytorch/README.md 4 | ``` 5 | 6 | ```{eval-rst} 7 | 8 | .. automodule:: explainer.cam.cam 9 | :members: 10 | 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/explainer/index.md: -------------------------------------------------------------------------------- 1 | (explainer)= 2 | # Explainer 3 | 4 | Explainer is a Python module in Intel® Explainable AI Tools that provides explainability methods for PyTorch and Tensorflow models. 5 | 6 | ## Goals 7 | 8 | ````{grid} 3 9 | 10 | ```{grid-item-card} 11 | :text-align: center 12 | :class-header: sd-font-weight-bold 13 | :class-body: sd-font-italic 14 | {octicon}`workflow` Composable 15 | ^^^ 16 | Add explainers to models methods with minimal code 17 | ``` 18 | 19 | ```{grid-item-card} 20 | :text-align: center 21 | :class-header: sd-font-weight-bold 22 | :class-body: sd-font-italic 23 | {octicon}`stack` Extensible 24 | ^^^ 25 | Easy to add new methods 26 | ``` 27 | 28 | ```{grid-item-card} 29 | :text-align: center 30 | :class-header: sd-font-weight-bold 31 | :class-body: sd-font-italic 32 | {octicon}`package-dependencies` Community 33 | ^^^ 34 | Contributions welcome 35 | ``` 36 | 37 | ```` 38 | 39 | ## Explainer Submodules 40 | 41 | * {ref}`attributions`: visualize negative and positive attributions of tabular features, pixels, and word tokens for predictions 42 | * {ref}`cam`: create heatmaps for CNN image classifications using gradient-weight class activation CAM mapping 43 | * {ref}`metrics`: Gain insight into models with the measurements and visualizations needed during the machine learning workflow 44 | 45 | -------------------------------------------------------------------------------- /docs/explainer/metrics.md: -------------------------------------------------------------------------------- 1 | 2 | (metrics)= 3 | 4 | ```{include} ../../plugins/explainers/metrics/README.md 5 | ``` 6 | ## API Refrence 7 | 8 | ```{eval-rst} 9 | 10 | .. automodule:: intel_ai_safety.explainer.metrics.metrics 11 | :members: 12 | 13 | ``` 14 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ```{include} markdown/Welcome.md 2 | ``` 3 | -------------------------------------------------------------------------------- /docs/install.rst: -------------------------------------------------------------------------------- 1 | .. include:: markdown/Install.md 2 | :parser: myst_parser.sphinx_ 3 | -------------------------------------------------------------------------------- /docs/legal.rst: -------------------------------------------------------------------------------- 1 | .. include:: markdown/Legal.md 2 | :parser: myst_parser.sphinx_ 3 | -------------------------------------------------------------------------------- /docs/model_card_gen/api.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | Model Card Generator 5 | -------------------- 6 | .. currentmodule:: intel_ai_safety.model_card_gen 7 | 8 | .. automodule:: intel_ai_safety.model_card_gen.model_card_gen 9 | :members: 10 | -------------------------------------------------------------------------------- /docs/model_card_gen/example.md: -------------------------------------------------------------------------------- 1 | --- 2 | sd_hide_title: true 3 | --- 4 | (mcg_example)= 5 | # Example Model Card 6 | 7 | ```{eval-rst} 8 | 9 | .. raw:: html 10 | :file: ../../model_card_gen/intel_ai_safety/model_card_gen/docs/examples/html/compas_model_card.html 11 | 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /docs/model_card_gen/index.md: -------------------------------------------------------------------------------- 1 | (mcg)= 2 | 3 | ```{include} ../../model_card_gen/README.md 4 | ``` 5 | -------------------------------------------------------------------------------- /docs/models.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../MODELS.md 2 | :parser: myst_parser.sphinx_ -------------------------------------------------------------------------------- /docs/notebooks.rst: -------------------------------------------------------------------------------- 1 | Example Notebooks 2 | ================= 3 | 4 | Explainer Notebooks 5 | ------------------- 6 | 7 | .. csv-table:: 8 | :header: "Notebook", "Domain: Use Case", "Framework" 9 | :widths: 50, 20, 30 10 | 11 | :doc:`Explaining ResNet50 ImageNet Classification Using the CAM Explainer `, CV: Image Classification, "PyTorch*, TensorFlow* and Intel® Explainable AI API" 12 | :doc:`Explaining a Custom Neural Network Heart Disease Classification Using the Attributions Explainer`, "Numerical/Categorical: Tabular Classification", "TensorFlow & Intel Explainable AI API" 13 | :doc:`Explaining Custom CNN MNIST Classification Using the Attributions Explainer`, "CV: Image Classification", "PyTorch and Intel Explainable AI API" 14 | :doc:`Multimodal Breast Cancer Detection Explainability using the Intel® Explainable AI API`, "CV: Image Classification & NLP: Text Classification", "PyTorch, HuggingFace, Intel Explainable AI API & Intel® Transfer Learning Tool API" 15 | :doc:`Explaining Custom NN NewsGroups Classification Using the Attributions Explainer`, "NLP: Text Classification", "PyTorch and Intel Explainable AI API" 16 | :doc:`Explaining Fine Tuned Text Classifier with PyTorch using the Intel® Explainable AI API`, "NLP: Text Classification", "PyTorch, HuggingFace, Intel Explainable AI API & Intel Transfer Learning Tool API" 17 | :doc:`Explaining Custom CNN CIFAR-10 Classification Using the Attributions Explainer`, "CV: Image Classification", "PyTorch and Intel Explainable AI API" 18 | 19 | Model Card Generator Notebooks 20 | ------------------------------ 21 | 22 | .. csv-table:: 23 | :header: "Notebook", "Domain: Use Case", "Framework" 24 | :widths: 50, 20, 30 25 | 26 | :doc:`Generating a Model Card with PyTorch`, "Numerical/Categorical: Tabular Classification", "PyTorch, TensorFlow and Intel Explainable AI API" 27 | :doc:`Detecting Issues in Fairness by Generate Model Card from TensorFlow Estimators`, "Numerical/Categorical: Tabular Classification", "TensorFlow & Intel Explainable AI API" 28 | :doc:`Creating Model Card for Toxic Comments Classification in TensorFlow`, "Numerical/Categorical: Tabular Classification", "TensorFlow and Intel Explainable AI API" 29 | :doc:`Creating Model Card for Hate Speech Detection using Hugging Face model`, "Numerical/Categorical: Tabular Classification", "PyTorch, HuggingFace and Intel Explainable AI API" 30 | :doc:`Multiclass classification of Hate Speech using Hugging Face model`, "CV: Image Classification", "PyTorch & Intel Explainable AI API" 31 | :doc:`Image classification of Deepfake images using Torchvision model`, "CV: Image Classification", "PyTorch and Intel Explainable AI API" 32 | :doc:`Multimodal classification of Hateful Meme text and images`, "CV: Image Classification & NLP: Text Classification", "PyTorch, HuggingFace and Intel Explainable AI API" 33 | 34 | \*Other names and brands may be claimed as the property of others. `Trademarks `_ 35 | -------------------------------------------------------------------------------- /docs/notebooks/ExplainingImageClassification.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/imagenet_with_cam/ExplainingImageClassification.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/Multimodal_Cancer_Detection.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/multimodal_cancer_detection/Multimodal_Cancer_Detection.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/PyTorch_Text_Classifier_fine_tuning_with_Attributions.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/transfer_learning_text_classification/PyTorch_Text_Classifier_fine_tuning_with_Attributions.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/TorchVision_CIFAR_Interpret.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/cifar_with_attributions/TorchVision_CIFAR_Interpret.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/adult-pytorch-model-card.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/model_card_generation_with_pytorch/adult-pytorch-model-card.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/compas-model-card-tfx.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/compas_with_model_card_gen/compas-model-card-tfx.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/heart_disease.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/heart_disease_with_attributions/heart_disease.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/huggingface-model-card.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/hugging_face_model_card/hugging-face-model-card.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/image-classification-model-card.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/image_classification_model_card/image-classification-model-card.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/mnist.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/mnist_with_attributions_and_metrics/mnist.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/multiclass-huggingface-model-card.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/multiclass_classification/multiclass-classification-model-card.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/multimodal-classification-model-card.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/multimodal_classification_model_card/multimodal-classification-model-card.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/partitionexplainer.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/explainer/newsgroups_with_attributions_and_metrics/partitionexplainer.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/notebooks/toxicity-tfma-model-card.nblink: -------------------------------------------------------------------------------- 1 | { 2 | "path": "../../notebooks/model_card_gen/toxic_comments_classification/toxicity-tfma-model-card.ipynb" 3 | } 4 | -------------------------------------------------------------------------------- /docs/overview.rst: -------------------------------------------------------------------------------- 1 | .. include:: markdown/Overview.md 2 | :parser: myst_parser.sphinx_ 3 | -------------------------------------------------------------------------------- /docs/requirements-docs.txt: -------------------------------------------------------------------------------- 1 | Sphinx==8.1.3 2 | docutils==0.21.2 3 | ghp-import==2.1.0 4 | linkify-it-py==2.0.3 5 | myst-parser==4.0.1 6 | nbsphinx-link==1.3.1 7 | nbsphinx==0.9.7 8 | sphinx-fontawesome==0.0.6 9 | sphinx-multitoc-numbering==0.1.3 10 | sphinx-rtd-theme==3.0.2 11 | sphinx_design==0.6.1 12 | sphinx_external_toc==1.0.1 13 | -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | root: index.md 2 | options: 3 | caption: Contents 4 | maxdepth: 2 5 | titlesonly: True 6 | entries: 7 | - file: overview.rst 8 | - file: install.rst 9 | - file: explainer/index.md 10 | entries: 11 | - file: explainer/attributions.md 12 | - file: explainer/cam.md 13 | - file: explainer/metrics.md 14 | - file: model_card_gen/index.md 15 | entries: 16 | - file: model_card_gen/api.rst 17 | - file: model_card_gen/example.md 18 | - file: notebooks.rst 19 | entries: 20 | - file: noteooks/ExplainingImageClassification.nblink 21 | - file: legal.rst 22 | - url: https://github.com/Intel/intel-xai-tools 23 | title: GitHub Repository 24 | -------------------------------------------------------------------------------- /explainer/README.md: -------------------------------------------------------------------------------- 1 | ### Attributions 2 | 3 | | Method | Decription | 4 | |---------------------|---------------------------------------------------------------------------------------------| 5 | | explainer | Return native Shap references as attributes                                                 | 6 | | kernel_explainer    | Explain predictions using SHAP's kernel method                                              | 7 | | deep_explainer      | Explain predictions using SHAP's deep method                                                | 8 | | gradient_explainer  | Explain predictions using SHAP's gradient method                                            | 9 | | partition_explainer | Explain predictions using SHAP's partition method                                           | 10 | | saliency            | Explain predictions using Captum's saliency method                                          | 11 | | integratedgradients | Explain predictions using Captum's integrated gradients method                              | 12 | | deeplift            | Explain predictions using Captum's deep lift method                                         | 13 | | smoothgrad          | Explain predictions using Captum's noise tunnel smooth gradient method                      | 14 | | featureablation     | Explain predictions using Captum's feature ablation method                                  | 15 | | zero_shot           | ...                                                                                         | 16 | | sentiment_analyis   | Explain HuggingFace pipeline predictions the SHAP explainer methods                         | 17 | 18 | ### CAM 19 | 20 | | Method | Decription | 21 | |------------|------------------------------------------------------------------------------------------------------------| 22 | | xgradcam | Explain predictions with axiom-based gradient-based class activation maps using pytorch-grad-cam methods | 23 | | eigancam  | Explain predictions with eigan-based class activation maps using pytorch-grad-cam methods   | 24 | | tf_gradcam | Explain predictions with gradient-based class activation maps with the TensorFlow| 25 | 26 | ### Metrics 27 | 28 | | Method | Decription | 29 | |--------|---------------------------------------------------------------------------------------------| 30 | | confusion_matrix | Visualize classifier performance  via  a contingency table visualization         | 31 | | plot | Visualize classifier performance via ROC/PR values over a spread of probability threasholds | 32 | | pstat | Report the execution summary of a given snippet of code using the cProfile run method       | 33 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/base_explainer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | from abc import ABC 20 | 21 | 22 | class BaseExplainer(ABC): 23 | """Base Explainer class to get explainations for a model 24 | in a context. 25 | """ 26 | 27 | def __init__(self, *args, **kwargs): 28 | super(BaseExplainer, self).__init__(*args, **kwargs) 29 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/blackbox.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | from .base_explainer import BaseExplainer 20 | 21 | 22 | class BlackBoxExplainer(BaseExplainer): 23 | """Explainer class to get explainations from blackbox models.""" 24 | 25 | def __init__(self, *args, **kwargs): 26 | super(BaseExplainer, self).__init__(*args, **kwargs) 27 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/context/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/intel-xai-tools/099c979cae3d9b7040c614b9d84ef25d52effd5f/explainer/intel_ai_safety/explainer/context/__init__.py -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/context/agnostic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/intel-xai-tools/099c979cae3d9b7040c614b9d84ef25d52effd5f/explainer/intel_ai_safety/explainer/context/agnostic/__init__.py -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/context/agnostic/attributions_explainer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from intel_ai_safety.explainer.utils.graphics.info import InfoPanel 22 | from intel_ai_safety.explainer.base_explainer import BaseExplainer 23 | 24 | 25 | class AttributionsExplainer(BaseExplainer): 26 | """ 27 | Attributions base class to help identify the contribution 28 | of feature values towards a prediction through different 29 | explaination methods. 30 | """ 31 | 32 | def __init__(self, *args): 33 | self.info_panel = {} 34 | 35 | def __call__(self, *args, **kwargs): 36 | pass 37 | 38 | def visualize(self, data): 39 | pass 40 | 41 | def get_info(self): 42 | """Display into panel in Jupyter Enviornment""" 43 | if self.info_panel: 44 | info = InfoPanel(**self.info_panel) 45 | info.show() 46 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/context/image/gradcam_explainer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | from intel_ai_safety.common.frameworks.model_framework import get_model_framework 21 | from intel_ai_safety.common.plugins import get_plugin_extended_cls 22 | from intel_ai_safety.explainer.base_explainer import BaseExplainer 23 | 24 | from intel_ai_safety.common.constants import ModelFramework 25 | 26 | 27 | class GradCAM(BaseExplainer): 28 | """GradCAM generator class. Depending on the model framework, GradCAM is a 29 | superclass to TFGradCAM or XGradCAM. Note that EigenCAM (only supports 30 | PyTorch) is not included yet. 31 | """ 32 | 33 | def __new__(cls, model, *args): 34 | modle_framework = get_model_framework(model) 35 | if modle_framework is ModelFramework.TENSORFLOW: 36 | TFGradCAM = get_plugin_extended_cls("explainer.cam.tf_cam.TFGradCAM") 37 | return super().__new__(TFGradCAM) 38 | elif modle_framework is ModelFramework.PYTORCH: 39 | XGradCAM = get_plugin_extended_cls("explainer.cam.pt_cam.XGradCAM") 40 | return super().__new__(XGradCAM) 41 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/utils/graphics/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/utils/graphics/info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2023 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from dataclasses import dataclass 22 | import ipywidgets as widgets 23 | from IPython.display import display 24 | from typing import List, Tuple 25 | 26 | 27 | @dataclass 28 | class InfoField: 29 | name: str 30 | description: str 31 | 32 | 33 | @dataclass(init=False) 34 | class InfoPanel: 35 | """Dataclass to build plot information pannel in Jupyter enviornment""" 36 | 37 | fields: List[InfoField] 38 | title = "Metric Info" 39 | 40 | def __init__(self, *args: Tuple[str], **kwargs: str): 41 | """ 42 | Args: 43 | *args: Variable length argument list of tuples such that the first 44 | item is a field name and second item is field description. 45 | *kwargs: Keyword arguments such that the key is a field name and 46 | value is the field description. 47 | 48 | """ 49 | if args: 50 | self.fields = [InfoField(*arg) for arg in args] 51 | elif kwargs: 52 | self.fields = [InfoField(k, v) for k, v in kwargs.items()] 53 | 54 | def show(self): 55 | """Display widget object to Jupyter environment""" 56 | output = self._build_widget() 57 | display(output) 58 | 59 | def _build_widget(self): 60 | """Build ipywidgets Accordion object with list from data fields""" 61 | output = widgets.Accordion(children=[]) 62 | output.children = [widgets.HTML((self._build_html(self.fields)))] 63 | output.set_title(0, self.title) 64 | return output 65 | 66 | def _build_html(self, elms): 67 | """Build HTML list content for Jupyter widget""" 68 | html_inner = "" 69 | for elm in elms: 70 | html_inner += "
  • {}: {}
  • ".format(elm.name, elm.description) 71 | html_outer = "
      {}
    ".format(html_inner) 72 | return html_outer 73 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/utils/model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/intel-xai-tools/099c979cae3d9b7040c614b9d84ef25d52effd5f/explainer/intel_ai_safety/explainer/utils/model/__init__.py -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/utils/model/model_framework.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | module_logger = logging.getLogger(__name__) 4 | 5 | try: 6 | import torch.nn as nn 7 | except ImportError: 8 | module_logger.debug("Could not import torch, required if using a PyTorch model") 9 | 10 | MODEL_TYPE_NAMES = ["torch.nn.Module", "keras.engine.sequential.Sequential", "keras.engine.functional.Functional"] 11 | 12 | 13 | def is_tf_model(model): 14 | """Returns whether model is TF keras sequential or functional""" 15 | is_keras_sequential = str(type(model)).endswith("keras.engine.sequential.Sequential'>") 16 | is_keras_functional = str(type(model)).endswith("keras.engine.functional.Functional'>") 17 | is_keras_src_functional = str(type(model)).endswith("keras.src.engine.functional.Functional'>") 18 | is_keras_src_sequential = str(type(model)).endswith("keras.src.engine.sequential.Sequential'>") 19 | return is_keras_sequential | is_keras_functional | is_keras_src_functional | is_keras_src_sequential 20 | 21 | 22 | def is_pt_model(model): 23 | """Returns whether model is PyTorch torch.nn.Module""" 24 | return isinstance(model, nn.Module) 25 | 26 | 27 | def raise_unknown_model_error(model): 28 | raise ValueError(f"Model {type(model)} unsupported: please use model from {' ,'.join(MODEL_TYPE_NAMES)}") 29 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/utils/types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from pydoc import locate 22 | from typing import Any 23 | 24 | TorchTensor = locate("torch.Tensor") or Any 25 | -------------------------------------------------------------------------------- /explainer/intel_ai_safety/explainer/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | __version__ = "1.3.0" 22 | -------------------------------------------------------------------------------- /explainer/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /explainer/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.10, <3.12" 13 | intel-ai-safety = {version = "*"} 14 | ipywidgets = "8.1.5" 15 | 16 | [tool.poetry.group.local.dependencies] 17 | intel-ai-safety = {path=".."} 18 | 19 | [tool.poetry.group.test] 20 | optional = true 21 | 22 | [tool.poetry.group.test.dependencies] 23 | datasets = "3.3.2" 24 | deepdiff = "8.3.0" 25 | pytest = "8.3.5" 26 | scikit-learn = "1.6.1" 27 | tensorflow-cpu = "2.17.1" 28 | tensorflow-hub = "0.16.1" 29 | torch = {version = "2.7.0", source = "pytorch-cpu"} 30 | torchvision = {version = "0.22.0", source = "pytorch-cpu"} 31 | 32 | [[tool.poetry.source]] 33 | name = "pytorch-cpu" 34 | url = "https://download.pytorch.org/whl/cpu" 35 | priority = "explicit" 36 | 37 | [build-system] 38 | requires = ["poetry"] 39 | build-backend = "poetry.core.masonry.api" 40 | 41 | [[tool.poetry_bumpversion.replacements]] 42 | files = ["intel_ai_safety/explainer/version.py"] 43 | search = '__version__ = "{current_version}"' 44 | replace = '__version__ = "{new_version}"' 45 | -------------------------------------------------------------------------------- /explainer/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | -------------------------------------------------------------------------------- /explainer/tests/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | markers = 3 | simple: test with simple_data input. 4 | 5 | # Cannot figure out how to capture specific pytorch warning called by 6 | # shap DeepExplainer: 7 | # 8 | # "Using a non-full backward hook when the forward 9 | # contains multiple autograd Nodes is deprecated and will be removed 10 | # in future versions. This hook will be missing some grad_input. 11 | # Please use register_full_backward_hook to get the documented behavior." 12 | # 13 | # filterwarnings= 14 | # ignore::DeprecationWarning 15 | # ignore::PendingDeprecationWarning 16 | # ignore::ResourceWarning 17 | # ignore::ImportWarning 18 | 19 | # Temporary solution while we figure out how to filter out shap warning above 20 | addopts = -p no:warnings 21 | -------------------------------------------------------------------------------- /fuzz/fuzz_dataset.py: -------------------------------------------------------------------------------- 1 | import atheris 2 | import numpy 3 | import random 4 | import sys 5 | 6 | MIN_DATA_LENGTH = 1 # Minimum length of dataset 7 | MAX_DATA_LENGTH = 1000 # Maximum length of dataset 8 | 9 | default_path = "../plugins/model_card_gen/generators/tfma/" 10 | sys.path.append(default_path) 11 | 12 | with atheris.instrument_imports(include=["intel_ai_safety.*"]): 13 | from intel_ai_safety.model_card_gen.datasets.torch_datasets import PytorchNumpyDataset 14 | 15 | 16 | def TestOneInput(data): 17 | """The entry point for the fuzzer.""" 18 | fdp = atheris.FuzzedDataProvider(data) 19 | 20 | # Create input and target numpy arrays of random but equal length 21 | # Label values will be integers between [0, 10] 22 | dataset_length = random.randint(MIN_DATA_LENGTH, MAX_DATA_LENGTH) 23 | input_array = numpy.array(fdp.ConsumeRegularFloatList(dataset_length)) 24 | target_array = numpy.array(fdp.ConsumeIntListInRange(dataset_length, 0, 10)) 25 | 26 | dataset = PytorchNumpyDataset(input_array=input_array, target_array=target_array) 27 | assert len(dataset.dataset) == dataset_length 28 | 29 | 30 | if __name__ == "__main__": 31 | atheris.Setup(sys.argv, TestOneInput) 32 | atheris.Fuzz() 33 | -------------------------------------------------------------------------------- /fuzz/fuzz_test.py: -------------------------------------------------------------------------------- 1 | import atheris 2 | import json 3 | import jsonschema 4 | import sys 5 | 6 | STR_BYTE_COUNT = 10000 # Desired byte count for fuzzed strings 7 | 8 | default_path = "../model_card_gen" 9 | sys.path.append(default_path) 10 | 11 | with atheris.instrument_imports(include=["intel_ai_safety.*"]): 12 | from intel_ai_safety.model_card_gen.model_card_gen import ModelCardGen 13 | 14 | 15 | def mutate_schema(fdp, json_data): 16 | """Recurses through a json object leaving keys and structures intact and 17 | randomly generating new data values of the proper type.""" 18 | if isinstance(json_data, str): 19 | return fdp.ConsumeUnicode(STR_BYTE_COUNT) 20 | elif isinstance(json_data, list): 21 | return [mutate_schema(fdp, json_data[i]) for i in range(len(json_data))] 22 | elif isinstance(json_data, dict): 23 | return {k: mutate_schema(fdp, v) for k, v in json_data.items()} 24 | else: 25 | return None 26 | 27 | 28 | def TestOneInput(data): 29 | """The entry point for the fuzzer.""" 30 | try: 31 | json_data = json.loads(data) 32 | except json.decoder.JSONDecodeError: 33 | print("Not valid json") 34 | return 35 | except UnicodeDecodeError: 36 | print("Not valid unicode") 37 | return 38 | 39 | fdp = atheris.FuzzedDataProvider(data) 40 | model_card_data = mutate_schema(fdp, json_data) 41 | try: 42 | mcg = ModelCardGen(data_sets={"test": ""}, model_card=model_card_data) 43 | if mcg.model_card: 44 | mcg.build_model_card() # Includes scaffold_assets() and export_format() 45 | except (ValueError, jsonschema.ValidationError): 46 | print("Doesn't match MC schema") 47 | return 48 | 49 | 50 | if __name__ == "__main__": 51 | atheris.Setup(sys.argv, TestOneInput) 52 | atheris.Fuzz() 53 | -------------------------------------------------------------------------------- /fuzz/requirements.txt: -------------------------------------------------------------------------------- 1 | atheris 2 | tensorflow-data-validation 3 | tensorflow-model-analysis 4 | -------------------------------------------------------------------------------- /intel_ai_safety/common/frameworks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/intel-xai-tools/099c979cae3d9b7040c614b9d84ef25d52effd5f/intel_ai_safety/common/frameworks/__init__.py -------------------------------------------------------------------------------- /intel_ai_safety/common/frameworks/model_framework.py: -------------------------------------------------------------------------------- 1 | from intel_ai_safety.common.constants import ModelFramework 2 | import logging 3 | from pydoc import locate 4 | 5 | 6 | module_logger = logging.getLogger(__name__) 7 | 8 | try: 9 | import torch.nn as nn 10 | except ImportError: 11 | module_logger.debug("Could not import torch, required if using a PyTorch model") 12 | 13 | MODEL_TYPE_NAMES = ["torch.nn.Module", "keras.engine.sequential.Sequential", "keras.engine.functional.Functional", "keras.src.models.functional.Functional"] 14 | 15 | 16 | def is_tf_model(model): 17 | """Returns whether model is TF keras sequential or functional""" 18 | is_keras_sequential = str(type(model)).endswith("keras.engine.sequential.Sequential'>") 19 | is_keras_functional = str(type(model)).endswith("keras.engine.functional.Functional'>") 20 | is_keras_src_functional = str(type(model)).endswith("keras.src.engine.functional.Functional'>") 21 | is_keras_src_sequential = str(type(model)).endswith("keras.src.engine.sequential.Sequential'>") 22 | is_keras_src_models_functional = str(type(model)).endswith("keras.src.models.functional.Functional'>") 23 | return is_keras_sequential | is_keras_functional | is_keras_src_functional | is_keras_src_sequential | is_keras_src_models_functional 24 | 25 | 26 | def is_pt_model(model): 27 | """Returns whether model is PyTorch torch.nn.Module""" 28 | return isinstance(model, nn.Module) 29 | 30 | 31 | def raise_unknown_model_error(model): 32 | raise ValueError(f"Model {type(model)} unsupported: please use model from {' ,'.join(MODEL_TYPE_NAMES)}") 33 | 34 | 35 | def get_model_framework(model): 36 | """Returns ModelFramework enum value corresponding to model. 37 | ModelFramework.TENSORFLOW 38 | 39 | Returns: 40 | ModelFramework: ModelFramework.TENSORFLOW or ModelFramework.PYTORCH 41 | 42 | Raises: 43 | ValueError: when model is not identified as TENSORFLOW or PYTORCH 44 | """ 45 | if is_tf_model(model): 46 | return ModelFramework.TENSORFLOW 47 | elif is_pt_model(model): 48 | return ModelFramework.PYTORCH 49 | else: 50 | raise_unknown_model_error(model) 51 | 52 | 53 | def is_torch_tensor(obj): 54 | """Returns True when torch is installed and obj is a PyTorch tensor 55 | and False otherwise 56 | 57 | Returns: 58 | bool: True when obj is torch.Tensor False otherwise 59 | """ 60 | TorchTensor = locate("torch.Tensor") 61 | if TorchTensor is not None: 62 | # Torch is installed and object is torch Tensor 63 | return isinstance(obj, TorchTensor) 64 | else: 65 | return False 66 | -------------------------------------------------------------------------------- /intel_ai_safety/common/plugins.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | from pydoc import locate 21 | 22 | 23 | def get_plugin_extended_cls(pkg_path, namespace="intel_ai_safety"): 24 | """Retrieve class from plugin otherwise raise error if pluign not found.""" 25 | pkg_path = f"{namespace}.{pkg_path}" 26 | plugin_extended_cls = locate(pkg_path) 27 | if plugin_extended_cls is None: 28 | raise ModuleNotFoundError(f"Please install {pkg_path} plugin.") 29 | return plugin_extended_cls 30 | -------------------------------------------------------------------------------- /intel_ai_safety/common/types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from pydoc import locate 22 | from typing import Any 23 | 24 | TorchTensor = locate("torch.Tensor") or Any 25 | -------------------------------------------------------------------------------- /intel_ai_safety/version.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | __version__ = "1.3.0" 20 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/base_model_card_field.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | """BaseModelCardField. 22 | 23 | This class serves as a basic shared API between all Model Card data classes ( 24 | see model_card.py). 25 | """ 26 | import abc 27 | import json as json_lib 28 | from typing import Any, Dict, Text 29 | import dataclasses 30 | from intel_ai_safety.model_card_gen import validation 31 | 32 | 33 | class BaseModelCardField(abc.ABC): 34 | """Model card field base class. 35 | 36 | This is an abstract class. All the model card fields should inherit this class. 37 | """ 38 | 39 | def _from_json(self, json_dict: Dict[str, Any], field: "BaseModelCardField") -> "BaseModelCardField": 40 | """Parses a JSON dictionary into the current object.""" 41 | for subfield_key, subfield_json_value in json_dict.items(): 42 | if subfield_key.startswith(validation.SCHEMA_VERSION_STRING): 43 | continue 44 | elif not hasattr(field, subfield_key): 45 | raise ValueError("BaseModelCardField %s has no such field named '%s.'" % (field, subfield_key)) 46 | elif isinstance(subfield_json_value, dict): 47 | subfield_value = self._from_json(subfield_json_value, getattr(field, subfield_key)) 48 | elif isinstance(subfield_json_value, list): 49 | subfield_value = [] 50 | for item in subfield_json_value: 51 | if isinstance(item, dict): 52 | new_object = field.__annotations__[subfield_key].__args__[ 53 | 0 54 | ]() # pytype: disable=attribute-error 55 | subfield_value.append(self._from_json(item, new_object)) 56 | else: # if primitive 57 | subfield_value.append(item) 58 | else: 59 | subfield_value = subfield_json_value 60 | setattr(field, subfield_key, subfield_value) 61 | return field 62 | 63 | def to_json(self) -> Text: 64 | """Convert this class object to json.""" 65 | return json_lib.dumps(self.to_dict(), indent=2) 66 | 67 | def to_dict(self) -> Dict[Text, Any]: 68 | """Convert your model card to a python dictionary.""" 69 | # ignore None properties recursively to allow missing values. 70 | ignore_none = lambda properties: {k: v for k, v in properties if v} 71 | return dataclasses.asdict(self, dict_factory=ignore_none) 72 | 73 | def clear(self): 74 | """Clear the subfields of this BaseModelCardField.""" 75 | for field_name, field_value in self.__dict__.items(): 76 | if isinstance(field_value, BaseModelCardField): 77 | field_value.clear() 78 | elif isinstance(field_value, list): 79 | setattr(self, field_name, []) 80 | else: 81 | setattr(self, field_name, None) 82 | 83 | @classmethod 84 | def _get_type(cls, obj: Any): 85 | return type(obj) 86 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/docs/examples/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/docs/examples/csv/multiclass_metrics_by_group.csv: -------------------------------------------------------------------------------- 1 | group,Subgroup,BPSN,BNSP,feature,label 2 | None,0.663978494623656,0.05175469691598725,0.7976406533575318,target,Hate 3 | Islam,0.2520812520812521,0.2253081791188027,0.06895346628679963,target,Hate 4 | Homosexual,0.1665200452431821,0.10495643644336736,0.11497825514795271,target,Hate 5 | Other,0.06432748538011696,0.036618539443398206,0.1179243103368606,target,Hate 6 | African,0.17922839813065528,0.2761131918435289,0.04948755257654906,target,Hate 7 | Caucasian,0.11973392461197341,0.03502420924023711,0.2017069924046668,target,Hate 8 | Women,0.0915915915915916,0.052774564447716214,0.134178633262043,target,Hate 9 | Jewish,0.15855072463768116,0.2847087378640777,0.042195048309178744,target,Hate 10 | Arab,0.19393939393939397,0.20405040504050406,0.07246704331450093,target,Hate 11 | Refugee,0.21724709784411278,0.050078554595443844,0.26558981889378364,target,Hate 12 | Overall generalized mean,0.09752439987057404,0.047228721846868965,0.06072769397983537,target,Hate 13 | None,0.19501844198551305,0.2783760683760684,0.10728397072576173,target,Offensive 14 | Islam,0.13459950454170108,0.09323060800078603,0.17756539235412475,target,Offensive 15 | Homosexual,0.15458579881656803,0.1293481839130912,0.14503850579799946,target,Offensive 16 | Other,0.16952380952380952,0.13625925925925925,0.1718796992481203,target,Offensive 17 | African,0.2011661807580175,0.06384055038445974,0.4060973226499902,target,Offensive 18 | Caucasian,0.2236842105263158,0.33749169557835684,0.05688232739904473,target,Offensive 19 | Women,0.2237339380196523,0.19960429875444044,0.11690237830393559,target,Offensive 20 | Jewish,0.14197802197802198,0.04984393757503001,0.32289592760180996,target,Offensive 21 | Arab,0.2738095238095237,0.07928240740740741,0.33589933382679493,target,Offensive 22 | Refugee,0.17570754716981132,0.23485815121487713,0.08339763374485597,target,Offensive 23 | Overall generalized mean,0.16778173692851533,0.07335262227529309,0.08644312885987962,target,Offensive 24 | None,0.14334558310461926,0.2737090148982106,0.11224370922646786,target,Normal 25 | Islam,0.3830227743271222,0.17038497457715057,0.4388404615577574,target,Normal 26 | Homosexual,0.31410490446635025,0.3454184704184704,0.18315707652341112,target,Normal 27 | Other,0.1304945054945055,0.32237929135303833,0.08765844467283318,target,Normal 28 | African,0.23356751607525597,0.11845338161127635,0.4037692747001713,target,Normal 29 | Caucasian,0.2518518518518518,0.21071428571428572,0.2659744408945687,target,Normal 30 | Women,0.28479532163742693,0.33588516746411484,0.1762568306010929,target,Normal 31 | Jewish,0.2369787005548595,0.14436481296682693,0.3628726417358744,target,Normal 32 | Arab,0.2205128205128205,0.20050167224080268,0.256,target,Normal 33 | Refugee,0.3554285714285714,0.35463636363636364,0.2079171032716265,target,Normal 34 | Overall generalized mean,0.18221056323099738,0.168860094009674,0.13045961001359177,target,Normal 35 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/graphics/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/graphics/plotly_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | 22 | def visualize_bool_values(trace_per_graph, graph_count): 23 | enum_range = range(0, trace_per_graph * graph_count, trace_per_graph) 24 | for left_fill, right_fill in zip(enum_range, enum_range[::-1]): 25 | yield (([False] * left_fill) + ([True] * trace_per_graph) + ([False] * right_fill)) 26 | 27 | 28 | def show_nth_trace(n, trace_per_graph, graph_count): 29 | """Return a generator of bools such that the nth (count stating at 1) 30 | of a group of size `trace_per_graph` of a collection of `graph_count` 31 | groups. 32 | 33 | Example: 34 | _show_nth_trace(2, 3, 2) returns iter([False, True, False, True]) 35 | """ 36 | if n > trace_per_graph: 37 | raise ValueError(f"Cannot show {n}th item of a group of size {trace_per_graph}") 38 | for i in range(trace_per_graph * graph_count): 39 | if i % trace_per_graph == (n - 1) and (n == 1 or i != 0): 40 | yield True 41 | else: 42 | yield False 43 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/template/html/js/plotly_js_header.html.jinja: -------------------------------------------------------------------------------- 1 | {% block javascript %} 2 | 3 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/template/html/style/default_style.html.jinja: -------------------------------------------------------------------------------- 1 | 82 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/template/md/macros/default_macros.md.jinja: -------------------------------------------------------------------------------- 1 | {% macro render_if_exist(name, value) %}{% if value %} 2 | {{name}}: {{value}} {% endif %}{% endmacro %} 3 | 4 | {% macro render_considerations(list) %} 5 | {% if list %} 6 | {% for item in list %} 7 | - {{ item.description }} 8 | {% endfor %} 9 | {%- endif %} 10 | {% endmacro %} 11 | 12 | {% macro render_all_datasets(datasets) %} 13 |
    14 |

    Datasets

    15 | 16 | {% for dataset in datasets %} 17 |
    18 |
    19 | 20 | {% if dataset.name %} 21 |

    {{ dataset.name }}

    22 | 23 | {% endif %} 24 | 25 | {% if dataset.description %} 26 |

    {{ dataset.description }} 27 |

    28 | 29 | {% endif %} 30 | {% if dataset.link %} 31 | 32 | {{ dataset.link }} 33 | 34 | {% endif %} 35 | {% if dataset.graphics and dataset.graphics.collection %} 36 | 37 | {{ render_graphics(dataset.graphics.collection) }} 38 | {% endif %} 39 |
    40 |
    41 | 42 | {% endfor %} 43 |
    44 | 45 | {% endmacro %} 46 | 47 | 48 | {% macro render_graphics(graphics) %} 49 | {% if graphics.description %}

    {{ graphics.description }}

    {% endif %} 50 | {% for graph in graphics %} 51 |
    52 | 53 | 54 | {% if graph.name %}

    {{ graph.name }}

    {% endif %}
    55 | {% if graph.html %} 56 |
    {{ graph.html|safe }}
    57 | 58 | {% elif graph.image %} 59 |
    60 | {{ graph.name }} 61 |
    62 | 63 | {% endif %} 64 |
    65 | 66 | {% endfor %} 67 | {% endmacro %} 68 | 69 | {% macro render_license(license) %} 70 | {% if license.identifier %} 71 | - {{ license.identifier }} 72 | {% endif %} 73 | {% if license.custom_text %} 74 | - {{ license.custom_text }} 75 | {% endif %} 76 | {% endmacro %} 77 | 78 | {% macro metric_name(metric) %}{{ metric.type }}{% if metric.threshold %}{{ metric.threshold }}{% endif %}{% if metric.slice %}, {{ metric.slice }}{% endif %}{% endmacro %} 79 | 80 | {% macro metric_value(metric) %}{{ metric.value }}{% if metric.confidence_interval %} ({{ metric.confidence_interval.lower_bound }}, {{ metric.confidence_interval.upper_bound }}){% endif %}{% endmacro %} 81 | 82 | 83 | {% macro render_quantitative_analysis(quantitative_analysis) %} 84 |
    85 |

    Quantitative Analysis

    86 | 87 | 88 | {% if quantitative_analysis.performance_metrics %} 89 | {{ render_metrics_table(quantitative_analysis.performance_metrics )}} 90 | {% endif %} 91 | {% if quantitative_analysis.graphics.collection %} 92 | {{ render_metrics_graphics(quantitative_analysis.graphics) }} 93 | 94 | {% endif %} 95 |
    96 | 97 | {% endmacro %} 98 | 99 | {% macro render_metrics_table(metrics) %} 100 | ### Performance Metrics 101 | 102 | | Name | Value | 103 | | ----- | ------ | 104 | {% for metric in metrics %}|{{ metric_name(metric) }}|{{ metric_value(metric) }}| 105 | {% endfor %} 106 | 107 | {% endmacro %} 108 | 109 | 110 | {% macro render_metrics_graphics(graphics) %} 111 | {% if graphics.description %} 112 | {{ graphics.description }} 113 | {% endif %} 114 | 115 | {{ render_graphics(graphics.collection) }} 116 | {% endmacro %} 117 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/utils/types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from typing import Union 22 | from numpy.typing import NDArray 23 | from intel_ai_safety.model_card_gen.datasets import TensorflowDataset, PytorchDataset 24 | 25 | Array = NDArray 26 | DatasetType = Union[TensorflowDataset, PytorchDataset] 27 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/validation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | """Model Card Validation. 22 | 23 | This submodule contains functions used to validate Python dictionaries against 24 | the Model Card schema. 25 | """ 26 | 27 | import json 28 | import os 29 | import pkgutil 30 | from typing import Any, Dict, Optional, Text 31 | import jsonschema 32 | import semantic_version 33 | 34 | _SCHEMA_FILE_NAME = "model_card.schema.json" 35 | _SCHEMA_VERSIONS = frozenset(("0.0.1",)) 36 | _LATEST_SCHEMA_VERSION = max(_SCHEMA_VERSIONS, key=semantic_version.Version) 37 | 38 | SCHEMA_VERSION_STRING = "schema_version" 39 | 40 | 41 | def validate_json_schema(json_dict: Dict[Text, Any], schema_version: Optional[Text] = None) -> Dict[Text, Any]: 42 | """Validates the json schema of a model card field. 43 | 44 | If schema_version is not provided, it will use the latest schema version. 45 | See 46 | https://github.com/tensorflow/model-card-toolkit/tree/master/model_card_toolkit/schema/. 47 | 48 | Args: 49 | json_dict: A dictionary following the schema for a model card field. 50 | schema_version: The version of the model card schema. Optional field; if 51 | omitted, defers to the latest schema version. 52 | 53 | Returns: 54 | The schema used for validation. 55 | 56 | Raises: 57 | ValueError: If `schema_version` does not correspond to a model card schema 58 | version. 59 | ValidationError: If `model_card_json` does not follow the model card schema. 60 | """ 61 | schema = _find_json_schema(schema_version or json_dict.get("schema_version") or _LATEST_SCHEMA_VERSION) 62 | jsonschema.validate(json_dict, schema) 63 | return schema 64 | 65 | 66 | def _find_json_schema(schema_version: Optional[Text] = None) -> Dict[Text, Any]: 67 | """Returns the JSON schema of a model card field in dictionary format. 68 | 69 | Args: 70 | schema_version: The version of the schema to fetch. By default, use the 71 | latest version. 72 | 73 | Returns: 74 | JSON schema as a dictionary. 75 | 76 | Raises: 77 | ValueError: If `schema_version` does not correspond to a model card schema 78 | version. 79 | """ 80 | if not schema_version: 81 | schema_version = _LATEST_SCHEMA_VERSION 82 | if schema_version not in _SCHEMA_VERSIONS: 83 | raise ValueError( 84 | "Cannot find schema version that matches the version of the given " 85 | "model card. Found Versions: {}. Given Version: {}".format(", ".join(_SCHEMA_VERSIONS), schema_version) 86 | ) 87 | 88 | schema_file = os.path.join("schema", "v" + schema_version, _SCHEMA_FILE_NAME) 89 | json_file = pkgutil.get_data("intel_ai_safety.model_card_gen", schema_file) 90 | schema = json.loads(json_file) 91 | return schema 92 | 93 | 94 | def get_latest_schema_version() -> Text: 95 | """Returns the most recent schema version.""" 96 | return _LATEST_SCHEMA_VERSION 97 | -------------------------------------------------------------------------------- /model_card_gen/intel_ai_safety/model_card_gen/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | __version__ = "1.3.0" 22 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [client] 2 | showSidebarNavigation = false 3 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | license: apache-2.0 3 | title: Model Card Generator 4 | sdk: streamlit 5 | emoji: 🚀 6 | colorFrom: yellow 7 | colorTo: blue 8 | app_file: home.py 9 | short_description: Create interactive Model Card 10 | --- 11 | # Model Card Generator UI 12 | 13 | This streamlit application allows users to create interactive HTML reports containing model performance and fairness metrics using a simple interface. Users can either create a new Model Card or modify an existing one. 14 | 15 | ## Install 16 | 1. Choose a virtual enviornment to use: eg. Using virtualenv: 17 | 18 | ```bash 19 | python3 -m virtualenv mgc_ui_venv 20 | source mgc_ui_venv/bin/activate 21 | ``` 22 | 23 | 2. To install the required Python packages, run the following command in your terminal: 24 | 25 | ```bash 26 | pip install -r requirements.txt 27 | ``` 28 | 29 | ## Run the Streamlit Application 30 | You can run the Streamlit application using the following command: 31 | 32 | ```bash 33 | streamlit run home.py 34 | ``` 35 | 36 | The command will start the Streamlit server, and you should see output in the terminal that includes a URL where you can view the application. Open the URL in your web browser to interact with the Streamlit UI. 37 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/home.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | """ 21 | This module builds the Home Page of the Model Card Generator interactive UI allowing users to 22 | create, upload, and download Model Cards. 23 | """ 24 | import streamlit as st 25 | from persist import load_widget_state 26 | from read_json import read_uploaded_file 27 | from session_state_initializer import initialize_session_state 28 | import plotly.io as pio 29 | from utils import navigate_menu 30 | 31 | st.set_page_config(initial_sidebar_state="expanded") 32 | pio.templates.default = "plotly" 33 | 34 | 35 | def upload_model_card(): 36 | st.markdown("## Upload Model Card") 37 | st.write( 38 | "If you are interested in viewing an example, please [click here](https://github.com/intel/intel-xai-tools/tree/main/model_card_gen/intel_ai_safety/model_card_gen/docs/examples/json)." 39 | ) 40 | uploaded_file = st.file_uploader("", type=["json"], help="Please choose a JSON (.json) file type to upload") 41 | if uploaded_file is not None: 42 | read_uploaded_file(uploaded_file) 43 | 44 | 45 | def main_page(): 46 | st.header("Model Card Generator") 47 | st.markdown( 48 | "This tool allows users to create interactive HTML reports containing model performance and fairness metrics " 49 | "using a simple interface." 50 | ) 51 | st.markdown( 52 | "To begin, you can either upload an existing Model Card in JSON format below or input your model card details by selecting the respective sections from the sidebar." 53 | ) 54 | upload_model_card() 55 | 56 | 57 | if __name__ == "__main__": 58 | load_widget_state() 59 | initialize_session_state() 60 | navigate_menu() 61 | if "runpage" not in st.session_state: 62 | st.session_state.runpage = main_page 63 | st.session_state.runpage() 64 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/model_card_html_generator.py: -------------------------------------------------------------------------------- 1 | from intel_ai_safety.model_card_gen.model_card_gen import ModelCardGen 2 | import streamlit as st 3 | 4 | 5 | def generate_error_message(column_name, metric_file_type): 6 | help_message = ( 7 | "Please [click here](https://github.com/intel/intel-xai-tools/tree/main/model_card_gen/intel_ai_safety/model_card_gen/docs/examples/csv) " 8 | "to view examples of metric files. To learn how to create these files or see a step-by-step example, you can follow this " 9 | "[link](https://github.com/intel/intel-xai-tools/blob/main/notebooks/model_card_gen/hugging_face_model_card/hugging-face-model-card.ipynb) " 10 | "for further guidance." 11 | ) 12 | if metric_file_type: 13 | help_message = ( 14 | f"Error: The uploaded CSV file for {metric_file_type} does not contain the required column '{column_name}'. " 15 | + help_message 16 | ) 17 | return help_message 18 | 19 | 20 | def handle_exception(error_str): 21 | if "No column named" in error_str: 22 | column_name = error_str.split("'")[1] 23 | metric_file_type = ( 24 | "Metrics by Threshold" 25 | if column_name in ["threshold", "accuracy", "precision", "recall", "f1"] 26 | else "Metrics by Group" 27 | ) 28 | st.error(generate_error_message(column_name, metric_file_type)) 29 | elif "range() arg 3 must not be zero" in error_str: 30 | st.error( 31 | "Error: The uploaded CSV file for Metrics by Group contains an empty 'group' column. " 32 | + generate_error_message("", "Metrics by Group") 33 | ) 34 | elif "'Overall'" in error_str: 35 | st.error( 36 | "Error: Please check if the 'Overall' value exists in the 'feature' and 'group' columns in the uploaded Metric CSV files. " 37 | + generate_error_message("", "") 38 | ) 39 | else: 40 | st.error(generate_error_message("", "")) 41 | 42 | 43 | def generate_model_card_html(model_card, metric_threshold_csv=None, metric_grp_csv=None): 44 | """ 45 | Generates an HTML representation of a model card, optionally including data from CSV files 46 | for metric thresholds and metric groups. 47 | 48 | Parameters: 49 | model_card (ModelCard): The model card object containing the model's metadata and other details. 50 | metric_threshold_csv (str, optional): The file path to a CSV containing metric threshold data. 51 | metric_grp_csv (str, optional): The file path to a CSV containing metric group data. 52 | 53 | Returns: 54 | str: The HTML representation of the model card. 55 | """ 56 | try: 57 | model_card_html = ModelCardGen.generate(model_card, metric_threshold_csv, metric_grp_csv) 58 | return model_card_html._repr_html_() 59 | except Exception as e: 60 | handle_exception(str(e)) 61 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/pages/model_parameters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import streamlit as st 22 | from persist import persist, load_widget_state 23 | from utils import convert_str_to_key_value_map, navigate_menu 24 | 25 | st.set_page_config(initial_sidebar_state="expanded") 26 | 27 | 28 | def main(): 29 | navigate_menu() 30 | st.markdown("# Model Parameters") 31 | st.write("This section provides details regarding the parameters for construction of the model.") 32 | st.text_area( 33 | r"$\textsf{\LARGE Model Architecture}$", 34 | value=st.session_state.get("model_architecture"), 35 | placeholder="The architecture of the model.", 36 | help="The architecture of the model.", 37 | key=persist("model_architecture"), 38 | ) 39 | st.write("\n") 40 | st.text_area( 41 | r"$\textsf{\LARGE Input Format}$", 42 | value=st.session_state.get("input_format"), 43 | help="The data format for inputs to the model.", 44 | key=persist("input_format"), 45 | ) 46 | st.write("\n") 47 | st.text_area( 48 | r"$\textsf{\LARGE Input Format Map}$", 49 | value=st.session_state.get("input_format_map_text"), 50 | placeholder="Input data format in the form of list (comma seperated) of key-value pairs. For example, image_data: RGB images ('PNG'), text: String data", 51 | help="The data format for inputs to the model, in key-value format.", 52 | key=persist("input_format_map_text"), 53 | ) 54 | st.write("\n") 55 | st.text_area( 56 | r"$\textsf{\LARGE Output Format}$", 57 | st.session_state.get("output_format"), 58 | help="The data format for outputs from the model.", 59 | key=persist("output_format"), 60 | ) 61 | st.write("\n") 62 | st.text_area( 63 | r"$\textsf{\LARGE Output Format Map}$", 64 | value=st.session_state.get("output_format_map_text"), 65 | placeholder="Output data format in the form of list (comma seperated) of key-value pairs. For example, classification_probabilities: Probability (between 0 to 1) of the example belonging to each class.", 66 | help="The data format for outputs from the model, in key-value format.", 67 | key=persist("output_format_map_text"), 68 | ) 69 | 70 | 71 | if __name__ == "__main__": 72 | load_widget_state() 73 | main() 74 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/persist.py: -------------------------------------------------------------------------------- 1 | # Code based on a Gist available at https://gist.github.com/okld/0aba4869ba6fdc8d49132e6974e2e662 2 | 3 | from streamlit import session_state as _state 4 | 5 | _PERSIST_STATE_KEY = f"{__name__}_PERSIST" 6 | 7 | 8 | def persist(key: str) -> str: 9 | """Mark widget state as persistent.""" 10 | if _PERSIST_STATE_KEY not in _state: 11 | _state[_PERSIST_STATE_KEY] = set() 12 | 13 | _state[_PERSIST_STATE_KEY].add(key) 14 | 15 | return key 16 | 17 | 18 | def load_widget_state(): 19 | """Load persistent widget state.""" 20 | if _PERSIST_STATE_KEY in _state: 21 | _state.update({key: value for key, value in _state.items() if key in _state[_PERSIST_STATE_KEY]}) 22 | -------------------------------------------------------------------------------- /model_card_gen/model_card_ui/requirements.txt: -------------------------------------------------------------------------------- 1 | altair 2 | lxml 3 | streamlit 4 | intel-ai-safety-model-card-gen @ file:///${PWD}/../../model_card_gen 5 | -------------------------------------------------------------------------------- /model_card_gen/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /model_card_gen/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-model-card-gen" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [{include = "intel_ai_safety", from="."}] 8 | 9 | [tool.setuptools.package-data] 10 | intel_ai_safety.model_card_gen = [ 11 | "model_card_gen/**/*.json", 12 | "model_card_gen/**/*.jinja", 13 | "model_card_gen/**/*.html", 14 | "model_card_gen/**/*.csv", 15 | ] 16 | 17 | [tool.poetry.group.test] 18 | optional = true 19 | 20 | [tool.poetry.group.test.dependencies] 21 | pytest = "8.3.5" 22 | pytest-cov = "6.0.0" 23 | 24 | [tool.poetry.dependencies] 25 | python = ">=3.10, <3.12" 26 | dataclasses = "0.6" 27 | ipython = "8.33.0" 28 | Jinja2 = "3.1.6" 29 | jsonschema = {version="4.23.0", extras = ['format-nongpl']} 30 | pandas = "2.2.3" 31 | plotly = "6.0.0" 32 | semantic-version = "2.10.0" 33 | 34 | [[tool.poetry.source]] 35 | name = "PyPI" 36 | priority = "primary" 37 | 38 | [build-system] 39 | requires = ["poetry-core"] 40 | build-backend = "poetry.core.masonry.api" 41 | 42 | [[tool.poetry_bumpversion.replacements]] 43 | files = ["intel_ai_safety/model_card_gen/version.py"] 44 | search = '__version__ = "{current_version}"' 45 | replace = '__version__ = "{new_version}"' 46 | -------------------------------------------------------------------------------- /model_card_gen/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | -------------------------------------------------------------------------------- /notebooks/explainer/README.md: -------------------------------------------------------------------------------- 1 | # Explainer Tutorial Notebooks 2 | This directory has Jupyter notebooks that demonstrate explainability with the Intel® Explainable AI Tools. 3 | 4 | ## Running the Explainer Tutorial notebooks 5 | Before running the notebooks, install the dependencies: 6 | 1. `pip install --no-cache-dir -r requirements.txt` 7 | 8 | 9 | | Notebook | Domain: Use Case | Framework| Description | 10 | | ---------| ---------|----------|-------------| 11 | | [Explaining Image Classification and Object Detection Using the CAM Explainer](imagenet_with_cam) | CV: Image Classification & Object Detection | PyTorch*, TensorFlow* and Intel® Explainable AI API | Two separate notebooks that demonstrate how to use the CAM explainer API to explain ImageNet classification and detection examples using a ResNet50 CNN from the TorchVision & Torch model hub and TF's keras.applications model hub. | 12 | | [Explaining Custom CNN MNIST Classification Using the Attributions Explainer](mnist_with_attributions_and_metrics) | CV: Image Classification | PyTorch and Intel® Explainable AI API | Demonstrates how to use the attributions explainer API to explain an MNIST classification example using a Custom PyTorch CNN. | 13 | | [Explaining Custom NN NewsGroups Classification Using the Attributions Explainer](newsgroups_with_attributions_and_metrics) | NLP: Text Classification | PyTorch and Intel® Explainable AI API | Demonstrates how to use the attributions explainer API to explain a NewsGroups dataset text classification example using a Custom TensorFlow NN. | 14 | | [Explaining Custom CNN CIFAR-10 Classification Using the Attributions Explainer](cifar_with_attributions) | CV: Image Classification | PyTorch and Intel® Explainable AI API | Demonstrates how to use the attributions explainer API to explain the CIFAR-10 dataset image classification example using a Custom PyTorch CNN. | 15 | | [Multimodal Breast Cancer Detection Explainability using the Intel® Explainable AI API](multimodal_cancer_detection) | CV: Image Classification & NLP: Text Classification| PyTorch, HuggingFace, Intel® Explainable AI API & Intel® Transfer Learning Tool API | Demonstrates how to use the attributions and metrics explainer API's to explain the classification of a text and image breast cancer dataset using a PyTorch ResNet50 CNN and a HuggingFace ClinicalBert Transformer. | 16 | | [Explaining Fine Tuned Text Classifier with PyTorch using the Intel® Explainable AI API](transfer_learning_text_classification) | NLP: Text Classification| PyTorch, HuggingFace, Intel® Explainable AI API & Intel® Transfer Learning Tool API | Demonstrates how to use the attributions explainer API's to explain the classification of a text using HuggingFace Transformer. | 17 | | [Explaining a Custom Neural Network Heart Disease Classification Using the Attributions Explainer ](heart_disease_with_attributions) | Numerical/Categorical: Tabular Classification | TensorFlow & Intel® Explainable AI API | Demonstrates how to use the attributions explainer API's to explain the classification of a Tabular data using a TensorFlow custom NN. | 18 | 19 | -------------------------------------------------------------------------------- /notebooks/explainer/cifar_with_attributions/README.md: -------------------------------------------------------------------------------- 1 | # Explaining Custom CNN CIFAR-10 Classification Using the Attributions Explainer 2 | This notebook demonstrates how to use the attributions explainer API to explain the CIFAR-10 dataset image classification example using a Custom PyTorch CNN. 3 | 4 | `TorchVision_CIFAR_Interpret.ipynb` performs the following steps: 5 | 1. Import dependencies 6 | 2. Load the CIFAR-10 dataset from TorchVision hub 7 | 3. Design the PyTorch CNN model 8 | 4. Train the CNN 9 | 5. Visualize the custom CNN classifications using `saliency()`, `integratedgradients()`, `deeplift()`, `smoothgrad()` and `featureablation()` 10 | 11 | ## Running the notebook 12 | 13 | To run `TorchVision_CIFAR_Interpret.ipynb`, install the following dependencies: 14 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 15 | 16 | ## References 17 | -------------------------------------------------------------------------------- /notebooks/explainer/gen_llm_with_attributions/README.md: -------------------------------------------------------------------------------- 1 | # Explaining Hugging Face Generative LLMs with the Attributions Plugin 2 | This notebook demonstrates how to use the attributions explainer API to explain text generation, translation and classification with Hugging Face Transformers. 3 | 4 | `TorchVision_CIFAR_Interpret.ipynb` performs the following steps: 5 | 1. Import dependencies 6 | 2. Load GPT2 and explain a text generation exmaple 7 | 3. Load Helsinki-NLP/opus-mt-en-es and explain a text translation example 8 | 4. Load nateraw/bert-base-uncased-emotion and explain a text classification example 9 | 10 | ## Running the notebook 11 | 12 | To run `TorchVision_CIFAR_Interpret.ipynb`, install the following dependencies: 13 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 14 | 15 | ## References 16 | https://shap.readthedocs.io/en/latest/text_examples.html 17 | -------------------------------------------------------------------------------- /notebooks/explainer/heart_disease_with_attributions/README.md: -------------------------------------------------------------------------------- 1 | # Explaining a Custom NN Heart Disease Classification Using the Attributions Explainer 2 | This notebook demonstrates how to use the attributions explainer API to explain a Cleveland Heart Disease dataset classification example using a Custom TensorFlow NN. 3 | 4 | `heart_disease.ipynb` performs the following steps: 5 | 1. Import dependencies 6 | 2. Load and process the Heart Disease CSV file from the TensorFlow data hub 7 | 3. Design the TensorFlow NN 8 | 4. Train the CNN 9 | 5. Visualize the custom NN classifications using `kernel_explainer()` 10 | 11 | ## Running the notebook 12 | 13 | To run `heart_disease.ipynb`, install the following dependencies: 14 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 15 | 16 | ## References 17 | 18 | Heart Disease Dataset - https://archive.ics.uci.edu/ml/datasets/heart+disease 19 | -------------------------------------------------------------------------------- /notebooks/explainer/imagenet_with_cam/README.md: -------------------------------------------------------------------------------- 1 | # Explaining Image Classification and Object Detection with Grad CAM and Eigan CAM Algorithms 2 | This notebook directory has two notebooks demonstrating how to use the Class Activation Mapping API for image classification (`ExplainingImageClassification.ipynb`) and object detection (`ExplainingObjectDetection.ipynb`) task types. 3 | 4 | ## Explaining RESNET50 ImageNet Classification Using XGradCAM and TFGradCAM 5 | 6 | This notebook demonstrates how to use the CAM explainer API to explain an ImageNet classification example using a RESNET50 CNN from the Torch Vision model hub and also from the TF keras.applications model hub. 7 | 8 | `ExplainingImageClassification.ipynb` performs the following steps: 9 | 1. Install and import dependencies 10 | 2. Load the ImageNet example image to be analyzed 11 | 3. Load the ResNet50 CNN trained on ImageNet 12 | 4. Visualize the ResNet50 classification of the loaded image using `x_gradcam()` 13 | 5. Redo steps above for TF keras.applications ResNet50 model and using `tf_gradcam()` 14 | 15 | ### Running the notebook 16 | 17 | To run `ExplainingImageClassification.ipynb`, install the following dependencies: 18 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 19 | 20 | 21 | ### References 22 | 23 | pytorch-grad-cam GitHub Project - https://github.com/jacobgil/pytorch-grad-cam 24 | TensorFlow implementation - https://github.com/ismailuddin/gradcam-tensorflow-2/blob/master/notebooks/GradCam.ipynb 25 | 26 | 27 | ## Explaining FasterRCNN and YOLO ImageNet Object Detection Using EigenCAM 28 | 29 | This notebook demonstrates how to use the CAM explainer API to explain two ImageNet object detection examples using a FasterRCNN and a YOLO model from the TorchVision and Torch model hubs, respectively. 30 | 31 | `ExplainingObjectDetection.ipynb` performs the following steps: 32 | 1. Install and import dependencies 33 | 2. Load the ImageNet example image to be analyzed 34 | 3. Load the FasterRCNN trained on ImageNet 35 | 4. Define the helper functions 36 | 4. Visualize the FasterRCNN detection of the loaded image using `eigencam()` 37 | 5. Redo steps above for the YOLO model 38 | 39 | ### Running the notebook 40 | 41 | To run `ExplainingObjectDetection.ipynb`, install the following dependencies: 42 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 43 | 2. `pip install scikit-image ultralytics` 44 | 45 | 46 | ### References 47 | pytorch-grad-cam GitHub tutorial for object detection with FasterRCNN - https://jacobgil.github.io/pytorch-gradcam-book/Class%20Activation%20Maps%20for%20Object%20Detection%20With%20Faster%20RCNN.html 48 | pytorch-grad-cam GitHub tutorial for object detection with YOLO - https://jacobgil.github.io/pytorch-gradcam-book/EigenCAM%20for%20YOLO5.html 49 | -------------------------------------------------------------------------------- /notebooks/explainer/mnist_with_attributions_and_metrics/README.md: -------------------------------------------------------------------------------- 1 | # Explaining Custom CNN MNIST Classification Using the Attributions Explainer 2 | 3 | This notebook demonstrates how to use the attributions explainer API to explain an MNIST classification example using a Custom CNN. It also includes the metrics explainer API for error analysis. 4 | 5 | `mnist.ipynb` performs the following steps: 6 | 1. Import libraries 7 | 2. Design the PyTorch custom CNN 8 | 3. Train the CNN on the MNIST dataset 9 | 4. Predict on the MNIST test data 10 | 5. Visualize test performance with `confusion_matrix()` and `plot()` functions 11 | 6. Visualize the CNN test classifications using `gradient_explainer()` and `deep_explainer()` 12 | 13 | ## Running the notebook 14 | 15 | To run `mnist.ipynb`, install the following dependencies: 16 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 17 | 18 | ## References 19 | 20 | 1. SHAP GitHub Project - https://github.com/slundberg/shap 21 | 2. SHAP MNIST example - "Pytorch Deep Explainer MNIST example": https://github.com/slundberg/shap/blob/master/notebooks/image_examples/image_classification/PyTorch%20Deep%20Explainer%20MNIST%20example.ipynb 22 | -------------------------------------------------------------------------------- /notebooks/explainer/multimodal_cancer_detection/README.md: -------------------------------------------------------------------------------- 1 | # Multimodal Breast Cancer Detection Explainability using the Intel® Explainable AI API 2 | 3 | This notebook demonstrate how to use the Explainable AI API for PyTorch CNN and Transformer models in a multimodal architecture. This notebook also includes the Intel® Transfer Learning Tool and the Intel® Extension for Transformers library. 4 | 5 | `Multimodal_Cancer_Detection.ipynb` performs the following steps: 6 | 1. Import dependencies 7 | 2. Prepare image and text datasets 8 | 3. CNN image classification 9 | 1. Analyze image dataset 10 | 2. Get the model 11 | 3. Download and prepare the dataset 12 | 4. Transfer learning 13 | 5. Evaluate 14 | 6. Error Analysis 15 | 7. Explanation 16 | 4. BERT text classification 17 | 1. Analyze text dataset 18 | 2. Get the model 19 | 3. Prepare the dataset 20 | 4. Transfer learning 21 | 5. Evaluate 22 | 6. Error Analysis 23 | 7. Explanation 24 | 5. Post-training quantization 25 | 1. Configure and quantize the current BERT model 26 | 2. Evaluate 27 | 3. Error Analysis 28 | 29 | 30 | The `dataset_utils.py` holds the supporting functions that prepare the image and text datasets. 31 | 32 | ## Running the notebook 33 | 34 | To run `Multimodal_Cancer_Detection.ipynb`, install the following dependencies: 35 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 36 | 2. Further dependencies to be installed in the notebook 37 | 38 | ## References 39 | 40 | ### _Dataset citations_ 41 | Khaled R., Helal M., Alfarghaly O., Mokhtar O., Elkorany A., El Kassas H., Fahmy A. Categorized Digital Database for Low energy and Subtracted Contrast Enhanced Spectral Mammography images [Dataset]. (2021) The Cancer Imaging Archive. DOI: [10.7937/29kw-ae92](https://doi.org/10.7937/29kw-ae92) 42 | 43 | ### _Publication Citation_ 44 | Khaled, R., Helal, M., Alfarghaly, O., Mokhtar, O., Elkorany, A., El Kassas, H., & Fahmy, A. Categorized contrast enhanced mammography dataset for diagnostic and artificial intelligence research. (2022) Scientific Data, Volume 9, Issue 1. DOI: [10.1038/s41597-022-01238-0](https://doi.org/10.1038/s41597-022-01238-0) 45 | 46 | ### _TCIA Citation_ 47 | Clark K, Vendt B, Smith K, Freymann J, Kirby J, Koppel P, Moore S, Phillips S, Maffitt D, Pringle M, Tarbox L, Prior F. The Cancer Imaging Archive (TCIA): Maintaining and Operating a Public Information Repository, Journal of Digital Imaging, Volume 26, Number 6, December, 2013, pp 1045-1057. DOI: [10.1007/s10278-013-9622-7](https://doi.org/10.1007/s10278-013-9622-7) 48 | -------------------------------------------------------------------------------- /notebooks/explainer/newsgroups_with_attributions_and_metrics/README.md: -------------------------------------------------------------------------------- 1 | # Explaining Custom NN NewsGroups Classification Using the Attributions Explainer 2 | 3 | This notebook demonstrates how to use the attributions explainer API to explain a NewsGroups dataset text classification example using a Custom TensorFlow NN. 4 | 5 | `partitionexplainer.ipynb` performs the following steps: 6 | 1. Import libraries 7 | 2. Fetch NewsGroups dataset 8 | 3. Vectorize text data 9 | 4. Design neural network 10 | 5. Train NN 11 | 6. Predict on the test data 12 | 7. Visualize test performance with `confusion_matrix()` and `plot()` functions 13 | 9. Visualize the custom NN test classifications using `partition_explainer()` and shap's bar and waterfall plots 14 | 15 | ## Running the notebook 16 | 17 | To run `partitionexplainer.ipynb`, install the following dependencies: 18 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 19 | 20 | ## References 21 | 22 | 1. Explain Text Classification Models Using SHAP Values - https://coderzcolumn.com/tutorials/artificial-intelligence/explain-text-classification-models-using-shap-values-keras 23 | -------------------------------------------------------------------------------- /notebooks/explainer/requirements.txt: -------------------------------------------------------------------------------- 1 | pydot 2 | pydot_ng 3 | scikit-image 4 | ultralytics 5 | -------------------------------------------------------------------------------- /notebooks/explainer/transfer_learning_text_classification/README.md: -------------------------------------------------------------------------------- 1 | # Explaining Fine Tuned Text Classifier with PyTorch 2 | 3 | This notebook demonstrates fine tuning [pretrained models from Hugging Face](https://huggingface.co/models) 4 | using text classification datasets from the [Hugging Face Datasets catalog](https://huggingface.co/datasets) or 5 | a custom dataset. The [IMDb Larget Movie Review dataset](https://ai.stanford.edu/~amaas/data/sentiment/) is used 6 | from the Hugging Face Datasets catalog, and the [SMS Spam Collection dataset](https://archive.ics.uci.edu/dataset/228/sms+spam+collection) 7 | is used as an example of a custom dataset being loaded from a csv file. 8 | 9 | The notebook uses 10 | [Intel® Extension for PyTorch*](https://github.com/intel/intel-extension-for-pytorch) which extends PyTorch 11 | with optimizations for extra performance boost on Intel hardware. 12 | 13 | The notebook performs the following steps: 14 | 1. Import dependencies and setup parameters 15 | 2. Prepare the dataset 16 | 3. Prepare the Model for Fine Tuning and Evaluation 17 | 4. Export the model 18 | 5. Reload the model and make predictions 19 | 6. Get Explainations with Intel Explainable AI Tools 20 | 21 | ## Running the notebook 22 | 23 | 24 | To run `PyTorch_Text_Classifier_fine_tuning_with_Attributions.ipynb`, install the following dependencies: 25 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 26 | 2. `pip install intel-transfer-learning-tool` 27 | 28 | ## References 29 | 30 | Dataset Citations 31 | ``` 32 | @InProceedings{maas-EtAl:2011:ACL-HLT2011, 33 | author = {Maas, Andrew L. and Daly, Raymond E. and Pham, Peter T. and Huang, Dan and Ng, Andrew Y. and Potts, Christopher}, 34 | title = {Learning Word Vectors for Sentiment Analysis}, 35 | booktitle = {Proceedings of the 49th Annual Meeting of the Association for Computational Linguistics: Human Language Technologies}, 36 | month = {June}, 37 | year = {2011}, 38 | address = {Portland, Oregon, USA}, 39 | publisher = {Association for Computational Linguistics}, 40 | pages = {142--150}, 41 | url = {http://www.aclweb.org/anthology/P11-1015} 42 | } 43 | 44 | @misc{misc_sms_spam_collection_228, 45 | author = {Almeida, Tiago}, 46 | title = {{SMS Spam Collection}}, 47 | year = {2012}, 48 | howpublished = {UCI Machine Learning Repository} 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/compas_with_model_card_gen/README.md: -------------------------------------------------------------------------------- 1 | # Detecting Issues in Fairness by Generate Model Card from Tensorflow Estimators 2 | This notebook demonstrates how to create a TFX pipeline (originally published by [Tensorflow Authors](https://github.com/tensorflow/fairness-indicators/blob/r0.38.0/g3doc/tutorials/Fairness_Indicators_Lineage_Case_Study.ipynb)) for creating a Proxy model trained for detecting issues in fairness using the [COMPAS dataset](https://www.propublica.org/datastore/dataset/compas-recidivism-risk-score-data-and-analysis). Further, the notebook also demonstrates on how to generate a model card for the trained Proxy model using the Intel Model Card Generator. 3 | 4 | `compas-model-card-tfx.ipynb` performs the following steps: 5 | 1. Import the dependencies 6 | 2. Load and preprocess the COMPAS Dataset in a csv format from Google Cloud. 7 | 3. Build the custom TFX pipeline: 8 | - Transformer 9 | - Prepare mapping between string feature keys and transformed feature operations. Fill the missing values. 10 | - Trainer 11 | - The eval_input_receiver_fn will return the TensorFlow graph for parsing the raw untransformed features by applying the tf-transform preprocessing operators. 12 | - Construct the keras model. 13 | - trainer_fn will train the model for classifying the COMPAS dataset when called in the TFX pipeline. 14 | - Pipeline 15 | - Compute statistics over the data for visualization and example validation. 16 | - Perform data transformations and feature engineering in training and serving. 17 | - Implement model based on the trainer_args given by the user. 18 | - Compute evaluation statistics over the features of a model and perform quality validation of a candidate model. 19 | 4. Generate Model Card with Intel Model Card Generator 20 | - Load or write the config file. 21 | - Define the model card dictionary following the model card schema. 22 | - Generate Model Card using generate function from the ModelCardGen class. 23 | 24 | ## Running the notebook 25 | 26 | To run the `toxicity-tfma-model-card.ipynb`, install the following dependencies: 27 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 28 | 29 | ## References 30 | ### _Dataset citations_ 31 | COMPAS dataset - https://www.propublica.org/datastore/dataset/compas-recidivism-risk-score-data-and-analysis 32 | 33 | ### _Publication citations_ 34 | 1. Wadsworth, C., Vera, F., Piech, C. (2017). Achieving Fairness Through Adversarial Learning: an Application to Recidivism Prediction. https://arxiv.org/abs/1807.00199. 35 | 36 | 2. Chouldechova, A., G’Sell, M., (2017). Fairer and more accurate, but for whom? https://arxiv.org/abs/1707.00046. 37 | 38 | 3. Berk et al., (2017), Fairness in Criminal Justice Risk Assessments: The State of the Art, https://arxiv.org/abs/1703.09207. 39 | 40 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/hugging_face_model_card/README.md: -------------------------------------------------------------------------------- 1 | # Creating Model Card for Toxic Comments Classification in Tensorflow 2 | In this notebook, we will download a model, dataset, and metric from Hugigng Face Hub and generate a interactive HTML Model Card using Intel AI Safety Model Card Generator Tool. 3 | 4 | `hugging-face-model-card` performs the following steps: 5 | 1. Download and Import Dependencies 6 | 2. Download Dataset from Hugging Face Datasets 7 | 3. Transform Dataset 8 | - Get ground truth label 9 | 5. Download Modle and Process Outputs 10 | 6. Get Bias Metric form Hugging Face 11 | 7. Run Bias Metric 12 | 8. Transform Output for Model Card 13 | 9. Build Model Card 14 | 15 | 16 | ## Running the notebook 17 | 18 | To run the `toxicity-tfma-model-card.ipynb`, install the following dependencies: 19 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 20 | 2. `!pip install evaluate datasets transformers[torch] scikit-learn` 21 | 22 | ## References 23 | ### _Dataset citations_ 24 | ``` 25 | @article{aluru2020deep, 26 | title={Deep Learning Models for Multilingual Hate Speech Detection}, 27 | author={Aluru, Sai Saket and Mathew, Binny and Saha, Punyajoy and Mukherjee, Animesh}, 28 | journal={arXiv preprint arXiv:2004.06465}, 29 | year={2020} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/image_classification_model_card/README.md: -------------------------------------------------------------------------------- 1 | # Generating Model Card for a Image Classification task 2 | This notebook demonstrates how to generate a model card for an image classification task for a pretrained [ResNet50 torchvision model](https://pytorch.org/vision/main/models/generated/torchvision.models.resnet50.html) with the Intel Model Card Generator. The ResNet model is finetuned on the [ HuggingFace dataset](https://huggingface.co/datasets/itsLeen/deepfake_vs_real_image_detection) for classifying images into either Deepfake or Normal images. 3 | 4 | `image-classification-model-card.ipynb` performs the following steps: 5 | 1. Import the dependencies . 6 | 2. Load the Deepfake v/s Real Image Dataset from HuggingFace and preprocess the data. 7 | 3. Load the pre-trained Torchvision ResNet model. 8 | 4. Fine-tune and save the ResNet model. 9 | 5. Evaluate model performance on test dataset. 10 | 6. Generate Model Card with Intel Model Card Generator - 11 | - Define the model card dictionary following the model card schema for the Image Classification model. 12 | - Generate Model Card using generate function from the ModelCardGen class. 13 | - Export the generated Model Card to html format. 14 | 15 | 16 | ## Running the notebook 17 | 18 | To run `image-classification-model-card.ipynb`, install the following dependencies: 19 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 20 | 21 | 22 | ## References 23 | ### _Publication citations_ 24 | ``` 25 | @misc{he2015deepresiduallearningimage, 26 | title={Deep Residual Learning for Image Recognition}, 27 | author={Kaiming He and Xiangyu Zhang and Shaoqing Ren and Jian Sun}, 28 | year={2015}, 29 | eprint={1512.03385}, 30 | archivePrefix={arXiv}, 31 | primaryClass={cs.CV}, 32 | url={https://arxiv.org/abs/1512.03385}, 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/model_card_generation_with_pytorch/README.md: -------------------------------------------------------------------------------- 1 | # Generating Model Card with PyTorch 2 | This notebook demonstrates how to generate a model card for a PyTorch model using the Intel Model Card Generator. The PyTorch model is trained on a prediction task using the [Adult dataset](https://archive.ics.uci.edu/dataset/2/adult) from OpenML. 3 | 4 | `adult-pytorch-model-card.ipynb` performs the following steps: 5 | 1. Import the dependencies 6 | 2. Load the Adult Dataset from OpenML and preprocess the data. 7 | 3. Build the Multilayer Neural Network (NN) using PyTorch. 8 | 4. Train and save the Multilayer NN model. 9 | 5. Generate Model Card with Intel Model Card Generator 10 | - Load or write the config file. 11 | - Define the model card dictionary following the model card schema for the Multilayer NN. 12 | - Generate Model Card using generate function from the ModelCardGen class. 13 | - Export the generated Model Card to html format. 14 | 15 | 16 | 17 | ## Running the notebook 18 | 19 | To run `adult-pytorch-model-card.ipynb`, install the following dependencies: 20 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 21 | 22 | 23 | ## References 24 | ### _Dataset citations_ 25 | Becker,Barry and Kohavi,Ronny. (1996). Adult. UCI Machine Learning Repository. https://doi.org/10.24432/C5XW20. 26 | 27 | 28 | ### _Publication citations_ 29 | Ron Kohavi, "Scaling Up the Accuracy of Naive-Bayes Classifiers: a Decision-Tree Hybrid", Proceedings of the Second International Conference on Knowledge Discovery and Data Mining, 1996 30 | 31 | 'Simoudis, Evangelos, Jiawei Han, and Usama Fayyad. Proceedings of the second international conference on knowledge discovery & data mining. No. CONF-960830-. AAAI Press, Menlo Park, CA (United States), 1996. 32 | 33 | Friedler, Sorelle A., et al. "A Comparative Study of Fairness-Enhancing Interventions in Machine Learning." Proceedings of the Conference on Fairness, Accountability, and Transparency, 2019, https://doi.org/10.1145/3287560.3287589. 34 | 35 | Lahoti, Preethi, et al. "Fairness without demographics through adversarially reweighted learning." Advances in neural information processing systems 33 (2020): 728-740. 36 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/multiclass_classification/README.md: -------------------------------------------------------------------------------- 1 | # Creating Model Card for Multiclass Classification of Hate Speech 2 | In this notebook, we will download a model, dataset, and metric from Hugging Face Hub and generate an interactive HTML Model Card using Intel AI Safety Model Card Generator Tool. 3 | 4 | `multiclass-classification-model-card.ipynb` performs the following steps: 5 | 1. Download and Import Dependencies 6 | 2. Download the Dataset from Hugging Face Datasets 7 | 3. Transform the Dataset 8 | - Get ground truth labels 9 | 5. Download the Model and Process the Model Outputs 10 | 6. Load the Bias Metric form Hugging Face 11 | 7. Run the Bias Metric for each class label 12 | 8. Transform the Output for the Model Card for each class label 13 | 9. Build the Model Card 14 | 15 | 16 | ## Running the notebook 17 | 18 | To run the `multiclass-classification-model-card.ipynb`, install the following dependencies: 19 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 20 | 2. `!pip install evaluate datasets transformers[torch] scikit-learn` 21 | 22 | ## References 23 | ### _Dataset citations_ 24 | ``` 25 | @article{mathew2020hatexplain, 26 | title={HateXplain: A Benchmark Dataset for Explainable Hate Speech Detection}, 27 | author={Mathew, Binny and Saha, Punyajoy and Yimam, Seid Muhie and Biemann, Chris and Goyal, Pawan and Mukherjee, Animesh}, 28 | journal={arXiv preprint arXiv:2012.10289}, 29 | year={2020} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/multimodal_classification_model_card/README.md: -------------------------------------------------------------------------------- 1 | # Generating Model Card for Multimodal Classification 2 | This notebook demonstrates generating a model card for multimodal vision and text classification task using PyTorch and [Roberta](https://arxiv.org/abs/1907.11692) models. The model is trained on a [Hateful Memes Challenge dataset](https://huggingface.co/datasets/neuralcatcher/hateful_memes) created by Facebook AI to detect hate speech in multimodal memes. Finally, we use the Intel Model Card Generator for analyzing the performance of our model. 3 | 4 | `multimodal-classification-model-card.ipynb` performs the following steps: 5 | 1. Import the dependencies. 6 | 2. Load the Hateful Meme Challenge dataset from Hugging Face. 7 | 3. Generate text features using the RoBERTa model and pre-process the images. 8 | 4. Build the PyTorch model for both image and text features. 9 | 5. Train and save the PyTorch model. 10 | 6. Evaluate model performance on the test dataset and process the evaluation output for the model card. 11 | 7. Generate Model Card with Intel Model Card Generator - 12 | - Define the model card dictionary following the model card schema for the Image Classification model. 13 | - Generate Model Card using generate function from the ModelCardGen class. 14 | - Export the generated Model Card to html format. 15 | 16 | 17 | ## Running the notebook 18 | 19 | To run `multimodal-classification-model-card.ipynb`, install the following dependencies: 20 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 21 | 22 | 23 | ## References 24 | ### _Publication citations_ 25 | ``` 26 | @misc{liu2019robertarobustlyoptimizedbert, 27 | title={RoBERTa: A Robustly Optimized BERT Pretraining Approach}, 28 | author={Yinhan Liu and Myle Ott and Naman Goyal and Jingfei Du and Mandar Joshi and Danqi Chen and Omer Levy and Mike Lewis and Luke Zettlemoyer and Veselin Stoyanov}, 29 | year={2019}, 30 | eprint={1907.11692}, 31 | archivePrefix={arXiv}, 32 | primaryClass={cs.CL}, 33 | url={https://arxiv.org/abs/1907.11692}, 34 | } 35 | 36 | @misc{kiela2021hatefulmemeschallengedetecting, 37 | title={The Hateful Memes Challenge: Detecting Hate Speech in Multimodal Memes}, 38 | author={Douwe Kiela and Hamed Firooz and Aravind Mohan and Vedanuj Goswami and Amanpreet Singh and Pratik Ringshia and Davide Testuggine}, 39 | year={2021}, 40 | eprint={2005.04790}, 41 | archivePrefix={arXiv}, 42 | primaryClass={cs.AI}, 43 | url={https://arxiv.org/abs/2005.04790}, 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /notebooks/model_card_gen/toxic_comments_classification/README.md: -------------------------------------------------------------------------------- 1 | # Creating Model Card for Toxic Comments Classification in Tensorflow 2 | This notebook demonstrates how to generate Model Card for a [Tensorflow model](https://colab.research.google.com/github/google/eng-edu/blob/main/ml/pc/exercises/fairness_text_toxicity_part1.ipynb?utm_source=practicum-fairness&utm_campaign=colab-external&utm_medium=referral&utm_content=fairnessexercise1-colab#scrollTo=2z_xzJ40j9Q-) trained to classify toxic comments using the [CivilComments dataset](https://www.tensorflow.org/datasets/catalog/civil_comments) from the Tensorflow data hub. 3 | 4 | `toxicity-tfma-model-card.ipynb` performs the following steps: 5 | 1. Import dependencies 6 | 2. Download and process the CivilComments Dataset from TensorFlow data hub. 7 | - Load the training and validation data. 8 | - Prepare feature map. 9 | - Parse training data and handle data imbalance in the training data. 10 | 3. Build the classification model based on dense feed-forward neural networks using Tensorflow Estimator . 11 | 4. Train the classification model. 12 | 5. Export the trained classification model in EvalSavedModel Format. 13 | 6. Generate Model Card with the help of Intel Model Card Generator 14 | - Load or write the config file. 15 | - Define the model card dictionary following the model card schema. 16 | - Generate Model Card using the generate function from the ModelCardGen class. 17 | 18 | 19 | ## Running the notebook 20 | 21 | To run the `toxicity-tfma-model-card.ipynb`, install the following dependencies: 22 | 1. [Intel® Explainable AI](https://github.com/Intel/intel-xai-tools) 23 | 2. `! pip install tensorflow_hub` 24 | 25 | ## References 26 | ### _Dataset citations_ 27 | ``` 28 | @misc{pavlopoulos2020toxicity, 29 | title={Toxicity Detection: Does Context Really Matter?}, 30 | author={John Pavlopoulos and Jeffrey Sorensen and Lucas Dixon and Nithum Thain and Ion Androutsopoulos}, 31 | year={2020}, eprint={2006.00998}, archivePrefix={arXiv}, primaryClass={cs.CL} 32 | } 33 | 34 | @article{DBLP:journals/corr/abs-1903-04561, 35 | author = {Daniel Borkan and 36 | Lucas Dixon and 37 | Jeffrey Sorensen and 38 | Nithum Thain and 39 | Lucy Vasserman}, 40 | title = {Nuanced Metrics for Measuring Unintended Bias with Real Data for Text 41 | Classification}, 42 | journal = {CoRR}, 43 | volume = {abs/1903.04561}, 44 | year = {2019}, 45 | url = {http://arxiv.org/abs/1903.04561}, 46 | archivePrefix = {arXiv}, 47 | eprint = {1903.04561}, 48 | timestamp = {Sun, 31 Mar 2019 19:01:24 +0200}, 49 | biburl = {https://dblp.org/rec/bib/journals/corr/abs-1903-04561}, 50 | bibsource = {dblp computer science bibliography, https://dblp.org} 51 | } 52 | 53 | @inproceedings{pavlopoulos-etal-2021-semeval, 54 | title = "{S}em{E}val-2021 Task 5: Toxic Spans Detection", 55 | author = "Pavlopoulos, John and Sorensen, Jeffrey and Laugier, L{'e}o and Androutsopoulos, Ion", 56 | booktitle = "Proceedings of the 15th International Workshop on Semantic Evaluation (SemEval-2021)", 57 | month = aug, 58 | year = "2021", 59 | address = "Online", 60 | publisher = "Association for Computational Linguistics", 61 | url = "https://aclanthology.org/2021.semeval-1.6", 62 | doi = "10.18653/v1/2021.semeval-1.6", 63 | pages = "59--69", 64 | } 65 | -------------------------------------------------------------------------------- /notebooks/performance/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | These two notebooks, together, compare the performance of `PartitionExplainer()` when toggling two binary experiment parameters: 3 | 1. Intel® oneDNN flags 4 | 2. AI Tools Environment (AI Tools) 5 | 6 | Thus, these notebooks are able to cover the following four user environments 7 | 8 | | |Intel® oneDNN OFF | Intel® oneDNN ON | 9 | | -- | :--: | :--: | 10 | | __Stock Environment__ | X | X | 11 | | __AI Tools Environment__ | X | X | 12 | 13 | A "stock environment" is one where all of the Python packages installed from either PyPi's or Conda's default channels. The AI Tools environment, on the other hand, installs all Python packages from Conda's Intel channel, if available. Otherwise, all packages that are not available on the Intel Conda channel are then installed via Conda's default channel. 14 | 15 | ## Notebook Descriptions 16 | ### __partition_image_bm.ipynb__ 17 | - executes the `PartitionExplainer()` twice - once with oneDNN flags set to off and a second time with the OneDNN flags set to on 18 | - Scales each experiment by increasing the number of the `max_evals` shap parameter 19 | - compares the performance of the two experiments 20 | - outputs results folders holding pickle files of the raw computation times and csv files holding the aggregated results used for visualization 21 | ### __aitools_vs_stock.ipynb__ 22 | - compares and visualizes two results folders output from the `partition_image_bm.ipynb` notebook 23 | - it is designed such that it expects one of the results folders is from a experiment ran in a stock environment and the other in an AI Tools environment so that the user can compare the two environments 24 | - no `PartitionExplaienr()` execution is actually done. It is only to compare experiments from `partition_image_bm.ipynb` 25 | 26 | # Environments 27 | In order to compare AI Tools and stock environments, two isolated Conda environments must be created. 28 | 29 | ### __Stock Conda environment__ 30 | ```bash 31 | conda create -n stock python=3.10 32 | conda activate stock 33 | pip install intel-xai --no-deps 34 | pip install tensorflow==2.17.1 torch=2.7.0 ipywidgets notebook opencv-python shap 35 | ``` 36 | 37 | ### __AI Tools Conda environment__ 38 | ```bash 39 | conda create -n intel -c intel python=3.10 40 | conda activate intel 41 | conda install -c intel --deps-only shap 42 | conda install --no-deps shap 43 | pip install --no-deps intel-xai 44 | conda install -c intel pytorch=2.7.0 tensorflow=2.17.1 ipywidgets matplotlib notebook opencv 45 | ``` 46 | -------------------------------------------------------------------------------- /plugins/benchmark/classification_metrics/classification_metrics/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | -------------------------------------------------------------------------------- /plugins/benchmark/classification_metrics/classification_metrics/tests/test_benchmark_classification.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | import pytest 21 | from scripts.benchmark_classification_metrics import load_model, read_test_split_jigsaw, read_test_split_tc 22 | 23 | MODEL_PATHS = ["dummy_model_path", "Intel/toxic-prompt-roberta"] 24 | 25 | 26 | @pytest.mark.common 27 | @pytest.mark.parametrize( 28 | ("invalid_model_path", "valid_model_path"), [("dummy_model_path", "Intel/toxic-prompt-roberta")] 29 | ) 30 | def test_model_loading(invalid_model_path, valid_model_path): 31 | """Test Loading of HuggingFace model path""" 32 | 33 | assert load_model(valid_model_path) 34 | with pytest.raises(EnvironmentError) as exception_error: 35 | load_model(invalid_model_path) 36 | assert "Please make sure that a valid model path is provided." in str(exception_error.value) 37 | 38 | 39 | @pytest.mark.common 40 | def test_dataset_loading(): 41 | csv_path = "dummy_path" 42 | with pytest.raises(Exception) as exception_error: 43 | read_test_split_jigsaw(csv_path) 44 | assert ( 45 | "Error loading test dataset for Jigsaw Unintended Bias. Please ensure the CSV file path is correct and the file contains the required columns: 'comment_text' and 'toxicity'." 46 | in str(exception_error.value) 47 | ) 48 | 49 | 50 | @pytest.mark.common 51 | def test_tc_dataset_loading(): 52 | csv_path = "hf://datasets/lmsys/toxic-chat/data/0124/toxic-chat_annotation_test.csv" 53 | assert read_test_split_tc(csv_path) 54 | -------------------------------------------------------------------------------- /plugins/benchmark/classification_metrics/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true -------------------------------------------------------------------------------- /plugins/benchmark/classification_metrics/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-benchmarks-classification" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "classification_metrics", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.10, <3.12" 13 | accelerate = "1.4.0" 14 | evaluate = "0.4.3" 15 | loguru = "0.7.3" 16 | numpy= "1.26.4" 17 | pandas = "2.2.3" 18 | scikit-learn = "1.6.1" 19 | torchmetrics = "*" 20 | torch = {version = "2.7.0", source = "pytorch-cpu"} 21 | transformers = "4.50.0" 22 | 23 | [tool.poetry.group.test] 24 | optional = true 25 | 26 | [tool.poetry.group.test.dependencies] 27 | pytest = '*' 28 | pytest-cov = '*' 29 | 30 | [[tool.poetry.source]] 31 | name = "pytorch-cpu" 32 | url = "https://download.pytorch.org/whl/cpu" 33 | priority = "explicit" 34 | 35 | [build-system] 36 | requires = ["poetry-core"] 37 | build-backend = "poetry.core.masonry.api" 38 | 39 | [[tool.poetry_bumpversion.replacements]] 40 | files = ["version.py"] 41 | search = '__version__ = "{current_version}"' 42 | replace = '__version__ = "{new_version}"' 43 | -------------------------------------------------------------------------------- /plugins/benchmark/classification_metrics/requirements.txt: -------------------------------------------------------------------------------- 1 | evaluate 2 | datasets 3 | loguru 4 | pandas 5 | scikit-learn 6 | torch 7 | torchmetrics 8 | transformers 9 | -------------------------------------------------------------------------------- /plugins/benchmark/classification_metrics/version.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Intel Corporation 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | # 18 | 19 | __version__ = "1.3.0" 20 | -------------------------------------------------------------------------------- /plugins/explainers/attributions-hugging-face/README.md: -------------------------------------------------------------------------------- 1 | ### Attributions 2 | 3 | | Method | Decription | 4 | |---------------------|---------------------------------------------------------------------------------------------| 5 | | llm_explainer | Explain output of text generation and classification HF Transformer LLMs using SHAP         | 6 | -------------------------------------------------------------------------------- /plugins/explainers/attributions-hugging-face/intel_ai_safety/explainer/attributions/hf_attributions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import shap 22 | from typing import List 23 | from intel_ai_safety.explainer.context.agnostic.attributions_explainer import AttributionsExplainer 24 | 25 | 26 | class LLMExplainer(AttributionsExplainer): 27 | """ 28 | Approximate an extension of shap values, known as Owen values, for generative and classification LLMs from 29 | Hugging Face. 30 | 31 | Args: 32 | model (HF Automodel or pipeline): model to be interpreted. If no tokenizer is supplied than model is assumed to be 33 | a pipeline 34 | tokenizer (HF Tokenizer): Toke 35 | 36 | reference: 37 | https://shap.readthedocs.io/en/stable/generated/shap.PartitionExplainer.html 38 | """ 39 | 40 | def __init__(self, model, tokenizer=None) -> None: 41 | 42 | super().__init__(self) 43 | self.shap_values = None 44 | self.explainer = shap.Explainer(model, tokenizer) 45 | 46 | def run_explainer(self, target_text: str, max_evals: int = 64) -> None: 47 | """ 48 | Execute the partition explanation on the target_text. 49 | 50 | Args: 51 | target_text (numpy.ndarray): 1-d numpy array of strings holding the text examples 52 | max_evals (int): number of evaluations used in the shap estimation. The higher the number result 53 | in a better the estimation. Defaults to 64. 54 | 55 | Returns: 56 | None 57 | """ 58 | self.shap_values = self.explainer(target_text, max_evals=max_evals) 59 | 60 | def visualize(self): 61 | """ 62 | Display the force plot of the of the target example(s) 63 | """ 64 | shap.text_plot(self.shap_values) 65 | 66 | 67 | def llm_explainer(model, target_text, tokenizer=None, max_evals=64): 68 | """ 69 | Instantiates LLMExplainer for text classification (currently with Pipeline class only) 70 | or generation (Pipeline and Auto classes) explanation and executes run_explainer() 71 | 72 | Args: 73 | model (function): the model 74 | target_text (numpy.ndarray): 1-d numpy array of strings holding the text examples 75 | tokenizer (string or callable): tokenizer associated with model 76 | max_evals (int): 77 | 78 | Reference: 79 | https://shap.readthedocs.io/en/stable/generated/shap.PartitionExplainer.html 80 | 81 | Returns: 82 | LLMExplainer 83 | """ 84 | llme = LLMExplainer(model, tokenizer) 85 | llme.run_explainer(target_text, max_evals=max_evals) 86 | return llme 87 | -------------------------------------------------------------------------------- /plugins/explainers/attributions-hugging-face/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /plugins/explainers/attributions-hugging-face/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer-attributions-hugging-face" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | intel-ai-safety-explainer = {version = "*"} 13 | python = ">=3.10, <3.12" 14 | shap = "0.47.0" 15 | 16 | [tool.poetry.group.local.dependencies] 17 | intel-ai-safety-explainer = {path = "../../../explainer"} 18 | intel-ai-safety = {path = "../../.."} 19 | 20 | [tool.poetry.group.test] 21 | optional = true 22 | 23 | [tool.poetry.group.test.dependencies] 24 | matplotlib = "*" 25 | pytest = "8.3.5" 26 | pytest-cov = "6.0.0" 27 | sentencepiece = "0.2.0" 28 | torch = {version = "2.7.0", source = "pytorch-cpu"} 29 | transformers = "4.50.0" 30 | 31 | [[tool.poetry.source]] 32 | name = "PyPI" 33 | priority = "primary" 34 | 35 | [[tool.poetry.source]] 36 | name = "pytorch-cpu" 37 | url = "https://download.pytorch.org/whl/cpu" 38 | priority = "explicit" 39 | 40 | [build-system] 41 | requires = ["poetry"] 42 | build-backend = "poetry.core.masonry.api" 43 | -------------------------------------------------------------------------------- /plugins/explainers/attributions-hugging-face/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import torch 3 | from transformers import AutoModelForCausalLM, AutoModelForSeq2SeqLM, AutoTokenizer, pipeline 4 | 5 | # tests adapted from https://shap.readthedocs.io/en/latest/text_examples.html 6 | 7 | 8 | @pytest.fixture(scope="session") 9 | def causal_lm(): 10 | """ 11 | Loads GPT2 from HF using AutoModelForCausalLM and returns model, 12 | tokenizer and example text. 13 | """ 14 | gen_tokenizer = AutoTokenizer.from_pretrained("gpt2", use_fast=True) 15 | gen_model = AutoModelForCausalLM.from_pretrained("gpt2") 16 | # set model decoder to true 17 | gen_model.config.is_decoder = True 18 | # set text-generation params under task_specific_params 19 | gen_model.config.task_specific_params["text-generation"] = { 20 | "do_sample": True, 21 | "max_length": 50, 22 | "max_new_tokens": 50, 23 | "temperature": 0.7, 24 | "top_k": 50, 25 | "no_repeat_ngram_size": 2, 26 | } 27 | # example prompt from allenai/real-toxicity-prompts 28 | gen_text = [ 29 | "Corruption involving the contractors is the chief \ 30 | culprit for the prison’s problems, according to a recent" 31 | ] 32 | 33 | return gen_model, gen_tokenizer, gen_text 34 | 35 | 36 | @pytest.fixture(scope="session") 37 | def seq2seq_lm(): 38 | """ 39 | Loads Helsinki-NLP/opus-mt-en-es from HF using AutoModelForSeq2SeqLM and returns model, 40 | tokenizer and example text. 41 | """ 42 | return ( 43 | AutoModelForSeq2SeqLM.from_pretrained("Helsinki-NLP/opus-mt-en-es"), 44 | AutoTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-es"), 45 | ["Pancha irons with four irons. With how many irons does Pancha iron?"], 46 | ) 47 | 48 | 49 | @pytest.fixture(scope="session") 50 | def classification_pipeline(): 51 | """ 52 | Loads nateraw/bert-base-uncased-emotion from HF using AutoModelForSeq2SeqLM 53 | and returns pipeline and example text. 54 | """ 55 | return ( 56 | pipeline("text-classification", model="nateraw/bert-base-uncased-emotion"), 57 | [ 58 | "She loved me sometimes, and I loved her too. \ 59 | How could one not have loved her great still eyes." 60 | ], 61 | ) 62 | -------------------------------------------------------------------------------- /plugins/explainers/attributions-hugging-face/tests/test_hf_attributions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2024 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ### libraries to support tests ### 22 | import pytest 23 | 24 | ### library to be tested ### 25 | from intel_ai_safety.explainer.attributions import hf_attributions as attributions 26 | 27 | 28 | @pytest.mark.parametrize("auto_model", ["causal_lm", "seq2seq_lm"]) 29 | def test_llm_explainer_auto_model(auto_model, request): 30 | """ 31 | Test LLMExplainer works with AutoModelForCausalLM and AutoModelForSeq2SeqLM 32 | """ 33 | model, tokenizer, text = request.getfixturevalue(auto_model) 34 | llme = attributions.LLMExplainer(model, tokenizer) 35 | llme.run_explainer(text) 36 | assert isinstance(llme, attributions.LLMExplainer) 37 | llme.visualize() 38 | 39 | 40 | def test_llm_explainer_pipeline(classification_pipeline): 41 | """ 42 | Test LLMExplainer works with classification pipeline 43 | """ 44 | classifier_pl, text = classification_pipeline 45 | llme = attributions.LLMExplainer(classifier_pl) 46 | llme.run_explainer(text) 47 | assert isinstance(llme, attributions.LLMExplainer) 48 | llme.visualize() 49 | -------------------------------------------------------------------------------- /plugins/explainers/attributions/README.md: -------------------------------------------------------------------------------- 1 | ### Attributions 2 | 3 | | Method | Decription | 4 | |---------------------|---------------------------------------------------------------------------------------------| 5 | | explainer | Return native Shap references as attributes                                                 | 6 | | kernel_explainer    | Explain predictions using SHAP's kernel method                                              | 7 | | deep_explainer      | Explain predictions using SHAP's deep method                                                | 8 | | gradient_explainer  | Explain predictions using SHAP's gradient method                                            | 9 | | partition_explainer | Explain predictions using SHAP's partition method                                           | 10 | -------------------------------------------------------------------------------- /plugins/explainers/attributions/intel_ai_safety/explainer/attributions/README.md: -------------------------------------------------------------------------------- 1 | # Feature Attributions 2 | 3 | ```python3 4 | from intel_ai_safety.explainer import attributions 5 | ``` 6 | 7 | Feature Attributions are an approach to explaining a model's predictions based on how the model has weighted the features it's been trained on. 8 | This set of functions visualizes features by utilizing [SHAP](https://github.com/slundberg/shap) (SHapley Additive exPlanations): an approach to explain the output of ML/DL models. 9 | 10 | ## Algorithm 11 | 12 | Determining feature importance within a model is done by utilizing the SHAP package. 13 | Shap accepts black box models and provides explanations through a game theoretic approach. 14 | 15 | ## Environment 16 | - Jupyter Notebooks 17 | 18 | ## XAI Methods 19 | - Shap Explainers 20 | - Deep Explainer 21 | - Gradient Explainer 22 | - Kernel Explainer 23 | - Partition Explainer 24 | - Zero Shot Explainer 25 | - Sentiment Analysis 26 | - Captum 27 | - Integrated Gradients 28 | - Deep Lift 29 | - Saliency 30 | - Smooth Grad via Noise Tunnel 31 | - Feature Ablation 32 | 33 | ## Toolkits 34 | - Shap 35 | - Captum 36 | 37 | ## References 38 | [SHAP](https://github.com/slundberg/shap)\ 39 | [Captum](https://github.com/pytorch/captum) 40 | -------------------------------------------------------------------------------- /plugins/explainers/attributions/intel_ai_safety/explainer/attributions/attributions_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2023 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | force_plot_info_panel = { 22 | "Plot Description": "This graph shows the attributed impact each feature" 23 | "value has on a model's prediction. This impact is measured by " 24 | "each feature value's estimated Shapely value. Each plot represents an" 25 | " individual prediction.", 26 | "Metric Description": "Shapley values is a concept borrowed from coalitional game theory. " 27 | "In its original application, this value can tell us how much " 28 | "payoff each player can reasonably expect given their contribution " 29 | "to the coalition. Applied to machine learning, each feature value " 30 | "for an instance is a player in a game and the prediction is the " 31 | "payout. Thus, the Shapley value for a prediction measures the " 32 | "relative the contribution each feature value had to the prediction.", 33 | "Plot Colors": "Red represents a positive impact. Blue represents a negative impact.", 34 | "Horizontal Axis": "Estimated Shapley value (impact on model prediction)", 35 | "Vertical Axis": "Feature and feature values for single prediction", 36 | "Expected Results": "The highest absolute Shapley value contributes the most to the " "model's prediction.", 37 | } 38 | 39 | shap_widget_info_panel = { 40 | "Error Analysis": "Allows the user to filter data points based on their error type.", 41 | "Impact Analysis": "Allows users to filter data points based on their associated SHAP " 42 | "impact score for top important features", 43 | "Feature Analysis": "Allows users to filter data points feature values.", 44 | "Base Value": "Refers to the expected or average SHAP value of the" "explaination model.", 45 | "Predicted Value": "Refers the estimated output score of the model calculated" 46 | "by base value plus the sum of SHAP values across all features.", 47 | } 48 | shap_widget_info_panel.update(force_plot_info_panel) 49 | -------------------------------------------------------------------------------- /plugins/explainers/attributions/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /plugins/explainers/attributions/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer-attributions" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | intel-ai-safety-explainer = {version = "*"} 13 | python = ">=3.10, <3.12" 14 | ipywidgets = "8.1.5" 15 | matplotlib = "3.10.1" 16 | numpy = "1.26.4" 17 | opencv-python = "4.11.0.86" 18 | plotly = "6.0.0" 19 | shap = "0.47.0" 20 | transformers = "4.50.0" 21 | 22 | [tool.poetry.group.local.dependencies] 23 | intel-ai-safety-explainer = {path = "../../../explainer"} 24 | intel-ai-safety = {path = "../../.."} 25 | 26 | [tool.poetry.group.test] 27 | optional = true 28 | 29 | [tool.poetry.group.test.dependencies] 30 | pytest = "8.3.5" 31 | pytest-cov = "6.0.0" 32 | tensorflow-cpu = "2.17.1" 33 | torch = {version = "2.7.0", source = "pytorch-cpu"} 34 | torchvision = {version = "0.22.0", source = "pytorch-cpu"} 35 | 36 | [[tool.poetry.source]] 37 | name = "PyPI" 38 | priority = "primary" 39 | 40 | [[tool.poetry.source]] 41 | name = "pytorch-cpu" 42 | url = "https://download.pytorch.org/whl/cpu" 43 | priority = "explicit" 44 | 45 | [build-system] 46 | requires = ["poetry"] 47 | build-backend = "poetry.core.masonry.api" 48 | -------------------------------------------------------------------------------- /plugins/explainers/cam-pytorch/README.md: -------------------------------------------------------------------------------- 1 | ### CAM (Class Activation Mapping) 2 | 3 | | Method | Decription | 4 | |------------|------------------------------------------------------------------------------------------------------------| 5 | | xgradcam | Explain predictions with axiom-based gradient-based class activation maps using pytorch-grad-cam methods | 6 | | eigancam  | Explain predictions with eigan-based class activation maps using pytorch-grad-cam methods   | 7 | -------------------------------------------------------------------------------- /plugins/explainers/cam-pytorch/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /plugins/explainers/cam-pytorch/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer-cam-pytorch" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.10, <3.12" 13 | intel-ai-safety-explainer = {version = "*"} 14 | grad-cam = "1.5.4" 15 | numpy = "1.26.4" 16 | opencv-python = "4.11.0.86" 17 | torch = {version = "2.7.0", source = "pytorch-cpu"} 18 | 19 | [tool.poetry.group.local.dependencies] 20 | intel-ai-safety-explainer = {path = "../../../explainer"} 21 | intel-ai-safety = {path = "../../.."} 22 | 23 | [tool.poetry.group.test] 24 | optional = true 25 | 26 | [tool.poetry.group.test.dependencies] 27 | pytest = "8.3.5" 28 | pytest-cov = "6.0.0" 29 | torchvision = {version = "0.22.0", source = "pytorch-cpu"} 30 | 31 | [[tool.poetry.source]] 32 | name = "pytorch-cpu" 33 | url = "https://download.pytorch.org/whl/cpu" 34 | priority = "explicit" 35 | 36 | [build-system] 37 | requires = ["poetry"] 38 | build-backend = "poetry.core.masonry.api" 39 | -------------------------------------------------------------------------------- /plugins/explainers/cam-pytorch/tests/test_cam.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2023 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | ### libraries to support tests ### 21 | import pytest 22 | import torch 23 | import torchvision 24 | 25 | torch.manual_seed(0) 26 | import numpy as np 27 | 28 | ### library to be tested ### 29 | from intel_ai_safety.explainer.cam import pt_cam as cam 30 | 31 | ################################### 32 | 33 | device = torch.device("cpu") 34 | 35 | 36 | # Non-test, helper functions definitions 37 | def process_output_fasterrcnn(output, class_labels, color, detection_threshold): 38 | boxes, classes, labels, colors = [], [], [], [] 39 | box = output["boxes"].tolist() 40 | name = [class_labels[i] for i in output["labels"].detach().numpy()] 41 | label = output["labels"].detach().numpy() 42 | 43 | for i in range(len(name)): 44 | score = output["scores"].detach().numpy()[i] 45 | if score < detection_threshold: 46 | continue 47 | boxes.append([int(b) for b in box[i]]) 48 | classes.append(name[i]) 49 | colors.append(color[label[i]]) 50 | 51 | return boxes, classes, colors 52 | 53 | 54 | # Test function definitions 55 | def test_x_gradcam(custom_pyt_CNN): 56 | model, X_test, class_names, y_test = custom_pyt_CNN 57 | image = torch.movedim(X_test[0], 0, 2).numpy() 58 | target_layer = model.conv_layers 59 | # use the highest-scoring category as the target class 60 | target_class = None 61 | image_dims = (28, 28) 62 | gcam = cam.x_gradcam(model, target_layer, target_class, image, image_dims) 63 | assert isinstance(gcam, cam.XGradCAM) 64 | gcam.visualize() 65 | 66 | 67 | def test_gradcam_pytorch(custom_pyt_CNN): 68 | model, X_test, class_names, y_test = custom_pyt_CNN 69 | image = torch.movedim(X_test[0], 0, 2).numpy() 70 | target_layer = model.conv_layers 71 | # use the highest-scoring category as the target class 72 | target_class = None 73 | image_dims = (28, 28) 74 | gcam = cam.GradCAM(model, target_layer, image_dims) 75 | gcam.run_explainer(image, target_class) 76 | assert isinstance(gcam, cam.XGradCAM) 77 | gcam.visualize() 78 | 79 | 80 | def test_eigencam(fasterRCNN, dog_cat_image): 81 | model, class_labels, color, transform_function = fasterRCNN 82 | target_layer = model.backbone 83 | 84 | # transform image to fit format of fasterRCNN 85 | rgb_img = np.float32(dog_cat_image) / 255 86 | transform = torchvision.transforms.ToTensor() 87 | input_tensor = transform(rgb_img) 88 | input_tensor = input_tensor.unsqueeze(0) 89 | output = model(input_tensor)[0] 90 | 91 | # set the detection threshold 92 | detection_threshold = 0.9 93 | 94 | # get the box coordinates, classes and colors for the detections 95 | boxes, classes, colors = process_output_fasterrcnn(output, class_labels, color, detection_threshold) 96 | 97 | ec = cam.eigencam(model, target_layer, boxes, classes, colors, transform_function, dog_cat_image, "cpu") 98 | assert isinstance(ec, cam.EigenCAM) 99 | ec.visualize() 100 | -------------------------------------------------------------------------------- /plugins/explainers/cam-tensorflow/README.md: -------------------------------------------------------------------------------- 1 | # CAM (Class Activation Mapping) 2 | 3 | | Method | Decription | 4 | |------------|------------------------------------------------------------------------------------------------------------| 5 | | tf_gradcam | Explain predictions with gradient-based class activation maps with the TensorFlow| 6 | 7 | 8 | CAM is an approach which localizes regions in the image responsible for a class prediction. 9 | Here, for object classification model, we support visualization of GradCAM, which is the state-of-the art CAM method. 10 | 11 | ## Algorithm 12 | CAM takes the input image and the trained model as input, and generates visualization by highlighting 13 | the region in the corresponding image that are responsible for the classification decision. 14 | 15 | ## Environment 16 | - Jupyter Notebooks 17 | 18 | 19 | ## References 20 | [TF GradCAM Implementation](https://github.com/ismailuddin/gradcam-tensorflow-2/blob/master/notebooks/GradCam.ipynb)
    21 | [Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization](https://arxiv.org/abs/1610.02391) 22 | -------------------------------------------------------------------------------- /plugins/explainers/cam-tensorflow/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /plugins/explainers/cam-tensorflow/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer-cam-tensorflow" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.10, <3.12" 13 | intel-ai-safety-explainer = {version = "*"} 14 | numpy = "1.26.4" 15 | opencv-python = "4.11.0.86" 16 | tensorflow-cpu = "2.17.1" 17 | 18 | [tool.poetry.group.local.dependencies] 19 | intel-ai-safety-explainer = {path = "../../../explainer"} 20 | intel-ai-safety = {path = "../../.."} 21 | 22 | [tool.poetry.group.test] 23 | optional = true 24 | 25 | [tool.poetry.group.test.dependencies] 26 | matplotlib = "3.10.1" 27 | pillow = "11.1.0" 28 | pytest = "8.3.5" 29 | pytest-cov = "6.0.0" 30 | tensorflow-cpu = "2.17.1" 31 | 32 | [[tool.poetry.source]] 33 | name = "pytorch-cpu" 34 | url = "https://download.pytorch.org/whl/cpu" 35 | priority = "explicit" 36 | 37 | [build-system] 38 | requires = ["poetry"] 39 | build-backend = "poetry.core.masonry.api" 40 | -------------------------------------------------------------------------------- /plugins/explainers/cam-tensorflow/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | 4 | 5 | @pytest.fixture(scope="session") 6 | def custom_tf_CNN(): 7 | """ 8 | Creates and trains a simple TF CNN on the mnist dataset. 9 | Returns the model, a subset of the test dataset and the class names. 10 | 11 | Taken from https://shap.readthedocs.io/en/stable/example_notebooks/image_examples/image_classification/Front%20Page%20DeepExplainer%20MNIST%20Example.html # noqa 12 | """ 13 | import tensorflow as tf 14 | from tensorflow.keras.datasets import mnist 15 | from tensorflow.keras.models import Sequential 16 | from tensorflow.keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D 17 | from tensorflow.keras import backend as K 18 | 19 | batch_size = 128 20 | num_classes = 10 21 | epochs = 3 22 | 23 | # input image dimensions 24 | img_rows, img_cols = 28, 28 25 | 26 | # the data, split between train and test sets 27 | (X_train, y_train), (X_test, y_test) = mnist.load_data() 28 | 29 | if K.image_data_format() == "channels_first": 30 | X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols) 31 | X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols) 32 | input_shape = (1, img_rows, img_cols) 33 | else: 34 | X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1) 35 | X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1) 36 | input_shape = (img_rows, img_cols, 1) 37 | 38 | X_train = X_train.astype("float32")[:500] 39 | X_test = X_test.astype("float32")[:100] 40 | X_train /= 255 41 | X_test /= 255 42 | y_train = y_train[:500] 43 | y_test = y_test[:100] 44 | print("x_train shape:", X_train.shape) 45 | print(X_train.shape[0], "train samples") 46 | print(X_test.shape[0], "test samples") 47 | 48 | # convert class vectors to binary class matrices 49 | y_train = tf.keras.utils.to_categorical(y_train, num_classes) 50 | y_test = tf.keras.utils.to_categorical(y_test, num_classes) 51 | 52 | model = Sequential() 53 | model.add(Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=input_shape)) 54 | model.add(Conv2D(64, (3, 3), activation="relu")) 55 | model.add(MaxPooling2D(pool_size=(2, 2))) 56 | model.add(Dropout(0.25)) 57 | model.add(Flatten()) 58 | model.add(Dense(128, activation="relu")) 59 | model.add(Dropout(0.5)) 60 | model.add(Dense(num_classes, activation="softmax")) 61 | 62 | model.compile( 63 | loss=tf.keras.losses.categorical_crossentropy, optimizer=tf.keras.optimizers.Adadelta(), metrics=["accuracy"] 64 | ) 65 | 66 | model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, y_test)) 67 | 68 | return model, X_test[:10], [str(i) for i in range(10)], y_test[:10] 69 | 70 | 71 | @pytest.fixture(scope="session") 72 | def dog_cat_image(): 73 | """Loads the cat-dog image exampe from imagenet.""" 74 | from PIL import Image 75 | import requests 76 | from io import BytesIO 77 | 78 | response = requests.get("https://raw.githubusercontent.com/jacobgil/pytorch-grad-cam/master/examples/both.png") 79 | return np.array(Image.open(BytesIO(response.content))) 80 | 81 | 82 | @pytest.fixture(scope="session") 83 | def tf_VGG(): 84 | """Loads the keras.applications VGG16 pretrained on imagenet""" 85 | from tensorflow.keras.applications import VGG16 86 | 87 | return VGG16(weights="imagenet") 88 | 89 | 90 | @pytest.fixture(scope="session") 91 | def tf_resnet50(): 92 | """Loads the keras.applications ResNet50 pretrained on imagenet""" 93 | from tensorflow.keras.applications.resnet50 import ResNet50 94 | 95 | return ResNet50(weights="imagenet") 96 | -------------------------------------------------------------------------------- /plugins/explainers/cam-tensorflow/tests/test_cam.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2023 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | ### libraries to support tests ### 21 | import pytest 22 | import numpy as np 23 | 24 | ### library to be tested ### 25 | from intel_ai_safety.explainer.cam import tf_cam as cam 26 | 27 | ################################### 28 | 29 | 30 | # Non-test, helper functions definitions 31 | def process_output_fasterrcnn(output, class_labels, color, detection_threshold): 32 | boxes, classes, labels, colors = [], [], [], [] 33 | box = output["boxes"].tolist() 34 | name = [class_labels[i] for i in output["labels"].detach().numpy()] 35 | label = output["labels"].detach().numpy() 36 | 37 | for i in range(len(name)): 38 | score = output["scores"].detach().numpy()[i] 39 | if score < detection_threshold: 40 | continue 41 | boxes.append([int(b) for b in box[i]]) 42 | classes.append(name[i]) 43 | colors.append(color[label[i]]) 44 | 45 | return boxes, classes, colors 46 | 47 | 48 | def test_tf_gradcam_vgg(tf_VGG, dog_cat_image): 49 | target_class = 281 50 | target_layer = tf_VGG.get_layer("block5_conv3") 51 | gcam = cam.tf_gradcam(tf_VGG, target_layer, target_class, dog_cat_image) 52 | assert isinstance(gcam, cam.TFGradCAM) 53 | gcam.visualize() 54 | 55 | 56 | def test_tf_gradcam_resnet50(tf_resnet50, dog_cat_image): 57 | target_class = 281 58 | target_layer = tf_resnet50.get_layer("conv5_block3_out") 59 | gcam = cam.tf_gradcam(tf_resnet50, target_layer, target_class, dog_cat_image) 60 | assert isinstance(gcam, cam.TFGradCAM) 61 | gcam.visualize() 62 | 63 | 64 | def test_gradcam_tf_resnet50(tf_resnet50, dog_cat_image): 65 | target_class = 281 66 | target_layer = tf_resnet50.get_layer("conv5_block3_out") 67 | gcam = cam.GradCAM(tf_resnet50, target_layer) 68 | gcam.run_explainer(dog_cat_image, target_class) 69 | assert isinstance(gcam, cam.TFGradCAM) 70 | gcam.visualize() 71 | -------------------------------------------------------------------------------- /plugins/explainers/captum/README.md: -------------------------------------------------------------------------------- 1 | ### Attributions 2 | 3 | | Method | Decription | 4 | |---------------------|---------------------------------------------------------------------------------------------| 5 | | saliency            | Explain predictions using Captum's saliency method                                          | 6 | | integratedgradients | Explain predictions using Captum's integrated gradients method                              | 7 | | deeplift            | Explain predictions using Captum's deep lift method                                         | 8 | | smoothgrad          | Explain predictions using Captum's noise tunnel smooth gradient method                      | 9 | | featureablation     | Explain predictions using Captum's feature ablation method                                  | 10 | -------------------------------------------------------------------------------- /plugins/explainers/captum/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /plugins/explainers/captum/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer-captum" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.10, <3.12" 13 | captum = "0.7.0" 14 | torch = {version = "2.7.0", source = "pytorch-cpu"} 15 | 16 | [[tool.poetry.source]] 17 | name = "pytorch-cpu" 18 | url = "https://download.pytorch.org/whl/cpu" 19 | priority = "explicit" 20 | 21 | [tool.poetry.group.test] 22 | optional = true 23 | 24 | [tool.poetry.group.test.dependencies] 25 | 26 | [build-system] 27 | requires = ["poetry"] 28 | build-backend = "poetry.core.masonry.api" 29 | -------------------------------------------------------------------------------- /plugins/explainers/metrics/README.md: -------------------------------------------------------------------------------- 1 | # Metrics 2 | 3 | ## Metrics 4 | 5 | | Method | Decription | 6 | |--------|---------------------------------------------------------------------------------------------| 7 | | confusion_matrix | Visualize classifier performance  via  a contingency table visualization         | 8 | | plot | Visualize classifier performance via ROC/PR values over a spread of probability threasholds | 9 | | pstat | Report the execution summary of a given snippet of code using the cProfile run method       | 10 | 11 | 12 | ```python 13 | from intel_ai_safety.explainer import metrics 14 | ``` 15 | 16 | Several base metrics are provided for ML/DL classification models. These metrics cover model execution and performance and orient the data scientist to where there is potential for classification bias. 17 | 18 | ## Algorithms 19 | Provided with a classfication model's predictions and their corresponding ground truths, staple performance metrics can be calculated to determine prediction behaviors in the real world. These functions leverage scikit-learn and plotly (eventually) to calculate and visualize said metrics, respectively. 20 | 21 | ## Environment 22 | - Jupyter Notebooks 23 | 24 | ## Metrics 25 | - Performance metrics 26 | - Confusion Matrix 27 | - Performance Plots 28 | - Execution metrics 29 | - Python profiler 30 | 31 | ## Toolkits 32 | - Scikit-learn 33 | - Plotly 34 | - Python Profilers 35 | 36 | ## References 37 | 38 | [Scikit-learn](https://github.com/scikit-learn/scikit-learn)\ 39 | [Plotly](https://github.com/plotly)\ 40 | [Python Profiler](https://github.com/python/cpython/blob/main/Lib/cProfile.py) 41 | -------------------------------------------------------------------------------- /plugins/explainers/metrics/intel_ai_safety/explainer/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from .metrics import * 22 | -------------------------------------------------------------------------------- /plugins/explainers/metrics/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /plugins/explainers/metrics/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "intel-ai-safety-explainer-metrics" 3 | version = "1.3.0" 4 | description = "" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [ 8 | {include = "intel_ai_safety", from="."}, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.10, <3.12" 13 | intel-ai-safety-explainer = {version = "*"} 14 | matplotlib = "3.10.1" 15 | numpy = "1.26.4" 16 | pandas = "2.2.3" 17 | plotly = "6.0.0" 18 | scikit-learn = "1.6.1" 19 | scikit-plot = "0.3.7" 20 | scipy = "1.15.2" 21 | seaborn = "0.13.2" 22 | 23 | [tool.poetry.group.local.dependencies] 24 | intel-ai-safety-explainer = {path = "../../../explainer"} 25 | intel-ai-safety = {path = "../../.."} 26 | 27 | [tool.poetry.group.test] 28 | optional = true 29 | 30 | [tool.poetry.group.test.dependencies] 31 | deepdiff = "8.3.0" 32 | pytest = "8.3.5" 33 | pytest-cov = "6.0.0" 34 | torch = {version = "2.7.0", source = "pytorch-cpu"} 35 | torchvision = {version = "0.22.0", source = "pytorch-cpu"} 36 | 37 | [[tool.poetry.source]] 38 | name = "pytorch-cpu" 39 | url = "https://download.pytorch.org/whl/cpu" 40 | priority = "explicit" 41 | 42 | [build-system] 43 | requires = ["poetry"] 44 | build-backend = "poetry.core.masonry.api" 45 | -------------------------------------------------------------------------------- /plugins/explainers/metrics/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | import torch 4 | from torchvision import datasets, transforms 5 | from torch import nn, optim 6 | from torch.nn import functional as F 7 | 8 | torch.manual_seed(0) 9 | 10 | 11 | @pytest.fixture(scope="session") 12 | def custom_pyt_CNN(): 13 | """ 14 | Creates and trains a simple PyTorch CNN on the mnist dataset. 15 | Returns the model, the test dataset loader and the class names. 16 | 17 | """ 18 | batch_size = 128 19 | num_epochs = 1 20 | device = torch.device("cpu") 21 | 22 | class Net(nn.Module): 23 | def __init__(self): 24 | super(Net, self).__init__() 25 | 26 | self.conv_layers = nn.Sequential( 27 | nn.Conv2d(1, 10, kernel_size=5), 28 | nn.MaxPool2d(2), 29 | nn.ReLU(), 30 | nn.Conv2d(10, 20, kernel_size=5), 31 | nn.Dropout(), 32 | nn.MaxPool2d(2), 33 | nn.ReLU(), 34 | ) 35 | self.fc_layers = nn.Sequential( 36 | nn.Linear(320, 50), nn.ReLU(), nn.Dropout(), nn.Linear(50, 10), nn.Softmax(dim=1) 37 | ) 38 | 39 | def forward(self, x): 40 | x = self.conv_layers(x) 41 | x = x.view(-1, 320) 42 | x = self.fc_layers(x) 43 | return x 44 | 45 | def train(model, device, train_loader, optimizer, epoch): 46 | model.train() 47 | for batch_idx, (data, target) in enumerate(train_loader): 48 | data, target = data.to(device), target.to(device) 49 | optimizer.zero_grad() 50 | output = model(data) 51 | loss = F.nll_loss(output.log(), target) 52 | loss.backward() 53 | optimizer.step() 54 | if batch_idx % 100 == 0: 55 | print( 56 | "Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format( 57 | epoch, 58 | batch_idx * len(data), 59 | len(train_loader.dataset), 60 | 100.0 * batch_idx / len(train_loader), 61 | loss.item(), 62 | ) 63 | ) 64 | 65 | train_loader = torch.utils.data.DataLoader( 66 | datasets.MNIST("mnist_data", train=True, download=True, transform=transforms.Compose([transforms.ToTensor()])), 67 | batch_size=batch_size, 68 | shuffle=True, 69 | ) 70 | 71 | test_loader = torch.utils.data.DataLoader( 72 | datasets.MNIST("mnist_data", train=False, transform=transforms.Compose([transforms.ToTensor()])), 73 | batch_size=batch_size, 74 | shuffle=True, 75 | ) 76 | 77 | model = Net().to(device) 78 | optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5) 79 | 80 | for epoch in range(1, num_epochs + 1): 81 | train(model, device, train_loader, optimizer, epoch) 82 | 83 | class_names = np.array(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) 84 | y_true = next(iter(test_loader))[1].to(device) 85 | X_test = next(iter(test_loader))[0].to(device) 86 | 87 | return model, X_test, class_names, y_true 88 | -------------------------------------------------------------------------------- /plugins/explainers/metrics/tests/test_metrics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2023 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | ### libraries to support tests ### 21 | from collections import namedtuple 22 | import pytest 23 | from deepdiff import DeepDiff 24 | import numpy as np 25 | import pandas as pd 26 | import torch 27 | 28 | ### library to be tested ### 29 | from intel_ai_safety.explainer import metrics 30 | 31 | ################################### 32 | 33 | # Namedtuple that holds necessary input and outputs to the cm and curve plots. 34 | Data = namedtuple("Data", ["y_true", "oh_y_true", "y_pred", "label_names", "recall", "cm"]) 35 | 36 | 37 | @pytest.fixture(scope="session") 38 | def simple_data(): 39 | """ 40 | A simple 3-class use case with only 5 examples. 41 | 42 | """ 43 | y_true = [2, 0, 1, 0, 1] 44 | oh_y_true = [[0, 0, 1], [1, 0, 0], [0, 1, 0], [1, 0, 0], [0, 1, 0]] 45 | y_pred = [[0.002, 0.09, 0.89], [0.01, 0.7, 0.29], [0.3, 0.67, 0.03], [0.55, 0.4, 0.05], [0.03, 0.86, 0.11]] 46 | label_names = ["cat", "dog", "horse"] 47 | ### correct solutions ### 48 | recall = { 49 | 0: np.array([1.0, 1.0, 0.5, 0.5, 0.5, 0.0]), 50 | 1: np.array([1.0, 1.0, 1.0, 0.5, 0.5, 0.0]), 51 | 2: np.array([1.0, 1.0, 1.0, 1.0, 1.0, 0.0]), 52 | } 53 | cm = pd.DataFrame( 54 | {label_names[0]: [0.5, 0.0, 0.0], label_names[1]: [0.5, 1.0, 0.0], label_names[2]: [0.0, 0.0, 1.0]}, 55 | index=label_names, 56 | ) 57 | 58 | return Data(y_true, oh_y_true, y_pred, label_names, recall, cm) 59 | 60 | 61 | @pytest.mark.simple 62 | def test_plot(simple_data): 63 | data = simple_data 64 | plotter = metrics.plot(data.y_true, data.y_pred, data.label_names) 65 | assert DeepDiff(plotter.recall, data.recall) == {} 66 | 67 | 68 | @pytest.mark.simple 69 | def test_confusion_matrix(simple_data): 70 | data = simple_data 71 | # test without one-hot-encoding 72 | cm = metrics.confusion_matrix(data.y_true, data.y_pred, data.label_names) 73 | assert cm.df.equals(data.cm) 74 | # test with one-hot-encoding 75 | cm = metrics.confusion_matrix(data.oh_y_true, data.y_pred, data.label_names) 76 | assert cm.df.equals(data.cm) 77 | 78 | 79 | def test_confusion_matrix_pyt(custom_pyt_CNN): 80 | model, X_test, class_names, y_true = custom_pyt_CNN 81 | 82 | # test the model 83 | model.eval() 84 | with torch.no_grad(): 85 | output = model(X_test) 86 | cm = metrics.confusion_matrix(y_true, output, class_names) 87 | assert isinstance(cm, metrics.metrics.ConfusionMatrix) 88 | cm.visualize() 89 | -------------------------------------------------------------------------------- /plugins/mlcommons/modelgauge/README.md: -------------------------------------------------------------------------------- 1 | # Modelgauge Neural-Chat Plugin 2 | 3 | ## Get Started 4 | 5 | ### Requirements 6 | * Linux system or WSL2 on Windows (validated on Ubuntu* 22.04/24.04 LTS) 7 | * Python 3.10 8 | * Poetry 9 | 10 | ## Install 11 | 1. Choose a virtual enviornment to use: eg. Using virtualenv: 12 | 13 | ```bash 14 | python3 -m virtualenv mg_env 15 | source mg_env/bin/activate 16 | ``` 17 | 18 | 2. Navigate to `modelgauge/suts`. In `neuralchat_sut.py`, modify the `HUGGING_FACE_REPO_ID` and `UNIQUE_ID` variables. Set `HUGGING_FACE_REPO_ID` to correspond with the repository ID of the model you intend to test. Assign a unique identifier to the `UNIQUE_ID` variable for the SUT: 19 | 20 | ```bash 21 | cd modelgauge/suts 22 | ``` 23 | 24 | 3. Resolve and lock the dependencies: 25 | 26 | ```bash 27 | poetry lock 28 | ``` 29 | 30 | 4. Install dependencies, and register System Under Test (SUTs) and tests: 31 | 32 | ```bash 33 | poetry install 34 | ``` 35 | 36 | ## Run Tests 37 | 1. Verify the registration of the SUT or the specific test you wish to execute: 38 | 39 | ```bash 40 | modelgauge list 41 | ``` 42 | To view a list of only the SUTs or the tests, you can use the corresponding commands. For a comprehensive list of available commands run the following command: 43 | 44 | ```bash 45 | modelgauge 46 | ``` 47 | 48 | 2. Enter your keys into the `secrets.toml` file found in the `config` folder. 49 | 50 | 3. To illustrate, the following command executes the `bbq` test on the `Intel/neural-chat-7b-v3-3` SUT: 51 | 52 | ```shell 53 | modelgauge run-test --sut Intel/neural-chat-7b-v3-3 --test bbq 54 | ``` 55 | The results from the test will be saved in the output directory. 56 | -------------------------------------------------------------------------------- /plugins/mlcommons/modelgauge/config/secrets.toml: -------------------------------------------------------------------------------- 1 | # Edit this file to add your secrets. 2 | 3 | # This is an example of how to define a secret. 4 | # The config is saying that within scope "demo" we have a 5 | # key named "api_key" that we are setting to value "12345". 6 | [demo] 7 | api_key = "12345" 8 | 9 | # Here are some commonly needed keys you can uncomment and use. 10 | # [together] 11 | # api_key = "" 12 | 13 | # [perspective_api] 14 | # api_key = "" 15 | -------------------------------------------------------------------------------- /plugins/mlcommons/modelgauge/modelgauge/suts/neuralchat_sut.py: -------------------------------------------------------------------------------- 1 | from modelgauge.suts.huggingface_client import HuggingFaceSUT, HuggingFaceToken 2 | from modelgauge.secret_values import InjectSecret 3 | from modelgauge.sut_registry import SUTS 4 | 5 | HUGGING_FACE_REPO_ID = "Intel/neural-chat-7b-v3-3" 6 | UNIQUE_ID = "neural-chat-7b-v3-3" 7 | SUTS.register(HuggingFaceSUT, UNIQUE_ID, HUGGING_FACE_REPO_ID, InjectSecret(HuggingFaceToken)) 8 | -------------------------------------------------------------------------------- /plugins/mlcommons/modelgauge/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "modelgauge-neuralchat-plugin" 3 | description = "ModelGauge SUT for running NeuralChat on standard tests." 4 | version = "0.0.1" 5 | authors = ["IntelAI "] 6 | readme = "README.md" 7 | packages = [{include = "modelgauge"}] 8 | 9 | [tool.poetry.dependencies] 10 | python = ">=3.10, <3.11" 11 | torch = "^2.1.2" 12 | transformers = "^4.38.1" 13 | pydantic = "^2.6.0" 14 | pandas-stubs = "^2.2.1.240316" 15 | modelgauge_huggingface = {git = "https://github.com/mlcommons/modelgauge.git", subdirectory = "plugins/huggingface", develop = true} 16 | modelgauge = {git = "https://github.com/mlcommons/modelgauge.git", develop = true} 17 | modelgauge_standard_tests = {git = "https://github.com/mlcommons/modelgauge.git", subdirectory = "plugins/standard_tests", develop = true} 18 | modelgauge_together= {git = "https://github.com/mlcommons/modelgauge.git", subdirectory = "plugins/together", develop = true} 19 | 20 | [build-system] 21 | requires = ["poetry-core"] 22 | build-backend = "poetry.core.masonry.api" 23 | 24 | [tool.mypy] 25 | # Using namespace packages to do plugins requires us not to have __init__.py files. 26 | # However, by default mypy uses those to map file paths to modules. This override fixes that. 27 | # https://mypy.readthedocs.io/en/stable/config_file.html#confval-explicit_package_bases 28 | explicit_package_bases = true 29 | mypy_path = "." 30 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/analyze/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from .pandas_analyzer import DFAnalyzer 22 | from .tf_analyzer import TFAnalyzer 23 | from .torch_analyzer import PTAnalyzer 24 | from .analyzer_factory import get_analyzers, get_analysis 25 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/analyze/analyzer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import pandas as pd 22 | import tensorflow_model_analysis as tfma 23 | from google.protobuf import text_format 24 | from typing import Text, Union, get_args 25 | from intel_ai_safety.model_card_gen.utils.types import DatasetType 26 | 27 | 28 | class ModelAnalyzer: 29 | def __init__(self, eval_config: Union[tfma.EvalConfig, Text] = None, dataset: DatasetType = None): 30 | """Start TFMA analysis 31 | Args: 32 | eval_config (tfma.EvalConfig or str): representing proto file path 33 | Return: 34 | EvalResult 35 | """ 36 | self.eval_config: tfma.EvalConfig = self.check_eval_config(eval_config) 37 | self.dataset: DatasetType = self.check_data(dataset) 38 | 39 | def check_eval_config(self, eval_config) -> tfma.EvalConfig: 40 | """Check that eval_config argument is of type tfma.EvalConfig or str""" 41 | if isinstance(eval_config, tfma.EvalConfig): 42 | return eval_config 43 | elif isinstance(eval_config, str): 44 | return self.parse_eval_config(eval_config) 45 | else: 46 | raise TypeError("ModelAnalyzer requres eval_config argument of type tfma.EvalConfig or str.") 47 | 48 | def check_data(self, dataset): 49 | """Check that data argument is of type pd.DataFrame or DatasetType""" 50 | if not (isinstance(dataset, get_args(DatasetType)) or isinstance(dataset, pd.DataFrame)): 51 | raise TypeError( 52 | "ModelAnalyzer.analyze requires data argument to be of type pd.DataFrame," 53 | "TensorflowDataset or PytorchDataset." 54 | ) 55 | return dataset 56 | 57 | def parse_eval_config(self, eval_config_path): 58 | """Parse proto file from file path to generate Eval config 59 | 60 | Args: 61 | eval_config_path (str): representing proto file path 62 | 63 | Returns: 64 | tfma.EvalConfig() 65 | """ 66 | with open(eval_config_path, "r") as f: 67 | eval_config_str = f.read() 68 | eval_config = text_format.Parse(eval_config_str, tfma.EvalConfig()) 69 | return eval_config 70 | 71 | def get_analysis(self): 72 | """Retrieve eval_results attribute""" 73 | return self.eval_result 74 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/analyze/pandas_analyzer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import pandas as pd 22 | import tensorflow_model_analysis as tfma 23 | from typing import Text, Union 24 | from intel_ai_safety.model_card_gen.utils.types import DatasetType 25 | from intel_ai_safety.model_card_gen.analyze.analyzer import ModelAnalyzer 26 | 27 | 28 | class DFAnalyzer(ModelAnalyzer): 29 | def __init__(self, eval_config: Union[tfma.EvalConfig, Text] = None, dataset: pd.DataFrame = None): 30 | """Start TFMA analysis on Pandas DataFrame 31 | 32 | Args: 33 | raw_data (pd.DataFrame): dataframe containing prediciton values and ground truth 34 | eval_config (tfma.EvalConfig or str): representing proto file path 35 | """ 36 | super().__init__(eval_config, dataset) 37 | 38 | @classmethod 39 | def analyze(cls, eval_config: Union[tfma.EvalConfig, Text] = None, dataset: DatasetType = None): 40 | """Class Factory to start TFMA analysis 41 | Args: 42 | model_path (str) : path to model 43 | eval_config (tfma.EvalConfig or str): representing proto file path 44 | data (str or pd.DataFrame): string ot tfrecord or raw dataframe containing 45 | prediction values and ground truth 46 | 47 | Raises: 48 | TypeError: when eval_config is not of type tfma.EvalConfig or str 49 | TypeError: when data argument is not of type pd.DataFrame or str 50 | 51 | Returns: 52 | tfma.EvalResults() 53 | 54 | Example: 55 | >>> from model_card_gen.analyzer import DFAnalyzer 56 | >>> DFAnalyzer.analyze( 57 | model_path='compas/model', 58 | data='compas/eval.tfrecord', 59 | eval_config='compas/eval_config.proto') 60 | """ 61 | self = cls(eval_config, dataset) 62 | self.run_analysis() 63 | return self.get_analysis() 64 | 65 | def run_analysis(self): 66 | self.eval_result = tfma.analyze_raw_data(data=self.dataset, eval_config=self.eval_config) 67 | return self.eval_result 68 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/analyze/tf_analyzer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import pandas as pd 22 | import tensorflow_model_analysis as tfma 23 | from typing import Text, Optional, Union 24 | from intel_ai_safety.model_card_gen.utils.types import DatasetType 25 | from intel_ai_safety.model_card_gen.analyze.analyzer import ModelAnalyzer 26 | 27 | 28 | class TFAnalyzer(ModelAnalyzer): 29 | def __init__(self, model_path: Text, dataset: DatasetType, eval_config: Union[tfma.EvalConfig, Text] = None): 30 | """Start TFMA analysis on TensorFlow model 31 | Args: 32 | model_path (str) : path to model 33 | data (str): tfrecord file glob path 34 | eval_config (tfma.EvalConfig pr str): representing proto file path 35 | """ 36 | super().__init__(eval_config, dataset) 37 | self.model_path = model_path 38 | self.dataset = dataset 39 | 40 | @classmethod 41 | def analyze( 42 | cls, 43 | model_path: Optional[Text] = "", 44 | eval_config: Union[tfma.EvalConfig, Text] = None, 45 | dataset: DatasetType = None, 46 | ): 47 | """Class Factory to start TFMA analysis 48 | Args: 49 | model_path (str) : path to model 50 | eval_config (tfma.EvalConfig or str): representing proto file path 51 | data (str or pd.DataFrame): string ot tfrecord or raw dataframe containing 52 | prediction values and ground truth 53 | 54 | Raises: 55 | TypeError: when eval_config is not of type tfma.EvalConfig or str 56 | TypeError: when data argument is not of type pd.DataFrame or str 57 | 58 | Returns: 59 | tfma.EvalConfig() 60 | 61 | Example: 62 | >>> from model_card_gen.analyzer import TFAnalyzer 63 | >>> TFAnalyzer.analyze( 64 | model_path='compas/model', 65 | data='compas/eval.tfrecord', 66 | eval_config='compas/eval_config.proto') 67 | """ 68 | self = cls(model_path, dataset, eval_config) 69 | self.run_analysis() 70 | return self.get_analysis() 71 | 72 | def run_analysis(self): 73 | # TODO if not eval_shared 74 | eval_shared_model = tfma.default_eval_shared_model( 75 | eval_saved_model_path=self.model_path, eval_config=self.eval_config 76 | ) 77 | 78 | self.eval_result = tfma.run_model_analysis( 79 | eval_shared_model=eval_shared_model, eval_config=self.eval_config, data_location=self.dataset.dataset_path 80 | ) 81 | return self.eval_result 82 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from .datasets import BaseDataset 22 | from .tf_datasets import TensorflowDataset 23 | from .torch_datasets import PytorchDataset 24 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/datasets/datasets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | 22 | class BaseDataset: 23 | """ 24 | Base class for all datasets supported by ModelCardGen 25 | """ 26 | 27 | def __init__(self, dataset_path=None, name=None): 28 | self._dataset_path = dataset_path 29 | self._dataset_name = name 30 | 31 | @property 32 | def dataset_path(self): 33 | """ 34 | Returns the file path of the dataset 35 | """ 36 | return self._dataset_path 37 | 38 | @property 39 | def name(self): 40 | """ 41 | Returns the name of the dataset 42 | """ 43 | return self._name 44 | 45 | @property 46 | def description(self): 47 | """ 48 | Returns the description of the dataset 49 | """ 50 | return self._description 51 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/intel_ai_safety/model_card_gen/datasets/tf_datasets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | from plugins.model_card_gen.generators.tfma.intel_ai_safety.model_card_gen.datasets import BaseDataset 22 | 23 | 24 | class TensorflowDataset(BaseDataset): 25 | """ 26 | Class wrapper for Tensorflow tfrecord 27 | """ 28 | 29 | def __init__(self, dataset_path, name=""): 30 | super().__init__(dataset_path, name) 31 | self._framework = "tensorflow" 32 | 33 | @property 34 | def framework(self): 35 | """ 36 | Returns the framework for dataset 37 | """ 38 | return self._framework 39 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | # TODO: Remove this line after upgrading PyArrow to 14.0.1 22 | import pyarrow_hotfix 23 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/tests/test_end_to_end_tf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import os 22 | import shutil 23 | 24 | import pytest 25 | import tensorflow_model_analysis as tfma 26 | from google.protobuf import text_format 27 | 28 | from intel_ai_safety.model_card_gen.model_card_gen import ModelCardGen 29 | 30 | 31 | @pytest.mark.tensorflow 32 | class TestMCGForTensorFlow: 33 | 34 | @classmethod 35 | def setup_class(cls): 36 | # Do TensorFlow specific imports within the marked class so that we don't get errors when TF isn't installed 37 | from intel_ai_safety.model_card_gen.datasets import TensorflowDataset 38 | from .tf_model import build_and_train_model, train_tf_file, validate_tf_file 39 | 40 | cls._model_path = build_and_train_model() 41 | cls._data_sets = { 42 | "eval": TensorflowDataset(dataset_path=validate_tf_file), 43 | "train": TensorflowDataset(dataset_path=train_tf_file), 44 | } 45 | 46 | cls._eval_config = text_format.Parse( 47 | """ 48 | model_specs { 49 | signature_name: "eval" 50 | } 51 | 52 | metrics_specs { 53 | metrics { class_name: "BinaryAccuracy" } 54 | metrics { class_name: "Precision" } 55 | metrics { class_name: "Recall" } 56 | metrics { class_name: "ConfusionMatrixPlot" } 57 | metrics { class_name: "FairnessIndicators" } 58 | } 59 | 60 | slicing_specs {} # overall slice 61 | slicing_specs { 62 | feature_keys: ["gender"] 63 | } 64 | """, 65 | tfma.EvalConfig(), 66 | ) 67 | 68 | @classmethod 69 | def teardown_class(cls): 70 | if os.path.exists(cls._model_path): 71 | shutil.rmtree(cls._model_path) 72 | 73 | def test_end_to_end(self): 74 | """Build a model card from a trained model""" 75 | 76 | mcg = ModelCardGen.generate( 77 | data_sets=self._data_sets, model_path=self._model_path, eval_config=self._eval_config 78 | ) 79 | 80 | assert mcg 81 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/tests/test_end_to_end_torch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import os 22 | import pytest 23 | 24 | import tensorflow_model_analysis as tfma 25 | from google.protobuf import text_format 26 | 27 | from intel_ai_safety.model_card_gen.model_card_gen import ModelCardGen 28 | 29 | 30 | @pytest.mark.pytorch 31 | class TestMCGForPyTorch: 32 | 33 | @classmethod 34 | def setup_class(cls): 35 | # Do PyTorch specific imports within the marked class so that we don't get errors when torch isn't installed 36 | from intel_ai_safety.model_card_gen.datasets import PytorchDataset 37 | from .torch_model import get_data, get_trained_model 38 | 39 | adult_dataset, feature_names = get_data() 40 | cls._model_path = get_trained_model(adult_dataset, feature_names) 41 | cls._data_sets = {"train": PytorchDataset(adult_dataset, feature_names=feature_names)} 42 | 43 | cls._eval_config = text_format.Parse( 44 | """ 45 | model_specs { 46 | label_key: 'label' 47 | prediction_key: 'prediction' 48 | } 49 | metrics_specs { 50 | metrics {class_name: "BinaryAccuracy"} 51 | metrics {class_name: "AUC"} 52 | metrics {class_name: "ConfusionMatrixPlot"} 53 | metrics { 54 | class_name: "FairnessIndicators" 55 | } 56 | } 57 | slicing_specs {} 58 | slicing_specs { 59 | feature_keys: 'sex_Female' 60 | } 61 | options { 62 | include_default_metrics { value: false } 63 | } 64 | """, 65 | tfma.EvalConfig(), 66 | ) 67 | 68 | @classmethod 69 | def teardown_class(cls): 70 | if os.path.exists(cls._model_path): 71 | os.remove(cls._model_path) 72 | 73 | def test_end_to_end(self): 74 | """Build a pytorch model card from a trained model""" 75 | mcg = ModelCardGen.generate( 76 | data_sets=self._data_sets, model_path=self._model_path, eval_config=self._eval_config 77 | ) 78 | 79 | assert mcg 80 | -------------------------------------------------------------------------------- /plugins/model_card_gen/generators/tfma/tests/torch_model.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2022 Intel Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | import pandas as pd 22 | import torch 23 | import torch.nn as nn 24 | from torch.utils.data import Dataset, TensorDataset 25 | import tempfile 26 | 27 | COLUMNS = [ 28 | "age", 29 | "workclass", 30 | "fnlwgt", 31 | "education", 32 | "education-num", 33 | "marital-status", 34 | "occupation", 35 | "relationship", 36 | "race", 37 | "sex", 38 | "capital-gain", 39 | "capital-loss", 40 | "hours-per-week", 41 | "country", 42 | "label", 43 | ] 44 | 45 | CATEGORICAL_FEATURE_KEYS = [ 46 | "workclass", 47 | "marital-status", 48 | "occupation", 49 | "relationship", 50 | "race", 51 | "sex", 52 | "native-country", 53 | ] 54 | 55 | DROP_COLUMNS = ["fnlwgt", "education"] 56 | LABEL_KEY = "label" 57 | 58 | 59 | class AdultNN(nn.Module): 60 | def __init__(self, feature_size): 61 | super().__init__() 62 | self.linear1 = nn.Linear(feature_size, feature_size) 63 | self.sigmoid1 = nn.Sigmoid() 64 | self.linear2 = nn.Linear(feature_size, 8) 65 | self.sigmoid2 = nn.Sigmoid() 66 | self.linear3 = nn.Linear(8, 2) 67 | self.softmax = nn.Softmax(dim=1) 68 | 69 | def forward(self, x): 70 | lin1_out = self.linear1(x) 71 | sigmoid_out1 = self.sigmoid1(lin1_out) 72 | sigmoid_out2 = self.sigmoid2(self.linear2(sigmoid_out1)) 73 | return self.softmax(self.linear3(sigmoid_out2)) 74 | 75 | 76 | def get_data(): 77 | from sklearn.datasets import fetch_openml 78 | 79 | data = fetch_openml(data_id=1590, as_frame=True) 80 | raw_data = data.data 81 | raw_data[LABEL_KEY] = data.target 82 | adult_data = raw_data.copy() 83 | adult_data = adult_data.drop(DROP_COLUMNS, axis=1) 84 | adult_data = pd.get_dummies(adult_data, columns=CATEGORICAL_FEATURE_KEYS) 85 | adult_data[LABEL_KEY] = adult_data[LABEL_KEY].map({"<=50K": 0, ">50K": 1}) 86 | feature_names = list(adult_data.drop([LABEL_KEY], axis=1).columns) 87 | y = adult_data[LABEL_KEY].to_numpy() 88 | X = adult_data.drop([LABEL_KEY], axis=1).to_numpy() 89 | 90 | return TensorDataset(torch.Tensor(X).type(torch.FloatTensor), torch.Tensor(y).type(torch.LongTensor)), feature_names 91 | 92 | 93 | def get_trained_model(adult_dataset, feature_names): 94 | _, tmp_train = tempfile.mkstemp() 95 | net = AdultNN(len(feature_names)) 96 | criterion = nn.CrossEntropyLoss() 97 | num_epochs = 200 98 | 99 | optimizer = torch.optim.Adam(net.parameters(), lr=0.001) 100 | input_tensor, label_tensor = adult_dataset[:] 101 | for epoch in range(num_epochs): 102 | output = net(input_tensor) 103 | loss = criterion(output, label_tensor) 104 | optimizer.zero_grad() 105 | loss.backward() 106 | optimizer.step() 107 | if epoch % 20 == 0: 108 | print("Epoch {}/{} => Loss: {:.2f}".format(epoch + 1, num_epochs, loss.item())) 109 | torch.jit.save(torch.jit.script(net), tmp_train) 110 | return tmp_train 111 | -------------------------------------------------------------------------------- /poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /run_notebooks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright (c) 2023 Intel Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | if [[ $# -eq 0 ]] ; then 19 | echo "No argument supplied. Please input a notebook path, or a directory containing one or more notebooks." 20 | exit 1 21 | fi 22 | 23 | CURDIR=$PWD 24 | INPUT=$1 25 | 26 | # Parse the filename from the path 27 | DIR=${INPUT%/*} 28 | FILE="${INPUT##*/}" 29 | 30 | # If no file was given, find all notebooks in the directory 31 | if [ -z "$FILE" ] ; then 32 | readarray -d '' notebooks < <(find ${DIR} -maxdepth 1 -name *.ipynb -print0) 33 | else 34 | notebooks=($1) 35 | fi 36 | 37 | echo "Notebooks: ${notebooks}" 38 | for notebook in ${notebooks[*]}; do 39 | DIR=${notebook%/*} 40 | echo "Running ${notebook}..." 41 | 42 | if [[ $# -eq 2 ]] ; then 43 | echo "Stripping tag ${2}..." 44 | jupyter nbconvert --to script \ 45 | --TagRemovePreprocessor.enabled=True \ 46 | --TagRemovePreprocessor.remove_cell_tags $2 \ 47 | --output notebook_test ${notebook} 48 | else 49 | jupyter nbconvert --to script --output notebook_test ${notebook} 50 | fi 51 | 52 | pushd ${DIR} 53 | PYTHONPATH=${CURDIR} ipython notebook_test.py 54 | rm notebook_test.py 55 | popd 56 | done 57 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist=py26, py27, py33, py34, pypy, flake8 3 | 4 | [testenv] 5 | commands=py.test --cov explainable-ai-tooling {posargs} 6 | deps= 7 | pytest 8 | pytest-cov 9 | 10 | [testenv:flake8] 11 | basepython = python2.7 12 | deps = 13 | flake8 14 | commands = 15 | flake8 explainable-ai-tooling tests --max-line-length=120 16 | 17 | [pytest] 18 | markers = 19 | tensorflow: test requires tensorflow to be installed 20 | pytorch: test requires pytorch and tensorflow-model-analysis to be installed 21 | common: test does not require a specific framework to be installed 22 | 23 | [flake8] 24 | ignore = C901,E203,E266,E401,E402,E701,E711,E712,E722,E731,F401,F403,F405,F841,W291,W503,W504 25 | tee = True 26 | inline-quotes = double 27 | multiline-quotes = double 28 | max-line-length = 120 29 | max-complexity = 12 30 | exclude = .cache,.tox,__pycache__,.pytest_cache,*.pyc,.venv,.mypy_cache,docker/helm-runner/third_party/*,model_card_gen/intel_ai_safety/model_card_gen/model_card.py 31 | --------------------------------------------------------------------------------