From f965a2b32c09477a9c76270e7b078bcb2f2b7f7d Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Fri, 8 Apr 2022 14:54:56 +0300 Subject: [PATCH 1/8] feat: sn-gan --- huggan/pytorch/sngan/README.md | 0 huggan/pytorch/sngan/__init__.py | 0 huggan/pytorch/sngan/train.py | 341 +++++++++++++++++++++++++++++++ 3 files changed, 341 insertions(+) create mode 100644 huggan/pytorch/sngan/README.md create mode 100644 huggan/pytorch/sngan/__init__.py create mode 100644 huggan/pytorch/sngan/train.py diff --git a/huggan/pytorch/sngan/README.md b/huggan/pytorch/sngan/README.md new file mode 100644 index 00000000..e69de29b diff --git a/huggan/pytorch/sngan/__init__.py b/huggan/pytorch/sngan/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/huggan/pytorch/sngan/train.py b/huggan/pytorch/sngan/train.py new file mode 100644 index 00000000..7cd51f63 --- /dev/null +++ b/huggan/pytorch/sngan/train.py @@ -0,0 +1,341 @@ +# Note - training loop and architectures are modified from https://github.com/pytorch/examples/blob/master/dcgan/main.py + +import argparse +import csv +import logging +import random +from pathlib import Path + +import pandas as pd +import torch +import torch.backends.cudnn as cudnn +import torch.nn as nn +import torch.optim as optim +import torch.utils.data +import torchvision.transforms as transforms +import torchvision.utils as vutils +from PIL import Image +from torch.nn.utils.parametrizations import spectral_norm +from torch.utils.data import DataLoader +from torchvision.transforms import (CenterCrop, Compose, Normalize, Resize, + ToTensor, ToPILImage) +from datasets import load_dataset +import tqdm +from accelerate import Accelerator + +logger = logging.getLogger(__name__) + + +class AverageMeter: + def __init__(self): + self.reset() + + def reset(self): + self.val, self.avg, self.sum, self.count = 0, 0, 0, 0 + + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + def __str__(self): + return str(self.avg) + + +def get_attributes(): + """ + Read punk attributes file and form one-hot matrix + """ + df = pd.concat( + [ + pd.read_csv(f, sep=", ", engine="python") + for f in Path("attributes").glob("*.csv") + ] + ) + accessories = df["accessories"].str.get_dummies(sep=" / ") + type_ = df["type"].str.get_dummies() + gender = df["gender"].str.get_dummies() + + return pd.concat([df["id"], accessories, type_, gender], axis=1).set_index("id") + + +# folder dataset +class Punks(torch.utils.data.Dataset): + def __init__(self, path, size=10_000): + self.path = Path(path) + self.size = size + # self.attributes = get_attributes() + self.transform = transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5, 0.5), (0.5, 0.5, 0.5, 0.5)), + ] + ) + + def __len__(self): + return self.size + + def __getitem__(self, index): + # randomly select attribute + # attribute = random.choice(self.attributes.columns) + # randomly select punk with that attribute + id_ = random.randint(0, self.size - 1) + + return self.transform( + Image.open(self.path / f"punk{int(id_):03}.png").convert("RGBA") + ) + + +# Custom weights initialization called on Generator and Discriminator +def weights_init(m): + classname = m.__class__.__name__ + if classname.find("Conv") != -1: + nn.init.normal_(m.weight.data, 0.0, 0.02) + elif classname.find("BatchNorm") != -1: + nn.init.normal_(m.weight.data, 1.0, 0.02) + nn.init.constant_(m.bias.data, 0) + + +class Generator(nn.Module): + def __init__(self, nc=4, nz=100, ngf=64): + super(Generator, self).__init__() + self.network = nn.Sequential( + nn.ConvTranspose2d(nz, ngf * 4, 3, 1, 0, bias=False), + nn.BatchNorm2d(ngf * 4), + nn.ReLU(True), + nn.ConvTranspose2d(ngf * 4, ngf * 2, 3, 2, 1, bias=False), + nn.BatchNorm2d(ngf * 2), + nn.ReLU(True), + nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 0, bias=False), + nn.BatchNorm2d(ngf), + nn.ReLU(True), + nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False), + nn.Tanh(), + ) + + def forward(self, input): + output = self.network(input) + return output + + +class Discriminator(nn.Module): + def __init__(self, nc, ndf): + super(Discriminator, self).__init__() + self.network = nn.Sequential( + spectral_norm(nn.Conv2d(nc, ndf, 4, 2, 1, bias=False)), + nn.LeakyReLU(0.2, inplace=True), + + spectral_norm(nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False)), + nn.LeakyReLU(0.2, inplace=True), + + spectral_norm(nn.Conv2d(ndf * 2, ndf * 4, 3, 2, 1, bias=False)), + nn.LeakyReLU(0.2, inplace=True), + + spectral_norm(nn.Conv2d(ndf * 4, 1, 3, 1, 0, bias=False)), + nn.Sigmoid(), + ) + + def forward(self, input): + output = self.network(input) + return output.view(-1, 1).squeeze(1) + + +def main(args): + # Initialize the accelerator. We will let the accelerator handle device placement for us in this example. + accelerator = Accelerator(fp16=args.fp16, cpu=args.cpu, mixed_precision=args.mixed_precision) + + # Setup logging, we only want one process per machine to log things on the screen. + # accelerator.is_local_main_process is only True for one process per machine. + logger.setLevel(logging.INFO if accelerator.is_local_main_process else logging.ERROR) + if accelerator.is_local_main_process: + # set up Weights and Biases if requested + if args.wandb: + import wandb + + wandb.init(project=str(args.output_dir).split("/")[-1]) + + Path(args.output_dir).mkdir(exist_ok=True) + + # for reproducibility + random.seed(args.manual_seed) + torch.manual_seed(args.manual_seed) + cudnn.benchmark = True + + dataset = load_dataset("AlekseyKorshuk/dooggies") + + image_size = 24 + transform = Compose( + [ + Resize(image_size), + ToTensor(), + Normalize((0.5, 0.5, 0.5, 0.5), (0.5, 0.5, 0.5, 0.5)), + ] + ) + + def transforms(examples): + examples["pixel_values"] = [transform(image.convert("RGBA")) for image in examples["image"]] + + del examples["image"] + + return examples + + transformed_dataset = dataset.with_transform(transforms) + + dataloader = DataLoader( + transformed_dataset["train"], batch_size=args.batch_size, shuffle=True, num_workers=args.workers + ) + + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + + net_g = Generator(args.nc, args.nz, args.ngf).to(device) + net_g.apply(weights_init) + + net_d = Discriminator(args.nc, args.ndf).to(device) + net_d.apply(weights_init) + + criterion = nn.BCEWithLogitsLoss() + + fixed_noise = torch.randn(args.batch_size, args.nz, 1, 1, device=device) + real_label = 1 + fake_label = 0 + + # setup optimizer + optimizer_d = optim.Adam(net_d.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) + optimizer_g = optim.Adam(net_g.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) + + net_g, net_d, optimizer_g, optimizer_d, dataloader = accelerator.prepare(net_g, net_d, optimizer_g, optimizer_d, dataloader) + + with open(f"{args.output_dir}/logs.csv", "w") as f: + csv.writer(f).writerow(["epoch", "loss_g", "loss_d", "d_x", "d_g_z1", "d_g_z2"]) + + for epoch in tqdm.tqdm(range(args.niter)): + + avg_loss_g = AverageMeter() + avg_loss_d = AverageMeter() + avg_d_x = AverageMeter() + avg_d_g_z1 = AverageMeter() + avg_d_g_z2 = AverageMeter() + + for data in dataloader: + ############################ + # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z))) + ########################### + # train with real + net_d.zero_grad() + real_cpu = data["pixel_values"].to(device) + + batch_size = real_cpu.size(0) + label = torch.full((batch_size,), real_label, dtype=torch.float, device=accelerator.device) + + output = net_d(real_cpu).view(-1) + loss_d_real = criterion(output, label) + accelerator.backward(loss_d_real) + + avg_d_x.update(output.mean().item(), batch_size) + + # train with fake + noise = torch.randn(batch_size, args.nz, 1, 1, device=accelerator.device) + fake = net_g(noise) + label.fill_(fake_label) + output = net_d(fake.detach()) + loss_d_fake = criterion(output, label) + accelerator.backward(loss_d_fake) + optimizer_d.step() + + avg_loss_d.update((loss_d_real + loss_d_fake).item(), batch_size) + avg_d_g_z1.update(output.mean().item()) + + ############################ + # (2) Update G network: maximize log(D(G(z))) + ########################### + net_g.zero_grad() + label.fill_(real_label) # fake labels are real for generator cost + output = net_d(fake) + # minimize loss but also maximize alpha channel + loss_g = criterion(output, label) + fake[:, -1].mean() + accelerator.backward(loss_g) + optimizer_g.step() + + avg_loss_g.update(loss_g.item(), batch_size) + avg_d_g_z2.update(output.mean().item()) + + # write logs + with open(f"{args.output_dir}/logs.csv", "a") as f: + csv.writer(f).writerow( + [epoch, avg_loss_g, avg_loss_d, avg_d_x, avg_d_g_z1, avg_d_g_z2] + ) + + train_logs = { + "epoch": epoch, + "discriminator_loss": avg_loss_d.avg, + "generator_loss": avg_loss_g.avg, + "D_x": avg_d_x.avg, + "D_G_z1": avg_d_g_z1.avg, + "D_G_z2": avg_d_g_z2.avg, + } + if accelerator.is_local_main_process: + if args.wandb: + wandb.log(train_logs) + + if (epoch + 1) % args.save_every == 0: + # save samples + fake = net_g(fixed_noise) + file_name = f"{args.output_dir}/fake_samples_epoch_{epoch}.png" + vutils.save_image( + fake.detach(), + file_name, + normalize=True, + ) + + if accelerator.is_local_main_process and args.wandb: + wandb.log({'generated_examples': wandb.Image(str(file_name))}) + + # save_checkpoints + torch.save(net_g.state_dict(), f"{args.output_dir}/net_g_epoch_{epoch}.pth") + torch.save(net_d.state_dict(), f"{args.output_dir}/net_d_epoch_{epoch}.pth") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--dataroot", default="data", help="path to dataset") + parser.add_argument( + "--workers", type=int, help="number of data loading workers", default=0 + ) + parser.add_argument("--batch_size", type=int, default=64, help="input batch size") + parser.add_argument( + "--nz", type=int, default=100, help="size of the latent z vector" + ) + parser.add_argument("--ngf", type=int, default=64) + parser.add_argument("--ndf", type=int, default=64) + parser.add_argument( + "--niter", type=int, default=1000, help="number of epochs to train for" + ) + parser.add_argument("--save_every", type=int, default=10, help="how often to save") + parser.add_argument( + "--lr", type=float, default=0.0002, help="learning rate, default=0.0002" + ) + parser.add_argument( + "--beta1", type=float, default=0.5, help="beta1 for adam. default=0.5" + ) + parser.add_argument( + "--output_dir", default="out-test", help="folder to output images and model checkpoints" + ) + parser.add_argument("--manual_seed", type=int, default=0, help="manual seed") + parser.add_argument("--wandb", action="store_true", help="if passed, will log to Weights and Biases.") + parser.add_argument("--fp16", action="store_true", help="If passed, will use FP16 training.") + parser.add_argument("--cpu", action="store_true", help="If passed, will train on the CPU.") + parser.add_argument( + "--mixed_precision", + type=str, + default="no", + choices=["no", "fp16", "bf16"], + help="Whether to use mixed precision. Choose" + "between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10." + "and an Nvidia Ampere GPU.", + ) + args = parser.parse_args() + args.cuda = True + args.nc = 4 + print(args) + main(args) From 59cf889715fc492a9c1c01a8a037be9c588f621f Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Fri, 8 Apr 2022 15:47:08 +0300 Subject: [PATCH 2/8] feat: sn-gan --- huggan/pytorch/sngan/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/huggan/pytorch/sngan/train.py b/huggan/pytorch/sngan/train.py index 7cd51f63..bde9be9d 100644 --- a/huggan/pytorch/sngan/train.py +++ b/huggan/pytorch/sngan/train.py @@ -194,7 +194,7 @@ def transforms(examples): net_d = Discriminator(args.nc, args.ndf).to(device) net_d.apply(weights_init) - criterion = nn.BCEWithLogitsLoss() + criterion = nn.BCELoss() fixed_noise = torch.randn(args.batch_size, args.nz, 1, 1, device=device) real_label = 1 From 6ec3559e1e5aa880f70873e269368630dd5281b9 Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Fri, 8 Apr 2022 18:59:45 +0300 Subject: [PATCH 3/8] feat: sn-gan --- huggan/pytorch/sngan/train.py | 42 ++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/huggan/pytorch/sngan/train.py b/huggan/pytorch/sngan/train.py index bde9be9d..468d3e33 100644 --- a/huggan/pytorch/sngan/train.py +++ b/huggan/pytorch/sngan/train.py @@ -101,17 +101,26 @@ class Generator(nn.Module): def __init__(self, nc=4, nz=100, ngf=64): super(Generator, self).__init__() self.network = nn.Sequential( - nn.ConvTranspose2d(nz, ngf * 4, 3, 1, 0, bias=False), + # input is Z, going into a convolution + nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False), + nn.BatchNorm2d(ngf * 8), + nn.ReLU(True), + # state size. (ngf*8) x 4 x 4 + nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 4), nn.ReLU(True), - nn.ConvTranspose2d(ngf * 4, ngf * 2, 3, 2, 1, bias=False), + # state size. (ngf*4) x 8 x 8 + nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 2), nn.ReLU(True), - nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 0, bias=False), + # state size. (ngf*2) x 16 x 16 + nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf), nn.ReLU(True), - nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False), - nn.Tanh(), + # state size. (ngf) x 32 x 32 + nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False), + nn.Tanh() + # state size. (nc) x 64 x 64 ) def forward(self, input): @@ -123,17 +132,24 @@ class Discriminator(nn.Module): def __init__(self, nc, ndf): super(Discriminator, self).__init__() self.network = nn.Sequential( + # input is (nc) x 64 x 64 spectral_norm(nn.Conv2d(nc, ndf, 4, 2, 1, bias=False)), nn.LeakyReLU(0.2, inplace=True), - + # state size. (ndf) x 32 x 32 spectral_norm(nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False)), + # nn.BatchNorm2d(ndf * 2), nn.LeakyReLU(0.2, inplace=True), - - spectral_norm(nn.Conv2d(ndf * 2, ndf * 4, 3, 2, 1, bias=False)), + # state size. (ndf*2) x 16 x 16 + spectral_norm(nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False)), + # nn.BatchNorm2d(ndf * 4), nn.LeakyReLU(0.2, inplace=True), - - spectral_norm(nn.Conv2d(ndf * 4, 1, 3, 1, 0, bias=False)), - nn.Sigmoid(), + # state size. (ndf*4) x 8 x 8 + spectral_norm(nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False)), + # nn.BatchNorm2d(ndf * 8), + nn.LeakyReLU(0.2, inplace=True), + # state size. (ndf*8) x 4 x 4 + spectral_norm(nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False)), + nn.Sigmoid() ) def forward(self, input): @@ -164,7 +180,7 @@ def main(args): dataset = load_dataset("AlekseyKorshuk/dooggies") - image_size = 24 + image_size = 64 transform = Compose( [ Resize(image_size), @@ -311,7 +327,7 @@ def transforms(examples): parser.add_argument( "--niter", type=int, default=1000, help="number of epochs to train for" ) - parser.add_argument("--save_every", type=int, default=10, help="how often to save") + parser.add_argument("--save_every", type=int, default=1, help="how often to save") parser.add_argument( "--lr", type=float, default=0.0002, help="learning rate, default=0.0002" ) From 7192f54986cdd7607e9b84dbb75ededb2c2107a8 Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Sat, 9 Apr 2022 17:21:36 +0300 Subject: [PATCH 4/8] feat: sn-gan --- huggan/README.md | 225 ++++++++++++++++++-------- huggan/pytorch/sngan/README.md | 155 ++++++++++++++++++ huggan/pytorch/sngan/train.py | 278 +++++++++++++++++---------------- 3 files changed, 465 insertions(+), 193 deletions(-) diff --git a/huggan/README.md b/huggan/README.md index d4262b25..7972cceb 100644 --- a/huggan/README.md +++ b/huggan/README.md @@ -8,13 +8,21 @@ _**Timeline**: April 4th, 2022 - April 17th, 2022_ Welcome to HugGAN Sprint! The goal of this sprint is to add more GANs and GAN-based demos to the Hugging Face Hub 🤗. -During the sprint, we’ll be bringing in some awesome speakers to talk about GANs and the future of generative models. Oh, and if you need access to compute for your project, we’ll help you there too! As an added bonus, if you choose to participate, we’ll send you a gift (specific details TBD). We encourage you to form teams of ~2-3 people! Make friends in the Discord :) +During the sprint, we’ll be bringing in some awesome speakers to talk about GANs and the future of generative models. +Oh, and if you need access to compute for your project, we’ll help you there too! As an added bonus, if you choose to +participate, we’ll send you a gift (specific details TBD). We encourage you to form teams of ~2-3 people! Make friends +in the Discord :) To join: 1. Fill out [this form](https://forms.gle/goq41UgzsvuKKTFFA), so we can keep track of who’s joining. -2. Send a reaction in the [#join-sprint channel](https://discord.com/channels/879548962464493619/954070850645135462) under the HugGAN category in Discord. This will add you to the rest of the related channels. If you haven't joined our discord yet, [click here](https://discord.gg/H3bUrDPTfS). -3. Once you’ve decided what you want to work on, add your project’s information to [this sheet](https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0), where you can describe your project and let us know if you need additional compute. Still brainstorming? Feel free to propose ideas in #sprint-discussions. +2. Send a reaction in the [#join-sprint channel](https://discord.com/channels/879548962464493619/954070850645135462) + under the HugGAN category in Discord. This will add you to the rest of the related channels. If you haven't joined + our discord yet, [click here](https://discord.gg/H3bUrDPTfS). +3. Once you’ve decided what you want to work on, add your project’s information + to [this sheet](https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0), + where you can describe your project and let us know if you need additional compute. Still brainstorming? Feel free to + propose ideas in #sprint-discussions. ## Table of Contents @@ -44,10 +52,13 @@ You'll need the following dependencies installed to use this repo: - [PyTorch](https://pytorch.org/) or [Keras](https://keras.io/) - depending on which framework you prefer ;) - [🤗 Datasets](https://huggingface.co/docs/datasets/index) -- [🤗 Accelerate](https://huggingface.co/docs/accelerate/index) - in case you're planning to train a PyTorch model and you want it to be run effortlessly +- [🤗 Accelerate](https://huggingface.co/docs/accelerate/index) - in case you're planning to train a PyTorch model and + you want it to be run effortlessly -We recommend installing the above libraries in a [virtual environment](https://docs.python.org/3/library/venv.html). -If you're unfamiliar with Python virtual environments, check out the [user guide](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). Create a virtual environment with the version of Python you're going to use and activate it. +We recommend installing the above libraries in a [virtual environment](https://docs.python.org/3/library/venv.html). If +you're unfamiliar with Python virtual environments, check out +the [user guide](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). Create a virtual +environment with the version of Python you're going to use and activate it. You should be able to run the command: @@ -71,7 +82,8 @@ cd community-events pip install . ``` -If you use `pip install -e .` instead of `pip install`, it will install the package in development mode, which can be useful if you are planning on contributing any changes here 🤗. +If you use `pip install -e .` instead of `pip install`, it will install the package in development mode, which can be +useful if you are planning on contributing any changes here 🤗. ## General workflow @@ -85,13 +97,18 @@ These steps are explained in more detail below. ### 1. Get a dataset and push to Hub -The first step is the most obvious one: to train a GAN (or any neural network), we need a dataset. This could be either a dataset that is already available on the [Hub](https://huggingface.co/datasets), or one that isn't already. Below we'll explain how to load the data in both cases. +The first step is the most obvious one: to train a GAN (or any neural network), we need a dataset. This could be either +a dataset that is already available on the [Hub](https://huggingface.co/datasets), or one that isn't already. Below +we'll explain how to load the data in both cases. Note that we maintain a list of interesting datasets to add to the Hub [here](#datasets-to-add). #### 1.1 Use a dataset already available on the Hub -Most famous computer vision datasets are already available on the [Hub](https://huggingface.co/datasets?task_categories=task_categories:image-classification) (such as [MNIST](https://huggingface.co/datasets/mnist), [Fashion MNIST](https://huggingface.co/datasets/fashion_mnist), [CIFAR-10](https://huggingface.co/datasets/cifar10), [CIFAR-100](https://huggingface.co/datasets/cifar100), etc.). +Most famous computer vision datasets are already available on +the [Hub](https://huggingface.co/datasets?task_categories=task_categories:image-classification) (such +as [MNIST](https://huggingface.co/datasets/mnist), [Fashion MNIST](https://huggingface.co/datasets/fashion_mnist) +, [CIFAR-10](https://huggingface.co/datasets/cifar10), [CIFAR-100](https://huggingface.co/datasets/cifar100), etc.). Loading a dataset can be done as follows: @@ -114,17 +131,23 @@ print(example['image']) #### 1.2 Upload a new dataset to the Hub -In case your dataset is not already on the Hub, you can upload it to the `huggan` [organization](https://huggingface.co/huggan). If you've signed up for the event by filling in the [spreadsheet]((https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0)), your Hugging Face account should be part of it. +In case your dataset is not already on the Hub, you can upload it to +the `huggan` [organization](https://huggingface.co/huggan). If you've signed up for the event by filling in +the [spreadsheet]((https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0)), +your Hugging Face account should be part of it. -Let's illustrate with an example how this was done for NVIDIA's [MetFaces dataset](https://github.com/NVlabs/metfaces-dataset): +Let's illustrate with an example how this was done for NVIDIA' +s [MetFaces dataset](https://github.com/NVlabs/metfaces-dataset):

