{"id":13645221,"url":"https://github.com/frgfm/torch-cam","last_synced_at":"2026-10-19T08:45:32.485Z","repository":{"id":37475676,"uuid":"249513553","full_name":"frgfm/torch-cam","owner":"frgfm","description":"Class activation maps for your PyTorch models (CAM, Grad-CAM, Grad-CAM++, Smooth Grad-CAM++, Score-CAM, SS-CAM, IS-CAM, XGrad-CAM, Layer-CAM, Finer-CAM, LeGrad, RefineCAM)","archived":false,"fork":false,"pushed_at":"2026-10-15T20:53:52.000Z","size":2901,"stargazers_count":2307,"open_issues_count":13,"forks_count":231,"subscribers_count":10,"default_branch":"main","last_synced_at":"2026-10-16T03:12:52.505Z","etag":null,"topics":["activation-maps","class-activation-map","cnn","deep-learning","grad-cam","gradcam","gradcam-plus-plus","interpretability","interpretable-deep-learning","python","pytorch","saliency-map","score-cam","smoothgrad"],"latest_commit_sha":null,"homepage":"https://frgfm.github.io/torch-cam/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frgfm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null},"funding":{"github":"frgfm","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-03-23T18:34:51.000Z","updated_at":"2026-10-15T15:49:32.000Z","dependencies_parsed_at":"2026-08-25T06:33:38.089Z","dependency_job_id":null,"html_url":"https://github.com/frgfm/torch-cam","commit_stats":{"total_commits":150,"total_committers":4,"mean_commits":37.5,"dds":"0.026666666666666616","last_synced_commit":"3f1c8e4d21f8936f13457d656c9a93b8be100de1"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/frgfm/torch-cam","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frgfm%2Ftorch-cam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frgfm%2Ftorch-cam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frgfm%2Ftorch-cam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frgfm%2Ftorch-cam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frgfm","download_url":"https://codeload.github.com/frgfm/torch-cam/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frgfm%2Ftorch-cam/sbom","scorecard":{"id":411400,"data":{"date":"2025-08-11","repo":{"name":"github.com/frgfm/torch-cam","commit":"ef34feae1a677c2fdbb5995723bf763cefb961da"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/8 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:81: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:85: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:98: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:103: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/page-build.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/page-build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/page-build.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/page-build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr-edited.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/pr-edited.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr-merged.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/pr-merged.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr-merged.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/pr-merged.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr-merged.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/pr-merged.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr-merged.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/pr-merged.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yaml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/push.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/push.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/push.yaml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/push.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/push.yaml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/push.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/push.yaml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/push.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/style.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/style.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/style.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/style.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/style.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/style.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/style.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/style.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/style.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/style.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:86: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:91: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:105: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:106: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:110: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/triage.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/frgfm/torch-cam/triage.yml/main?enable=pin","Warn: pipCommand not pinned by hash: docs/build.sh:8","Info:   0 out of  39 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  24 third-party GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel permissions set to 'read-all': .github/workflows/pr-edited.yml:12","Info: jobLevel 'contents' permission set to 'read': .github/workflows/triage.yml:10","Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/page-build.yml:1","Warn: no topLevel permission defined: .github/workflows/pr-edited.yml:1","Warn: no topLevel permission defined: .github/workflows/pr-merged.yml:1","Warn: no topLevel permission defined: .github/workflows/push.yaml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/style.yml:1","Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Warn: no topLevel permission defined: .github/workflows/triage.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.3.1 not signed: https://api.github.com/repos/frgfm/torch-cam/releases/52404987","Warn: release artifact v0.2.0 not signed: https://api.github.com/repos/frgfm/torch-cam/releases/41212205","Warn: release artifact v0.3.1 does not have provenance: https://api.github.com/repos/frgfm/torch-cam/releases/52404987","Warn: release artifact v0.2.0 does not have provenance: https://api.github.com/repos/frgfm/torch-cam/releases/41212205"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":3,"reason":"7 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2014-14 / GHSA-652x-xj99-gmcc","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-9wx4-h78v-vm56","Warn: Project is vulnerable to: PYSEC-2014-13 / GHSA-cfj3-7x9c-4p3h","Warn: Project is vulnerable to: PYSEC-2018-28 / GHSA-x84v-xcm2-53pg","Warn: Project is vulnerable to: PYSEC-2015-17","Warn: Project is vulnerable to: PYSEC-2023-74"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T22:47:48.669Z","repository_id":37475676,"created_at":"2025-08-18T22:47:48.669Z","updated_at":"2025-08-18T22:47:48.669Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38352851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-19T02:00:06.414Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activation-maps","class-activation-map","cnn","deep-learning","grad-cam","gradcam","gradcam-plus-plus","interpretability","interpretable-deep-learning","python","pytorch","saliency-map","score-cam","smoothgrad"],"created_at":"2024-08-02T01:02:31.408Z","updated_at":"2026-10-19T08:45:32.475Z","avatar_url":"https://github.com/frgfm.png","language":"Python","funding_links":["https://github.com/sponsors/frgfm"],"categories":["XAI Libraries for Vision/Vision-Language","Python","Object Detection Applications","🧰 Tool","Python Libraries(sort in alphabeta order)"],"sub_categories":["2023","Evaluation methods"],"readme":"\u003ch1 align=\"center\"\u003e\n  TorchCAM: class activation explorer\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eEnglish\u003c/strong\u003e | \u003ca href=\"README.zh-CN.md\"\u003e简体中文\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/frgfm/torch-cam/actions/workflows/package.yml\"\u003e\n    \u003cimg alt=\"CI Status\" src=\"https://img.shields.io/github/actions/workflow/status/frgfm/torch-cam/package.yml?branch=main\u0026label=CI\u0026logo=github\u0026style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/astral-sh/ruff\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Linter-Ruff-FCC21B?style=flat-square\u0026logo=ruff\u0026logoColor=white\" alt=\"ruff\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/astral-sh/ty\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Typecheck-Ty-261230?style=flat-square\u0026logo=astral\u0026logoColor=white\" alt=\"ty\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.codacy.com/gh/frgfm/torch-cam/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=frgfm/torch-cam\u0026amp;utm_campaign=Badge_Grade\"\u003e\u003cimg src=\"https://app.codacy.com/project/badge/Grade/87eaeec3e15442188f96c36bace5faf4\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/frgfm/torch-cam\"\u003e\n    \u003cimg src=\"https://img.shields.io/codecov/c/github/frgfm/torch-cam.svg?logo=codecov\u0026style=flat-square\u0026label=Coverage\" alt=\"Test coverage percentage\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/torchcam/\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/torchcam.svg?logo=PyPI\u0026logoColor=fff\u0026style=flat-square\u0026label=PyPI\" alt=\"PyPi Version\"\u003e\n  \u003c/a\u003e\n  \u003cimg alt=\"GitHub release (latest by date)\" src=\"https://img.shields.io/github/v/release/frgfm/torch-cam?label=Release\u0026logo=github\"\u003e\n  \u003cimg src=\"https://img.shields.io/pypi/pyversions/torchcam.svg?logo=Python\u0026label=Python\u0026logoColor=fff\u0026style=flat-square\" alt=\"pyversions\"\u003e\n  \u003ca href=\"https://github.com/frgfm/torch-cam/blob/main/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/frgfm/torch-cam.svg?label=License\u0026logoColor=fff\u0026style=flat-square\" alt=\"License\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://huggingface.co/spaces/frgfm/torch-cam\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue\" alt=\"Huggingface Spaces\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://colab.research.google.com/github/frgfm/notebooks/blob/main/torch-cam/quicktour.ipynb\"\u003e\n    \u003cimg src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open in Colab\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://frgfm.github.io/torch-cam\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/frgfm/torch-cam/docs.yml?branch=main\u0026label=Documentation\u0026logo=read-the-docs\u0026logoColor=white\u0026style=flat-square\" alt=\"Documentation Status\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nExplain PyTorch decisions: activation maps for image classifiers, detectors, segmenters and VLMs, and token contributions for text classifiers.\n\nDebugging one surprising classifier result? Use the [predicted-versus-expected agent workflow](https://frgfm.github.io/torch-cam/getting-started/debug-prediction/), install the [portable skill](https://github.com/frgfm/torch-cam/blob/main/.agents/skills/torchcam-debug-prediction/SKILL.md) in your coding agent with `npx skills add frgfm/torch-cam`, or start from [`llms.txt`](https://frgfm.github.io/torch-cam/llms.txt).\n\n\u003cp align=\"center\"\u003e\n    \u003ca alt=\"cam_examples\"\u003e\n        \u003cimg src=\"https://github.com/frgfm/torch-cam/releases/download/v0.3.1/example.png\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003eSource: image from \u003ca href=\"https://www.woopets.fr/assets/races/000/066/big-portrait/border-collie.jpg\"\u003ewoopets\u003c/a\u003e (activation maps created with a pretrained \u003ca href=\"https://pytorch.org/vision/stable/models.html#torchvision.models.resnet18\"\u003eResnet-18\u003c/a\u003e)\u003c/em\u003e\n\u003c/p\u003e\n\n\n## Why TorchCAM\n\n- **12 CAM methods plus VLM token maps**: from CAM and Grad-CAM to LeGrad, RefineCAM and [TAM](https://frgfm.github.io/torch-cam/getting-started/advanced-usage/#token-activation-maps-for-vlms).\n- **CNNs and Vision Transformers**: automatic target-layer resolution for CNNs, LeGrad and reshape transforms for ViTs.\n- **Beyond classification**: explain [detections, segmentation masks and embeddings](https://frgfm.github.io/torch-cam/getting-started/advanced-usage/#understanding-targets-and-the-call-signature) with the same extractors.\n- **Text decision models**: fast `TokenAblation` measures each token's effect; `TokenIG` provides embedding Integrated Gradients with numerical checks. Both return class-specific signed maps, including for Laya's decision architecture.\n- **Lean**: fully typed, with only 4 runtime dependencies (PyTorch, NumPy, Pillow, Matplotlib).\n- **Measurable**: built-in faithfulness metrics (average drop, increase in confidence, deletion/insertion).\n- **Agent-ready**: `explain()` saves a manifest-backed evidence bundle that humans and coding agents can verify.\n\n## Quick Tour\n\n### Explain a prediction\n\n```python\nfrom urllib.request import urlretrieve\nfrom PIL import Image\nfrom torchvision.models import ResNet18_Weights, resnet18\nfrom torchvision.transforms.functional import center_crop, resize\nfrom torchcam.explain import explain\n\nurlretrieve(\"https://github.com/pytorch/hub/raw/master/images/dog.jpg\", \"dog.jpg\")\nimage = Image.open(\"dog.jpg\").convert(\"RGB\")\nweights = ResNet18_Weights.DEFAULT\nmodel = resnet18(weights=weights).eval()\n\npreprocess = weights.transforms()\ninput_tensor = preprocess(image).unsqueeze(0)\nmodel_image = center_crop(\n    resize(image, preprocess.resize_size, interpolation=preprocess.interpolation, antialias=preprocess.antialias),\n    preprocess.crop_size,\n)\nresult = explain(model, input_tensor, class_names=weights.meta[\"categories\"])\nresult.save(\"torchcam-explanation\", model_image)  # CAMs, heatmaps, overlays and manifest.json\n```\n\nPass `expected_class_idx` to compare the prediction with the class you expected. See [Debug one prediction](https://frgfm.github.io/torch-cam/getting-started/debug-prediction/) for the full contract.\n\n### Explain a text decision\n\nUse your existing classifier and tokenizer; TorchCAM adds no Transformers or Laya dependency.\n`TokenAblation` and `TokenIG` are available in the development version (install from source below).\n\n\u003c!-- --8\u003c-- [start:quickstart-text] --\u003e\n```python\nfrom torchcam.methods import TokenAblation\n\n# model and tokenizer are your loaded text classifier and its tokenizer.\ninputs = tokenizer(\"I was charged twice. Please refund the duplicate payment.\", return_tensors=\"pt\", return_special_tokens_mask=True)\ninputs = {key: value.to(next(model.parameters()).device) for key, value in inputs.items()}\ntoken_mask = inputs[\"attention_mask\"].bool() \u0026 ~inputs.pop(\"special_tokens_mask\").bool()\nextractor = TokenAblation(model, output_transform=lambda output: output.logits)\nresult = extractor(inputs, replacement_id=tokenizer.mask_token_id, token_mask=token_mask)\n\nprobabilities = result.scores.softmax(-1)  # Use the model's calibration instead when applicable.\ncontributions = result.attributions      # (batch, classes, input_tokens), signed class-logit changes\n```\n\u003c!-- --8\u003c-- [end:quickstart-text] --\u003e\n\nPositive effects mean replacing a token lowers that class score; other tokens stay fixed. Effects can interact and\nneed not add up. Use a replacement ID appropriate to the model, and exclude special/context tokens with `token_mask`.\nFor additive embedding-path contributions, use `TokenIG`. Token effects are not probabilities; highlight positive\nvalues beside each decision's probability for a simple CAM-style display.\nSee [Text decision models](https://frgfm.github.io/torch-cam/getting-started/text-decisions/) for masks, baselines,\nefficiency, the result contract, and Laya integration.\n\n### Setting your CAM\n\nTorchCAM leverages [PyTorch hooking mechanisms](https://pytorch.org/tutorials/beginner/former_torchies/nnft_tutorial.html#forward-and-backward-function-hooks) to seamlessly retrieve all required information to produce the class activation without additional efforts from the user. Each CAM object acts as a wrapper around your model.\n\nYou can find the exhaustive list of supported CAM methods in the [documentation](https://frgfm.github.io/torch-cam/reference/methods/), then use it as follows:\n\n```python\nfrom torchvision.models import get_model, get_model_weights\nfrom torchcam.methods import LayerCAM\n\n# Define your model\nmodel = get_model(\"resnet18\", weights=get_model_weights(\"resnet18\").DEFAULT).eval()\n# Set your CAM extractor\ncam_extractor = LayerCAM(model)\n```\n\n*Please note that by default, the layer at which the CAM is retrieved is set to the last non-reduced convolutional layer. If you wish to investigate a specific layer, use the `target_layer` argument in the constructor.*\n\n### Retrieving the class activation map\n\nOnce your CAM extractor is set, you only need to use your model to infer on your data as usual. If any additional information is required, the extractor will get it for you automatically.\n\n\u003c!-- --8\u003c-- [start:quickstart-input] --\u003e\n```python\nfrom urllib.request import urlretrieve\nfrom torchvision.io import decode_image\nfrom torchvision.models import get_model, get_model_weights\n\n# Get a model and an image\nweights = get_model_weights(\"resnet18\").DEFAULT\nmodel = get_model(\"resnet18\", weights=weights).eval()\npreprocess = weights.transforms()\nurlretrieve(\"https://github.com/pytorch/hub/raw/master/images/dog.jpg\", \"dog.jpg\")\nimg = decode_image(\"dog.jpg\")\n\ninput_tensor = preprocess(img)\n```\n\u003c!-- --8\u003c-- [end:quickstart-input] --\u003e\n\nCompute the class activation map:\n\n\u003c!-- --8\u003c-- [start:quickstart-cam] --\u003e\n```python hl_lines=\"3 6\"\nfrom torchcam.methods import LayerCAM\n\nwith LayerCAM(model) as cam_extractor:\n  out = model(input_tensor.unsqueeze(0))\n  # Retrieve the CAM by passing the class index and the model output\n  activation_map = cam_extractor(out.squeeze(0).argmax().item(), out)\n```\n\u003c!-- --8\u003c-- [end:quickstart-cam] --\u003e\n\nHere `class_idx` (the first argument) is the index in the model's output logits of the class you want to explain — `out.squeeze(0).argmax().item()` picks the top prediction, but you can pass any class index. The extractor returns one activation map per target layer.\n\nIf you want to visualize your heatmap, you only need to cast the CAM to a numpy ndarray:\n\n```python\nimport matplotlib.pyplot as plt\n# Visualize the raw CAM\nplt.imshow(activation_map[0].squeeze(0).numpy()); plt.axis('off'); plt.tight_layout(); plt.show()\n```\n\n![raw_heatmap](https://github.com/frgfm/torch-cam/releases/download/v0.1.2/raw_heatmap.png)\n\nOr if you wish to overlay it on your input image:\n\n\u003c!-- --8\u003c-- [start:quickstart-overlay] --\u003e\n```python hl_lines=\"4 11\"\nimport matplotlib.pyplot as plt\nfrom torchvision.transforms.v2.functional import to_pil_image\nfrom torchvision.transforms.functional import center_crop, resize\nfrom torchcam.utils import overlay_mask\n\n# Use the same spatial transforms as inference, before normalization.\nmodel_image = center_crop(\n    resize(img, preprocess.resize_size, interpolation=preprocess.interpolation, antialias=preprocess.antialias),\n    preprocess.crop_size,\n)\nresult = overlay_mask(to_pil_image(model_image), to_pil_image(activation_map[0].squeeze(0), mode='F'), alpha=0.5)\nplt.imshow(result); plt.axis('off'); plt.tight_layout(); plt.show()\n```\n\u003c!-- --8\u003c-- [end:quickstart-overlay] --\u003e\n\n![overlayed_heatmap](https://github.com/frgfm/torch-cam/releases/download/v0.1.2/overlayed_heatmap.png)\n\n\u003e [!TIP]\n\u003e Using your own (non-torchvision) model, a Vision Transformer, 3D/video data, or batched inputs? Read the [**Advanced usage guide**](https://frgfm.github.io/torch-cam/getting-started/advanced-usage/) — it also covers how to choose the right `target_layer` and CAM method.\n\u003e\n\u003e Hitting a `cannot register a hook ...` / `requires grad` error, a `NaN`, or a blank heatmap? See [**Troubleshooting**](https://frgfm.github.io/torch-cam/getting-started/troubleshooting/).\n\n## Setup\n\nPython 3.11 (or higher) and [uv](https://docs.astral.sh/uv/)/[pip](https://pip.pypa.io/en/stable/installation/) are required to install TorchCAM. TorchCAM 0.5.0 requires PyTorch 2.4.1 or higher (`torch\u003e=2.4.1,\u003c3`) and supports NumPy 1.26.4 and NumPy 2 (`numpy\u003e=1.26.4,\u003c3`). Use the matching torchvision release.\n\nOn macOS, TorchCAM 0.5.0 requires Apple Silicon when using published PyTorch wheels. Intel Mac users can use Python 3.11 or 3.12 and install the previous release with `pip install \"torchcam==0.4.1\"`.\n\n### Stable release\n\nYou can install the last stable release of the package using [pypi](https://pypi.org/project/torchcam/) as follows:\n\n```shell\npip install torchcam\n```\n\n### Latest version\n\nAlternatively, if you wish to use the latest features of the project that haven't made their way to a release yet, you can install the package from source:\n\n```shell\npip install \"torchcam @ git+https://github.com/frgfm/torch-cam.git\"\n```\n\n\n## CAM Zoo\n\nThis project is developed and maintained by [its author](#author), but the implementation was based on the following research papers:\n\n- [Learning Deep Features for Discriminative Localization](https://arxiv.org/abs/1512.04150): the original CAM paper\n- [Grad-CAM](https://arxiv.org/abs/1610.02391): GradCAM paper, generalizing CAM to models without global average pooling.\n- [Grad-CAM++](https://arxiv.org/abs/1710.11063): improvement of GradCAM++ for more accurate pixel-level contribution to the activation.\n- [Smooth Grad-CAM++](https://arxiv.org/abs/1908.01224): SmoothGrad mechanism coupled with GradCAM.\n- [Score-CAM](https://arxiv.org/abs/1910.01279): score-weighting of class activation for better interpretability.\n- [SS-CAM](https://arxiv.org/abs/2006.14255): SmoothGrad mechanism coupled with Score-CAM.\n- [IS-CAM](https://arxiv.org/abs/2010.03023): integration-based variant of Score-CAM.\n- [XGrad-CAM](https://arxiv.org/abs/2008.02312): improved version of Grad-CAM in terms of sensitivity and conservation.\n- [Layer-CAM](http://mftp.mmcheng.net/Papers/21TIP_LayerCAM.pdf): Grad-CAM alternative leveraging pixel-wise contribution of the gradient to the activation.\n- [Finer-CAM](https://arxiv.org/abs/2501.11309): contrastive CAM objective highlighting differences between similar classes.\n- [LeGrad](https://arxiv.org/abs/2404.03214): layerwise positive attention-gradient maps for Vision Transformers.\n- [RefineCAM](https://arxiv.org/abs/2605.14641): multi-layer refinement producing high-resolution activation maps.\n\n*Not sure which one to use? See [Choosing a CAM method](https://frgfm.github.io/torch-cam/getting-started/advanced-usage/#choosing-a-cam-method).*\n\n\u003cp align=\"center\"\u003e\n    \u003ca alt=\"wallaby_video_cam\"\u003e\n        \u003cimg src=\"https://github.com/frgfm/torch-cam/releases/download/v0.2.0/video_example_wallaby.gif\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003eSource: \u003ca href=\"https://www.youtube.com/watch?v=hZJN5BzKfxk\"\u003eYouTube video\u003c/a\u003e (activation maps created by \u003ca href=\"https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.LayerCAM\"\u003eLayer-CAM\u003c/a\u003e with a pretrained \u003ca href=\"https://pytorch.org/vision/stable/models.html#torchvision.models.resnet18\"\u003eResNet-18\u003c/a\u003e)\u003c/em\u003e\n\u003c/p\u003e\n\n\n\n## What else\n\n### Documentation\n\nThe full package documentation is available [here](https://frgfm.github.io/torch-cam/) for detailed specifications.\n\n### Playground app\n\nThe Streamlit explorer has three tabs, each with a model selector. Models load only when you request an explanation:\n\n- **Image classifiers**: pretrained torchvision models, class probabilities, CAMs and overlays.\n- **VLMs**: [BLIP](https://huggingface.co/Salesforce/blip-image-captioning-base), [Qwen3-VL 2B](https://huggingface.co/Qwen/Qwen3-VL-2B-Instruct) and [Gemma 4 E2B](https://huggingface.co/google/gemma-4-E2B-it) generate captions. Select a token to view its CAM and next-token probability. See [VLM attribution](https://frgfm.github.io/torch-cam/getting-started/advanced-usage/#token-activation-maps-for-vlms) for architecture-specific targets.\n- **Decision models**: [Laya](https://huggingface.co/convaiinnovations/laya) and [Decider-0.8B](https://huggingface.co/Mapika/decider-0.8b) score allowed routing choices directly. [MiniLM](https://huggingface.co/cross-encoder/nli-MiniLM2-L6-H768) and [DeBERTa](https://huggingface.co/MoritzLaurer/deberta-v3-base-zeroshot-v2.0) provide NLI baselines. All use `TokenAblation`, with one probability and input-token heatmap per option; signed effects are downloadable as JSON.\n\nUploads accept JPEG/PNG and clear on tab changes; other controls persist. The cache retains one model, with serialized\ninference per model; active requests can keep an evicted model alive during replacement. A GPU is recommended for the\nlarger VLMs; Gemma requires CUDA or a BF16-accelerated CPU. The VLM displays its actual processed image beside the map.\nText explanations are limited to 64 ticket tokens. See [text decision models](https://frgfm.github.io/torch-cam/getting-started/text-decisions/)\nfor replacement baselines, native probability calibration and interpretation limits.\n\nInstall the optional demo dependencies ([Streamlit](https://streamlit.io/), Transformers and Laya) to run it locally:\n\n```\npip install -e \".[demo]\"\n```\n\nYou can then easily run your app in your default browser by running:\n\n```\nstreamlit run demo/app.py\n```\n\nThe first computation downloads the selected pretrained checkpoint; later computations use the local model cache.\nFor offline verification, `python demo/smoke.py` checks navigation, UI state, input alignment and native model adapters\nusing small random-weight fixtures. These fixtures are only tests; the app always requests pretrained checkpoints.\n`python demo/smoke.py --pretrained` downloads the deployed models, checks routing examples and verifies that masking\nhigh-ranked regions reduces subject-token confidence more than masking low-ranked regions across multiple removal\nfractions. Gemma is skipped on CPUs without BF16 acceleration. Trusted deployments run it.\nThe deployed version is available on [Hugging Face Spaces](https://huggingface.co/spaces/frgfm/torch-cam).\n\n![torchcam_demo](https://github.com/frgfm/torch-cam/releases/download/v0.2.0/torchcam_demo.png)\n\n### Visualization script\n\nAn example script is provided for you to benchmark the heatmaps produced by multiple CAM approaches on the same image:\n\n```shell\npython scripts/cam_example.py --arch resnet18 --class-idx 232 --rows 2\n```\n\n![gradcam_sample](https://github.com/frgfm/torch-cam/releases/download/v0.3.1/example.png)\n\n*All script arguments can be checked using `python scripts/cam_example.py --help`*\n\n### Performance benchmarks\n\nThe purpose of CAM methods is to provide interpretability and they do so by pointing the biggest influence factors on the model outputs. Ideally the CAM should pinpoint all the visual cues that have any influence of the output classification score.\nFor this, we use two metrics:\n\n- [Increase in Confidence](https://frgfm.github.io/torch-cam/reference/metrics/#torchcam.metrics.ClassificationMetric) (higher is better): the fraction of inputs for which masking with the CAM increases the probability of the original predicted class.\n- [Average Drop](https://frgfm.github.io/torch-cam/reference/metrics/#torchcam.metrics.ClassificationMetric) (lower is better): the mean relative decrease in that class probability after masking, with increases counted as zero drop.\n\nThe table below records **historical October 2025 results**, obtained with earlier metric and CAM implementations. These values have not been revalidated with the current implementation. The ResNet-18 LayerCAM row has been corrected to match the recorded CSV and [original benchmark notebook](https://github.com/frgfm/notebooks/blob/main/torch-cam/performance_benchmark.ipynb).\n\n| CAM method | Arch | Average drop (↓) | Increase in confidence (↑) |\n| ---------- | ---- | ---------------- | -------------------------- |\n| [GradCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAM) | resnet18 | 0.2686 | 0.2250 |\n| [GradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAMpp) | resnet18 | 0.5271 | 0.1962 |\n| [SmoothGradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.SmoothGradCAMpp) | resnet18 | 0.2088 | 0.2499 |\n| [LayerCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.LayerCAM) | resnet18 | 0.1805 | 0.2894 |\n| [GradCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAM) | mobilenet_v3_large | 0.2678 | 0.3483 |\n| [GradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAMpp) | mobilenet_v3_large | 0.3182 | 0.2535 |\n| [SmoothGradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.SmoothGradCAMpp) | mobilenet_v3_large | 0.2681 | 0.2678 |\n| [LayerCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.LayerCAM) | mobilenet_v3_large | 0.2526 | 0.2882 |\n\nThe recorded protocol used the validation set of [imagenette2-320](https://github.com/fastai/imagenette), `Resize(256)` followed by `CenterCrop(224)`, and target layers `layer4` for ResNet-18 and `features` for MobileNet V3 Large. It evaluated the original predicted class. Masking multiplies the ImageNet-normalized input by the CAM: a zero mask therefore corresponds to the ImageNet mean RGB color, not black. No original random seed was recorded; stochastic CAMs and changes to CAM or metric numerics require a fresh benchmark run.\n\nYou can run a new benchmark on your hardware with an explicit seed and weight version as follows:\n\n```bash\nuv run --extra scripts python scripts/eval_perf.py ~/Downloads/imagenette2-320 LayerCAM --arch mobilenet_v3_large --seed 0 --weights IMAGENET1K_V2\n```\n\nThe optional `--deletion-insertion` evaluation uses a normalized zero baseline for both curves and 20 perturbation steps by default. It generates CAMs separately from the classification metrics, consuming extra random draws that can change subsequent stochastic classification CAMs even with the same seed; compare stochastic methods using the same flags. This differs from the original RISE protocol, which uses a blurred image as its insertion baseline; scores from different protocols are not directly comparable.\n\n*All script arguments can be checked using `python scripts/eval_perf.py --help`*\n\n### Latency benchmark\n\nYou crave for beautiful activation maps, but you don't know whether it fits your needs in terms of latency?\n\nThe table below preserves **historical October 2021 CPU latency measurements** (initial forward pass not included), from the [original benchmark commit](https://github.com/frgfm/torch-cam/commit/8237aef5756daeb85a49f87293cafef35277c295). They have not been revalidated with current implementations. The GPU column has been retired because the original timer did not synchronize CUDA operations; the current `scripts/eval_latency.py` synchronizes CUDA before and after timing.\n\n| CAM method | Arch | CPU mean (std) |\n| ---------- | ---- | -------------- |\n| [CAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.CAM) | resnet18           | 0.14ms (0.03ms)      |\n| [GradCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAM) | resnet18           | 40.66ms (1.82ms)     |\n| [GradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAMpp) | resnet18           | 41.61ms (3.24ms)     |\n| [SmoothGradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.SmoothGradCAMpp) | resnet18           | 239.27ms (7.85ms)    |\n| [ScoreCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.ScoreCAM) | resnet18           | 6796.89ms (415.14ms) |\n| [XGradCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.XGradCAM) | resnet18           | 40.63ms (2.03ms)     |\n| [LayerCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.LayerCAM) | resnet18           | 40.91ms (1.79ms)     |\n| [CAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.CAM) | mobilenet_v3_large | N/A*                 |\n| [GradCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAM) | mobilenet_v3_large | 26.64ms (3.46ms)     |\n| [GradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.GradCAMpp) | mobilenet_v3_large | 25.50ms (3.10ms)     |\n| [SmoothGradCAMpp](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.SmoothGradCAMpp) | mobilenet_v3_large | 156.25ms (4.89ms)    |\n| [ScoreCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.ScoreCAM) | mobilenet_v3_large | 679.16ms (55.04ms)   |\n| [XGradCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.XGradCAM) | mobilenet_v3_large | 24.21ms (2.94ms)     |\n| [LayerCAM](https://frgfm.github.io/torch-cam/reference/methods/#torchcam.methods.LayerCAM) | mobilenet_v3_large | 25.14ms (3.17ms)     |\n\n**The base CAM method cannot work with architectures that have multiple fully-connected layers*\n\nThese CPU measurements used 100 iterations on (224, 224) inputs and a laptop with an [Intel(R) Core(TM) i7-10750H](https://ark.intel.com/content/www/us/en/ark/products/201837/intel-core-i710750h-processor-12m-cache-up-to-5-00-ghz.html).\n\nYou can run this latency benchmark for any CAM method  on your hardware as follows:\n\n```bash\nuv run --extra scripts python scripts/eval_latency.py SmoothGradCAMpp --device cpu --weights none --output latency.json\n```\n\nEach command runs five fresh processes with one CPU thread. It reports the first call after extractor setup, then runs 10 full CAM warm-up calls before collecting 100 samples. Use `--repeat`, `--threads`, `--warmup`, and `--it` to change these settings. `--weights none` uses an untrained model and avoids downloads; omit it to use pretrained weights.\n\nThe default `--scope extractor` excludes the initial model forward pass. `--scope end-to-end` includes the forward pass and CAM extraction; both exclude image loading, preprocessing, device transfers, and extractor setup. The JSON report saves raw samples, median/p95 latency, resolved layers and weights, versions, revision, and script hash. Summary latency statistics are medians of trial statistics; memory uses the highest peak. Peak RSS is the highest RAM use of a worker through setup and measurement, including output checks. CUDA allocated and reserved memory are reported separately. RSS is unavailable on Windows.\n\nViT and Swin spatial methods preserve channel-first targets and reshape token/channel-last targets. In `eval_latency.py`, LeGrad needs an explicit transformer block (`--target-layer encoder.layers.encoder_layer_11` for `vit_b_16`), and RefineCAM needs at least two repeated `--target-layer` arguments. `cam_example.py` uses `--target` for both methods: `--target encoder.layers.encoder_layer_11` for LeGrad or `--target layer3,layer4` for RefineCAM. Targets in one extractor must share a tensor layout.\n\n*All script arguments can be checked using `python scripts/eval_latency.py --help`*\n\n### Example notebooks\n\nExplore these runnable notebooks, hosted in [frgfm/notebooks](https://github.com/frgfm/notebooks/tree/main/torch-cam):\n\nEach notebook includes setup cells that pin a development snapshot with fixes after TorchCAM 0.5.0. Run those cells to use the intended implementation.\n\n| Notebook | Use case | Run |\n|:---------|:---------|:----|\n| [Quicktour](https://github.com/frgfm/notebooks/blob/main/torch-cam/quicktour.ipynb) | Extract CAMs, create overlays, and fuse multiple layers | [Colab](https://colab.research.google.com/github/frgfm/notebooks/blob/main/torch-cam/quicktour.ipynb) |\n| [Debug a prediction](https://github.com/frgfm/notebooks/blob/main/torch-cam/debug_prediction.ipynb) | Compare predicted and expected classes and save an evidence bundle | [Colab](https://colab.research.google.com/github/frgfm/notebooks/blob/main/torch-cam/debug_prediction.ipynb) |\n| [Vision Transformers](https://github.com/frgfm/notebooks/blob/main/torch-cam/vision_transformers.ipynb) | Explain a torchvision ViT with LeGrad and token-based GradCAM | [Colab](https://colab.research.google.com/github/frgfm/notebooks/blob/main/torch-cam/vision_transformers.ipynb) |\n| [Latency benchmark](https://github.com/frgfm/notebooks/blob/main/torch-cam/latency_benchmark.ipynb) | Measure CAM extraction and end-to-end latency on your hardware | [Colab](https://colab.research.google.com/github/frgfm/notebooks/blob/main/torch-cam/latency_benchmark.ipynb) |\n| [Performance benchmark](https://github.com/frgfm/notebooks/blob/main/torch-cam/performance_benchmark.ipynb) | Evaluate confidence and deletion/insertion faithfulness with an explicit baseline | [Colab](https://colab.research.google.com/github/frgfm/notebooks/blob/main/torch-cam/performance_benchmark.ipynb) |\n\n## Author\n\nTorchCAM is created and maintained by [François-Guillaume (F-G) Fernandez](https://fgfm.dev) ([@frgfm](https://github.com/frgfm)).\n\n## Citation\n\nIf you wish to cite this project, feel free to use this [BibTeX](http://www.bibtex.org/) reference:\n\n```bibtex\n@misc{torcham2020,\n    title={TorchCAM: class activation explorer},\n    author={François-Guillaume Fernandez},\n    year={2020},\n    month={March},\n    publisher = {GitHub},\n    howpublished = {\\url{https://github.com/frgfm/torch-cam}}\n}\n```\n\n## Contributing\n\nFeeling like extending the range of possibilities of CAM? Or perhaps submitting a paper implementation? Any sort of contribution is greatly appreciated!\n\nYou can find a short guide in [`CONTRIBUTING`](CONTRIBUTING.md) to help grow this project!\n\n## License\n\nDistributed under the Apache 2.0 License. See [`LICENSE`](LICENSE) for more information.\n\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ffrgfm%2Ftorch-cam.svg?type=large\u0026issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Ffrgfm%2Ftorch-cam?ref=badge_large\u0026issueType=license)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrgfm%2Ftorch-cam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrgfm%2Ftorch-cam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrgfm%2Ftorch-cam/lists"}