3leach commited on
Commit
000c736
1 Parent(s): 7b7522c

First model version

Browse files
args.json ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "pretrained_model_name_or_path": "booth-ai/realisticVisionV20_v20_inpainting",
3
+ "pretrained_vae_name_or_path": "stabilityai/sd-vae-ft-mse",
4
+ "revision": "main",
5
+ "tokenizer_name": null,
6
+ "instance_data_dir": null,
7
+ "class_data_dir": null,
8
+ "instance_prompt": null,
9
+ "class_prompt": null,
10
+ "save_sample_negative_prompt": null,
11
+ "n_save_sample": 4,
12
+ "save_guidance_scale": 7.5,
13
+ "save_infer_steps": 50,
14
+ "pad_tokens": false,
15
+ "with_prior_preservation": false,
16
+ "prior_loss_weight": 1.0,
17
+ "num_class_images": 100,
18
+ "output_dir": "./models/outgrowths_7",
19
+ "seed": 3434554,
20
+ "resolution": 512,
21
+ "center_crop": false,
22
+ "train_text_encoder": false,
23
+ "train_batch_size": 4,
24
+ "sample_batch_size": 2,
25
+ "num_train_epochs": 176,
26
+ "max_train_steps": 10000,
27
+ "gradient_accumulation_steps": 1,
28
+ "gradient_checkpointing": false,
29
+ "learning_rate": 2e-06,
30
+ "scale_lr": false,
31
+ "lr_scheduler": "constant",
32
+ "lr_warmup_steps": 0,
33
+ "use_8bit_adam": false,
34
+ "adam_beta1": 0.9,
35
+ "adam_beta2": 0.999,
36
+ "adam_weight_decay": 0.01,
37
+ "adam_epsilon": 1e-08,
38
+ "max_grad_norm": 1.0,
39
+ "push_to_hub": false,
40
+ "hub_token": null,
41
+ "hub_model_id": null,
42
+ "logging_dir": "logs",
43
+ "log_interval": 10,
44
+ "save_interval": 500,
45
+ "save_min_steps": 500,
46
+ "mixed_precision": "no",
47
+ "not_cache_latents": true,
48
+ "hflip": true,
49
+ "local_rank": -1,
50
+ "concepts_list": [
51
+ {
52
+ "instance_prompt": "photo of zwx dog",
53
+ "class_prompt": "photo of a dog",
54
+ "instance_data_dir": "./512",
55
+ "class_data_dir": "../../../data/dog"
56
+ }
57
+ ]
58
+ }
feature_extractor/preprocessor_config.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "crop_size": {
3
+ "height": 224,
4
+ "width": 224
5
+ },
6
+ "do_center_crop": true,
7
+ "do_convert_rgb": true,
8
+ "do_normalize": true,
9
+ "do_rescale": true,
10
+ "do_resize": true,
11
+ "feature_extractor_type": "CLIPFeatureExtractor",
12
+ "image_mean": [
13
+ 0.48145466,
14
+ 0.4578275,
15
+ 0.40821073
16
+ ],
17
+ "image_processor_type": "CLIPFeatureExtractor",
18
+ "image_std": [
19
+ 0.26862954,
20
+ 0.26130258,
21
+ 0.27577711
22
+ ],
23
+ "resample": 3,
24
+ "rescale_factor": 0.00392156862745098,
25
+ "size": {
26
+ "shortest_edge": 224
27
+ }
28
+ }
model_index.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "StableDiffusionInpaintPipeline",
3
+ "_diffusers_version": "0.21.0.dev0",
4
+ "_name_or_path": "booth-ai/realisticVisionV20_v20_inpainting",
5
+ "feature_extractor": [
6
+ "transformers",
7
+ "CLIPFeatureExtractor"
8
+ ],
9
+ "requires_safety_checker": true,
10
+ "safety_checker": [
11
+ null,
12
+ null
13
+ ],
14
+ "scheduler": [
15
+ "diffusers",
16
+ "DDIMScheduler"
17
+ ],
18
+ "text_encoder": [
19
+ "transformers",
20
+ "CLIPTextModel"
21
+ ],
22
+ "tokenizer": [
23
+ "transformers",
24
+ "CLIPTokenizer"
25
+ ],
26
+ "unet": [
27
+ "diffusers",
28
+ "UNet2DConditionModel"
29
+ ],
30
+ "vae": [
31
+ "diffusers",
32
+ "AutoencoderKL"
33
+ ]
34
+ }
samples/0/0.png ADDED
samples/0/1.png ADDED
samples/0/2.png ADDED
samples/0/3.png ADDED
scheduler/scheduler_config.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "DDIMScheduler",
3
+ "_diffusers_version": "0.21.0.dev0",
4
+ "beta_end": 0.012,
5
+ "beta_schedule": "scaled_linear",
6
+ "beta_start": 0.00085,
7
+ "clip_sample": false,
8
+ "clip_sample_range": 1.0,
9
+ "dynamic_thresholding_ratio": 0.995,
10
+ "num_train_timesteps": 1000,
11
+ "prediction_type": "epsilon",
12
+ "rescale_betas_zero_snr": false,
13
+ "sample_max_value": 1.0,
14
+ "set_alpha_to_one": false,
15
+ "steps_offset": 1,
16
+ "thresholding": false,
17
+ "timestep_spacing": "leading",
18
+ "trained_betas": null
19
+ }
text_encoder/config.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "booth-ai/realisticVisionV20_v20_inpainting",
3
+ "architectures": [
4
+ "CLIPTextModel"
5
+ ],
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": 0,
8
+ "dropout": 0.0,
9
+ "eos_token_id": 2,
10
+ "hidden_act": "quick_gelu",
11
+ "hidden_size": 768,
12
+ "initializer_factor": 1.0,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 3072,
15
+ "layer_norm_eps": 1e-05,
16
+ "max_position_embeddings": 77,
17
+ "model_type": "clip_text_model",
18
+ "num_attention_heads": 12,
19
+ "num_hidden_layers": 12,
20
+ "pad_token_id": 1,
21
+ "projection_dim": 768,
22
+ "torch_dtype": "float16",
23
+ "transformers_version": "4.32.1",
24
+ "vocab_size": 49408
25
+ }
text_encoder/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5f3183e9cd8a1c4cfd99fc68b0c6d1832d009ad672c3577ab0e81939ec1be15b
3
+ size 246144152
tokenizer/merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer/special_tokens_map.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<|startoftext|>",
4
+ "lstrip": false,
5
+ "normalized": true,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "<|endoftext|>",
11
+ "lstrip": false,
12
+ "normalized": true,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": "<|endoftext|>",
17
+ "unk_token": {
18
+ "content": "<|endoftext|>",
19
+ "lstrip": false,
20
+ "normalized": true,
21
+ "rstrip": false,
22
+ "single_word": false
23
+ }
24
+ }
tokenizer/tokenizer_config.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "bos_token": {
4
+ "__type": "AddedToken",
5
+ "content": "<|startoftext|>",
6
+ "lstrip": false,
7
+ "normalized": true,
8
+ "rstrip": false,
9
+ "single_word": false
10
+ },
11
+ "clean_up_tokenization_spaces": true,
12
+ "do_lower_case": true,
13
+ "eos_token": {
14
+ "__type": "AddedToken",
15
+ "content": "<|endoftext|>",
16
+ "lstrip": false,
17
+ "normalized": true,
18
+ "rstrip": false,
19
+ "single_word": false
20
+ },
21
+ "errors": "replace",
22
+ "model_max_length": 77,
23
+ "pad_token": "<|endoftext|>",
24
+ "tokenizer_class": "CLIPTokenizer",
25
+ "unk_token": {
26
+ "__type": "AddedToken",
27
+ "content": "<|endoftext|>",
28
+ "lstrip": false,
29
+ "normalized": true,
30
+ "rstrip": false,
31
+ "single_word": false
32
+ }
33
+ }
tokenizer/vocab.json ADDED
The diff for this file is too large to render. See raw diff
 