drawing

-Previously, this dataset was only hosted on [Google Drive](https://github.com/NVlabs/metfaces-dataset#overview), and not really easily accessible. +Previously, this dataset was only hosted on [Google Drive](https://github.com/NVlabs/metfaces-dataset#overview), and not +really easily accessible. -To begin with, one should check that one is correctly logged in and that `git-lfs` is installed so that the dataset can be uploaded. +To begin with, one should check that one is correctly logged in and that `git-lfs` is installed so that the dataset can +be uploaded. Run: @@ -140,7 +163,10 @@ from huggingface_hub import notebook_login notebook_login() ``` -It is recommended to login with your access token that can be found under your HuggingFace profile (icon in the top right corner on [hf.co](http://hf.co/), then Settings -> Access Tokens -> User Access Tokens -> New Token (if you haven't generated one already). Alternatively, you can go to [your token settings](https://huggingface.co/settings/tokens) directly. +It is recommended to login with your access token that can be found under your HuggingFace profile (icon in the top +right corner on [hf.co](http://hf.co/), then Settings -> Access Tokens -> User Access Tokens -> New Token (if you +haven't generated one already). Alternatively, you can go +to [your token settings](https://huggingface.co/settings/tokens) directly. You can then copy-paste this token to log in locally. @@ -150,7 +176,8 @@ Next, let's make sure that `git-lfs` is correctly installed. To so, simply run: git-lfs -v ``` -The output should show something like `git-lfs/2.13.2 (GitHub; linux amd64; go 1.15.4)`. If your console states that the `git-lfs` command was not found, please make sure to install it [here](https://git-lfs.github.com/) or simply via: +The output should show something like `git-lfs/2.13.2 (GitHub; linux amd64; go 1.15.4)`. If your console states that +the `git-lfs` command was not found, please make sure to install it [here](https://git-lfs.github.com/) or simply via: ```bash sudo apt-get install git-lfs @@ -158,7 +185,13 @@ git config --global user.email "you@example.com" git config --global user.name "Your Name" ``` -Next, one can leverage the [`ImageFolder`](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder) builder to very easily upload an image dataset to the hub. In case the dataset you're uploading has a direct download URL, you can simply provide it to the `data_files` argument as shown below. Otherwise, you'll need to go to the link of the dataset and manually download it first as a zip/tar (which was the case for MetFaces), and provide the file through the `data_files` argument. Alternatively, it may be that you have a folder with images, in which case you can provide it using the `data_dir` argument. Note that the latter assumes a [particular structure](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder). +Next, one can leverage the [`ImageFolder`](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder) +builder to very easily upload an image dataset to the hub. In case the dataset you're uploading has a direct download +URL, you can simply provide it to the `data_files` argument as shown below. Otherwise, you'll need to go to the link of +the dataset and manually download it first as a zip/tar (which was the case for MetFaces), and provide the file through +the `data_files` argument. Alternatively, it may be that you have a folder with images, in which case you can provide it +using the `data_dir` argument. Note that the latter assumes +a [particular structure](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder). ```python from datasets import load_dataset @@ -169,7 +202,8 @@ dataset = load_dataset("imagefolder", data_dir="path_to_folder") dataset = load_dataset("imagefolder", data_files="path_to_file_or_direct_download_link") # note that you can also provide them as separate splits, like so: -dataset = load_dataset("imagefolder", data_files={"train": ["path/to/file1", "path/to/file2"], "test": ["path/to/file3", "path/to/file4"]}) +dataset = load_dataset("imagefolder", data_files={"train": ["path/to/file1", "path/to/file2"], + "test": ["path/to/file3", "path/to/file4"]}) ``` Once you've loaded your dataset, you can push it to the Hub with a single line of code: @@ -178,15 +212,19 @@ Once you've loaded your dataset, you can push it to the Hub with a single line o dataset.push_to_hub("huggan/name-of-your-dataset") ``` -Et voila! Your dataset is now available on the Hub :) If you wait a bit, the Dataset viewer should be able to preview images in the browser. The MetFaces dataset can be seen here: https://huggingface.co/datasets/huggan/metfaces. +Et voila! Your dataset is now available on the Hub :) If you wait a bit, the Dataset viewer should be able to preview +images in the browser. The MetFaces dataset can be seen here: https://huggingface.co/datasets/huggan/metfaces.

drawing

-The cool thing is that anyone can now access this dataset from anywhere, using `load_dataset` 🎉🥳 this means that you can easily load the dataset on another computer for instance, or in a different environment. Amazing, isn't it? +The cool thing is that anyone can now access this dataset from anywhere, using `load_dataset` 🎉🥳 this means that you +can easily load the dataset on another computer for instance, or in a different environment. Amazing, isn't it? -❗ Note: When uploading a dataset, make sure that it has appropriate column names. The `ImageFolder` utility automatically creates `image` and `label` columns, however if there's only one image class, it makes sense to remove the `label` column before pushing to the hub. This can be done as follows: +❗ Note: When uploading a dataset, make sure that it has appropriate column names. The `ImageFolder` utility +automatically creates `image` and `label` columns, however if there's only one image class, it makes sense to remove +the `label` column before pushing to the hub. This can be done as follows: ```python dataset = dataset.remove_columns("label") @@ -196,7 +234,10 @@ Note that you can always update a dataset by simply calling `push_to_hub` again #### 1.3 Processing the data -Once you've uploaded your dataset, you can load it and create a dataloader for it. The code example below shows how to apply some data augmentation and creating a PyTorch Dataloader (the [PyTorch example scripts](pytorch) all leverage this). More info can also be found in the [docs](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#process-image-data). +Once you've uploaded your dataset, you can load it and create a dataloader for it. The code example below shows how to +apply some data augmentation and creating a PyTorch Dataloader (the [PyTorch example scripts](pytorch) all leverage +this). More info can also be found in +the [docs](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#process-image-data). ```python from datasets import load_dataset @@ -217,46 +258,71 @@ transform = Compose( ] ) + # define function def transforms(examples): - examples["image"] = [transform(image.convert("RGB")) for image in examples["image"]] + examples["image"] = [transform(image.convert("RGB")) for image in examples["image"]] + + return examples - return examples transformed_dataset = dataset.with_transform(transforms) # create dataloader dataloader = DataLoader( - transformed_dataset["train"], batch_size="your batch size", shuffle=True, num_workers="your number of CPU cores" + transformed_dataset["train"], batch_size="your batch size", shuffle=True, num_workers="your number of CPU cores" ) ``` -As can be seen, we leverage the [`with_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.with_transform) method here, which will make sure the image transformations will only be performed when iterating over the data (i.e. data augmentation is performed on-the-fly, making it very RAM-friendly) rather than performing it on the entire dataset in one go (which would be the case if you use [`map`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.map)). The `with_transform` method does the same thing as [`set_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.set_transform), except that it does return a new `Dataset` rather than performing the operation in-place. +As can be seen, we leverage +the [`with_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.with_transform) +method here, which will make sure the image transformations will only be performed when iterating over the data (i.e. +data augmentation is performed on-the-fly, making it very RAM-friendly) rather than performing it on the entire dataset +in one go (which would be the case if you +use [`map`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.map)). +The `with_transform` method does the same thing +as [`set_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.set_transform) +, except that it does return a new `Dataset` rather than performing the operation in-place. ### 2. Train a model and push to Hub -Next, one can start training a model. This could be any model you'd like. However, we provide some example scripts to help you get started, in [PyTorch](pytorch). An example is the [DCGAN](pytorch/dcgan) model for unconditional image generation. Simply follow the README that explains all the details of the relevant implementation, and run it in your environment. +Next, one can start training a model. This could be any model you'd like. However, we provide some example scripts to +help you get started, in [PyTorch](pytorch). An example is the [DCGAN](pytorch/dcgan) model for unconditional image +generation. Simply follow the README that explains all the details of the relevant implementation, and run it in your +environment. -The PyTorch example scripts all leverage 🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), which provides an easy API to make your scripts run on any kind of distributed setting (multi-GPUs, TPUs etc.) and with mixed precision, while still letting you write your own training loop. +The PyTorch example scripts all leverage 🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), which provides +an easy API to make your scripts run on any kind of distributed setting (multi-GPUs, TPUs etc.) and with mixed +precision, while still letting you write your own training loop. Alternatively, we also provide a [Links to Check Out](#links-to-check-out) section to give you some inspiration. -Below, we explain in more detail how to upload your model to the Hub, depending on the framework you're using (sections [2.1](#21-pytorch) and [2.2](#22-keras)). In section [2.3](#33-alternative-ways-to-upload-a-model-to-the-hub), we'll explain how to write a nice model card. In section [2.4](24-model-cards), we'll illustrate alternative ways to upload (and re-use) a model to (and from) the hub. Finally, in section [2.5](25-accelerate), we explain 🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), the awesome library that makes training PyTorch models on any kind of environment a breeze. Be sure to check it out! +Below, we explain in more detail how to upload your model to the Hub, depending on the framework you're using ( +sections [2.1](#21-pytorch) and [2.2](#22-keras)). In section [2.3](#33-alternative-ways-to-upload-a-model-to-the-hub), +we'll explain how to write a nice model card. In section [2.4](24-model-cards), we'll illustrate alternative ways to +upload (and re-use) a model to (and from) the hub. Finally, in section [2.5](25-accelerate), we explain +🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), the awesome library that makes training PyTorch models on +any kind of environment a breeze. Be sure to check it out! #### 2.1 PyTorch -If you're planning to train a custom PyTorch model, it's recommended to make it inherit from `PyTorchModelHubMixin`. This makes sure you can push it to the Hub at the end of training, and reload it afterwards using `from_pretrained`, as shown in the code example below: +If you're planning to train a custom PyTorch model, it's recommended to make it inherit from `PyTorchModelHubMixin`. +This makes sure you can push it to the Hub at the end of training, and reload it afterwards using `from_pretrained`, as +shown in the code example below: ```python from huggingface_hub import PyTorchModelHubMixin + class MyGenerator(nn.Module, PyTorchModelHubMixin): - def __init__(self, **kwargs): - super().__init__() - self.config = kwargs.pop("config", None) - self.layer = ... - def forward(self, ...): - return ... + def __init__(self, **kwargs): + super().__init__() + self.config = kwargs.pop("config", None) + self.layer = ... + + def forward(self, ...): + return ... + # Create model model = MyGenerator() @@ -268,7 +334,9 @@ model.push_to_hub("huggan/name-of-your-model"). reloaded = MyGenerator.from_pretrained("huggan/name-of-your-model"). ``` -This `PyTorchModelHubMixin` class is available in the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which comes pre-installed if you install `datasets` (or `transformers`) in your environment. +This `PyTorchModelHubMixin` class is available in +the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which comes pre-installed if you +install `datasets` (or `transformers`) in your environment. #### 2.2 Keras @@ -291,15 +359,22 @@ push_to_hub_keras(model, "huggan/my-cool-model") reloaded = from_pretrained_keras("huggan/my-cool-model") ``` -These methods are available in the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which comes pre-installed if you install `datasets` (or `transformers`) in your environment. Note that the `push_to_hub_keras` method supports pushing several models (such as a generator and discriminator) to the same repo, as illustrated [here](https://github.com/huggingface/huggingface_hub/issues/533#issuecomment-1058093158). +These methods are available in the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which +comes pre-installed if you install `datasets` (or `transformers`) in your environment. Note that the `push_to_hub_keras` +method supports pushing several models (such as a generator and discriminator) to the same repo, as +illustrated [here](https://github.com/huggingface/huggingface_hub/issues/533#issuecomment-1058093158). #### 2.3 Alternative ways to upload a model to the Hub -Besides the methods explained in sections 2.1 and 2.2 above, you can also share model assets directly from git, which is explained in depth in [this guide](https://huggingface.co/docs/hub/adding-a-model#uploading-your-files). +Besides the methods explained in sections 2.1 and 2.2 above, you can also share model assets directly from git, which is +explained in depth in [this guide](https://huggingface.co/docs/hub/adding-a-model#uploading-your-files). #### 2.4 Model cards -When uploading a model to the Hub, it's important to include a so-called [model card](https://huggingface.co/course/chapter4/4?fw=pt) with it. This is just a README (in Markdown) 🃏 that includes: +When uploading a model to the Hub, it's important to include a +so-called [model card](https://huggingface.co/course/chapter4/4?fw=pt) with it. This is just a README (in Markdown) 🃏 +that includes: + - license, - task, - `huggan` and `gan` tags, @@ -308,16 +383,18 @@ When uploading a model to the Hub, it's important to include a so-called [model - information on dataset, intended uses, - a model output. -If you trained one of the example models, this model card will be automatically generated for you. If you didn’t train the model yourself, be sure to both credit the original authors and include the associated license in your model card! Here is an [example model repo](https://huggingface.co/merve/anime-faces-generator). +If you trained one of the example models, this model card will be automatically generated for you. If you didn’t train +the model yourself, be sure to both credit the original authors and include the associated license in your model card! +Here is an [example model repo](https://huggingface.co/merve/anime-faces-generator). You can also use this [template model card](model_card_template.md) - as a guide to build your own. +as a guide to build your own. ![Alt text](assets/example_model.png?raw=true "Title") #### 2.5 Accelerate -HuggingFace `accelerate` is an awesome library for training PyTorch models. Here we show why. +HuggingFace `accelerate` is an awesome library for training PyTorch models. Here we show why. Basically, the library requires to replace this: @@ -334,7 +411,7 @@ for batch in my_training_dataloader: loss.backward() my_optimizer.step() ``` - + by this: ```diff @@ -360,7 +437,9 @@ by this: my_optimizer.step() ``` -and BOOM, your script runs on **any kind of hardware**, including CPU, multi-CPU, GPU, multi-GPU and TPU. It also supports things like [DeepSpeed](https://github.com/microsoft/DeepSpeed) and [mixed precision](https://arxiv.org/abs/1710.03740) for training efficiently. +and BOOM, your script runs on **any kind of hardware**, including CPU, multi-CPU, GPU, multi-GPU and TPU. It also +supports things like [DeepSpeed](https://github.com/microsoft/DeepSpeed) +and [mixed precision](https://arxiv.org/abs/1710.03740) for training efficiently. You can now run your script as follows: @@ -368,7 +447,8 @@ You can now run your script as follows: accelerate config ``` -=> Accelerate will ask what kind of environment you'd like to run your script on, simply answer the questions being asked. Next: +=> Accelerate will ask what kind of environment you'd like to run your script on, simply answer the questions being +asked. Next: ```bash accelerate launch @@ -384,13 +464,17 @@ You can of course change the environment by running `accelerate config` again. ### 3. Create a demo -Once you share a model, you then should share a [Space](https://huggingface.co/spaces) based on your SDK of choice (Gradio or Streamlit) or as a static page. 🌌 +Once you share a model, you then should share a [Space](https://huggingface.co/spaces) based on your SDK of choice ( +Gradio or Streamlit) or as a static page. 🌌 ![Alt text](assets/example_space.png?raw=true "Title") -Here is an [example Space](https://huggingface.co/spaces/merve/anime-face-generator) corresponding to the model example shared above. Don’t know how to create a space? Read more about how to add spaces [here](https://huggingface.co/docs/hub/spaces). +Here is an [example Space](https://huggingface.co/spaces/merve/anime-face-generator) corresponding to the model example +shared above. Don’t know how to create a space? Read more about how to add +spaces [here](https://huggingface.co/docs/hub/spaces). Below, we list some other great example GAN Spaces: + - AnimeGANv2: https://huggingface.co/spaces/akhaliq/AnimeGANv2 - ArcaneGAN: https://huggingface.co/spaces/akhaliq/ArcaneGAN - This Pokemon does not exist: https://huggingface.co/spaces/ronvolutional/ai-pokemon-card @@ -399,17 +483,20 @@ Below, we list some other great example GAN Spaces: ## Example Scripts -In this repo, we have provided some example scripts you can use to train your own GANs. Below is a table of the available scripts: +In this repo, we have provided some example scripts you can use to train your own GANs. Below is a table of the +available scripts: -| Name | Paper | -| ----------- | ----------- | -| [DCGAN](pytorch/dcgan) | [Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks](https://arxiv.org/abs/1511.06434) | -| [pix2pix](pytorch/pix2pix) | [Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/abs/1611.07004) | -| [CycleGAN](pytorch/cyclegan) | [Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks](https://arxiv.org/abs/1703.10593) +| Name | Paper | +|------------------------------| ----------- | +| [DCGAN](pytorch/dcgan) | [Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks](https://arxiv.org/abs/1511.06434) | +| [pix2pix](pytorch/pix2pix) | [Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/abs/1611.07004) | +| [CycleGAN](pytorch/cyclegan) | [Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks](https://arxiv.org/abs/1703.10593) | +| [SN-GAN](pytorch/sngan) | [Spectral Normalization for Generative Adversarial Networks](https://arxiv.org/abs/1802.05957) | ## Datasets to add -Below, we list some datasets which could be added to the Hub (feel free to add on one of these, or open a PR to add more datasets!): +Below, we list some datasets which could be added to the Hub (feel free to add on one of these, or open a PR to add more +datasets!): - DeepFashion: https://mmlab.ie.cuhk.edu.hk/projects/DeepFashion.html - Flowers: https://www.robots.ox.ac.uk/~vgg/data/flowers/ @@ -417,9 +504,11 @@ Below, we list some datasets which could be added to the Hub (feel free to add o ## Links to Check Out -Below, we list some possible awesome project ideas (feel free to work on one of these, or open a PR to add more project ideas!): +Below, we list some possible awesome project ideas (feel free to work on one of these, or open a PR to add more project +ideas!): PyTorch: + - Lightweight-GAN: https://github.com/lucidrains/lightweight-gan - StyleGAN2: https://github.com/lucidrains/stylegan2-pytorch - StyleGAN2-ada: https://github.com/NVlabs/stylegan2-ada @@ -439,6 +528,7 @@ PyTorch: - Denoising Diffusion GAN: https://github.com/NVlabs/denoising-diffusion-gan Keras: + - WGAN-GP: https://keras.io/examples/generative/wgan_gp/ - Conditional GAN: https://keras.io/examples/generative/conditional_gan/ - CycleGAN, DiscoGAN etc.: https://github.com/eriklindernoren/Keras-GAN @@ -447,12 +537,14 @@ Keras: - Deformable GAN: https://github.com/AliaksandrSiarohin/pose-gan General links & tutorials: + - https://github.com/yhlleo/GAN-Metrics - https://paperswithcode.com/task/image-generation ## GAN metrics -There have been several quantitative measures defined for assessing the quality of GANs (and other generative models). Refer to [this page](pytorch/metrics) for more info. +There have been several quantitative measures defined for assessing the quality of GANs (and other generative models). +Refer to [this page](pytorch/metrics) for more info. ## Evaluation @@ -467,13 +559,21 @@ TODO ## Communication and Problems -If you encounter any problems or have any questions, you should use one of the following platforms depending on your type of problem. Hugging Face is an "open-source-first" organization meaning that we'll try to solve all problems in the most public and most transparent way possible so that everybody in the community profits. +If you encounter any problems or have any questions, you should use one of the following platforms depending on your +type of problem. Hugging Face is an "open-source-first" organization meaning that we'll try to solve all problems in the +most public and most transparent way possible so that everybody in the community profits. The following table summarizes what platform to use for which problem. -- Problem/question/bug with the 🤗 Datasets library that you think is a general problem that also impacts other people, please open an [Issues on Datasets](https://github.com/huggingface/datasets/issues/new?assignees=&labels=bug&template=bug-report.md&title=) and ping @nielsrogge. -- Problem/question with a modified, customized training script that is less likely to impact other people, please post your problem/question [on the forum](https://discuss.huggingface.co/) and ping @nielsrogge. -- Other questions regarding the event, rules of the event, or if you are not sure where to post your question, please ask in the Discord channel [**#sprint-discussions**](https://discord.com/channels/879548962464493619/954111918895943720). +- Problem/question/bug with the 🤗 Datasets library that you think is a general problem that also impacts other people, + please open + an [Issues on Datasets](https://github.com/huggingface/datasets/issues/new?assignees=&labels=bug&template=bug-report.md&title=) + and ping @nielsrogge. +- Problem/question with a modified, customized training script that is less likely to impact other people, please post + your problem/question [on the forum](https://discuss.huggingface.co/) and ping @nielsrogge. +- Other questions regarding the event, rules of the event, or if you are not sure where to post your question, please + ask in the Discord channel [** + #sprint-discussions**](https://discord.com/channels/879548962464493619/954111918895943720). ## Talks @@ -483,4 +583,7 @@ TODO - Memory efficient training: -In case, you are getting out-of-memory errors on your GPU, we recommend to use [bitsandbytes](https://github.com/facebookresearch/bitsandbytes) to replace the native memory-intensive Adam optimizer with the one of `bitsandbytes`. It can be used to both train the generator and the discriminator in case you're training a GAN. +In case, you are getting out-of-memory errors on your GPU, we recommend to +use [bitsandbytes](https://github.com/facebookresearch/bitsandbytes) to replace the native memory-intensive Adam +optimizer with the one of `bitsandbytes`. It can be used to both train the generator and the discriminator in case +you're training a GAN. diff --git a/huggan/pytorch/sngan/README.md b/huggan/pytorch/sngan/README.md index e69de29b..dafccf24 100644 --- a/huggan/pytorch/sngan/README.md +++ b/huggan/pytorch/sngan/README.md @@ -0,0 +1,155 @@ +# Train SN-GAN on your custom data + +This folder contains a script to train [SN-GAN](https://arxiv.org/abs/1802.05957) for unconditional image generation, leveraging the [Hugging Face](https://huggingface.co/) ecosystem for processing your data and pushing the model to the Hub. + +The script leverages 🤗 Datasets for loading and processing data, and 🤗 Accelerate for instantly running on CPU, single, multi-GPUs or TPU, also supporting fp16/mixed precision. + +

