From e7001f063cb20f4316f51b5b06a7c5520c5b3c31 Mon Sep 17 00:00:00 2001 From: Brett Kuprel Date: Mon, 27 Jun 2022 15:46:04 -0400 Subject: [PATCH] simplified --- README.md | 18 ++- examples/alien.png | Bin 0 -> 55993 bytes image_from_text.py | 129 ++++++++++++++++++ image_from_text_flax.py | 126 ----------------- min_dalle/image_from_text.py | 70 ---------- ...ge_from_text_flax.py => min_dalle_flax.py} | 83 +++-------- .../min_dalle_torch.py | 100 ++++---------- min_dalle/models/__init__.py | 0 8 files changed, 182 insertions(+), 344 deletions(-) create mode 100644 examples/alien.png create mode 100644 image_from_text.py delete mode 100644 image_from_text_flax.py delete mode 100644 min_dalle/image_from_text.py rename min_dalle/{image_from_text_flax.py => min_dalle_flax.py} (52%) rename image_from_text_torch.py => min_dalle/min_dalle_torch.py (55%) delete mode 100644 min_dalle/models/__init__.py diff --git a/README.md b/README.md index d9ef931..eef8bc5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# min DALL·E +# min(DALL·E) This is a minimal implementation of [DALL·E Mini](https://github.com/borisdayma/dalle-mini) in both Flax and PyTorch @@ -11,21 +11,19 @@ Run `sh setup.sh` to install dependencies and download pretrained models. The o Here are some examples ``` -python3 image_from_text_flax.py \ - --dalle_bart_path='./pretrained/dalle_bart_mega' \ - --vqgan_path='./pretrained/vqgan' \ - --image_path='./generated/avacado_armchair_flax.png' \ - --seed=4 \ +python3 image_from_text.py --text='alien life' --seed=7 +``` +![Alien](examples/alien.png) + +``` +python3 image_from_text.py --mega --seed=4 \ --text='a comfy chair that looks like an avocado' ``` ![Avocado Armchair](examples/avocado_armchair.png) ``` -python3 image_from_text_flax.py \ - --dalle_path='./pretrained/dalle-mega' \ - --seed=100 \ - --image_path='./generated/godzilla_trial.png' \ +python3 image_from_text.py --mega --seed=100 \ --text='court sketch of godzilla on trial' ``` diff --git a/examples/alien.png b/examples/alien.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4c59b4bed353a546153fbbd36fc56b6a91b793 GIT binary patch literal 55993 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 O0000 Tuple[dict, dict, List[str]]: + print("loading model") + for f in ['config.json', 'flax_model.msgpack', 'vocab.json', 'merges.txt']: + assert(os.path.exists(os.path.join(path, f))) + with open(path + '/config.json', 'r') as f: + config = json.load(f) + with open(path + '/vocab.json') as f: + vocab = json.load(f) + with open(path + '/merges.txt') as f: + merges = f.read().split("\n")[1:-1] + return config, vocab, merges + + +def ascii_from_image(image: Image.Image, size: int) -> str: + rgb_pixels = image.resize((size, int(0.55 * size))).convert('L').getdata() + chars = list('.,;/IOX') + chars = [chars[i * len(chars) // 256] for i in rgb_pixels] + chars = [chars[i * size: (i + 1) * size] for i in range(size // 2)] + return '\n'.join(''.join(row) for row in chars) + + +def save_image(image: numpy.ndarray, path: str) -> Image.Image: + if os.path.isdir(path): + path = os.path.join(path, 'generated.png') + elif not path.endswith('.png'): + path += '.png' + print("saving image to", path) + image: Image.Image = Image.fromarray(numpy.asarray(image)) + image.save(path) + return image + + +def tokenize_text( + text: str, + config: dict, + vocab: dict, + merges: List[str] +) -> numpy.ndarray: + print("tokenizing text") + tokens = TextTokenizer(vocab, merges)(text) + print("text tokens", tokens) + text_tokens = numpy.ones((2, config['max_text_length']), dtype=numpy.int32) + text_tokens[0, :len(tokens)] = tokens + text_tokens[1, :2] = [tokens[0], tokens[-1]] + return text_tokens + + +if __name__ == '__main__': + args = parser.parse_args() + + model_name = 'mega' if args.mega == True else 'mini' + model_path = './pretrained/dalle_bart_{}'.format(model_name) + config, vocab, merges = load_dalle_bart_metadata(model_path) + text_tokens = tokenize_text(args.text, config, vocab, merges) + params_dalle_bart = load_dalle_bart_flax_params(model_path) + + image_tokens = numpy.zeros(config['image_length']) + if args.torch == True: + image_tokens[:args.image_token_count] = generate_image_tokens_torch( + text_tokens = text_tokens, + seed = args.seed, + config = config, + params = params_dalle_bart, + image_token_count = args.image_token_count + ) + else: + image_tokens[...] = generate_image_tokens_flax( + text_tokens = text_tokens, + seed = args.seed, + config = config, + params = params_dalle_bart, + ) + + if args.image_token_count == config['image_length']: + image = detokenize_torch(image_tokens) + image = save_image(image, args.image_path) + print(ascii_from_image(image, size=128)) \ No newline at end of file diff --git a/image_from_text_flax.py b/image_from_text_flax.py deleted file mode 100644 index 7dfea9e..0000000 --- a/image_from_text_flax.py +++ /dev/null @@ -1,126 +0,0 @@ -import jax -from jax import numpy as jnp -import numpy -import argparse - -from min_dalle.load_params import load_dalle_bart_flax_params -from min_dalle.image_from_text import ( - load_dalle_bart_metadata, - tokenize, - detokenize_torch, - save_image, - ascii_from_image -) -from min_dalle.models.dalle_bart_encoder_flax import DalleBartEncoderFlax -from min_dalle.models.dalle_bart_decoder_flax import DalleBartDecoderFlax - - -parser = argparse.ArgumentParser() -parser.add_argument( - '--text', - help='text to generate image from', - type=str -) -parser.add_argument( - '--seed', - help='random seed', - type=int, - default=0 -) -parser.add_argument( - '--image_path', - help='generated image path', - type=str, - default='generated.png' -) -parser.add_argument( - '--dalle_bart_path', - help='pretraied dalle bart path', - type=str, - default='./pretrained/dalle_bart_mini' -) -parser.add_argument( - '--vqgan_path', - help='pretraied vqgan path', - type=str, - default='./pretrained/vqgan' -) - - -def encode_flax( - text_tokens: numpy.ndarray, - config: dict, - params: dict -) -> jnp.ndarray: - print("loading flax encoder") - encoder: DalleBartEncoderFlax = DalleBartEncoderFlax( - attention_head_count = config['encoder_attention_heads'], - embed_count = config['d_model'], - glu_embed_count = config['encoder_ffn_dim'], - text_token_count = config['max_text_length'], - text_vocab_count = config['encoder_vocab_size'], - layer_count = config['encoder_layers'] - ).bind({'params': params.pop('encoder')}) - - print("encoding text tokens") - encoder_state = encoder(text_tokens) - del encoder - return encoder_state - -def decode_flax( - text_tokens: jnp.ndarray, - encoder_state: jnp.ndarray, - config: dict, - seed: int, - params: dict -) -> jnp.ndarray: - print("loading flax decoder") - decoder = DalleBartDecoderFlax( - image_token_count = config['image_length'], - text_token_count = config['max_text_length'], - image_vocab_count = config['image_vocab_size'], - attention_head_count = config['decoder_attention_heads'], - embed_count = config['d_model'], - glu_embed_count = config['decoder_ffn_dim'], - layer_count = config['decoder_layers'], - start_token = config['decoder_start_token_id'] - ) - print("sampling image tokens") - image_tokens = decoder.sample_image_tokens( - text_tokens, - encoder_state, - jax.random.PRNGKey(seed), - params.pop('decoder') - ) - del decoder - return image_tokens - -def generate_image_tokens_flax( - text: str, - seed: int, - dalle_bart_path: str -) -> numpy.ndarray: - config, vocab, merges = load_dalle_bart_metadata(dalle_bart_path) - text_tokens = tokenize(text, config, vocab, merges) - params_dalle_bart = load_dalle_bart_flax_params(dalle_bart_path) - encoder_state = encode_flax(text_tokens, config, params_dalle_bart) - image_tokens = decode_flax( - text_tokens, - encoder_state, - config, seed, - params_dalle_bart - ) - return numpy.array(image_tokens) - -if __name__ == '__main__': - args = parser.parse_args() - - image_tokens = generate_image_tokens_flax( - args.text, - args.seed, - args.dalle_bart_path - ) - print("image tokens", list(image_tokens)) - image = detokenize_torch(image_tokens, args.vqgan_path) - image = save_image(image, args.image_path) - print(ascii_from_image(image, size=128)) \ No newline at end of file diff --git a/min_dalle/image_from_text.py b/min_dalle/image_from_text.py deleted file mode 100644 index ea836ba..0000000 --- a/min_dalle/image_from_text.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -import json -import numpy -import torch -from PIL import Image -from typing import Tuple, List - -from .text_tokenizer import TextTokenizer -from .models.vqgan_detokenizer import VQGanDetokenizer -from .load_params import load_vqgan_torch_params - - -def load_dalle_bart_metadata(path: str) -> Tuple[dict, dict, List[str]]: - print("loading model") - for f in ['config.json', 'flax_model.msgpack', 'vocab.json', 'merges.txt']: - assert(os.path.exists(os.path.join(path, f))) - with open(path + '/config.json', 'r') as f: - config = json.load(f) - with open(path + '/vocab.json') as f: - vocab = json.load(f) - with open(path + '/merges.txt') as f: - merges = f.read().split("\n")[1:-1] - return config, vocab, merges - - -def ascii_from_image(image: Image.Image, size: int) -> str: - rgb_pixels = image.resize((size, int(0.55 * size))).convert('L').getdata() - chars = list('.,;/IOX') - chars = [chars[i * len(chars) // 256] for i in rgb_pixels] - chars = [chars[i * size: (i + 1) * size] for i in range(size // 2)] - return '\n'.join(''.join(row) for row in chars) - - -def save_image(image: numpy.ndarray, path: str) -> Image.Image: - if os.path.isdir(path): - path = os.path.join(path, 'generated.png') - elif not path.endswith('.png'): - path += '.png' - print("saving image to", path) - image: Image.Image = Image.fromarray(numpy.asarray(image)) - image.save(path) - return image - - -def tokenize( - text: str, - config: dict, - vocab: dict, - merges: List[str] -) -> numpy.ndarray: - print("tokenizing text") - tokens = TextTokenizer(vocab, merges)(text) - print("text tokens", tokens) - text_tokens = numpy.ones((2, config['max_text_length']), dtype=numpy.int32) - text_tokens[0, :len(tokens)] = tokens - text_tokens[1, :2] = [tokens[0], tokens[-1]] - return text_tokens - - -def detokenize_torch( - image_tokens: numpy.ndarray, - model_path: str -) -> numpy.ndarray: - print("detokenizing image") - params = load_vqgan_torch_params(model_path) - detokenizer = VQGanDetokenizer() - detokenizer.load_state_dict(params) - image_tokens = torch.tensor(image_tokens).to(torch.long) - image = detokenizer.forward(image_tokens).to(torch.uint8) - return image.detach().numpy() \ No newline at end of file diff --git a/min_dalle/image_from_text_flax.py b/min_dalle/min_dalle_flax.py similarity index 52% rename from min_dalle/image_from_text_flax.py rename to min_dalle/min_dalle_flax.py index 3f6f56a..884f271 100644 --- a/min_dalle/image_from_text_flax.py +++ b/min_dalle/min_dalle_flax.py @@ -1,50 +1,9 @@ import jax from jax import numpy as jnp import numpy -import argparse -from load_params import load_dalle_bart_flax_params -from image_from_text import ( - load_dalle_bart_metadata, - tokenize, - detokenize_torch, - save_image, - ascii_from_image -) -from models.dalle_bart_encoder_flax import DalleBartEncoderFlax -from models.dalle_bart_decoder_flax import DalleBartDecoderFlax - - -parser = argparse.ArgumentParser() -parser.add_argument( - '--text', - help='text to generate image from', - type=str -) -parser.add_argument( - '--seed', - help='random seed', - type=int, - default=0 -) -parser.add_argument( - '--image_path', - help='generated image path', - type=str, - default='generated.png' -) -parser.add_argument( - '--dalle_bart_path', - help='pretraied dalle bart path', - type=str, - default='./pretrained/dalle_bart_mini' -) -parser.add_argument( - '--vqgan_path', - help='pretraied vqgan path', - type=str, - default='./pretrained/vqgan' -) +from .models.dalle_bart_encoder_flax import DalleBartEncoderFlax +from .models.dalle_bart_decoder_flax import DalleBartDecoderFlax def encode_flax( @@ -67,6 +26,7 @@ def encode_flax( del encoder return encoder_state + def decode_flax( text_tokens: jnp.ndarray, encoder_state: jnp.ndarray, @@ -95,32 +55,25 @@ def decode_flax( del decoder return image_tokens + def generate_image_tokens_flax( - text: str, - seed: int, - dalle_bart_path: str + text_tokens: numpy.ndarray, + seed: int, + config: dict, + params: dict ) -> numpy.ndarray: - config, vocab, merges = load_dalle_bart_metadata(dalle_bart_path) - text_tokens = tokenize(text, config, vocab, merges) - params_dalle_bart = load_dalle_bart_flax_params(dalle_bart_path) - encoder_state = encode_flax(text_tokens, config, params_dalle_bart) + encoder_state = encode_flax( + text_tokens, + config, + params + ) image_tokens = decode_flax( text_tokens, encoder_state, - config, seed, - params_dalle_bart - ) - return numpy.array(image_tokens) - -if __name__ == '__main__': - args = parser.parse_args() - - image_tokens = generate_image_tokens_flax( - args.text, - args.seed, - args.dalle_bart_path + config, + seed, + params ) + image_tokens = numpy.array(image_tokens) print("image tokens", list(image_tokens)) - image = detokenize_torch(image_tokens, args.vqgan_path) - image = save_image(image, args.image_path) - print(ascii_from_image(image, size=128)) \ No newline at end of file + return image_tokens \ No newline at end of file diff --git a/image_from_text_torch.py b/min_dalle/min_dalle_torch.py similarity index 55% rename from image_from_text_torch.py rename to min_dalle/min_dalle_torch.py index 2642d22..ad7b8eb 100644 --- a/image_from_text_torch.py +++ b/min_dalle/min_dalle_torch.py @@ -1,61 +1,17 @@ import numpy import torch from torch import Tensor -import argparse from typing import Dict -from min_dalle.image_from_text import ( - load_dalle_bart_metadata, - tokenize, - detokenize_torch, - save_image, - ascii_from_image -) -from min_dalle.models.dalle_bart_encoder_torch import DalleBartEncoderTorch -from min_dalle.models.dalle_bart_decoder_torch import DalleBartDecoderTorch +from .models.vqgan_detokenizer import VQGanDetokenizer +from .models.dalle_bart_encoder_torch import DalleBartEncoderTorch +from .models.dalle_bart_decoder_torch import DalleBartDecoderTorch -from min_dalle.load_params import ( - load_dalle_bart_flax_params, +from .load_params import ( + load_vqgan_torch_params, convert_dalle_bart_torch_from_flax_params ) -parser = argparse.ArgumentParser() -parser.add_argument( - '--text', - help='text to generate image from', - type=str -) -parser.add_argument( - '--seed', - help='random seed', - type=int, - default=0 -) -parser.add_argument( - '--image_token_count', - help='image tokens to sample', - type=int, - default=256 -) -parser.add_argument( - '--image_path', - help='generated image path', - type=str, - default='generated.png' -) -parser.add_argument( - '--dalle_bart_path', - help='pretraied dalle bart path', - type=str, - default='./pretrained/dalle_bart_mini' -) -parser.add_argument( - '--vqgan_path', - help='pretraied vqgan path', - type=str, - default='./pretrained/vqgan' -) - def encode_torch( text_tokens: numpy.ndarray, @@ -123,37 +79,35 @@ def decode_torch( def generate_image_tokens_torch( - text: str, - seed: int, - image_token_count: int, - dalle_bart_path: str + text_tokens: numpy.ndarray, + seed: int, + config: dict, + params: dict, + image_token_count: int ) -> numpy.ndarray: - config, vocab, merges = load_dalle_bart_metadata(dalle_bart_path) - text_tokens = tokenize(text, config, vocab, merges) - params_dalle_bart = load_dalle_bart_flax_params(dalle_bart_path) - encoder_state = encode_torch(text_tokens, config, params_dalle_bart) + encoder_state = encode_torch( + text_tokens, + config, + params + ) image_tokens = decode_torch( text_tokens, encoder_state, - config, seed, params_dalle_bart, + config, + seed, + params, image_token_count ) return image_tokens.detach().numpy() -if __name__ == '__main__': - args = parser.parse_args() - image_tokens = generate_image_tokens_torch( - args.text, - args.seed, - args.image_token_count, - args.dalle_bart_path - ) - if args.image_token_count < 256: - print("image tokens", list(image_tokens, )) - else: - image = detokenize_torch(image_tokens, args.vqgan_path) - image = save_image(image, args.image_path) - print(ascii_from_image(image, size=128)) - +def detokenize_torch(image_tokens: numpy.ndarray) -> numpy.ndarray: + print("detokenizing image") + model_path = './pretrained/vqgan' + params = load_vqgan_torch_params(model_path) + detokenizer = VQGanDetokenizer() + detokenizer.load_state_dict(params) + image_tokens = torch.tensor(image_tokens).to(torch.long) + image = detokenizer.forward(image_tokens).to(torch.uint8) + return image.detach().numpy() \ No newline at end of file diff --git a/min_dalle/models/__init__.py b/min_dalle/models/__init__.py deleted file mode 100644 index e69de29..0000000