diff --git a/cli/modules/interrogate.py b/cli/modules/interrogate.py index 96fabb66e..a96c8cf42 100755 --- a/cli/modules/interrogate.py +++ b/cli/modules/interrogate.py @@ -71,7 +71,7 @@ async def interrogate(f): keywords = {} if 'caption' in res: for term in res.caption.split(', '): - term = term.replace('(', '').replace(')', '').split(':') + term = term.replace('(', '').replace(')', '').replace('\\', '').split(':') if len(term) < 2: continue keywords[term[0]] = term[1] diff --git a/cli/modules/process.py b/cli/modules/process.py index 85709bc83..b6dfe948b 100755 --- a/cli/modules/process.py +++ b/cli/modules/process.py @@ -342,7 +342,7 @@ def interrogate(img, fn, intag = None): if model == 'deepdanbooru': tag = res.caption if 'caption' in res else '' tags = tag.split(',') - tags = [t.replace('(', '').replace(')', '').split(':')[0].strip() for t in tags] + tags = [t.replace('(', '').replace(')', '').replace('\\', '').split(':')[0].strip() for t in tags] if intag is not None: for t in intag.split(',')[::-1]: tags.insert(0, t.strip()) @@ -385,22 +385,16 @@ def process_file(f: str, dst: str = None, preview: bool = False, offline: bool = return fn # overrides - if 'original' in opts: - params.keep_original = True - if 'face' in opts: - params.extract_face = True - if 'body' in opts: - params.extract_body = True - if 'blur' in opts: - params.face_blur = True - params.body_blur = True - if 'range' in opts: - params.face_range = True - params.body_range = True - if 'upscale' in opts: - params.face_upscale = True - if 'restore' in opts: - params.face_restore = True + if len(opts) > 0: + params.keep_original = True if 'original' in opts else False + params.extract_face = True if 'face' in opts else False + params.extract_body = True if 'body' in opts else False + params.face_blur = True if 'blur' in opts else False + params.body_blur = True if 'blur' in opts else False + params.face_range = True if 'range' in opts else False + params.body_range = True if 'range' in opts else False + params.face_upscale = True if 'upscale' in opts else False + params.face_restore = True if 'upscale' in opts else False log.info({ 'processing': f }) try: diff --git a/cli/train-lora.py b/cli/train-lora.py index ed2be10f3..daa42ec67 100755 --- a/cli/train-lora.py +++ b/cli/train-lora.py @@ -19,6 +19,7 @@ import gc import sys import json import time +import shutil import argparse import tempfile import torch @@ -39,78 +40,78 @@ sys.path.append(locon_path) from train_network import train options = Map({ - "v2": False, - "v_parameterization": False, - "pretrained_model_name_or_path": "", - "train_data_dir": "", - "shuffle_caption": False, + "bucket_no_upscale": False, + "bucket_reso_steps": 64, + "cache_latents": True, + "caption_dropout_every_n_epochs": None, + "caption_dropout_rate": 0.0, "caption_extension": ".txt", "caption_extention": ".txt", - "keep_tokens": None, - "color_aug": False, - "flip_aug": False, - "face_crop_aug_range": None, - "random_crop": False, - "debug_dataset": False, - "resolution": "512,512", - "cache_latents": True, - "enable_bucket": False, - "min_bucket_reso": 256, - "max_bucket_reso": 1024, - "bucket_reso_steps": 64, - "bucket_no_upscale": False, - "reg_data_dir": None, - "in_json": "", - "dataset_repeats": 1, - "output_dir": "", - "output_name": "", - "save_precision": "fp16", - "save_every_n_epochs": None, - "save_n_epoch_ratio": None, - "save_last_n_epochs": None, - "save_last_n_epochs_state": None, - "save_state": False, - "resume": None, - "max_grad_norm": 0.0, - "train_batch_size": 1, - "max_token_length": None, - "use_8bit_adam": False, - "mem_eff_attn": False, - "xformers": False, - "vae": None, - "learning_rate": 1e-04, - "max_train_steps": 8000, - "max_train_epochs": None, - "max_data_loader_n_workers": 8, - "persistent_data_loader_workers": False, - "seed": 42, - "gradient_checkpointing": False, - "gradient_accumulation_steps": 1, - "mixed_precision": "fp16", - "full_fp16": False, + "caption_tag_dropout_rate": 0.0, "clip_skip": None, - "logging_dir": None, + "color_aug": False, + "dataset_repeats": 1, + "debug_dataset": False, + "enable_bucket": False, + "face_crop_aug_range": None, + "flip_aug": False, + "full_fp16": False, + "gradient_accumulation_steps": 1, + "gradient_checkpointing": False, + "in_json": "", + "keep_tokens": None, + "learning_rate": 5e-05, "log_prefix": None, - "lr_scheduler": "cosine", - "lr_warmup_steps": 0, - "prior_loss_weight": 1.0, - "no_metadata": False, - "save_model_as": "ckpt", - "unet_lr": 0.001, - "text_encoder_lr": 5e-05, + "logging_dir": None, "lr_scheduler_num_cycles": 1, "lr_scheduler_power": 1, - "network_weights": None, - "network_module": "networks.lora", - "network_dim": 16, + "lr_scheduler": "cosine", + "lr_warmup_steps": 0, + "max_bucket_reso": 1024, + "max_data_loader_n_workers": 8, + "max_grad_norm": 0.0, + "max_token_length": None, + "max_train_epochs": None, + "max_train_steps": 5000, + "mem_eff_attn": False, + "min_bucket_reso": 256, + "mixed_precision": "fp16", "network_alpha": 1.0, "network_args": None, - "network_train_unet_only": False, + "network_dim": 16, + "network_module": "networks.lora", "network_train_text_encoder_only": False, + "network_train_unet_only": False, + "network_weights": None, + "no_metadata": False, + "output_dir": "", + "output_name": "", + "persistent_data_loader_workers": False, + "pretrained_model_name_or_path": "", + "prior_loss_weight": 1.0, + "random_crop": False, + "reg_data_dir": None, + "resolution": "512,512", + "resume": None, + "save_every_n_epochs": None, + "save_last_n_epochs_state": None, + "save_last_n_epochs": None, + "save_model_as": "ckpt", + "save_n_epoch_ratio": None, + "save_precision": "fp16", + "save_state": False, + "seed": 42, + "shuffle_caption": False, + "text_encoder_lr": 5e-05, + "train_batch_size": 1, + "train_data_dir": "", "training_comment": "mood-magic", - "caption_dropout_rate": 0.0, - "caption_dropout_every_n_epochs": None, - "caption_tag_dropout_rate": 0.0, + "unet_lr": 0.001, + "use_8bit_adam": False, + "v_parameterization": False, + "v2": False, + "vae": None, + "xformers": False, }) @@ -134,7 +135,7 @@ if __name__ == '__main__': parser.add_argument('--tag', type=str, default=None, required=False, help='primary tag') parser.add_argument('--dir', type=str, default=None, required=False, help='folder containing lora checkpoints') parser.add_argument('--interim', type=int, default=0, help = 'save interim checkpoints after n epoch') - parser.add_argument('--process', type=str, default='original', required=True, help='list of processing steps: original,face,body,blur,range,upscale,restore') + parser.add_argument('--process', type=str, default='original', required=False, help='list of processing steps: original,face,body,blur,range,upscale,restore') parser.add_argument('--noprocess', default = False, action='store_true', help = 'skip processing and use existing input data') parser.add_argument('--notrain', default = False, action='store_true', help = 'just run processing and skip training') parser.add_argument('--nocaptions', default = False, action='store_true', help = 'skip creating captions and tags') @@ -145,7 +146,7 @@ if __name__ == '__main__': parser.add_argument('--steps', type=int, default=4000, required=False, help='training steps, default: %(default)s') parser.add_argument('--dim', type=int, default=40, required=False, help='network dimension, default: %(default)s') parser.add_argument('--repeats', type=int, default=10, required=False, help='number of repeats per image, default: %(default)s') - parser.add_argument('--alpha', type=float, default=1, required=False, help='alpha for weights scaling, default: %(default)s') + parser.add_argument('--alpha', type=float, default=0, required=False, help='alpha for weights scaling, default: half of dim') parser.add_argument('--batch', type=int, default=1, required=False, help='batch size, default: %(default)s') parser.add_argument('--lr', type=float, default=1e-04, required=False, help='model learning rate, default: %(default)s') parser.add_argument('--unetlr', type=float, default=1e-04, required=False, help='unet learning rate, default: %(default)s') @@ -182,6 +183,7 @@ if __name__ == '__main__': options.output_name = args.output options.max_train_steps = args.steps options.network_dim = args.dim + options.network_alpha = args.dim // 2 if args.alpha == 0 else args.alpha options.gradient_accumulation_steps = args.gradient options.save_every_n_epochs = args.interim if args.interim > 0 else None options.learning_rate = args.lr @@ -193,13 +195,9 @@ if __name__ == '__main__': transformers.logging.set_verbosity_error() mem_stats() - concept = 'lora' - if args.tag is not None: - concept = args.tag.split(',')[0].strip() - dir = os.path.join(tempfile.gettempdir(), args.output, str(args.repeats) + '_' + concept) - Path(dir).mkdir(parents=True, exist_ok=True) json_file = os.path.join(tempfile.gettempdir(), args.output, args.output + '.json') - options.train_data_dir = os.path.join(tempfile.gettempdir(), args.output) + base = os.path.join(tempfile.gettempdir(), args.output) + options.train_data_dir = base res = None if args.dreambooth: @@ -215,28 +213,52 @@ if __name__ == '__main__': # preprocess processing_options = args.process.split(',') processing_options = [opt.strip() for opt in re.split(',| ', args.process)] - log.info({ 'processing options': processing_options }) + log.info({ 'processing steps': processing_options }) if os.path.exists(json_file): os.remove(json_file) - for f in files: - try: - res, metadata = modules.process.process_file(f = f, dst = dir, preview = False, offline = args.offline, txt = args.dreambooth, tag = args.tag, opts = processing_options) - if not args.dreambooth: - with open(json_file, "w") as outfile: - outfile.write(json.dumps(metadata, indent=2)) - except ValueError as e: - exit(1) + + steps = [step for step in processing_options if step in ['face', 'body', 'original']] + for step in steps: + # processing_options = [step for step in processing_options if step not in ['face', 'body', 'original']].append(step) + if step == 'face': + opts = [step for step in processing_options if step not in ['body', 'original']] + if step == 'body': + opts = [step for step in processing_options if step not in ['face', 'original', 'upscale', 'restore']] + if step == 'original': + opts = [step for step in processing_options if step not in ['face', 'body', 'upscale', 'restore', 'blur', 'range']] + log.info({ 'processing step': opts }) + concept = step + if concept == 'original' and args.tag is not None: + concept = args.tag.split(',')[0].strip() + dir = os.path.join(base, str(args.repeats) + '_' + concept) + if os.path.exists(dir): + shutil.rmtree(dir, ignore_errors=True) + Path(dir).mkdir(parents=True, exist_ok=True) + + for f in files: + try: + res, metadata = modules.process.process_file(f = f, dst = dir, preview = False, offline = args.offline, txt = args.dreambooth, tag = args.tag, opts = opts) + if not args.dreambooth: + with open(json_file, "w") as outfile: + outfile.write(json.dumps(metadata, indent=2)) + except ValueError as e: + exit(1) + log.info({ 'processed step': step, 'outputs': res, 'inputs': len(files), 'metadata': json_file, 'path': dir }) + modules.process.unload_models() mem_stats() + + dirs = [os.path.join(base, dir) for dir in os.listdir(base) if os.path.isdir(os.path.join(base, dir))] + log.info({ 'input datasets': dirs, 'metadata': json_file }) + if not args.nolatents and not args.dreambooth: # create latents - latents.create_vae_latents(Map({ 'input': dir, 'json': json_file })) - latents.unload_vae() + for dir in dirs: + latents.create_vae_latents(Map({ 'input': dir, 'json': json_file })) + latents.unload_vae() mem_stats() - - log.info({ 'processed': res, 'inputs': len(files), 'metadata': json_file, 'path': dir }) else: log.info({ 'skip processing': len(files), 'metadata': json_file, 'path': dir }) diff --git a/extensions-builtin/sd-extension-system-info b/extensions-builtin/sd-extension-system-info index 6ed701667..9069918f1 160000 --- a/extensions-builtin/sd-extension-system-info +++ b/extensions-builtin/sd-extension-system-info @@ -1 +1 @@ -Subproject commit 6ed70166778165a281d4050c5449eaf8cf7c956a +Subproject commit 9069918f1ac4b52731fff3cf1746ea00685375d0 diff --git a/extensions-builtin/seed_travel b/extensions-builtin/seed_travel index 24f72e095..5a4a4b591 160000 --- a/extensions-builtin/seed_travel +++ b/extensions-builtin/seed_travel @@ -1 +1 @@ -Subproject commit 24f72e095a63bf5f6df1fbef2c7e188ed229b5c8 +Subproject commit 5a4a4b591d5d785e7a46068b0eef442b5799ffe6 diff --git a/extensions-builtin/stable-diffusion-webui-images-browser b/extensions-builtin/stable-diffusion-webui-images-browser index 0db94f5af..e508543da 160000 --- a/extensions-builtin/stable-diffusion-webui-images-browser +++ b/extensions-builtin/stable-diffusion-webui-images-browser @@ -1 +1 @@ -Subproject commit 0db94f5af9eda4ad09ec08439cfdf0908b7e140a +Subproject commit e508543da1accc323953e8e5c08083f15ba68a2b diff --git a/modules/lora b/modules/lora index 0cacefc74..7b0af4f38 160000 --- a/modules/lora +++ b/modules/lora @@ -1 +1 @@ -Subproject commit 0cacefc749abb1c8a1a30cb0192b0623668d04a2 +Subproject commit 7b0af4f3824b0ce7c9d1936bb8c58ae00fef4832 diff --git a/ui-config.json b/ui-config.json index d3c905e69..ff5d0daba 100644 --- a/ui-config.json +++ b/ui-config.json @@ -1335,5 +1335,9 @@ "customscript/seed_travel.py/img2img/SSIM CenterCrop% (0 to disable)/value": 0, "customscript/seed_travel.py/img2img/SSIM CenterCrop% (0 to disable)/minimum": 0, "customscript/seed_travel.py/img2img/SSIM CenterCrop% (0 to disable)/maximum": 100, - "customscript/seed_travel.py/img2img/SSIM CenterCrop% (0 to disable)/step": 1 + "customscript/seed_travel.py/img2img/SSIM CenterCrop% (0 to disable)/step": 1, + "customscript/seed_travel.py/txt2img/SSIM minimum substep/visible": true, + "customscript/seed_travel.py/txt2img/SSIM minimum substep/value": 0.0001, + "customscript/seed_travel.py/img2img/SSIM minimum substep/visible": true, + "customscript/seed_travel.py/img2img/SSIM minimum substep/value": 0.0001 } \ No newline at end of file