+ drawing +

+ + +## Launching the script + +To train the model with the default parameters (5 epochs, 64x64 images, etc.) on [MNIST](https://huggingface.co/datasets/mnist), first run: + +```bash +accelerate config +``` + +and answer the questions asked about your environment. Next, launch the script as follows: + +```bash +accelerate launch train.py +``` + +This will create a local "images" directory, containing generated images over the course of the training. + +To train on another dataset available on the hub, simply do (for instance): + +```bash +python train.py --dataset cifar-10 +``` + +In case you'd like to tweak the script to your liking, first fork the "community-events" [repo](https://github.com/huggingface/community-events) (see the button on the top right), then clone it locally: + +```bash +git clone https://github.com//community-events.git +``` + +and edit to your liking. + +## Training on your own data + +You can of course also train on your own images. For this, one can leverage Datasets' [ImageFolder](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder). Make sure to authenticate with the hub first, by running the `huggingface-cli login` command in a terminal, or the following in case you're working in a notebook: + +```python +from huggingface_hub import notebook_login + +notebook_login() +``` + +Next, run the following in a notebook/script: + +```python +from datasets import load_dataset + +# first: load dataset +# option 1: from local folder +dataset = load_dataset("imagefolder", data_dir="path_to_folder") +# option 2: from remote URL (e.g. a zip file) +dataset = load_dataset("imagefolder", data_files="URL to .zip file") + +# next: push to the hub (assuming git-LFS is installed) +dataset.push_to_hub("huggan/my-awesome-dataset") +``` + +You can then simply pass the name of the dataset to the script: + +```bash +accelerate launch train.py --dataset huggan/my-awesome-dataset +``` + +## Pushing model to the Hub + +You can push your trained generator to the hub after training by specifying the `push_to_hub` flag, along with a `model_name` and `pytorch_dump_folder_path`. + +```bash +accelerate launch train.py --push_to_hub --model_name sn-gan-mnist +``` + +This is made possible by making the generator inherit from `PyTorchModelHubMixin`available in the `huggingface_hub` library. + +This means that after training, generating a new image can be done as follows: + +```python +import torch +import torch.nn as nn +from torchvision.transforms import ToPILImage +from huggingface_hub import PyTorchModelHubMixin + +class Generator(nn.Module, PyTorchModelHubMixin): + def __init__(self, num_channels=4, latent_dim=100, hidden_size=64): + super(Generator, self).__init__() + self.model = nn.Sequential( + # input is Z, going into a convolution + nn.ConvTranspose2d(latent_dim, hidden_size * 8, 4, 1, 0, bias=False), + nn.BatchNorm2d(hidden_size * 8), + nn.ReLU(True), + # state size. (hidden_size*8) x 4 x 4 + nn.ConvTranspose2d(hidden_size * 8, hidden_size * 4, 4, 2, 1, bias=False), + nn.BatchNorm2d(hidden_size * 4), + nn.ReLU(True), + # state size. (hidden_size*4) x 8 x 8 + nn.ConvTranspose2d(hidden_size * 4, hidden_size * 2, 4, 2, 1, bias=False), + nn.BatchNorm2d(hidden_size * 2), + nn.ReLU(True), + # state size. (hidden_size*2) x 16 x 16 + nn.ConvTranspose2d(hidden_size * 2, hidden_size, 4, 2, 1, bias=False), + nn.BatchNorm2d(hidden_size), + nn.ReLU(True), + # state size. (hidden_size) x 32 x 32 + nn.ConvTranspose2d(hidden_size, num_channels, 4, 2, 1, bias=False), + nn.Tanh() + # state size. (num_channels) x 64 x 64 + ) + + def forward(self, noise): + pixel_values = self.model(noise) + + return pixel_values + +model = Generator.from_pretrained("huggan/my-awesome-model") + +device = "cuda" if torch.cuda.is_available() else "cpu" +model.to(device) + +with torch.no_grad(): + z = torch.randn(1, 100, 1, 1, device=device) + pixel_values = model(z) + +# turn into actual image +image = pixel_values[0] +image = (image + 1) /2 +image = ToPILImage()(image) +image.save("generated.png") +``` + +## Weights and Biases integration + +You can easily add logging to [Weights and Biases](https://wandb.ai/site) by passing the `--wandb` flag: + +```bash +accelerate launch train.py --wandb +```` + +You can then follow the progress of your GAN in a browser: + +

