Skip to content

Commit

Permalink
there is nothing to it
Browse files Browse the repository at this point in the history
  • Loading branch information
lucidrains committed Jun 1, 2023
1 parent 5a7b0c7 commit 1c2f18c
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 5 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@


# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Upload Python Package

on:
release:
types: [published]

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,55 @@
# TPDNE (wip)
## TPDNE (wip)

Thispersondoesnotexist went down, so this time, while building it back up, I am going to open source all of it. I'll try to make it modular enough so anyone can deploy their own ever-dreaming GAN (or soon to be 1-2 step DDPM) to be public facing
<a href="https://twitter.com/kasiababis/status/1379370542986330112">Thispersondoesnotexist</a> went down, so this time, while building it back up, I am going to open source all of it. I'll try to make it modular enough so anyone can deploy their own ever-dreaming GAN (or soon to be 1-2 step DDPM) to be public facing

I may also take some time to do something I've always wanted. To Dreambooth my dog into the machine and have it dream her up forever to the public.

## Explained

The site is hosted on Hetzner on a 100$ / month GPU server. Images are generated live, so people, try as they might, cannot exhaust the amount of faces they experience. Through this, they gain an intuition for how vast the latent space of these neural networks are. It also allowed me to explain it to laypeople as having an 'artificial intelligence endlessly dreaming', without it having to be an exaggeration.

How was this feasible without scaling issues? Well, the site is actually a magic trick. Each user, when refreshing the page, actually sees the same image at any point in time. Images are replaced every 250ms, below the human reaction time. By the time the user studies the face and refreshes, the next face will be there, but it is the same face that everyone experiences around the world at the same time.

The model itself was trained by <a href="https://research.nvidia.com/person/tero-karras">Tero Karras</a> under the name <a href="https://arxiv.org/abs/1912.04958">StyleGAN 2</a>.

## Install

```bash
$ pip install TPDNE-utils
```

## Usage

```python
from TPDNE_utils import sample_image_and_save_repeatedly

# some function that returns a sampled image in the form of a 3 dimensional ndarray

def generate_image():
import numpy as np
return np.random.randn(3, 1024, 1024)

# saves a new sampled image every 250ms as out/sampled.webp

sample_image_and_save_repeatedly(generate_image, 'out/sampled')

# use pm2 (node process manager) to run this script
# then use nginx to serve out/sampled.web
# optionally put behind cloudflare

```

## Todo

- [ ] take care of an nginx template that can be generated from a command-line

## Citations

```bibtex
@inproceedings{Karras2020ada,
title = {Training Generative Adversarial Networks with Limited Data},
author = {Tero Karras and Miika Aittala and Janne Hellsten and Samuli Laine and Jaakko Lehtinen and Timo Aila},
booktitle = {Proc. NeurIPS},
year = {2020}
}
```
Empty file removed TPDNE/__init__.py
Empty file.
Empty file removed TPDNE/tpdne.py
Empty file.
1 change: 1 addition & 0 deletions TPDNE_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from TPDNE_utils.tpdne import sample_image_and_save_repeatedly
48 changes: 48 additions & 0 deletions TPDNE_utils/tpdne.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import numpy as np
from time import time, sleep
from pathlib import Path
from functools import wraps
from PIL import Image

from beartype import beartype
from beartype.typing import Callable

@beartype
def sample_image_and_save_repeatedly(
fn: Callable[..., np.ndarray], # function that returns a ndarray of shape (3, <width>, <height>)
output_path: str = './out/random', # path to the output image, without extension (will be saved as webp)
*,
call_every_ms: int = 250, # how often to sample
tmp_dir = '/tmp', # to store temporary images, before symbolically linking to the output path
num_rotated_tmp_images = 10,
verbose: bool = True
):
tmp_dir = Path(tmp_dir)
output_path = Path(output_path).with_suffix('.webp')
call_every_seconds = call_every_ms / 1000

assert tmp_dir.is_dir()
output_path.parents[0].mkdir(parents = True, exist_ok = True)

tmp_image_index = 0

while True:
start = time()
image_tensor = fn()

tmp_image_index = (tmp_image_index + 1) % num_rotated_tmp_images
tmp_path = str(tmp_dir / f'{tmp_image_index}.webp')

Image.fromarray(image_tensor, 'RGB').save(tmp_path, format = 'webp')
os.system(f'ln -nfs {tmp_path} {output_path}')

elapsed = time() - start

if verbose:
print(f'{elapsed:.3f}s - tmp image at {tmp_path}, output image at {output_path}')

if elapsed >= call_every_seconds:
continue

sleep(call_every_seconds - elapsed)
10 changes: 7 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
from setuptools import setup, find_packages

setup(
name = 'TPDNE',
name = 'TPDNE-utils',
packages = find_packages(exclude=[]),
version = '0.0.1',
version = '0.0.2',
license='MIT',
description = 'TPDNE',
author = 'Phil Wang',
author_email = 'lucidrains@gmail.com',
long_description_content_type = 'text/markdown',
url = 'https://github.com/lucidrains/TPDNE',
keywords = [],
install_requires=[],
install_requires = [
'beartype',
'numpy',
'pillow'
],
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
Expand Down

0 comments on commit 1c2f18c

Please sign in to comment.