2
0
mirror of https://github.com/Shawn-Shan/fawkes.git synced 2025-02-22 18:47:06 +05:30

Situation: Fawkes is a brilliant research project. I personally enjoyed reading the research paper. However, numerous issues and pull requests have resulted from how difficult it is to run after initially downloading it due to poorly documented python version requirements and compatibility collapse with numerous dependencies following ~4 years of drift. Example links in the last paragraph for brevity.

Action: I rewrote the setup code to depend on pyenv and poetry allowing us to explicitly require the use of python 3.9.0 rather than having users guess at how best to execute the code. I've used stricter dependency requirements (lots of ~= in pyproject.toml dependencies) as the project is unlikely to be maintained regularly and reviving the code required a lot of dependency incompatibility navigation we should avoid for future users.

Result: A new user can build this great research project with ~10 lines! A big win in my opinion.

Some relevant pull requests and issues.
https://github.com/Shawn-Shan/fawkes/pull/168
https://github.com/Shawn-Shan/fawkes/pull/158
https://github.com/Shawn-Shan/fawkes/issues/186
https://github.com/Shawn-Shan/fawkes/issues/178
This commit is contained in:
John Pulford 2025-02-08 22:26:46 +00:00
parent 272469421b
commit 5e9bef774d
8 changed files with 1509 additions and 121 deletions

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.9.0

View File

@ -18,6 +18,25 @@ This code is intended only for personal privacy protection or academic research.
Usage
-----
### Local Development (Most reliable and future-proof method of running fawkes)
```commandline
# Install pyenv before running these commands
# Instructions to install pyenv vary per OS.
pyenv install 3.9.0
pyenv global 3.9.0
pip install poetry
# After this point global python can be anything
# the fawkes repos .python-version file tells pyenv to use 3.9.0 when inside the fawkes folder.
pip install poetry # Install poetry
pyenv install 3.9.0
cd fawkes
poetry install
poetry run python .\fawkes\protection.py -d ./imgs --mode low
```
`$ fawkes`
Options:
@ -34,9 +53,6 @@ Options:
`fawkes -d ./imgs --mode low`
or `python3 protection.py -d ./imgs --mode low`
### Tips
- The perturbation generation takes ~60 seconds per image on a CPU machine, and it would be much faster on a GPU

View File

@ -195,7 +195,7 @@ class FawkesMaskGeneration:
dtype=tf.float32)
# make the optimizer
optimizer = tf.keras.optimizers.Adadelta(float(self.learning_rate))
optimizer = tf.keras.optimizers.legacy.Adadelta(float(self.learning_rate))
const_numpy = np.ones(len(source_imgs)) * self.initial_const
self.const = tf.Variable(const_numpy, dtype=np.float32)

View File

@ -75,7 +75,7 @@ class Fawkes(object):
extractors = ["extractor_0", "extractor_2"]
else:
raise Exception("mode must be one of 'min', 'low', 'mid', 'high'")
raise Exception("mode must be one of 'low', 'mid', 'high'")
return th, max_step, lr, extractors
def run_protection(self, image_paths, th=0.04, sd=1e7, lr=10, max_step=500, batch_size=1, format='png',

1428
poetry.lock generated Normal file

File diff suppressed because it is too large Load Diff

11
publish.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
# Publish the package
poetry publish --build
# Get the current version
VERSION=$(poetry version -s)
# Create and push a Git tag
git tag v$VERSION
git push origin v$VERSION

48
pyproject.toml Normal file
View File

@ -0,0 +1,48 @@
[project]
name = "fawkes"
version = "0.1.0"
description = ""
authors = [
{name = "Shawn Shan", email = "shawnshan@cs.uchicago.edu"}
]
license = "BSD"
homepage = "https://github.com/Shawn-Shan/fawkes"
keywords = ["fawkes", "privacy", "ML"]
classifiers = [
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Topic :: System :: Monitoring",
]
readme = "README.md"
requires-python = "~=3.9"
dependencies = [
"numpy (>=1.22,<2.0)",
"tensorflow-io-gcs-filesystem (>=0.23.1,<0.24.0)",
"tensorflow (==2.12)",
"keras (>=2.12.0,<2.13.0)",
"setuptools (>=75.8.0,<76.0.0)",
"mtcnn (>=0.1.0,<0.2.0)",
"pillow (>=11.1.0,<12.0.0)",
"bleach (>=6.2.0,<7.0.0)",
"pyqt5 (==5.15.2)",
# Despite the name amd runs this implementation fine.
# There's no built in poetry env variable that'll tell us if an AMD GPU is present (which would imply tensorflow-rocm could be a more efficient implementation).
# A script could probably be built that intelligently runs pip install under the hood but this is hard to track for a newbie.
"tensorflow-intel (==2.12.0)"
]
[tool.poetry.dependencies]
python = "~3.9"
[tool.poetry.scripts]
fawkes = "fawkes:main"
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

116
setup.py
View File

@ -1,116 +0,0 @@
import os
import re
import sys
from setuptools import setup, Command
__PATH__ = os.path.abspath(os.path.dirname(__file__))
with open("README.md", "r") as fh:
long_description = fh.read()
def read_version():
__PATH__ = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(__PATH__, 'fawkes/__init__.py')) as f:
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
f.read(), re.M)
if version_match:
return version_match.group(1)
raise RuntimeError("Unable to find __version__ string")
__version__ = read_version()
# brought from https://github.com/kennethreitz/setup.py
class DeployCommand(Command):
description = 'Build and deploy the package to PyPI.'
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
@staticmethod
def status(s):
print(s)
def run(self):
assert 'dev' not in __version__, (
"Only non-devel versions are allowed. "
"__version__ == {}".format(__version__))
with os.popen("git status --short") as fp:
git_status = fp.read().strip()
if git_status:
print("Error: git repository is not clean.\n")
os.system("git status --short")
sys.exit(1)
try:
from shutil import rmtree
self.status('Removing previous builds ...')
rmtree(os.path.join(__PATH__, 'dist'))
except OSError:
pass
self.status('Building Source and Wheel (universal) distribution ...')
os.system('{0} setup.py sdist'.format(sys.executable))
self.status('Uploading the package to PyPI via Twine ...')
ret = os.system('twine upload dist/*')
if ret != 0:
sys.exit(ret)
self.status('Creating git tags ...')
os.system('git tag v{0}'.format(__version__))
os.system('git tag --list')
sys.exit()
setup_requires = []
install_requires = [
'numpy>=1.19.5',
'tensorflow==2.4.1',
'keras==2.4.3',
'mtcnn',
'pillow>=7.0.0',
'bleach>=2.1.0'
]
setup(
name='fawkes',
version=__version__,
license='BSD',
description='An utility to protect user privacy',
long_description=long_description,
long_description_content_type='text/markdown',
url="https://github.com/Shawn-Shan/fawkes",
author='Shawn Shan',
author_email='shawnshan@cs.uchicago.edu',
keywords='fawkes privacy ML',
classifiers=[
'Development Status :: 3 - Alpha',
'License :: OSI Approved :: MIT License',
"Operating System :: OS Independent",
'Programming Language :: Python :: 3',
'Topic :: System :: Monitoring',
],
packages=['fawkes'],
install_requires=install_requires,
setup_requires=setup_requires,
entry_points={
'console_scripts': ['fawkes=fawkes:main'],
},
cmdclass={
'deploy': DeployCommand,
},
include_package_data=True,
zip_safe=False,
python_requires='>=3.5',
)