+ drawing +

+ + +# Citation + +This repo is entirely based on PyTorch's official [DCGAN tutorial](https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html) and [SN-GAN](https://arxiv.org/abs/1802.05957), but with added HuggingFace goodies. diff --git a/huggan/pytorch/sngan/train.py b/huggan/pytorch/sngan/train.py index 468d3e33..5a31ffdb 100644 --- a/huggan/pytorch/sngan/train.py +++ b/huggan/pytorch/sngan/train.py @@ -3,25 +3,25 @@ import argparse import csv import logging +import os import random from pathlib import Path -import pandas as pd import torch import torch.backends.cudnn as cudnn import torch.nn as nn import torch.optim as optim import torch.utils.data -import torchvision.transforms as transforms import torchvision.utils as vutils -from PIL import Image from torch.nn.utils.parametrizations import spectral_norm from torch.utils.data import DataLoader -from torchvision.transforms import (CenterCrop, Compose, Normalize, Resize, - ToTensor, ToPILImage) +from torchvision.transforms import (CenterCrop, Compose, Normalize, Resize, ToTensor) from datasets import load_dataset import tqdm from accelerate import Accelerator +from huggan.pytorch.metrics.fid_score import calculate_fretchet +from huggan.pytorch.metrics.inception import InceptionV3 +from huggan.pytorch.huggan_mixin import HugGANModelHubMixin logger = logging.getLogger(__name__) @@ -43,50 +43,6 @@ def __str__(self): return str(self.avg) -def get_attributes(): - """ - Read punk attributes file and form one-hot matrix - """ - df = pd.concat( - [ - pd.read_csv(f, sep=", ", engine="python") - for f in Path("attributes").glob("*.csv") - ] - ) - accessories = df["accessories"].str.get_dummies(sep=" / ") - type_ = df["type"].str.get_dummies() - gender = df["gender"].str.get_dummies() - - return pd.concat([df["id"], accessories, type_, gender], axis=1).set_index("id") - - -# folder dataset -class Punks(torch.utils.data.Dataset): - def __init__(self, path, size=10_000): - self.path = Path(path) - self.size = size - # self.attributes = get_attributes() - self.transform = transforms.Compose( - [ - transforms.ToTensor(), - transforms.Normalize((0.5, 0.5, 0.5, 0.5), (0.5, 0.5, 0.5, 0.5)), - ] - ) - - def __len__(self): - return self.size - - def __getitem__(self, index): - # randomly select attribute - # attribute = random.choice(self.attributes.columns) - # randomly select punk with that attribute - id_ = random.randint(0, self.size - 1) - - return self.transform( - Image.open(self.path / f"punk{int(id_):03}.png").convert("RGBA") - ) - - # Custom weights initialization called on Generator and Discriminator def weights_init(m): classname = m.__class__.__name__ @@ -97,63 +53,60 @@ def weights_init(m): nn.init.constant_(m.bias.data, 0) -class Generator(nn.Module): - def __init__(self, nc=4, nz=100, ngf=64): +class Generator(nn.Module, HugGANModelHubMixin): + def __init__(self, num_channels=4, latent_dim=100, generator_hidden_size=64): super(Generator, self).__init__() - self.network = nn.Sequential( + self.model = nn.Sequential( # input is Z, going into a convolution - nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False), - nn.BatchNorm2d(ngf * 8), + nn.ConvTranspose2d(latent_dim, generator_hidden_size * 8, 4, 1, 0, bias=False), + nn.BatchNorm2d(generator_hidden_size * 8), nn.ReLU(True), - # state size. (ngf*8) x 4 x 4 - nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False), - nn.BatchNorm2d(ngf * 4), + # state size. (generator_hidden_size*8) x 4 x 4 + nn.ConvTranspose2d(generator_hidden_size * 8, generator_hidden_size * 4, 4, 2, 1, bias=False), + nn.BatchNorm2d(generator_hidden_size * 4), nn.ReLU(True), - # state size. (ngf*4) x 8 x 8 - nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False), - nn.BatchNorm2d(ngf * 2), + # state size. (generator_hidden_size*4) x 8 x 8 + nn.ConvTranspose2d(generator_hidden_size * 4, generator_hidden_size * 2, 4, 2, 1, bias=False), + nn.BatchNorm2d(generator_hidden_size * 2), nn.ReLU(True), - # state size. (ngf*2) x 16 x 16 - nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False), - nn.BatchNorm2d(ngf), + # state size. (generator_hidden_size*2) x 16 x 16 + nn.ConvTranspose2d(generator_hidden_size * 2, generator_hidden_size, 4, 2, 1, bias=False), + nn.BatchNorm2d(generator_hidden_size), nn.ReLU(True), - # state size. (ngf) x 32 x 32 - nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False), + # state size. (generator_hidden_size) x 32 x 32 + nn.ConvTranspose2d(generator_hidden_size, num_channels, 4, 2, 1, bias=False), nn.Tanh() - # state size. (nc) x 64 x 64 + # state size. (num_channels) x 64 x 64 ) def forward(self, input): - output = self.network(input) + output = self.model(input) return output class Discriminator(nn.Module): - def __init__(self, nc, ndf): + def __init__(self, num_channels, discriminator_hidden_size): super(Discriminator, self).__init__() - self.network = nn.Sequential( - # input is (nc) x 64 x 64 - spectral_norm(nn.Conv2d(nc, ndf, 4, 2, 1, bias=False)), + self.model = nn.Sequential( + # input is (num_channels) x 64 x 64 + spectral_norm(nn.Conv2d(num_channels, discriminator_hidden_size, 4, 2, 1, bias=False)), nn.LeakyReLU(0.2, inplace=True), - # state size. (ndf) x 32 x 32 - spectral_norm(nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False)), - # nn.BatchNorm2d(ndf * 2), + # state size. (discriminator_hidden_size) x 32 x 32 + spectral_norm(nn.Conv2d(discriminator_hidden_size, discriminator_hidden_size * 2, 4, 2, 1, bias=False)), nn.LeakyReLU(0.2, inplace=True), - # state size. (ndf*2) x 16 x 16 - spectral_norm(nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False)), - # nn.BatchNorm2d(ndf * 4), + # state size. (discriminator_hidden_size*2) x 16 x 16 + spectral_norm(nn.Conv2d(discriminator_hidden_size * 2, discriminator_hidden_size * 4, 4, 2, 1, bias=False)), nn.LeakyReLU(0.2, inplace=True), - # state size. (ndf*4) x 8 x 8 - spectral_norm(nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False)), - # nn.BatchNorm2d(ndf * 8), + # state size. (discriminator_hidden_size*4) x 8 x 8 + spectral_norm(nn.Conv2d(discriminator_hidden_size * 4, discriminator_hidden_size * 8, 4, 2, 1, bias=False)), nn.LeakyReLU(0.2, inplace=True), - # state size. (ndf*8) x 4 x 4 - spectral_norm(nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False)), + # state size. (discriminator_hidden_size*8) x 4 x 4 + spectral_norm(nn.Conv2d(discriminator_hidden_size * 8, 1, 4, 1, 0, bias=False)), nn.Sigmoid() ) def forward(self, input): - output = self.network(input) + output = self.model(input) return output.view(-1, 1).squeeze(1) @@ -178,12 +131,12 @@ def main(args): torch.manual_seed(args.manual_seed) cudnn.benchmark = True - dataset = load_dataset("AlekseyKorshuk/dooggies") + dataset = load_dataset(args.dataset) - image_size = 64 transform = Compose( [ - Resize(image_size), + Resize(args.image_size), + CenterCrop(args.image_size), ToTensor(), Normalize((0.5, 0.5, 0.5, 0.5), (0.5, 0.5, 0.5, 0.5)), ] @@ -199,33 +152,40 @@ def transforms(examples): transformed_dataset = dataset.with_transform(transforms) dataloader = DataLoader( - transformed_dataset["train"], batch_size=args.batch_size, shuffle=True, num_workers=args.workers + transformed_dataset["train"], batch_size=args.batch_size, shuffle=True, num_workers=args.num_workers ) - device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + generator = Generator(args.num_channels, args.latent_dim, args.generator_hidden_size).to(accelerator.device) + generator.apply(weights_init) - net_g = Generator(args.nc, args.nz, args.ngf).to(device) - net_g.apply(weights_init) - - net_d = Discriminator(args.nc, args.ndf).to(device) - net_d.apply(weights_init) + discriminator = Discriminator(args.num_channels, args.discriminator_hidden_size).to(accelerator.device) + discriminator.apply(weights_init) criterion = nn.BCELoss() - fixed_noise = torch.randn(args.batch_size, args.nz, 1, 1, device=device) + fixed_noise = torch.randn(args.batch_size, args.latent_dim, 1, 1, device=accelerator.device) real_label = 1 fake_label = 0 + # Initialize Inceptionv3 (for FID metric) + model = InceptionV3() + # setup optimizer - optimizer_d = optim.Adam(net_d.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) - optimizer_g = optim.Adam(net_g.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) + discriminator_optimizer = optim.Adam(discriminator.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) + generator_optimizer = optim.Adam(generator.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) - net_g, net_d, optimizer_g, optimizer_d, dataloader = accelerator.prepare(net_g, net_d, optimizer_g, optimizer_d, dataloader) + generator, discriminator, generator_optimizer, discriminator_optimizer, dataloader = accelerator.prepare(generator, + discriminator, + generator_optimizer, + discriminator_optimizer, + dataloader) with open(f"{args.output_dir}/logs.csv", "w") as f: csv.writer(f).writerow(["epoch", "loss_g", "loss_d", "d_x", "d_g_z1", "d_g_z2"]) - for epoch in tqdm.tqdm(range(args.niter)): + logger.info("***** Running training *****") + logger.info(f" Num Epochs = {args.num_epochs}") + for epoch in tqdm.tqdm(range(args.num_epochs)): avg_loss_g = AverageMeter() avg_loss_d = AverageMeter() @@ -235,43 +195,43 @@ def transforms(examples): for data in dataloader: ############################ - # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z))) + # (1) Update D model: maximize log(D(x)) + log(1 - D(G(z))) ########################### # train with real - net_d.zero_grad() - real_cpu = data["pixel_values"].to(device) + discriminator.zero_grad() + real_cpu = data["pixel_values"].to(accelerator.device) batch_size = real_cpu.size(0) label = torch.full((batch_size,), real_label, dtype=torch.float, device=accelerator.device) - output = net_d(real_cpu).view(-1) + output = discriminator(real_cpu).view(-1) loss_d_real = criterion(output, label) accelerator.backward(loss_d_real) avg_d_x.update(output.mean().item(), batch_size) # train with fake - noise = torch.randn(batch_size, args.nz, 1, 1, device=accelerator.device) - fake = net_g(noise) + noise = torch.randn(batch_size, args.latent_dim, 1, 1, device=accelerator.device) + fake = generator(noise) label.fill_(fake_label) - output = net_d(fake.detach()) + output = discriminator(fake.detach()) loss_d_fake = criterion(output, label) accelerator.backward(loss_d_fake) - optimizer_d.step() + discriminator_optimizer.step() avg_loss_d.update((loss_d_real + loss_d_fake).item(), batch_size) avg_d_g_z1.update(output.mean().item()) ############################ - # (2) Update G network: maximize log(D(G(z))) + # (2) Update G model: maximize log(D(G(z))) ########################### - net_g.zero_grad() + generator.zero_grad() label.fill_(real_label) # fake labels are real for generator cost - output = net_d(fake) + output = discriminator(fake) # minimize loss but also maximize alpha channel loss_g = criterion(output, label) + fake[:, -1].mean() accelerator.backward(loss_g) - optimizer_g.step() + generator_optimizer.step() avg_loss_g.update(loss_g.item(), batch_size) avg_d_g_z2.update(output.mean().item()) @@ -294,9 +254,9 @@ def transforms(examples): if args.wandb: wandb.log(train_logs) - if (epoch + 1) % args.save_every == 0: + if (epoch + 1) % args.logging_steps == 0: # save samples - fake = net_g(fixed_noise) + fake = generator(fixed_noise) file_name = f"{args.output_dir}/fake_samples_epoch_{epoch}.png" vutils.save_image( fake.detach(), @@ -308,37 +268,64 @@ def transforms(examples): wandb.log({'generated_examples': wandb.Image(str(file_name))}) # save_checkpoints - torch.save(net_g.state_dict(), f"{args.output_dir}/net_g_epoch_{epoch}.pth") - torch.save(net_d.state_dict(), f"{args.output_dir}/net_d_epoch_{epoch}.pth") + torch.save(generator.state_dict(), f"{args.output_dir}/generator_epoch_{epoch}.pth") + torch.save(discriminator.state_dict(), f"{args.output_dir}/discriminator_epoch_{epoch}.pth") + + # Calculate FID metric + fid = calculate_fretchet(real_cpu, fake, model.to(accelerator.device)) + logger.info(f"FID: {fid}") + if accelerator.is_local_main_process and args.wandb: + wandb.log({"FID": fid}) + + # Optionally push to hub + if accelerator.is_main_process and args.push_to_hub: + # os.makedirs(f"{args.output_dir}/{args.model_name}", exist_ok=True) + generator.push_to_hub( + repo_path_or_name=f"{args.output_dir}/{args.model_name}", + organization=args.organization_name, + ) if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument("--dataroot", default="data", help="path to dataset") + parser.add_argument("--dataset", type=str, default="mnist", help="Dataset to load from the HuggingFace hub.") parser.add_argument( - "--workers", type=int, help="number of data loading workers", default=0 + "--num_workers", type=int, help="Number of data loading workers", default=0 ) - parser.add_argument("--batch_size", type=int, default=64, help="input batch size") parser.add_argument( - "--nz", type=int, default=100, help="size of the latent z vector" + "--image_size", + type=int, + default=64, + help="Spatial size to use when resizing images for training.", ) - parser.add_argument("--ngf", type=int, default=64) - parser.add_argument("--ndf", type=int, default=64) + parser.add_argument("--batch_size", type=int, default=16, help="Input batch size") + parser.add_argument("--latent_dim", type=int, default=100, help="Dimensionality of the latent space.") parser.add_argument( - "--niter", type=int, default=1000, help="number of epochs to train for" + "--generator_hidden_size", + type=int, + default=64, + help="Hidden size of the generator's feature maps.", ) - parser.add_argument("--save_every", type=int, default=1, help="how often to save") parser.add_argument( - "--lr", type=float, default=0.0002, help="learning rate, default=0.0002" + "--discriminator_hidden_size", + type=int, + default=64, + help="Hidden size of the discriminator's feature maps.", ) parser.add_argument( - "--beta1", type=float, default=0.5, help="beta1 for adam. default=0.5" + "--num_epochs", type=int, default=5, help="Number of epochs to train for" ) parser.add_argument( - "--output_dir", default="out-test", help="folder to output images and model checkpoints" + "--lr", type=float, default=0.0002, help="Learning rate" ) - parser.add_argument("--manual_seed", type=int, default=0, help="manual seed") - parser.add_argument("--wandb", action="store_true", help="if passed, will log to Weights and Biases.") + parser.add_argument( + "--beta1", type=float, default=0.5, help="Beta1 for adam" + ) + parser.add_argument( + "--output_dir", default="./output", help="Folder to output images and model checkpoints" + ) + parser.add_argument("--manual_seed", type=int, default=0, help="Manual seed") + parser.add_argument("--wandb", action="store_true", help="If passed, will log to Weights and Biases.") parser.add_argument("--fp16", action="store_true", help="If passed, will use FP16 training.") parser.add_argument("--cpu", action="store_true", help="If passed, will train on the CPU.") parser.add_argument( @@ -347,11 +334,38 @@ def transforms(examples): default="no", choices=["no", "fp16", "bf16"], help="Whether to use mixed precision. Choose" - "between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10." - "and an Nvidia Ampere GPU.", + "between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10." + "and an Nvidia Ampere GPU.", + ) + parser.add_argument( + "--push_to_hub", + action="store_true", + help="Whether to push the model to the HuggingFace hub after training.", + ) + parser.add_argument( + "--model_name", + default=None, + type=str, + help="Name of the model on the hub.", + ) + parser.add_argument( + "--organization_name", + default="huggan", + type=str, + help="Organization name to push to, in case args.push_to_hub is specified.", + ) + parser.add_argument( + "--logging_steps", + type=int, + default=50, + help="Number of steps between each logging", ) args = parser.parse_args() - args.cuda = True - args.nc = 4 - print(args) + args.num_channels = 4 + if args.push_to_hub: + assert args.output_dir is not None, "Need an `output_dir` to create a repo when `--push_to_hub` is passed." + assert args.model_name is not None, "Need a `model_name` to create a repo when `--push_to_hub` is passed." + + if args.output_dir is not None: + os.makedirs(args.output_dir, exist_ok=True) main(args) From 874876173c50684e64246440acda93c7b974821c Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Sat, 9 Apr 2022 17:43:25 +0300 Subject: [PATCH 5/8] feat: sn-gan --- huggan/README.md | 224 +++++++++++++---------------------------------- 1 file changed, 61 insertions(+), 163 deletions(-) diff --git a/huggan/README.md b/huggan/README.md index 7972cceb..f71ce3b3 100644 --- a/huggan/README.md +++ b/huggan/README.md @@ -8,21 +8,13 @@ _**Timeline**: April 4th, 2022 - April 17th, 2022_ Welcome to HugGAN Sprint! The goal of this sprint is to add more GANs and GAN-based demos to the Hugging Face Hub 🤗. -During the sprint, we’ll be bringing in some awesome speakers to talk about GANs and the future of generative models. -Oh, and if you need access to compute for your project, we’ll help you there too! As an added bonus, if you choose to -participate, we’ll send you a gift (specific details TBD). We encourage you to form teams of ~2-3 people! Make friends -in the Discord :) +During the sprint, we’ll be bringing in some awesome speakers to talk about GANs and the future of generative models. Oh, and if you need access to compute for your project, we’ll help you there too! As an added bonus, if you choose to participate, we’ll send you a gift (specific details TBD). We encourage you to form teams of ~2-3 people! Make friends in the Discord :) To join: 1. Fill out [this form](https://forms.gle/goq41UgzsvuKKTFFA), so we can keep track of who’s joining. -2. Send a reaction in the [#join-sprint channel](https://discord.com/channels/879548962464493619/954070850645135462) - under the HugGAN category in Discord. This will add you to the rest of the related channels. If you haven't joined - our discord yet, [click here](https://discord.gg/H3bUrDPTfS). -3. Once you’ve decided what you want to work on, add your project’s information - to [this sheet](https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0), - where you can describe your project and let us know if you need additional compute. Still brainstorming? Feel free to - propose ideas in #sprint-discussions. +2. Send a reaction in the [#join-sprint channel](https://discord.com/channels/879548962464493619/954070850645135462) under the HugGAN category in Discord. This will add you to the rest of the related channels. If you haven't joined our discord yet, [click here](https://discord.gg/H3bUrDPTfS). +3. Once you’ve decided what you want to work on, add your project’s information to [this sheet](https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0), where you can describe your project and let us know if you need additional compute. Still brainstorming? Feel free to propose ideas in #sprint-discussions. ## Table of Contents @@ -52,13 +44,10 @@ You'll need the following dependencies installed to use this repo: - [PyTorch](https://pytorch.org/) or [Keras](https://keras.io/) - depending on which framework you prefer ;) - [🤗 Datasets](https://huggingface.co/docs/datasets/index) -- [🤗 Accelerate](https://huggingface.co/docs/accelerate/index) - in case you're planning to train a PyTorch model and - you want it to be run effortlessly +- [🤗 Accelerate](https://huggingface.co/docs/accelerate/index) - in case you're planning to train a PyTorch model and you want it to be run effortlessly -We recommend installing the above libraries in a [virtual environment](https://docs.python.org/3/library/venv.html). If -you're unfamiliar with Python virtual environments, check out -the [user guide](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). Create a virtual -environment with the version of Python you're going to use and activate it. +We recommend installing the above libraries in a [virtual environment](https://docs.python.org/3/library/venv.html). +If you're unfamiliar with Python virtual environments, check out the [user guide](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). Create a virtual environment with the version of Python you're going to use and activate it. You should be able to run the command: @@ -82,8 +71,7 @@ cd community-events pip install . ``` -If you use `pip install -e .` instead of `pip install`, it will install the package in development mode, which can be -useful if you are planning on contributing any changes here 🤗. +If you use `pip install -e .` instead of `pip install`, it will install the package in development mode, which can be useful if you are planning on contributing any changes here 🤗. ## General workflow @@ -97,18 +85,13 @@ These steps are explained in more detail below. ### 1. Get a dataset and push to Hub -The first step is the most obvious one: to train a GAN (or any neural network), we need a dataset. This could be either -a dataset that is already available on the [Hub](https://huggingface.co/datasets), or one that isn't already. Below -we'll explain how to load the data in both cases. +The first step is the most obvious one: to train a GAN (or any neural network), we need a dataset. This could be either a dataset that is already available on the [Hub](https://huggingface.co/datasets), or one that isn't already. Below we'll explain how to load the data in both cases. Note that we maintain a list of interesting datasets to add to the Hub [here](#datasets-to-add). #### 1.1 Use a dataset already available on the Hub -Most famous computer vision datasets are already available on -the [Hub](https://huggingface.co/datasets?task_categories=task_categories:image-classification) (such -as [MNIST](https://huggingface.co/datasets/mnist), [Fashion MNIST](https://huggingface.co/datasets/fashion_mnist) -, [CIFAR-10](https://huggingface.co/datasets/cifar10), [CIFAR-100](https://huggingface.co/datasets/cifar100), etc.). +Most famous computer vision datasets are already available on the [Hub](https://huggingface.co/datasets?task_categories=task_categories:image-classification) (such as [MNIST](https://huggingface.co/datasets/mnist), [Fashion MNIST](https://huggingface.co/datasets/fashion_mnist), [CIFAR-10](https://huggingface.co/datasets/cifar10), [CIFAR-100](https://huggingface.co/datasets/cifar100), etc.). Loading a dataset can be done as follows: @@ -131,23 +114,17 @@ print(example['image']) #### 1.2 Upload a new dataset to the Hub -In case your dataset is not already on the Hub, you can upload it to -the `huggan` [organization](https://huggingface.co/huggan). If you've signed up for the event by filling in -the [spreadsheet]((https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0)), -your Hugging Face account should be part of it. +In case your dataset is not already on the Hub, you can upload it to the `huggan` [organization](https://huggingface.co/huggan). If you've signed up for the event by filling in the [spreadsheet]((https://docs.google.com/spreadsheets/d/1aAHqOOk2SOw4j6mrJLkLT6ZyKyLDOvGF5D9tuUqnoG8/edit#gid=0)), your Hugging Face account should be part of it. -Let's illustrate with an example how this was done for NVIDIA' -s [MetFaces dataset](https://github.com/NVlabs/metfaces-dataset): +Let's illustrate with an example how this was done for NVIDIA's [MetFaces dataset](https://github.com/NVlabs/metfaces-dataset):