train_inpainting_dreambooth.py ADDED
@@ -0,0 +1,1032 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import hashlib
3
+ import itertools
4
+ import json
5
+ import math
6
+ import os
7
+ import random
8
+ import shutil
9
+ from contextlib import nullcontext
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+ import torch.utils.checkpoint
16
+ from accelerate import Accelerator
17
+ from accelerate.logging import get_logger
18
+ from accelerate.utils import set_seed
19
+ from huggingface_hub import HfFolder, Repository, whoami
20
+ from PIL import Image, ImageOps
21
+ from torch.utils.data import Dataset
22
+ # from torchvision import transforms
23
+ # from torchvision.transforms import v2
24
+ from opencv_transforms import transforms
25
+ from tqdm.auto import tqdm
26
+ from transformers import CLIPTextModel, CLIPTokenizer
27
+
28
+ from diffusers import (AutoencoderKL, DDIMScheduler, DDPMScheduler,
29
+ StableDiffusionInpaintPipeline, UNet2DConditionModel)
30
+ from diffusers.optimization import get_scheduler
31
+ from diffusers.utils import is_wandb_available
32
+
33
+ if is_wandb_available():
34
+ import wandb
35
+
36
+ torch.backends.cudnn.benchmark = True
37
+
38
+
39
+ logger = get_logger(__name__)
40
+
41
+
42
+ def parse_args(input_args=None):
43
+ parser = argparse.ArgumentParser(description="Simple example of a training script.")
44
+ parser.add_argument(
45
+ "--pretrained_model_name_or_path",
46
+ type=str,
47
+ default=None,
48
+ required=True,
49
+ help="Path to pretrained model or model identifier from huggingface.co/models.",
50
+ )
51
+ parser.add_argument(
52
+ "--pretrained_vae_name_or_path",
53
+ type=str,
54
+ default=None,
55
+ help="Path to pretrained vae or vae identifier from huggingface.co/models.",
56
+ )
57
+ parser.add_argument(
58
+ "--revision",
59
+ type=str,
60
+ default="fp16",
61
+ required=False,
62
+ help="Revision of pretrained model identifier from huggingface.co/models.",
63
+ )
64
+ parser.add_argument(
65
+ "--tokenizer_name",
66
+ type=str,
67
+ default=None,
68
+ help="Pretrained tokenizer name or path if not the same as model_name",
69
+ )
70
+ parser.add_argument(
71
+ "--instance_data_dir",
72
+ type=str,
73
+ default=None,
74
+ help="A folder containing the training data of instance images.",
75
+ )
76
+ parser.add_argument(
77
+ "--class_data_dir",
78
+ type=str,
79
+ default=None,
80
+ help="A folder containing the training data of class images.",
81
+ )
82
+ parser.add_argument(
83
+ "--instance_prompt",
84
+ type=str,
85
+ default=None,
86
+ help="The prompt with identifier specifying the instance",
87
+ )
88
+ parser.add_argument(
89
+ "--class_prompt",
90
+ type=str,
91
+ default=None,
92
+ help="The prompt to specify images in the same class as provided instance images.",
93
+ )
94
+ # parser.add_argument(
95
+ # "--save_sample_prompt",
96
+ # type=str,
97
+ # default=None,
98
+ # help="The prompt used to generate sample outputs to save.",
99
+ # )
100
+ parser.add_argument(
101
+ "--save_sample_negative_prompt",
102
+ type=str,
103
+ default=None,
104
+ help="The negative prompt used to generate sample outputs to save.",
105
+ )
106
+ parser.add_argument(
107
+ "--n_save_sample",
108
+ type=int,
109
+ default=4,
110
+ help="The number of samples to save.",
111
+ )
112
+ parser.add_argument(
113
+ "--save_guidance_scale",
114
+ type=float,
115
+ default=7.5,
116
+ help="CFG for save sample.",
117
+ )
118
+ parser.add_argument(
119
+ "--save_infer_steps",
120
+ type=int,
121
+ default=50,
122
+ help="The number of inference steps for save sample.",
123
+ )
124
+ parser.add_argument(
125
+ "--pad_tokens",
126
+ default=False,
127
+ action="store_true",
128
+ help="Flag to pad tokens to length 77.",
129
+ )
130
+ parser.add_argument(
131
+ "--with_prior_preservation",
132
+ default=False,
133
+ action="store_true",
134
+ help="Flag to add prior preservation loss.",
135
+ )
136
+ parser.add_argument("--prior_loss_weight", type=float, default=1.0, help="The weight of prior preservation loss.")
137
+ parser.add_argument(
138
+ "--num_class_images",
139
+ type=int,
140
+ default=100,
141
+ help=(
142
+ "Minimal class images for prior preservation loss. If not have enough images, additional images will be"
143
+ " sampled with class_prompt."
144
+ ),
145
+ )
146
+ parser.add_argument(
147
+ "--output_dir",
148
+ type=str,
149
+ default="text-inversion-model",
150
+ help="The output directory where the model predictions and checkpoints will be written.",
151
+ )
152
+ parser.add_argument("--seed", type=int, default=None, help="A seed for reproducible training.")
153
+ parser.add_argument(
154
+ "--resolution",
155
+ type=int,
156
+ default=512,
157
+ help=(
158
+ "The resolution for input images, all the images in the train/validation dataset will be resized to this"
159
+ " resolution"
160
+ ),
161
+ )
162
+ parser.add_argument(
163
+ "--center_crop", action="store_true", help="Whether to center crop images before resizing to resolution"
164
+ )
165
+ parser.add_argument("--train_text_encoder", action="store_true", help="Whether to train the text encoder")
166
+ parser.add_argument(
167
+ "--train_batch_size", type=int, default=4, help="Batch size (per device) for the training dataloader."
168
+ )
169
+ parser.add_argument(
170
+ "--sample_batch_size", type=int, default=4, help="Batch size (per device) for sampling images."
171
+ )
172
+ parser.add_argument("--num_train_epochs", type=int, default=1)
173
+ parser.add_argument(
174
+ "--max_train_steps",
175
+ type=int,
176
+ default=None,
177
+ help="Total number of training steps to perform. If provided, overrides num_train_epochs.",
178
+ )
179
+ parser.add_argument(
180
+ "--gradient_accumulation_steps",
181
+ type=int,
182
+ default=1,
183
+ help="Number of updates steps to accumulate before performing a backward/update pass.",
184
+ )
185
+ parser.add_argument(
186
+ "--gradient_checkpointing",
187
+ action="store_true",
188
+ help="Whether or not to use gradient checkpointing to save memory at the expense of slower backward pass.",
189
+ )
190
+ parser.add_argument(
191
+ "--learning_rate",
192
+ type=float,
193
+ default=5e-6,
194
+ help="Initial learning rate (after the potential warmup period) to use.",
195
+ )
196
+ parser.add_argument(
197
+ "--scale_lr",
198
+ action="store_true",
199
+ default=False,
200
+ help="Scale the learning rate by the number of GPUs, gradient accumulation steps, and batch size.",
201
+ )
202
+ parser.add_argument(
203
+ "--lr_scheduler",
204
+ type=str,
205
+ default="constant",
206
+ help=(
207
+ 'The scheduler type to use. Choose between ["linear", "cosine", "cosine_with_restarts", "polynomial",'
208
+ ' "constant", "constant_with_warmup"]'
209
+ ),
210
+ )
211
+ parser.add_argument(
212
+ "--lr_warmup_steps", type=int, default=500, help="Number of steps for the warmup in the lr scheduler."
213
+ )
214
+ parser.add_argument(
215
+ "--use_8bit_adam", action="store_true", help="Whether or not to use 8-bit Adam from bitsandbytes."
216
+ )
217
+ parser.add_argument("--adam_beta1", type=float, default=0.9, help="The beta1 parameter for the Adam optimizer.")
218
+ parser.add_argument("--adam_beta2", type=float, default=0.999, help="The beta2 parameter for the Adam optimizer.")
219
+ parser.add_argument("--adam_weight_decay", type=float, default=1e-2, help="Weight decay to use.")
220
+ parser.add_argument("--adam_epsilon", type=float, default=1e-08, help="Epsilon value for the Adam optimizer")
221
+ parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
222
+ parser.add_argument("--push_to_hub", action="store_true", help="Whether or not to push the model to the Hub.")
223
+ parser.add_argument("--hub_token", type=str, default=None, help="The token to use to push to the Model Hub.")
224
+ parser.add_argument(
225
+ "--hub_model_id",
226
+ type=str,
227
+ default=None,
228
+ help="The name of the repository to keep in sync with the local `output_dir`.",
229
+ )
230
+ parser.add_argument(
231
+ "--logging_dir",
232
+ type=str,
233
+ default="logs",
234
+ help=(
235
+ "[TensorBoard](https://www.tensorflow.org/tensorboard) log directory. Will default to"
236
+ " *output_dir/runs/**CURRENT_DATETIME_HOSTNAME***."
237
+ ),
238
+ )
239
+ parser.add_argument("--log_interval", type=int, default=10, help="Log every N steps.")
240
+ parser.add_argument("--save_interval", type=int, default=10_000, help="Save weights every N steps.")
241
+ parser.add_argument("--save_min_steps", type=int, default=0, help="Start saving weights after N steps.")
242
+ parser.add_argument(
243
+ "--mixed_precision",
244
+ type=str,
245
+ default="no",
246
+ choices=["no", "fp16", "bf16"],
247
+ help=(
248
+ "Whether to use mixed precision. Choose"
249
+ "between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10."
250
+ "and an Nvidia Ampere GPU."
251
+ ),
252
+ )
253
+ parser.add_argument("--not_cache_latents", action="store_true", help="Do not precompute and cache latents from VAE.")
254
+ parser.add_argument("--hflip", action="store_true", help="Apply horizontal flip data augmentation.")
255
+ parser.add_argument("--local_rank", type=int, default=-1, help="For distributed training: local_rank")
256
+ parser.add_argument(
257
+ "--concepts_list",
258
+ type=str,
259
+ default=None,
260
+ help="Path to json containing multiple concepts, will overwrite parameters like instance_prompt, class_prompt, etc.",
261
+ )
262
+
263
+ if input_args is not None:
264
+ args = parser.parse_args(input_args)
265
+ else:
266
+ args = parser.parse_args()
267
+
268
+ env_local_rank = int(os.environ.get("LOCAL_RANK", -1))
269
+ if env_local_rank != -1 and env_local_rank != args.local_rank:
270
+ args.local_rank = env_local_rank
271
+
272
+ return args
273
+
274
+ def get_cutout_holes(height, width, min_holes=8, max_holes=32, min_height=16, max_height=128, min_width=16, max_width=128):
275
+ holes = []
276
+ for _n in range(random.randint(min_holes, max_holes)):
277
+ hole_height = random.randint(min_height, max_height)
278
+ hole_width = random.randint(min_width, max_width)
279
+ y1 = random.randint(0, height - hole_height)
280
+ x1 = random.randint(0, width - hole_width)
281
+ y2 = y1 + hole_height
282
+ x2 = x1 + hole_width
283
+ holes.append((x1, y1, x2, y2))
284
+ return holes
285
+
286
+ import torchvision
287
+
288
+ def generate_random_mask(image):
289
+ # mask = torch.zeros_like(image[:1])
290
+ # print('foobar', mask.shape)
291
+ mask = image[-1].unsqueeze(0)
292
+ # torchvision.transforms.functional.to_pil_image(mask).save('foomask2.png')
293
+
294
+ # if random.uniform(0, 1) < 0.25:
295
+ # mask = torch.zeros_like(image[:1])
296
+ # mask.fill_(1.)
297
+ # print('foobar',image.shape)
298
+ # torchvision.transforms.functional.to_pil_image(image[:4]).save('fooimageinside2.png')
299
+ # print('foobar',image[:3].shape)
300
+ masked_image = image[:-1] * (mask < 0.5)
301
+ # torchvision.transforms.functional.to_pil_image(masked_image).save('foomaskedimage2.png')
302
+ return mask, masked_image
303
+
304
+ image_transforms = transforms.Compose(
305
+ [
306
+ torchvision.transforms.RandomHorizontalFlip(0.5 * True),
307
+ # transforms.Resize(size, interpolation=transforms.InterpolationMode.BILINEAR),
308
+ # transforms.CenterCrop(size) if center_crop else transforms.RandomCrop(size),
309
+ transforms.RandomResizedCrop(512, scale=(0.75,1.0)),
310
+ torchvision.transforms.ToTensor(),
311
+ torchvision.transforms.Normalize([0.5], [0.5]),
312
+ ]
313
+ )
314
+ # instance_image = Image.open("/home/neil/Documents/diffusers/examples/dreambooth/512_/a corner sofa in midnight blue in a room with vibrant walls and eclectic artwork, creating a lively and energetic atmosphere. .png")
315
+ # alpha = instance_image.split()[-1]
316
+ # instance_image.putalpha(ImageOps.invert(alpha))
317
+ # instance_image.save('foofull.png')
318
+ # # rgb_instance_image = instance_image.convert('RGB')
319
+ # # rgb_instance_image.save('foofullrgb.png')
320
+ # example = {}
321
+ # example["instance_images"] = image_transforms(instance_image)
322
+ # torchvision.transforms.functional.to_pil_image(example["instance_images"]).save('fooimage.png')
323
+ # example["instance_masks"], example["instance_masked_images"] = generate_random_mask(example["instance_images"])
324
+ # example["instance_images"] = example["instance_images"][:3]
325
+ # torchvision.transforms.functional.to_pil_image(example["instance_images"]).save('fooimage1.png')
326
+ # breakpoint()
327
+
328
+ # example = {}
329
+ # instance_image = Image.open("/home/neil/Documents/diffusers/examples/dreambooth/512_/a corner sofa in midnight blue in a room with vibrant walls and eclectic artwork, creating a lively and energetic atmosphere. .png")
330
+ # instance_image.save('fooinstance2.png')
331
+ # alpha = instance_image.split()[-1]
332
+ # alpha.save('fooalpha2.png')
333
+ # instance_image.putalpha(ImageOps.invert(alpha))
334
+ # instance_image.convert("RGB").save('foofull2rgb.png')
335
+ # instance_image.save('foofull2.png')
336
+
337
+ # example["instance_images"] = image_transforms(instance_image)
338
+ # torchvision.transforms.functional.to_pil_image(example["instance_images"]).save('fooimage2.png')
339
+ # example["instance_masks"], example["instance_masked_images"] = generate_random_mask(example["instance_images"])
340
+ # torchvision.transforms.functional.to_pil_image(example["instance_masks"]).save('fooinstance_masks.png')
341
+ # torchvision.transforms.functional.to_pil_image(example["instance_masked_images"]).save('fooinstance_masked_images.png')
342
+ # example["instance_images"] = example["instance_images"][:3]
343
+ # final = torchvision.transforms.functional.to_pil_image(example["instance_images"])
344
+ # final.save('fooimage3.png')
345
+ # breakpoint()
346
+
347
+ class DreamBoothDataset(Dataset):
348
+ """
349
+ A dataset to prepare the instance and class images with the prompts for fine-tuning the model.
350
+ It pre-processes the images and the tokenizes prompts.
351
+ """
352
+
353
+ def __init__(
354
+ self,
355
+ concepts_list,
356
+ tokenizer,
357
+ with_prior_preservation=True,
358
+ size=512,
359
+ center_crop=False,
360
+ num_class_images=None,
361
+ pad_tokens=False,
362
+ hflip=False
363
+ ):
364
+ self.size = size
365
+ self.center_crop = center_crop
366
+ self.tokenizer = tokenizer
367
+ self.with_prior_preservation = with_prior_preservation
368
+ self.pad_tokens = pad_tokens
369
+
370
+ self.instance_images_path = []
371
+ self.class_images_path = []
372
+
373
+ for concept in concepts_list:
374
+ inst_img_path = [(x, concept["instance_prompt"]) for x in Path(concept["instance_data_dir"]).iterdir() if x.is_file()]
375
+ self.instance_images_path.extend(inst_img_path)
376
+
377
+ if with_prior_preservation:
378
+ class_img_path = [(x, concept["class_prompt"]) for x in Path(concept["class_data_dir"]).iterdir() if x.is_file()]
379
+ self.class_images_path.extend(class_img_path[:num_class_images])
380
+
381
+ random.shuffle(self.instance_images_path)
382
+ self.num_instance_images = len(self.instance_images_path)
383
+ self.num_class_images = len(self.class_images_path)
384
+ self._length = max(self.num_class_images, self.num_instance_images)
385
+
386
+ self.image_transforms = transforms.Compose(
387
+ [
388
+ torchvision.transforms.RandomHorizontalFlip(0.5 * hflip),
389
+ transforms.RandomResizedCrop(size, scale=(0.75,1.0)),
390
+ torchvision.transforms.ToTensor(),
391
+ torchvision.transforms.Normalize([0.5], [0.5]),
392
+ ]
393
+ )
394
+
395
+ def __len__(self):
396
+ return self._length
397
+
398
+ def __getitem__(self, index):
399
+ example = {}
400
+ instance_path, instance_prompt = self.instance_images_path[index % self.num_instance_images]
401
+ instance_image = Image.open(instance_path)
402
+ alpha = instance_image.split()[-1]
403
+ instance_image.putalpha(ImageOps.invert(alpha))
404
+
405
+ example["instance_images"] = self.image_transforms(instance_image)
406
+ example["instance_masks"], example["instance_masked_images"] = generate_random_mask(example["instance_images"])
407
+ # torchvision.transforms.functional.to_pil_image(example["instance_masks"][0]).save('foo_instance_masks.png')
408
+ # torchvision.transforms.functional.to_pil_image(example["instance_masked_images"][0]).save('foo_instance_masked_images.png')
409
+ example["instance_images"] = example["instance_images"][:3]
410
+ # torchvision.transforms.functional.to_pil_image(example["instance_images"]).save('foo_instance_image.png')
411
+ example["instance_prompt_ids"] = self.tokenizer(
412
+ # instance_prompt,
413
+ os.path.basename(instance_prompt),
414
+ padding="max_length" if self.pad_tokens else "do_not_pad",
415
+ truncation=True,
416
+ max_length=self.tokenizer.model_max_length,
417
+ ).input_ids
418
+ if self.with_prior_preservation:
419
+ class_path, class_prompt = self.class_images_path[index % self.num_class_images]
420
+ class_image = Image.open(class_path)
421
+ alpha = instance_image.split()[-1]
422
+ instance_image.putalpha(ImageOps.invert(alpha))
423
+ example["instance_images"] = self.image_transforms(instance_image)
424
+ example["instance_masks"], example["instance_masked_images"] = generate_random_mask(example["instance_images"])
425
+ example["instance_images"] = self.image_transforms(instance_image.convert("RGB"))
426
+ example["class_prompt_ids"] = self.tokenizer(
427
+ class_prompt,
428
+ padding="max_length" if self.pad_tokens else "do_not_pad",
429
+ truncation=True,
430
+ max_length=self.tokenizer.model_max_length,
431
+ ).input_ids
432
+
433
+ return example
434
+
435
+
436
+ class PromptDataset(Dataset):
437
+ "A simple dataset to prepare the prompts to generate class images on multiple GPUs."
438
+
439
+ def __init__(self, prompt, num_samples):
440
+ self.prompt = prompt
441
+ self.num_samples = num_samples
442
+
443
+ def __len__(self):
444
+ return self.num_samples
445
+
446
+ def __getitem__(self, index):
447
+ example = {}
448
+ example["prompt"] = self.prompt
449
+ example["index"] = index
450
+ return example
451
+
452
+
453
+ class LatentsDataset(Dataset):
454
+ def __init__(self, latents_cache, text_encoder_cache):
455
+ self.latents_cache = latents_cache
456
+ self.text_encoder_cache = text_encoder_cache
457
+
458
+ def __len__(self):
459
+ return len(self.latents_cache)
460
+
461
+ def __getitem__(self, index):
462
+ return self.latents_cache[index], self.text_encoder_cache[index]
463
+
464
+
465
+ class AverageMeter:
466
+ def __init__(self, name=None):
467
+ self.name = name
468
+ self.reset()
469
+
470
+ def reset(self):
471
+ self.sum = self.count = self.avg = 0
472
+
473
+ def update(self, val, n=1):
474
+ self.sum += val * n
475
+ self.count += n
476
+ self.avg = self.sum / self.count
477
+
478
+
479
+ def get_full_repo_name(model_id: str, organization: Optional[str] = None, token: Optional[str] = None):
480
+ if token is None:
481
+ token = HfFolder.get_token()
482
+ if organization is None:
483
+ username = whoami(token)["name"]
484
+ return f"{username}/{model_id}"
485
+ else:
486
+ return f"{organization}/{model_id}"
487
+
488
+
489
+ def main(args):
490
+ logging_dir = Path(args.output_dir, "0", args.logging_dir)
491
+
492
+ accelerator = Accelerator(
493
+ gradient_accumulation_steps=args.gradient_accumulation_steps,
494
+ mixed_precision=args.mixed_precision,
495
+ log_with="tensorboard",
496
+ project_dir=logging_dir,
497
+ )
498
+
499
+ # Currently, it's not possible to do gradient accumulation when training two models with accelerate.accumulate
500
+ # This will be enabled soon in accelerate. For now, we don't allow gradient accumulation when training two models.
501
+ # TODO (patil-suraj): Remove this check when gradient accumulation with two models is enabled in accelerate.
502
+ if args.train_text_encoder and args.gradient_accumulation_steps > 1 and accelerator.num_processes > 1:
503
+ raise ValueError(
504
+ "Gradient accumulation is not supported when training the text encoder in distributed training. "
505
+ "Please set gradient_accumulation_steps to 1. This feature will be supported in the future."
506
+ )
507
+
508
+ if args.seed is not None:
509
+ set_seed(args.seed)
510
+
511
+ if args.concepts_list is None:
512
+ args.concepts_list = [
513
+ {
514
+ "instance_prompt": args.instance_prompt,
515
+ "class_prompt": args.class_prompt,
516
+ "instance_data_dir": args.instance_data_dir,
517
+ "class_data_dir": args.class_data_dir
518
+ }
519
+ ]
520
+ else:
521
+ with open(args.concepts_list, "r") as f:
522
+ args.concepts_list = json.load(f)
523
+
524
+ if args.with_prior_preservation:
525
+ pipeline = None
526
+ for concept in args.concepts_list:
527
+ class_images_dir = Path(concept["class_data_dir"])
528
+ class_images_dir.mkdir(parents=True, exist_ok=True)
529
+ cur_class_images = len(list(class_images_dir.iterdir()))
530
+
531
+ if cur_class_images < args.num_class_images:
532
+ torch_dtype = torch.float16 if accelerator.device.type == "cuda" else torch.float32
533
+ if pipeline is None:
534
+ pipeline = StableDiffusionInpaintPipeline.from_pretrained(
535
+ args.pretrained_model_name_or_path,
536
+ vae=AutoencoderKL.from_pretrained(
537
+ args.pretrained_vae_name_or_path or args.pretrained_model_name_or_path,
538
+ revision=None if args.pretrained_vae_name_or_path else args.revision,
539
+ torch_dtype=torch_dtype
540
+ ),
541
+ torch_dtype=torch_dtype,
542
+ safety_checker=None,
543
+ revision=args.revision
544
+ )
545
+ pipeline.set_progress_bar_config(disable=True)
546
+ pipeline.to(accelerator.device)
547
+
548
+ num_new_images = args.num_class_images - cur_class_images
549
+ logger.info(f"Number of class images to sample: {num_new_images}.")
550
+
551
+ sample_dataset = PromptDataset(concept["class_prompt"], num_new_images)
552
+ sample_dataloader = torch.utils.data.DataLoader(sample_dataset, batch_size=args.sample_batch_size)
553
+
554
+ sample_dataloader = accelerator.prepare(sample_dataloader)
555
+
556
+ inp_img = Image.new("RGB", (512, 512), color=(0, 0, 0))
557
+ inp_mask = Image.new("L", (512, 512), color=255)
558
+
559
+ with torch.autocast("cuda"),torch.inference_mode():
560
+ for example in tqdm(
561
+ sample_dataloader, desc="Generating class images", disable=not accelerator.is_local_main_process
562
+ ):
563
+ images = pipeline(
564
+ prompt=example["prompt"],
565
+ image=inp_img,
566
+ mask_image=inp_mask,
567
+ num_inference_steps=args.save_infer_steps
568
+ ).images
569
+
570
+ for i, image in enumerate(images):
571
+ hash_image = hashlib.sha1(image.tobytes()).hexdigest()
572
+ image_filename = class_images_dir / f"{example['index'][i] + cur_class_images}-{hash_image}.jpg"
573
+ image.save(image_filename)
574
+
575
+ del pipeline
576
+ if torch.cuda.is_available():
577
+ torch.cuda.empty_cache()
578
+
579
+ # Load the tokenizer
580
+ if args.tokenizer_name:
581
+ tokenizer = CLIPTokenizer.from_pretrained(
582
+ args.tokenizer_name,
583
+ revision=args.revision,
584
+ )
585
+ elif args.pretrained_model_name_or_path:
586
+ tokenizer = CLIPTokenizer.from_pretrained(
587
+ args.pretrained_model_name_or_path,
588
+ subfolder="tokenizer",
589
+ revision=args.revision,
590
+ )
591
+
592
+ # Load models and create wrapper for stable diffusion
593
+ text_encoder = CLIPTextModel.from_pretrained(
594
+ args.pretrained_model_name_or_path,
595
+ subfolder="text_encoder",
596
+ revision=args.revision,
597
+ )
598
+ vae = AutoencoderKL.from_pretrained(
599
+ args.pretrained_model_name_or_path,
600
+ subfolder="vae",
601
+ revision=args.revision,
602
+ )
603
+ unet = UNet2DConditionModel.from_pretrained(
604
+ args.pretrained_model_name_or_path,
605
+ subfolder="unet",
606
+ revision=args.revision,
607
+ torch_dtype=torch.float32
608
+ )
609
+
610
+ vae.requires_grad_(False)
611
+ if not args.train_text_encoder:
612
+ text_encoder.requires_grad_(False)
613
+
614
+ if args.gradient_checkpointing:
615
+ unet.enable_gradient_checkpointing()
616
+ if args.train_text_encoder:
617
+ text_encoder.gradient_checkpointing_enable()
618
+
619
+ if args.scale_lr:
620
+ args.learning_rate = (
621
+ args.learning_rate * args.gradient_accumulation_steps * args.train_batch_size * accelerator.num_processes
622
+ )
623
+
624
+ # Use 8-bit Adam for lower memory usage or to fine-tune the model in 16GB GPUs
625
+ if args.use_8bit_adam:
626
+ try:
627
+ import bitsandbytes as bnb
628
+ except ImportError:
629
+ raise ImportError(
630
+ "To use 8-bit Adam, please install the bitsandbytes library: `pip install bitsandbytes`."
631
+ )
632
+
633
+ optimizer_class = bnb.optim.AdamW8bit
634
+ else:
635
+ optimizer_class = torch.optim.AdamW
636
+
637
+ params_to_optimize = (
638
+ itertools.chain(unet.parameters(), text_encoder.parameters()) if args.train_text_encoder else unet.parameters()
639
+ )
640
+ optimizer = optimizer_class(
641
+ params_to_optimize,
642
+ lr=args.learning_rate,
643
+ betas=(args.adam_beta1, args.adam_beta2),
644
+ weight_decay=args.adam_weight_decay,
645
+ eps=args.adam_epsilon,
646
+ )
647
+
648
+ noise_scheduler = DDPMScheduler.from_config(args.pretrained_model_name_or_path, subfolder="scheduler")
649
+
650
+ train_dataset = DreamBoothDataset(
651
+ concepts_list=args.concepts_list,
652
+ tokenizer=tokenizer,
653
+ with_prior_preservation=args.with_prior_preservation,
654
+ size=args.resolution,
655
+ center_crop=args.center_crop,
656
+ num_class_images=args.num_class_images,
657
+ pad_tokens=args.pad_tokens,
658
+ hflip=args.hflip
659
+ )
660
+
661
+ def collate_fn(examples):
662
+ input_ids = [example["instance_prompt_ids"] for example in examples]
663
+ pixel_values = [example["instance_images"] for example in examples]
664
+ mask_values = [example["instance_masks"] for example in examples]
665
+ masked_image_values = [example["instance_masked_images"] for example in examples]
666
+
667
+ # Concat class and instance examples for prior preservation.
668
+ # We do this to avoid doing two forward passes.
669
+ if args.with_prior_preservation:
670
+ input_ids += [example["class_prompt_ids"] for example in examples]
671
+ pixel_values += [example["class_images"] for example in examples]
672
+ mask_values += [example["class_masks"] for example in examples]
673
+ masked_image_values += [example["class_masked_images"] for example in examples]
674
+
675
+ pixel_values = torch.stack(pixel_values).to(memory_format=torch.contiguous_format).float()
676
+ mask_values = torch.stack(mask_values).to(memory_format=torch.contiguous_format).float()
677
+ masked_image_values = torch.stack(masked_image_values).to(memory_format=torch.contiguous_format).float()
678
+
679
+ input_ids = tokenizer.pad(
680
+ {"input_ids": input_ids},
681
+ padding=True,
682
+ return_tensors="pt",
683
+ ).input_ids
684
+
685
+ batch = {
686
+ "input_ids": input_ids,
687
+ "pixel_values": pixel_values,
688
+ "mask_values": mask_values,
689
+ "masked_image_values": masked_image_values
690
+ }
691
+ return batch
692
+
693
+ train_dataloader = torch.utils.data.DataLoader(
694
+ train_dataset, batch_size=args.train_batch_size, shuffle=True, collate_fn=collate_fn, pin_memory=True, num_workers=8
695
+ )
696
+
697
+ weight_dtype = torch.float32
698
+ if args.mixed_precision == "fp16":
699
+ weight_dtype = torch.float16
700
+ elif args.mixed_precision == "bf16":
701
+ weight_dtype = torch.bfloat16
702
+
703
+ # Move text_encode and vae to gpu.
704
+ # For mixed precision training we cast the text_encoder and vae weights to half-precision
705
+ # as these models are only used for inference, keeping weights in full precision is not required.
706
+ vae.to(accelerator.device, dtype=weight_dtype)
707
+ if not args.train_text_encoder:
708
+ text_encoder.to(accelerator.device, dtype=weight_dtype)
709
+
710
+ if not args.not_cache_latents:
711
+ latents_cache = []
712
+ text_encoder_cache = []
713
+ for batch in tqdm(train_dataloader, desc="Caching latents"):
714
+ with torch.no_grad():
715
+ batch["pixel_values"] = batch["pixel_values"].to(accelerator.device, non_blocking=True, dtype=weight_dtype)
716
+ batch["input_ids"] = batch["input_ids"].to(accelerator.device, non_blocking=True)
717
+ latents_cache.append(vae.encode(batch["pixel_values"]).latent_dist)
718
+ if args.train_text_encoder:
719
+ text_encoder_cache.append(batch["input_ids"])
720
+ else:
721
+ text_encoder_cache.append(text_encoder(batch["input_ids"])[0])
722
+ train_dataset = LatentsDataset(latents_cache, text_encoder_cache)
723
+ train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=1, collate_fn=lambda x: x, shuffle=True)
724
+
725
+ del vae
726
+ if not args.train_text_encoder:
727
+ del text_encoder
728
+ if torch.cuda.is_available():
729
+ torch.cuda.empty_cache()
730
+
731
+ # Scheduler and math around the number of training steps.
732
+ overrode_max_train_steps = False
733
+ num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps)
734
+ if args.max_train_steps is None:
735
+ args.max_train_steps = args.num_train_epochs * num_update_steps_per_epoch
736
+ overrode_max_train_steps = True
737
+
738
+ lr_scheduler = get_scheduler(
739
+ args.lr_scheduler,
740
+ optimizer=optimizer,
741
+ num_warmup_steps=args.lr_warmup_steps * args.gradient_accumulation_steps,
742
+ num_training_steps=args.max_train_steps * args.gradient_accumulation_steps,
743
+ )
744
+
745
+ if args.train_text_encoder:
746
+ unet, text_encoder, optimizer, train_dataloader, lr_scheduler = accelerator.prepare(
747
+ unet, text_encoder, optimizer, train_dataloader, lr_scheduler
748
+ )
749
+ else:
750
+ unet, optimizer, train_dataloader, lr_scheduler = accelerator.prepare(
751
+ unet, optimizer, train_dataloader, lr_scheduler
752
+ )
753
+
754
+ # We need to recalculate our total training steps as the size of the training dataloader may have changed.
755
+ num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps)
756
+ if overrode_max_train_steps:
757
+ args.max_train_steps = args.num_train_epochs * num_update_steps_per_epoch
758
+ # Afterwards we recalculate our number of training epochs
759
+ args.num_train_epochs = math.ceil(args.max_train_steps / num_update_steps_per_epoch)
760
+
761
+ # We need to initialize the trackers we use, and also store our configuration.
762
+ # The trackers initializes automatically on the main process.
763
+ if accelerator.is_main_process:
764
+ accelerator.init_trackers("dreambooth")
765
+
766
+ # Train!
767
+ total_batch_size = args.train_batch_size * accelerator.num_processes * args.gradient_accumulation_steps
768
+
769
+ logger.info("***** Running training *****")
770
+ logger.info(f" Num examples = {len(train_dataset)}")
771
+ logger.info(f" Num batches each epoch = {len(train_dataloader)}")
772
+ logger.info(f" Num Epochs = {args.num_train_epochs}")
773
+ logger.info(f" Instantaneous batch size per device = {args.train_batch_size}")
774
+ logger.info(f" Total train batch size (w. parallel, distributed & accumulation) = {total_batch_size}")
775
+ logger.info(f" Gradient Accumulation steps = {args.gradient_accumulation_steps}")
776
+ logger.info(f" Total optimization steps = {args.max_train_steps}")
777
+
778
+ def save_weights(step):
779
+ # Create the pipeline using using the trained modules and save it.
780
+ if accelerator.is_main_process:
781
+ if args.train_text_encoder:
782
+ text_enc_model = accelerator.unwrap_model(text_encoder, keep_fp32_wrapper=True)
783
+ else:
784
+ text_enc_model = CLIPTextModel.from_pretrained(args.pretrained_model_name_or_path, subfolder="text_encoder", revision=args.revision)
785
+ scheduler = DDIMScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", clip_sample=False, set_alpha_to_one=False, steps_offset=1)
786
+ pipeline = StableDiffusionInpaintPipeline.from_pretrained(
787
+ args.pretrained_model_name_or_path,
788
+ unet=accelerator.unwrap_model(unet, keep_fp32_wrapper=True).to(torch.float16),
789
+ text_encoder=text_enc_model.to(torch.float16),
790
+ vae=AutoencoderKL.from_pretrained(
791
+ args.pretrained_vae_name_or_path or args.pretrained_model_name_or_path,
792
+ subfolder=None if args.pretrained_vae_name_or_path else "vae",
793
+ revision=None if args.pretrained_vae_name_or_path else args.revision,
794
+ # torch_dtype=torch.float16
795
+ ).half(),
796
+ safety_checker=None,
797
+ scheduler=scheduler,
798
+ torch_dtype=torch.float16,
799
+ revision=args.revision,
800
+ )
801
+ save_dir = os.path.join(args.output_dir, f"{step}")
802
+ pipeline.save_pretrained(save_dir)
803
+ with open(os.path.join(save_dir, "args.json"), "w") as f:
804
+ json.dump(args.__dict__, f, indent=2)
805
+
806
+ shutil.copy("train_inpainting_dreambooth.py", save_dir)
807
+
808
+ pipeline = pipeline.to(accelerator.device)
809
+ pipeline.set_progress_bar_config(disable=True)
810
+ for idx, concept in enumerate(args.concepts_list):
811
+ g_cuda = torch.Generator(device=accelerator.device).manual_seed(args.seed)
812
+ sample_dir = os.path.join(save_dir, "samples", str(idx))
813
+ os.makedirs(sample_dir, exist_ok=True)
814
+ # inp_img = Image.new("RGB", (512, 512), color=(0, 0, 0))
815
+ inp_img = Image.open("/home/neil/Documents/diffusers/examples/dreambooth/512/a olive leather couch sofa Inside a Bedouin-inspired setting, soft sandy tones, hanging lanterns, and an endless view of sand dunes. .png")
816
+ inp_mask = ImageOps.invert(inp_img.split()[-1])
817
+ # inp_mask = Image.new("L", (512, 512), color=255)
818
+ with torch.inference_mode():
819
+ for i in tqdm(range(args.n_save_sample), desc="Generating samples"):
820
+ if i>1:
821
+ images = pipeline(
822
+ # prompt=concept["instance_prompt"],
823
+ prompt="a olive leather couch sofa in a sleek and sophisticated mid century home interior, emphasizing clean lines and subtle design details.",
824
+ image=inp_img.convert('RGB'),
825
+ mask_image=inp_mask,
826
+ negative_prompt=args.save_sample_negative_prompt,#"minimalist, sad, bad teeth, reflection, lens, lens flare, drawn, airbrush, blur, makeup, out of focus, hands, arms, veil, bad anatomy, mutation, deformed, cropped, signed, Mediocre, Screenshot, UI, watermark, cartoon",
827
+ guidance_scale=args.save_guidance_scale,
828
+ num_inference_steps=args.save_infer_steps,
829
+ generator=g_cuda
830
+ ).images
831
+ else:
832
+ images = pipeline(
833
+ # prompt=concept["instance_prompt"],
834
+ prompt="a olive leather couch sofa Inside a Bedouin-inspired setting, soft sandy tones, hanging lanterns, and an endless view of sand dunes. ",
835
+ image=inp_img.convert('RGB'),
836
+ mask_image=inp_mask,
837
+ negative_prompt=args.save_sample_negative_prompt,
838
+ guidance_scale=args.save_guidance_scale,
839
+ num_inference_steps=args.save_infer_steps,
840
+ generator=g_cuda
841
+ ).images
842
+ images[0].save(os.path.join(sample_dir, f"{i}.png"))
843
+ del pipeline
844
+ if torch.cuda.is_available():
845
+ torch.cuda.empty_cache()
846
+ print(f"[*] Weights saved at {save_dir}")
847
+ unet.to(torch.float32)
848
+ text_enc_model.to(torch.float32)
849
+
850
+ # Only show the progress bar once on each machine.
851
+ progress_bar = tqdm(range(args.max_train_steps), disable=not accelerator.is_local_main_process)
852
+ progress_bar.set_description("Steps")
853
+ global_step = 0
854
+ loss_avg = AverageMeter()
855
+ text_enc_context = nullcontext() if args.train_text_encoder else torch.no_grad()
856
+ for epoch in range(args.num_train_epochs):
857
+ unet.train()
858
+ if args.train_text_encoder:
859
+ text_encoder.train()
860
+ random.shuffle(train_dataset.class_images_path)
861
+ for step, batch in enumerate(train_dataloader):
862
+ with accelerator.accumulate(unet):
863
+ # Convert images to latent space
864
+ with torch.no_grad():
865
+ if not args.not_cache_latents:
866
+ latent_dist = batch[0][0]
867
+ else:
868
+ latent_dist = vae.encode(batch["pixel_values"].to(dtype=weight_dtype)).latent_dist
869
+ masked_latent_dist = vae.encode(batch["masked_image_values"].to(dtype=weight_dtype)).latent_dist
870
+ # torchvision.transforms.functional.to_pil_image(transforms.Normalize(mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],std=[1/0.229, 1/0.224, 1/0.255])(batch["pixel_values"][0])).save('batchim.png')
871
+ # breakpoint()
872
+ latents = latent_dist.sample() * 0.18215
873
+ masked_image_latents = masked_latent_dist.sample() * 0.18215
874
+ mask = F.interpolate(batch["mask_values"], scale_factor=1 / 8)
875
+
876
+ # Sample noise that we'll add to the latents
877
+ noise = torch.randn_like(latents)
878
+ bsz = latents.shape[0]
879
+ # Sample a random timestep for each image
880
+ timesteps = torch.randint(0, noise_scheduler.config.num_train_timesteps, (bsz,), device=latents.device)
881
+ timesteps = timesteps.long()
882
+
883
+ latents_copy = torch.clone(latents)
884
+ # Add noise to the latents according to the noise magnitude at each timestep
885
+ # (this is the forward diffusion process)
886
+ noisy_latents = noise_scheduler.add_noise(latents, noise, timesteps)
887
+
888
+ # Get the text embedding for conditioning
889
+ with text_enc_context:
890
+ if not args.not_cache_latents:
891
+ if args.train_text_encoder:
892
+ encoder_hidden_states = text_encoder(batch[0][1])[0]
893
+ else:
894
+ encoder_hidden_states = batch[0][1]
895
+ else:
896
+ encoder_hidden_states = text_encoder(batch["input_ids"])[0]
897
+
898
+ latent_model_input = torch.cat([noisy_latents, mask, masked_image_latents], dim=1)
899
+ # Predict the noise residual
900
+ noise_pred = unet(latent_model_input, timesteps, encoder_hidden_states).sample
901
+
902
+ def latents_to_pil(latents):
903
+ # bath of latents -> list of images
904
+ latents = (1 / 0.18215) * latents
905
+ with torch.no_grad():
906
+ image = vae.decode(latents).sample
907
+ image = (image / 2 + 0.5).clamp(0, 1)
908
+ image = image.detach().cpu().permute(0, 2, 3, 1).numpy()
909
+ images = (image * 255).round().astype("uint8")
910
+ pil_images = [Image.fromarray(image) for image in images]
911
+ return pil_images
912
+
913
+ def pil_to_latent(input_im):
914
+ # Single image -> single latent in a batch (so size 1, 4, 64, 64)
915
+ with torch.no_grad():
916
+ latent = vae.encode(tfms.ToTensor()(input_im).unsqueeze(0).to(torch_device)*2-1) # Note scaling
917
+ return 0.18215 * latent.latent_dist.sample()
918
+
919
+ if args.with_prior_preservation:
920
+ # Chunk the noise and noise_pred into two parts and compute the loss on each part separately.
921
+ noise_pred, noise_pred_prior = torch.chunk(noise_pred, 2, dim=0)
922
+ noise, noise_prior = torch.chunk(noise, 2, dim=0)
923
+
924
+ # Compute instance loss
925
+ loss = F.mse_loss(noise_pred.float(), noise.float(), reduction="none").mean([1, 2, 3]).mean()
926
+
927
+ # Compute prior loss
928
+ prior_loss = F.mse_loss(noise_pred_prior.float(), noise_prior.float(), reduction="mean")
929
+
930
+ # Add the prior loss to the instance loss.
931
+ loss = loss + args.prior_loss_weight * prior_loss
932
+ else:
933
+ loss = F.mse_loss(noise_pred.float(), noise.float(), reduction="mean")
934
+
935
+ # im_pred = torch.cat([noise_scheduler.step(noise_pred[:1], timesteps[0], noisy_latents[:1]).prev_sample,
936
+ # noise_scheduler.step(noise_pred[1:2], timesteps[1], noisy_latents[1:2]).prev_sample,
937
+ # noise_scheduler.step(noise_pred[2:3], timesteps[2], noisy_latents[2:3]).prev_sample,
938
+ # noise_scheduler.step(noise_pred[3:4], timesteps[3], noisy_latents[3:4]).prev_sample])
939
+
940
+ # im_real = torch.cat([noise_scheduler.step(noise[:1], timesteps[0], noisy_latents[:1]).prev_sample,
941
+ # noise_scheduler.step(noise[1:2], timesteps[1], noisy_latents[1:2]).prev_sample,
942
+ # noise_scheduler.step(noise[2:3], timesteps[2], noisy_latents[2:3]).prev_sample,
943
+ # noise_scheduler.step(noise[3:4], timesteps[3], noisy_latents[3:4]).prev_sample])
944
+
945
+ # import numpy as np
946
+ # import cv2
947
+
948
+ # # def tensor_to_canny(tensor):
949
+ # # canny_image = np.asarray(tensor.to('cpu'))
950
+ # # canny_image = cv2.Canny(np.uint8(canny_image), 100, 200)
951
+ # # # return Image.fromarray(canny_image)
952
+ # # return canny_image
953
+ # # canny = batch["mask_values"][0][0]
954
+ # # canny = tensor_to_canny(canny)
955
+ # # Image.fromarray(canny).save('pcanny.png')
956
+ # # canny = cv2.dilate(canny, np.ones((5,5),np.uint8), iterations=5)
957
+ # # Image.fromarray(canny).save('pdilatecanny.png')
958
+ # # breakpoint()
959
+ # def get_band(tensor):
960
+ # canny_image = np.uint8(np.asarray(tensor.to('cpu')))
961
+ # dilated = cv2.dilate(canny_image, np.ones((5,5),np.uint8), iterations=10)
962
+ # # return torchvision.transforms.ToTensor()(dilated) * (tensor < 0.5)
963
+ # return dilated, canny_image
964
+ # dilated, canny_image = get_band(batch["mask_values"][0][0])
965
+ # # Image.fromarray(dilated).save('pdilated.png')
966
+ # # Image.fromarray(canny_image).save('pcanny.png')
967
+ # # Image.fromarray(dilated-canny_image).save('pxor.png')
968
+ # band = dilated-canny_image
969
+ # band = torch.from_numpy(band*0.3 + 1)
970
+ # breakpoint()
971
+ # im_pred = im_pred*band
972
+ # im_real = im_real*band
973
+ # breakpoint()
974
+ # loss = F.mse_loss(im_real.float(), im_pred.float(), reduction="mean")
975
+
976
+ # # latents_to_pil(latents_copy[:1])[0].save('ppp1.png')
977
+ # # noise_scheduler.step(noise_pred, timesteps, latents, return_dict=False)[0]
978
+ # # loss = F.mse_loss(vae.decode(noise_pred.float()).sample, vae.decode(noise.float()).sample, reduction="mean")
979
+
980
+ # def generate_random_mask(image):
981
+ # # mask = torch.zeros_like(image[:1])
982
+ # # print('foobar', mask.shape)
983
+ # mask = image[-1].unsqueeze(0)
984
+ # # torchvision.transforms.functional.to_pil_image(mask).save('foomask2.png')
985
+
986
+ # # if random.uniform(0, 1) < 0.25:
987
+ # # mask = torch.zeros_like(image[:1])
988
+ # # mask.fill_(1.)
989
+ # # print('foobar',image.shape)
990
+ # # torchvision.transforms.functional.to_pil_image(image[:4]).save('fooimageinside2.png')
991
+ # # print('foobar',image[:3].shape)
992
+ # masked_image = image[:-1] * (mask < 0.5)
993
+ # # torchvision.transforms.functional.to_pil_image(masked_image).save('foomaskedimage2.png')
994
+ # return mask, masked_image
995
+
996
+ accelerator.backward(loss)
997
+ # if accelerator.sync_gradients:
998
+ # params_to_clip = (
999
+ # itertools.chain(unet.parameters(), text_encoder.parameters())
1000
+ # if args.train_text_encoder
1001
+ # else unet.parameters()
1002
+ # )
1003
+ # accelerator.clip_grad_norm_(params_to_clip, args.max_grad_norm)
1004
+ optimizer.step()
1005
+ lr_scheduler.step()
1006
+ optimizer.zero_grad(set_to_none=True)
1007
+ loss_avg.update(loss.detach_(), bsz)
1008
+
1009
+ if not global_step % args.log_interval:
1010
+ logs = {"loss": loss_avg.avg.item(), "lr": lr_scheduler.get_last_lr()[0]}
1011
+ progress_bar.set_postfix(**logs)
1012
+ accelerator.log(logs, step=global_step)
1013
+
1014
+ if global_step > 0 and not global_step % args.save_interval and global_step >= args.save_min_steps:
1015
+ save_weights(global_step)
1016
+
1017
+ progress_bar.update(1)
1018
+ global_step += 1
1019
+
1020
+ if global_step >= args.max_train_steps:
1021
+ break
1022
+
1023
+ accelerator.wait_for_everyone()
1024
+
1025
+ save_weights(global_step)
1026
+
1027
+ accelerator.end_training()
1028
+
1029
+
1030
+ if __name__ == "__main__":
1031
+ args = parse_args()
1032
+ main(args)
unet/config.json ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "UNet2DConditionModel",
3
+ "_diffusers_version": "0.21.0.dev0",
4
+ "_name_or_path": "booth-ai/realisticVisionV20_v20_inpainting",
5
+ "act_fn": "silu",
6
+ "addition_embed_type": null,
7
+ "addition_embed_type_num_heads": 64,
8
+ "addition_time_embed_dim": null,
9
+ "attention_head_dim": 8,
10
+ "attention_type": "default",
11
+ "block_out_channels": [
12
+ 320,
13
+ 640,
14
+ 1280,
15
+ 1280
16
+ ],
17
+ "center_input_sample": false,
18
+ "class_embed_type": null,
19
+ "class_embeddings_concat": false,
20
+ "conv_in_kernel": 3,
21
+ "conv_out_kernel": 3,
22
+ "cross_attention_dim": 768,
23
+ "cross_attention_norm": null,
24
+ "down_block_types": [
25
+ "CrossAttnDownBlock2D",
26
+ "CrossAttnDownBlock2D",
27
+ "CrossAttnDownBlock2D",
28
+ "DownBlock2D"
29
+ ],
30
+ "downsample_padding": 1,
31
+ "dual_cross_attention": false,
32
+ "encoder_hid_dim": null,
33
+ "encoder_hid_dim_type": null,
34
+ "flip_sin_to_cos": true,
35
+ "freq_shift": 0,
36
+ "in_channels": 9,
37
+ "layers_per_block": 2,
38
+ "mid_block_only_cross_attention": null,
39
+ "mid_block_scale_factor": 1,
40
+ "mid_block_type": "UNetMidBlock2DCrossAttn",
41
+ "norm_eps": 1e-05,
42
+ "norm_num_groups": 32,
43
+ "num_attention_heads": null,
44
+ "num_class_embeds": null,
45
+ "only_cross_attention": false,
46
+ "out_channels": 4,
47
+ "projection_class_embeddings_input_dim": null,
48
+ "resnet_out_scale_factor": 1.0,
49
+ "resnet_skip_time_act": false,
50
+ "resnet_time_scale_shift": "default",
51
+ "sample_size": 64,
52
+ "time_cond_proj_dim": null,
53
+ "time_embedding_act_fn": null,
54
+ "time_embedding_dim": null,
55
+ "time_embedding_type": "positional",
56
+ "timestep_post_act": null,
57
+ "transformer_layers_per_block": 1,
58
+ "up_block_types": [
59
+ "UpBlock2D",
60
+ "CrossAttnUpBlock2D",
61
+ "CrossAttnUpBlock2D",
62
+ "CrossAttnUpBlock2D"
63
+ ],
64
+ "upcast_attention": false,
65
+ "use_linear_projection": false
66
+ }
unet/diffusion_pytorch_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:057028cbeb1ca5aacd36fc81ed7f2c5ae063330d4bfd37c1a42b63cc77d0e50d
3
+ size 1719154104
vae/config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "AutoencoderKL",
3
+ "_diffusers_version": "0.21.0.dev0",
4
+ "_name_or_path": "stabilityai/sd-vae-ft-mse",
5
+ "act_fn": "silu",
6
+ "block_out_channels": [
7
+ 128,
8
+ 256,
9
+ 512,
10
+ 512
11
+ ],
12
+ "down_block_types": [
13
+ "DownEncoderBlock2D",
14
+ "DownEncoderBlock2D",
15
+ "DownEncoderBlock2D",
16
+ "DownEncoderBlock2D"
17
+ ],
18
+ "force_upcast": true,
19
+ "in_channels": 3,
20
+ "latent_channels": 4,
21
+ "layers_per_block": 2,
22
+ "norm_num_groups": 32,
23
+ "out_channels": 3,
24
+ "sample_size": 256,
25
+ "scaling_factor": 0.18215,
26
+ "up_block_types": [
27
+ "UpDecoderBlock2D",
28
+ "UpDecoderBlock2D",
29
+ "UpDecoderBlock2D",
30
+ "UpDecoderBlock2D"
31
+ ]
32
+ }
vae/diffusion_pytorch_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3e4c08995484ee61270175e9e7a072b66a6e4eeb5f0c266667fe1f45b90daf9a
3
+ size 167335342