{"id":19382874,"url":"https://github.com/locuslab/projected_sinkhorn","last_synced_at":"2025-10-20T00:18:05.446Z","repository":{"id":62578119,"uuid":"170267356","full_name":"locuslab/projected_sinkhorn","owner":"locuslab","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-25T10:14:56.000Z","size":99439,"stargazers_count":88,"open_issues_count":2,"forks_count":15,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-09-25T12:27:15.754Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/locuslab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-12T06:47:47.000Z","updated_at":"2025-07-07T13:12:31.000Z","dependencies_parsed_at":"2024-11-10T09:36:50.458Z","dependency_job_id":null,"html_url":"https://github.com/locuslab/projected_sinkhorn","commit_stats":{"total_commits":13,"total_committers":1,"mean_commits":13.0,"dds":0.0,"last_synced_commit":"3bd1818e39d5e80efd3709392e70074f3e714bdb"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/locuslab/projected_sinkhorn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locuslab%2Fprojected_sinkhorn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locuslab%2Fprojected_sinkhorn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locuslab%2Fprojected_sinkhorn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locuslab%2Fprojected_sinkhorn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/locuslab","download_url":"https://codeload.github.com/locuslab/projected_sinkhorn/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locuslab%2Fprojected_sinkhorn/sbom","scorecard":{"id":596858,"data":{"date":"2025-08-11","repo":{"name":"github.com/locuslab/projected_sinkhorn","commit":"3bd1818e39d5e80efd3709392e70074f3e714bdb"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Binary-Artifacts","score":7,"reason":"binaries present in source code","details":["Warn: binary detected: projected_sinkhorn/__pycache__/__init__.cpython-36.pyc:1","Warn: binary detected: projected_sinkhorn/__pycache__/lambertw.cpython-36.pyc:1","Warn: binary detected: projected_sinkhorn/__pycache__/projected_sinkhorn.cpython-36.pyc:1"],"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":"Code-Review","score":0,"reason":"Found 0/13 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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"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":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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"}}]},"last_synced_at":"2025-08-20T23:21:01.377Z","repository_id":62578119,"created_at":"2025-08-20T23:21:01.378Z","updated_at":"2025-08-20T23:21:01.378Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001484,"owners_count":26083102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"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":[],"created_at":"2024-11-10T09:23:39.836Z","updated_at":"2025-10-09T13:31:40.173Z","avatar_url":"https://github.com/locuslab.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wasserstein Examples via Projected Sinkhorn Iterates\n\n*A repository that implements the projected sinkhorn algorithm, and applies it towards generating Wasserstein adversarial examples. Created by [Eric Wong](https://riceric22.github.io), and joint work with Frank R. Schmidt and [Zico Kolter](http://zicokolter.com). See our paper on arXiv [here][paper].*\n\n[paper]: http://arxiv.org/abs/1902.07906\n\n[lambertw]: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.special.lambertw.html\n[sinkhorn]: https://arxiv.org/abs/1306.0895\n\n## News\n+ 02/21/2019 - Initial release (v0.1) with preprint. \n+ 10/23/2019 - A certified defense against the Wasserstein attack using randomized smoothing [here](https://github.com/alevine0/wasserstein_smoothing) by Alexander Levine and Soheil Feizi\n\n## What is in this repository? \n+ An implementation of the Projected Sinkhorn Iteration for images described in our [paper][paper].\n+ A PyTorch port of the `lambertw` function [(scipy documentation)][lambertw]. \n+ Model weights for the models trained/evaluated in the paper. \n+ Training and evaluation code for adversarial training over the Wasserstein ball\n\n## Installation \u0026 Usage\nYou can install this these functions with \n`pip install projected_sinkhorn`. The package contains the following functions: \n+ `projected_sinkhorn(X, Y, C, epsilon, lam, verbose=False, plan=False, objective='2norm', maxiters=50, return_objective=False)` computes the projection of `Y` onto the Wasserstein ball around `X`. \n+ `conjugate_sinkhorn(X, Y, C, epsilon, lam, verbose=False, plan=False, objective='2norm', maxiters=50, return_objective=False)` computes the support function (conjugate) of the Wasserstein ball. \n+ `wasserstein_cost(X, p=2, kernel_size=5)` creates a cost matrix for the p-Wasserstein distance for a given kernel size. \n+ `lambertw(z0, tol=1e-5)` computes the lambertw function of `z0` on the zero branch. The code is a direct port of the zero branch of the [scipy version][lambertw]. \n\n## Why do we care about Wasserstein adversarial examples? \nWhile much work in adversarial examples research has focused on norm-bounded perturbations, these types \nof perturbations largely ignore structure that we typically believe to exist in the data. For example, \nin images we can consider transformations such as translations, rotations, or distortions to be \nsmall, adversarial changes, yet these types of transformations can be extremely large when measured \nwith respect to some p-norm. This work represents a step towards describing convex perturbation regions: \nconvex sets of allowable perturbations beyond the norm-ball, which can capture structure or invariants in \nthe application domain. \n\nTo this end, we propose adversarial examples which are close in Wasserstein distance. For images, this has \nan interpretation of moving pixel mass: two images that are close in Wasserstein distance require moving only \na small amount of pixel mass a small distance to transform one image to the other. Examples of image transformations \nthat are small in Wasserstein distance include rotations and translations. In practice, we find that adversarial examples \ngenerated within this ball have perturbations that reflect the actual content and structure of the image itself. For example, in the following figure we can see a Wasserstein perturbation on the top row, which doesn't attack the empty space around the six,  vs an l-infinity perturbation on the bottom row, which attacks all pixels indiscriminately. \n\n\u003cimg src=\"https://github.com/locuslab/projected_sinkhorn/blob/master/images/perturbation.png\" width=\"800\"\u003e\n\nWe derived a fast, modified [sinkhorn iteration][sinkhorn] that solves the projection problem onto the Wasserstein ball, and restrict our transport plans to local regions to make this tractable for image datasets. The resulting algorithm is fast enough to be run as a subroutine within a PGD adversary, and furthermore within an adversarial training loop. For CIFAR10 classifiers, we find that an adversarial radius of 0.1 is enough to fool the classifier 97% of the time (equivalent to allowing the adversary to move 10\\% of the mass one pixel), when restricted to local 5 by 5 transport plans. The main experimental results in the paper can be summarized in the following table. \n\n|          | CIFAR10 Acc | CIFAR10 Adv Acc (eps=0.1) | MNIST Acc | MNIST Adv Acc (eps=1.0) |\n| --------:| ----------:|----------:| ---------:| ------------:|\n| Standard     |       95% |       3% |     99% |          4% |\n| l-inf robust |       66% |      61% |     98% |         48% |\n| Adv training |       81% |      76% |     97% |         86% |\n| Binarization |         - |        - |     99% |         14% |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocuslab%2Fprojected_sinkhorn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocuslab%2Fprojected_sinkhorn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocuslab%2Fprojected_sinkhorn/lists"}