drawing

-Previously, this dataset was only hosted on [Google Drive](https://github.com/NVlabs/metfaces-dataset#overview), and not -really easily accessible. +Previously, this dataset was only hosted on [Google Drive](https://github.com/NVlabs/metfaces-dataset#overview), and not really easily accessible. -To begin with, one should check that one is correctly logged in and that `git-lfs` is installed so that the dataset can -be uploaded. +To begin with, one should check that one is correctly logged in and that `git-lfs` is installed so that the dataset can be uploaded. Run: @@ -163,10 +140,7 @@ from huggingface_hub import notebook_login notebook_login() ``` -It is recommended to login with your access token that can be found under your HuggingFace profile (icon in the top -right corner on [hf.co](http://hf.co/), then Settings -> Access Tokens -> User Access Tokens -> New Token (if you -haven't generated one already). Alternatively, you can go -to [your token settings](https://huggingface.co/settings/tokens) directly. +It is recommended to login with your access token that can be found under your HuggingFace profile (icon in the top right corner on [hf.co](http://hf.co/), then Settings -> Access Tokens -> User Access Tokens -> New Token (if you haven't generated one already). Alternatively, you can go to [your token settings](https://huggingface.co/settings/tokens) directly. You can then copy-paste this token to log in locally. @@ -176,8 +150,7 @@ Next, let's make sure that `git-lfs` is correctly installed. To so, simply run: git-lfs -v ``` -The output should show something like `git-lfs/2.13.2 (GitHub; linux amd64; go 1.15.4)`. If your console states that -the `git-lfs` command was not found, please make sure to install it [here](https://git-lfs.github.com/) or simply via: +The output should show something like `git-lfs/2.13.2 (GitHub; linux amd64; go 1.15.4)`. If your console states that the `git-lfs` command was not found, please make sure to install it [here](https://git-lfs.github.com/) or simply via: ```bash sudo apt-get install git-lfs @@ -185,13 +158,7 @@ git config --global user.email "you@example.com" git config --global user.name "Your Name" ``` -Next, one can leverage the [`ImageFolder`](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder) -builder to very easily upload an image dataset to the hub. In case the dataset you're uploading has a direct download -URL, you can simply provide it to the `data_files` argument as shown below. Otherwise, you'll need to go to the link of -the dataset and manually download it first as a zip/tar (which was the case for MetFaces), and provide the file through -the `data_files` argument. Alternatively, it may be that you have a folder with images, in which case you can provide it -using the `data_dir` argument. Note that the latter assumes -a [particular structure](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder). +Next, one can leverage the [`ImageFolder`](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder) builder to very easily upload an image dataset to the hub. In case the dataset you're uploading has a direct download URL, you can simply provide it to the `data_files` argument as shown below. Otherwise, you'll need to go to the link of the dataset and manually download it first as a zip/tar (which was the case for MetFaces), and provide the file through the `data_files` argument. Alternatively, it may be that you have a folder with images, in which case you can provide it using the `data_dir` argument. Note that the latter assumes a [particular structure](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#imagefolder). ```python from datasets import load_dataset @@ -202,8 +169,7 @@ dataset = load_dataset("imagefolder", data_dir="path_to_folder") dataset = load_dataset("imagefolder", data_files="path_to_file_or_direct_download_link") # note that you can also provide them as separate splits, like so: -dataset = load_dataset("imagefolder", data_files={"train": ["path/to/file1", "path/to/file2"], - "test": ["path/to/file3", "path/to/file4"]}) +dataset = load_dataset("imagefolder", data_files={"train": ["path/to/file1", "path/to/file2"], "test": ["path/to/file3", "path/to/file4"]}) ``` Once you've loaded your dataset, you can push it to the Hub with a single line of code: @@ -212,19 +178,15 @@ Once you've loaded your dataset, you can push it to the Hub with a single line o dataset.push_to_hub("huggan/name-of-your-dataset") ``` -Et voila! Your dataset is now available on the Hub :) If you wait a bit, the Dataset viewer should be able to preview -images in the browser. The MetFaces dataset can be seen here: https://huggingface.co/datasets/huggan/metfaces. +Et voila! Your dataset is now available on the Hub :) If you wait a bit, the Dataset viewer should be able to preview images in the browser. The MetFaces dataset can be seen here: https://huggingface.co/datasets/huggan/metfaces.

drawing

-The cool thing is that anyone can now access this dataset from anywhere, using `load_dataset` 🎉🥳 this means that you -can easily load the dataset on another computer for instance, or in a different environment. Amazing, isn't it? +The cool thing is that anyone can now access this dataset from anywhere, using `load_dataset` 🎉🥳 this means that you can easily load the dataset on another computer for instance, or in a different environment. Amazing, isn't it? -❗ Note: When uploading a dataset, make sure that it has appropriate column names. The `ImageFolder` utility -automatically creates `image` and `label` columns, however if there's only one image class, it makes sense to remove -the `label` column before pushing to the hub. This can be done as follows: +❗ Note: When uploading a dataset, make sure that it has appropriate column names. The `ImageFolder` utility automatically creates `image` and `label` columns, however if there's only one image class, it makes sense to remove the `label` column before pushing to the hub. This can be done as follows: ```python dataset = dataset.remove_columns("label") @@ -234,10 +196,7 @@ Note that you can always update a dataset by simply calling `push_to_hub` again #### 1.3 Processing the data -Once you've uploaded your dataset, you can load it and create a dataloader for it. The code example below shows how to -apply some data augmentation and creating a PyTorch Dataloader (the [PyTorch example scripts](pytorch) all leverage -this). More info can also be found in -the [docs](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#process-image-data). +Once you've uploaded your dataset, you can load it and create a dataloader for it. The code example below shows how to apply some data augmentation and creating a PyTorch Dataloader (the [PyTorch example scripts](pytorch) all leverage this). More info can also be found in the [docs](https://huggingface.co/docs/datasets/v2.0.0/en/image_process#process-image-data). ```python from datasets import load_dataset @@ -258,71 +217,46 @@ transform = Compose( ] ) - # define function def transforms(examples): - examples["image"] = [transform(image.convert("RGB")) for image in examples["image"]] - - return examples + examples["image"] = [transform(image.convert("RGB")) for image in examples["image"]] + return examples transformed_dataset = dataset.with_transform(transforms) # create dataloader dataloader = DataLoader( - transformed_dataset["train"], batch_size="your batch size", shuffle=True, num_workers="your number of CPU cores" + transformed_dataset["train"], batch_size="your batch size", shuffle=True, num_workers="your number of CPU cores" ) ``` -As can be seen, we leverage -the [`with_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.with_transform) -method here, which will make sure the image transformations will only be performed when iterating over the data (i.e. -data augmentation is performed on-the-fly, making it very RAM-friendly) rather than performing it on the entire dataset -in one go (which would be the case if you -use [`map`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.map)). -The `with_transform` method does the same thing -as [`set_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.set_transform) -, except that it does return a new `Dataset` rather than performing the operation in-place. +As can be seen, we leverage the [`with_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.with_transform) method here, which will make sure the image transformations will only be performed when iterating over the data (i.e. data augmentation is performed on-the-fly, making it very RAM-friendly) rather than performing it on the entire dataset in one go (which would be the case if you use [`map`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.map)). The `with_transform` method does the same thing as [`set_transform`](https://huggingface.co/docs/datasets/v2.0.0/en/package_reference/main_classes#datasets.Dataset.set_transform), except that it does return a new `Dataset` rather than performing the operation in-place. ### 2. Train a model and push to Hub -Next, one can start training a model. This could be any model you'd like. However, we provide some example scripts to -help you get started, in [PyTorch](pytorch). An example is the [DCGAN](pytorch/dcgan) model for unconditional image -generation. Simply follow the README that explains all the details of the relevant implementation, and run it in your -environment. +Next, one can start training a model. This could be any model you'd like. However, we provide some example scripts to help you get started, in both [PyTorch](pytorch) and [Tensorflow](tensorflow). An example is the [DCGAN](pytorch/dcgan) model for unconditional image generation. Simply follow the README that explains all the details of the relevant implementation, and run it in your environment. -The PyTorch example scripts all leverage 🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), which provides -an easy API to make your scripts run on any kind of distributed setting (multi-GPUs, TPUs etc.) and with mixed -precision, while still letting you write your own training loop. +The PyTorch example scripts all leverage 🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), which provides an easy API to make your scripts run on any kind of distributed setting (multi-GPUs, TPUs etc.) and with mixed precision, while still letting you write your own training loop. Alternatively, we also provide a [Links to Check Out](#links-to-check-out) section to give you some inspiration. -Below, we explain in more detail how to upload your model to the Hub, depending on the framework you're using ( -sections [2.1](#21-pytorch) and [2.2](#22-keras)). In section [2.3](#33-alternative-ways-to-upload-a-model-to-the-hub), -we'll explain how to write a nice model card. In section [2.4](24-model-cards), we'll illustrate alternative ways to -upload (and re-use) a model to (and from) the hub. Finally, in section [2.5](25-accelerate), we explain -🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), the awesome library that makes training PyTorch models on -any kind of environment a breeze. Be sure to check it out! +Below, we explain in more detail how to upload your model to the Hub, depending on the framework you're using (sections [2.1](#21-pytorch) and [2.2](#22-keras)). In section [2.3](#33-alternative-ways-to-upload-a-model-to-the-hub), we'll explain how to write a nice model card. In section [2.4](24-model-cards), we'll illustrate alternative ways to upload (and re-use) a model to (and from) the hub. Finally, in section [2.5](25-accelerate), we explain 🤗 [Accelerate](https://huggingface.co/docs/accelerate/index), the awesome library that makes training PyTorch models on any kind of environment a breeze. Be sure to check it out! #### 2.1 PyTorch -If you're planning to train a custom PyTorch model, it's recommended to make it inherit from `PyTorchModelHubMixin`. -This makes sure you can push it to the Hub at the end of training, and reload it afterwards using `from_pretrained`, as -shown in the code example below: +If you're planning to train a custom PyTorch model, it's recommended to make it inherit from `PyTorchModelHubMixin`. This makes sure you can push it to the Hub at the end of training, and reload it afterwards using `from_pretrained`, as shown in the code example below: ```python from huggingface_hub import PyTorchModelHubMixin - class MyGenerator(nn.Module, PyTorchModelHubMixin): - def __init__(self, **kwargs): - super().__init__() - self.config = kwargs.pop("config", None) - self.layer = ... - - def forward(self, ...): - return ... - + def __init__(self, **kwargs): + super().__init__() + self.config = kwargs.pop("config", None) + self.layer = ... + def forward(self, ...): + return ... # Create model model = MyGenerator() @@ -334,9 +268,7 @@ model.push_to_hub("huggan/name-of-your-model"). reloaded = MyGenerator.from_pretrained("huggan/name-of-your-model"). ``` -This `PyTorchModelHubMixin` class is available in -the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which comes pre-installed if you -install `datasets` (or `transformers`) in your environment. +This `PyTorchModelHubMixin` class is available in the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which comes pre-installed if you install `datasets` (or `transformers`) in your environment. #### 2.2 Keras @@ -359,22 +291,15 @@ push_to_hub_keras(model, "huggan/my-cool-model") reloaded = from_pretrained_keras("huggan/my-cool-model") ``` -These methods are available in the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which -comes pre-installed if you install `datasets` (or `transformers`) in your environment. Note that the `push_to_hub_keras` -method supports pushing several models (such as a generator and discriminator) to the same repo, as -illustrated [here](https://github.com/huggingface/huggingface_hub/issues/533#issuecomment-1058093158). +These methods are available in the [`huggingface_hub` library](https://github.com/huggingface/huggingface_hub), which comes pre-installed if you install `datasets` (or `transformers`) in your environment. Note that the `push_to_hub_keras` method supports pushing several models (such as a generator and discriminator) to the same repo, as illustrated [here](https://github.com/huggingface/huggingface_hub/issues/533#issuecomment-1058093158). #### 2.3 Alternative ways to upload a model to the Hub -Besides the methods explained in sections 2.1 and 2.2 above, you can also share model assets directly from git, which is -explained in depth in [this guide](https://huggingface.co/docs/hub/adding-a-model#uploading-your-files). +Besides the methods explained in sections 2.1 and 2.2 above, you can also share model assets directly from git, which is explained in depth in [this guide](https://huggingface.co/docs/hub/adding-a-model#uploading-your-files). #### 2.4 Model cards -When uploading a model to the Hub, it's important to include a -so-called [model card](https://huggingface.co/course/chapter4/4?fw=pt) with it. This is just a README (in Markdown) 🃏 -that includes: - +When uploading a model to the Hub, it's important to include a so-called [model card](https://huggingface.co/course/chapter4/4?fw=pt) with it. This is just a README (in Markdown) 🃏 that includes: - license, - task, - `huggan` and `gan` tags, @@ -383,18 +308,16 @@ that includes: - information on dataset, intended uses, - a model output. -If you trained one of the example models, this model card will be automatically generated for you. If you didn’t train -the model yourself, be sure to both credit the original authors and include the associated license in your model card! -Here is an [example model repo](https://huggingface.co/merve/anime-faces-generator). +If you trained one of the example models, this model card will be automatically generated for you. If you didn’t train the model yourself, be sure to both credit the original authors and include the associated license in your model card! Here is an [example model repo](https://huggingface.co/merve/anime-faces-generator). You can also use this [template model card](model_card_template.md) -as a guide to build your own. + as a guide to build your own. ![Alt text](assets/example_model.png?raw=true "Title") #### 2.5 Accelerate -HuggingFace `accelerate` is an awesome library for training PyTorch models. Here we show why. +HuggingFace `accelerate` is an awesome library for training PyTorch models. Here we show why. Basically, the library requires to replace this: @@ -411,7 +334,7 @@ for batch in my_training_dataloader: loss.backward() my_optimizer.step() ``` - + by this: ```diff @@ -437,9 +360,7 @@ by this: my_optimizer.step() ``` -and BOOM, your script runs on **any kind of hardware**, including CPU, multi-CPU, GPU, multi-GPU and TPU. It also -supports things like [DeepSpeed](https://github.com/microsoft/DeepSpeed) -and [mixed precision](https://arxiv.org/abs/1710.03740) for training efficiently. +and BOOM, your script runs on **any kind of hardware**, including CPU, multi-CPU, GPU, multi-GPU and TPU. It also supports things like [DeepSpeed](https://github.com/microsoft/DeepSpeed) and [mixed precision](https://arxiv.org/abs/1710.03740) for training efficiently. You can now run your script as follows: @@ -447,8 +368,7 @@ You can now run your script as follows: accelerate config ``` -=> Accelerate will ask what kind of environment you'd like to run your script on, simply answer the questions being -asked. Next: +=> Accelerate will ask what kind of environment you'd like to run your script on, simply answer the questions being asked. Next: ```bash accelerate launch @@ -464,17 +384,13 @@ You can of course change the environment by running `accelerate config` again. ### 3. Create a demo -Once you share a model, you then should share a [Space](https://huggingface.co/spaces) based on your SDK of choice ( -Gradio or Streamlit) or as a static page. 🌌 +Once you share a model, you then should share a [Space](https://huggingface.co/spaces) based on your SDK of choice (Gradio or Streamlit) or as a static page. 🌌 ![Alt text](assets/example_space.png?raw=true "Title") -Here is an [example Space](https://huggingface.co/spaces/merve/anime-face-generator) corresponding to the model example -shared above. Don’t know how to create a space? Read more about how to add -spaces [here](https://huggingface.co/docs/hub/spaces). +Here is an [example Space](https://huggingface.co/spaces/merve/anime-face-generator) corresponding to the model example shared above. Don’t know how to create a space? Read more about how to add spaces [here](https://huggingface.co/docs/hub/spaces). Below, we list some other great example GAN Spaces: - - AnimeGANv2: https://huggingface.co/spaces/akhaliq/AnimeGANv2 - ArcaneGAN: https://huggingface.co/spaces/akhaliq/ArcaneGAN - This Pokemon does not exist: https://huggingface.co/spaces/ronvolutional/ai-pokemon-card @@ -483,20 +399,18 @@ Below, we list some other great example GAN Spaces: ## Example Scripts -In this repo, we have provided some example scripts you can use to train your own GANs. Below is a table of the -available scripts: +In this repo, we have provided some example scripts you can use to train your own GANs. Below is a table of the available scripts: -| Name | Paper | -|------------------------------| ----------- | -| [DCGAN](pytorch/dcgan) | [Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks](https://arxiv.org/abs/1511.06434) | -| [pix2pix](pytorch/pix2pix) | [Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/abs/1611.07004) | -| [CycleGAN](pytorch/cyclegan) | [Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks](https://arxiv.org/abs/1703.10593) | +| Name | Paper | +| ----------- | ----------- | +| [DCGAN](pytorch/dcgan) | [Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks](https://arxiv.org/abs/1511.06434) | +| [pix2pix](pytorch/pix2pix) | [Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/abs/1611.07004) | +| [CycleGAN](pytorch/cyclegan) | [Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks](https://arxiv.org/abs/1703.10593) | | [SN-GAN](pytorch/sngan) | [Spectral Normalization for Generative Adversarial Networks](https://arxiv.org/abs/1802.05957) | ## Datasets to add -Below, we list some datasets which could be added to the Hub (feel free to add on one of these, or open a PR to add more -datasets!): +Below, we list some datasets which could be added to the Hub (feel free to add on one of these, or open a PR to add more datasets!): - DeepFashion: https://mmlab.ie.cuhk.edu.hk/projects/DeepFashion.html - Flowers: https://www.robots.ox.ac.uk/~vgg/data/flowers/ @@ -504,11 +418,9 @@ datasets!): ## Links to Check Out -Below, we list some possible awesome project ideas (feel free to work on one of these, or open a PR to add more project -ideas!): +Below, we list some possible awesome project ideas (feel free to work on one of these, or open a PR to add more project ideas!): PyTorch: - - Lightweight-GAN: https://github.com/lucidrains/lightweight-gan - StyleGAN2: https://github.com/lucidrains/stylegan2-pytorch - StyleGAN2-ada: https://github.com/NVlabs/stylegan2-ada @@ -528,7 +440,6 @@ PyTorch: - Denoising Diffusion GAN: https://github.com/NVlabs/denoising-diffusion-gan Keras: - - WGAN-GP: https://keras.io/examples/generative/wgan_gp/ - Conditional GAN: https://keras.io/examples/generative/conditional_gan/ - CycleGAN, DiscoGAN etc.: https://github.com/eriklindernoren/Keras-GAN @@ -537,14 +448,12 @@ Keras: - Deformable GAN: https://github.com/AliaksandrSiarohin/pose-gan General links & tutorials: - - https://github.com/yhlleo/GAN-Metrics - https://paperswithcode.com/task/image-generation ## GAN metrics -There have been several quantitative measures defined for assessing the quality of GANs (and other generative models). -Refer to [this page](pytorch/metrics) for more info. +There have been several quantitative measures defined for assessing the quality of GANs (and other generative models). Refer to [this page](pytorch/metrics) for more info. ## Evaluation @@ -559,21 +468,13 @@ TODO ## Communication and Problems -If you encounter any problems or have any questions, you should use one of the following platforms depending on your -type of problem. Hugging Face is an "open-source-first" organization meaning that we'll try to solve all problems in the -most public and most transparent way possible so that everybody in the community profits. +If you encounter any problems or have any questions, you should use one of the following platforms depending on your type of problem. Hugging Face is an "open-source-first" organization meaning that we'll try to solve all problems in the most public and most transparent way possible so that everybody in the community profits. The following table summarizes what platform to use for which problem. -- Problem/question/bug with the 🤗 Datasets library that you think is a general problem that also impacts other people, - please open - an [Issues on Datasets](https://github.com/huggingface/datasets/issues/new?assignees=&labels=bug&template=bug-report.md&title=) - and ping @nielsrogge. -- Problem/question with a modified, customized training script that is less likely to impact other people, please post - your problem/question [on the forum](https://discuss.huggingface.co/) and ping @nielsrogge. -- Other questions regarding the event, rules of the event, or if you are not sure where to post your question, please - ask in the Discord channel [** - #sprint-discussions**](https://discord.com/channels/879548962464493619/954111918895943720). +- Problem/question/bug with the 🤗 Datasets library that you think is a general problem that also impacts other people, please open an [Issues on Datasets](https://github.com/huggingface/datasets/issues/new?assignees=&labels=bug&template=bug-report.md&title=) and ping @nielsrogge. +- Problem/question with a modified, customized training script that is less likely to impact other people, please post your problem/question [on the forum](https://discuss.huggingface.co/) and ping @nielsrogge. +- Other questions regarding the event, rules of the event, or if you are not sure where to post your question, please ask in the Discord channel [**#sprint-discussions**](https://discord.com/channels/879548962464493619/954111918895943720). ## Talks @@ -583,7 +484,4 @@ TODO - Memory efficient training: -In case, you are getting out-of-memory errors on your GPU, we recommend to -use [bitsandbytes](https://github.com/facebookresearch/bitsandbytes) to replace the native memory-intensive Adam -optimizer with the one of `bitsandbytes`. It can be used to both train the generator and the discriminator in case -you're training a GAN. +In case, you are getting out-of-memory errors on your GPU, we recommend to use [bitsandbytes](https://github.com/facebookresearch/bitsandbytes) to replace the native memory-intensive Adam optimizer with the one of `bitsandbytes`. It can be used to both train the generator and the discriminator in case you're training a GAN. \ No newline at end of file From 36ec15ea44a3f28c7bf6ab00cb42a08a86bc708a Mon Sep 17 00:00:00 2001 From: Aleksey Korshuk <48794610+AlekseyKorshuk@users.noreply.github.com> Date: Sat, 9 Apr 2022 18:50:14 +0300 Subject: [PATCH 6/8] Update huggan/pytorch/sngan/README.md Co-authored-by: Nathan Raw --- huggan/pytorch/sngan/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/huggan/pytorch/sngan/README.md b/huggan/pytorch/sngan/README.md index dafccf24..58a4a1b5 100644 --- a/huggan/pytorch/sngan/README.md +++ b/huggan/pytorch/sngan/README.md @@ -28,7 +28,7 @@ This will create a local "images" directory, containing generated images over th To train on another dataset available on the hub, simply do (for instance): ```bash -python train.py --dataset cifar-10 +python train.py --dataset cifar10 ``` In case you'd like to tweak the script to your liking, first fork the "community-events" [repo](https://github.com/huggingface/community-events) (see the button on the top right), then clone it locally: From 0487fff4319ad2990fb5ad1f160b3831278208ba Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Sat, 9 Apr 2022 18:52:13 +0300 Subject: [PATCH 7/8] fix: comments from review --- huggan/pytorch/sngan/train.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/huggan/pytorch/sngan/train.py b/huggan/pytorch/sngan/train.py index 5a31ffdb..b58a77bd 100644 --- a/huggan/pytorch/sngan/train.py +++ b/huggan/pytorch/sngan/train.py @@ -279,7 +279,6 @@ def transforms(examples): # Optionally push to hub if accelerator.is_main_process and args.push_to_hub: - # os.makedirs(f"{args.output_dir}/{args.model_name}", exist_ok=True) generator.push_to_hub( repo_path_or_name=f"{args.output_dir}/{args.model_name}", organization=args.organization_name, @@ -292,12 +291,6 @@ def transforms(examples): parser.add_argument( "--num_workers", type=int, help="Number of data loading workers", default=0 ) - parser.add_argument( - "--image_size", - type=int, - default=64, - help="Spatial size to use when resizing images for training.", - ) parser.add_argument("--batch_size", type=int, default=16, help="Input batch size") parser.add_argument("--latent_dim", type=int, default=100, help="Dimensionality of the latent space.") parser.add_argument( @@ -362,6 +355,7 @@ def transforms(examples): ) args = parser.parse_args() args.num_channels = 4 + args.image_size = 64 if args.push_to_hub: assert args.output_dir is not None, "Need an `output_dir` to create a repo when `--push_to_hub` is passed." assert args.model_name is not None, "Need a `model_name` to create a repo when `--push_to_hub` is passed." From 94cc003597c6ba976bed73aaf4b7d3c06f9dc3da Mon Sep 17 00:00:00 2001 From: AlekseyKorshuk Date: Sat, 9 Apr 2022 23:08:25 +0300 Subject: [PATCH 8/8] fix: README.md --- huggan/pytorch/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/huggan/pytorch/README.md b/huggan/pytorch/README.md index d32dd1ed..dfc29de4 100644 --- a/huggan/pytorch/README.md +++ b/huggan/pytorch/README.md @@ -14,6 +14,7 @@ Currently, it contains the following examples: | [DCGAN](dcgan) | [Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks](https://arxiv.org/abs/1511.06434) | | [pix2pix](pix2pix) | [Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/abs/1611.07004) | | [CycleGAN](cyclegan) | [Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks](https://arxiv.org/abs/1703.10593) -| [Lightweight GAN](lightweight_gan) | [Towards Faster and Stabilized GAN Training for High-fidelity Few-shot Image Synthesis](https://openreview.net/forum?id=1Fqg133qRaI) +| [Lightweight GAN](lightweight_gan) | [Towards Faster and Stabilized GAN Training for High-fidelity Few-shot Image Synthesis](https://openreview.net/forum?id=1Fqg133qRaI) | +| [SN-GAN](pytorch/sngan) | [Spectral Normalization for Generative Adversarial Networks](https://arxiv.org/abs/1802.05957) |