mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
update interrogate and train
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
# Merge repos
|
||||
# Publish extensions
|
||||
|
||||
- Move sd-extensions/scripts/save-steps-animation script to automatic/extensions-builtin
|
||||
- Move sd-extensions/api to automatic/cli
|
||||
- [https://github.com/vladmandic/automatic]
|
||||
- [https://github.com/vladmandic/sd-extensions]
|
||||
- [https://github.com/vladmandic/generative-art]
|
||||
- `sd-extension-aesthetic-scorer`
|
||||
- `sd-extension-steps-animation`
|
||||
- `sd-extension-system-info`
|
||||
|
||||
# Investigating
|
||||
|
||||
@@ -16,6 +14,7 @@ Need to study more to determine best out-of-the-box settings:
|
||||
- Impact of Codeformer
|
||||
- Impact of Hires fix:
|
||||
- e.g 25 steps and denoising strength 0.25-0.7
|
||||
- Impact of non-square target resolution
|
||||
|
||||
## SDAPI
|
||||
|
||||
|
||||
+1
-1
@@ -4,5 +4,5 @@ export TF_CPP_MIN_LOG_LEVEL=2
|
||||
export FORCE_CUDA="1"
|
||||
export ATTN_PRECISION=fp16
|
||||
export PYTORCH_CUDA_ALLOC_CONF=garbage_collection_threshold:0.9,max_split_size_mb:512
|
||||
exec accelerate launch --num_cpu_threads_per_process=6 launch.py --api --xformers --disable-console-progressbars
|
||||
exec accelerate launch --num_cpu_threads_per_process=6 launch.py --api --xformers --disable-console-progressbars "$@"
|
||||
# --opt-channelslast
|
||||
|
||||
@@ -16,6 +16,10 @@ from util import log, Map
|
||||
import sdapi as sdapi
|
||||
|
||||
|
||||
stats = { 'captions': {}, 'keywords': {} }
|
||||
exclude = ['a', 'in', 'on', 'out', 'at', 'the', 'and', 'with', 'next', 'to', 'it', 'for', 'of', 'into', 'that']
|
||||
|
||||
|
||||
def decode(encoding):
|
||||
if encoding.startswith("data:image/"):
|
||||
encoding = encoding.split(";")[1].split(",")[1]
|
||||
@@ -25,6 +29,8 @@ def decode(encoding):
|
||||
def encode(f):
|
||||
image = Image.open(f)
|
||||
exif = image.getexif()
|
||||
if image.mode == 'RGBA':
|
||||
image = image.convert('RGB')
|
||||
with io.BytesIO() as stream:
|
||||
image.save(stream, 'JPEG', exif = exif)
|
||||
values = stream.getvalue()
|
||||
@@ -32,6 +38,13 @@ def encode(f):
|
||||
return encoded
|
||||
|
||||
|
||||
def print_summary():
|
||||
captions = dict(sorted(stats['captions'].items(), key=lambda x:x[1], reverse=True))
|
||||
log.info({ 'caption stats': captions })
|
||||
keywords = dict(sorted(stats['keywords'].items(), key=lambda x:x[1], reverse=True))
|
||||
log.info({ 'keyword stats': keywords })
|
||||
|
||||
|
||||
async def interrogate(f):
|
||||
if not filetype.is_image(f):
|
||||
log.info({ 'interrogate skip': f })
|
||||
@@ -41,7 +54,6 @@ async def interrogate(f):
|
||||
# run clip
|
||||
json.model = 'clip'
|
||||
res = await sdapi.post('/sdapi/v1/interrogate', json)
|
||||
# res = sdapi.postsync('/sdapi/v1/interrogate', json)
|
||||
caption = ""
|
||||
style = ""
|
||||
if 'caption' in res:
|
||||
@@ -50,18 +62,22 @@ async def interrogate(f):
|
||||
if ', by' in caption:
|
||||
style = caption.split(', by')[1].strip()
|
||||
log.info({ 'interrogate style': style })
|
||||
for word in caption.split(' '):
|
||||
if word not in exclude:
|
||||
stats['captions'][word] = stats['captions'][word] + 1 if word in stats['captions'] else 1
|
||||
else:
|
||||
log.error({ 'interrogate clip error': res })
|
||||
# run booru
|
||||
json.model = 'deepdanbooru'
|
||||
res = await sdapi.post('/sdapi/v1/interrogate', json)
|
||||
# res = sdapi.postsync('/sdapi/v1/interrogate', json)
|
||||
keywords = {}
|
||||
if 'caption' in res:
|
||||
for term in res.caption.split(', '):
|
||||
term = term.replace('(', '').replace(')', '').split(':')
|
||||
keywords[term[0]] = term[1]
|
||||
keywords = dict(sorted(keywords.items(), key=lambda x:x[1], reverse=True))
|
||||
for word in keywords.items():
|
||||
stats['keywords'][word[0]] = stats['keywords'][word[0]] + 1 if word[0] in stats['keywords'] else 1
|
||||
log.info({ 'interrogate keywords': keywords })
|
||||
else:
|
||||
log.error({ 'interrogate booru error': res })
|
||||
@@ -80,12 +96,13 @@ async def main():
|
||||
elif os.path.isdir(arg):
|
||||
for root, _dirs, files in os.walk(arg):
|
||||
for f in files:
|
||||
await interrogate(os.path.join(root, f))
|
||||
caption, keywords, _style = await interrogate(os.path.join(root, f))
|
||||
else:
|
||||
log.error({ 'interrogate unknown file type': arg })
|
||||
else:
|
||||
log.error({ 'interrogate file missing': arg })
|
||||
await sdapi.close()
|
||||
print_summary()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -34,7 +34,8 @@ def plot(logdir: str, name: str):
|
||||
|
||||
step, loss, rate = plt.np.loadtxt(f, delimiter = ',', skiprows = 1, usecols = [0, 3, 4], unpack = True)
|
||||
d = settings(logdir, name)
|
||||
window = d.get('gradient_step', 1) * d.get('batch_size', 1)
|
||||
# window = d.get('gradient_step', 1) * d.get('batch_size', 1)
|
||||
window = d.get('save_embedding_every', 1)
|
||||
try:
|
||||
log.debug({ 'loss plot': name, 'output': img, 'data': f, 'records': len(step) })
|
||||
except:
|
||||
|
||||
+8
-1
@@ -29,7 +29,14 @@
|
||||
"process_focal_crop_edges_weight": 0.5,
|
||||
"process_focal_crop_debug": false,
|
||||
"split_threshold": 0.5,
|
||||
"overlap_ratio": 0.2
|
||||
"overlap_ratio": 0.2,
|
||||
"process_multicrop": null,
|
||||
"process_multicrop_mindim": null,
|
||||
"process_multicrop_maxdim": null,
|
||||
"process_multicrop_minarea": null,
|
||||
"process_multicrop_maxarea": null,
|
||||
"process_multicrop_objective": null,
|
||||
"process_multicrop_threshold": null
|
||||
},
|
||||
"train_embedding": {
|
||||
"id_task": 0,
|
||||
|
||||
+26
-22
@@ -264,18 +264,37 @@ async def create(params):
|
||||
async def train(params):
|
||||
log.debug({ 'train start' })
|
||||
args.train_embedding.embedding_name = params.name
|
||||
args.train_embedding.data_root = args.preprocess.process_dst
|
||||
|
||||
imgs = [f for f in os.listdir(args.preprocess.process_dst) if os.path.isfile(os.path.join(args.preprocess.process_dst, f)) and filetype.is_image(os.path.join(args.preprocess.process_dst, f))]
|
||||
args.train_embedding.data_root = args.preprocess.process_dst
|
||||
if len(imgs) == 0:
|
||||
log.error({ 'train no input images in folder': args.preprocess.process_dst })
|
||||
return
|
||||
|
||||
if params.grad == -1:
|
||||
grad = (len(imgs) // args.train_embedding.batch_size)
|
||||
args.train_embedding.gradient_step = max(grad, 30)
|
||||
args.train_embedding.gradient_step = len(imgs) // args.train_embedding.batch_size
|
||||
log.info({ 'dynamic gradient step': args.train_embedding.gradient_step })
|
||||
if params.steps == -1:
|
||||
args.train_embedding.steps = 5000 // args.train_embedding.gradient_step
|
||||
args.train_embedding.steps = params.maxsteps // args.train_embedding.gradient_step
|
||||
log.info({ 'dynamic steps': args.train_embedding.steps })
|
||||
|
||||
epoch_size = args.train_embedding.batch_size * args.train_embedding.gradient_step
|
||||
if args.train_embedding.create_image_every == -1:
|
||||
args.train_embedding.create_image_every = args.train_embedding.steps // 10
|
||||
if args.train_embedding.save_embedding_every == -1:
|
||||
args.train_embedding.save_embedding_every = args.train_embedding.steps // 10
|
||||
if args.train_embedding.learn_rate == -1:
|
||||
loss_args = {
|
||||
"steps": args.train_embedding.steps,
|
||||
"step": epoch_size,
|
||||
"loss_start": params.rstart,
|
||||
"loss_end": params.rend,
|
||||
"loss_type": 'power',
|
||||
"power": params.rdescend
|
||||
}
|
||||
args.train_embedding.learn_rate = gen_loss_rate_str(**loss_args)
|
||||
log.debug({ 'learning rate': args.train_embedding.learn_rate, 'params': loss_args })
|
||||
|
||||
log.info({ 'train embedding': {
|
||||
'name': params.name,
|
||||
'source': args.preprocess.process_dst,
|
||||
@@ -284,7 +303,7 @@ async def train(params):
|
||||
'batch': args.train_embedding.batch_size,
|
||||
'gradient-step': args.train_embedding.gradient_step,
|
||||
'sampling': args.train_embedding.latent_sampling_method,
|
||||
'epoch-size': args.train_embedding.batch_size * args.train_embedding.gradient_step }
|
||||
'epoch-size': epoch_size }
|
||||
})
|
||||
log.info({ 'learn-rate': args.train_embedding.learn_rate })
|
||||
log.debug({ 'train args': args.train_embedding })
|
||||
@@ -389,11 +408,12 @@ async def main():
|
||||
parser.add_argument("--init", type = str, default = "person", required = False, help = "initialization class, default: %(default)s")
|
||||
parser.add_argument("--dst", type = str, default = "/tmp", required = False, help = "destination image folder for processed images, default: %(default)s")
|
||||
parser.add_argument("--steps", type = int, default = -1, required = False, help = "training steps, default: %(default)s")
|
||||
parser.add_argument("--maxsteps", type = int, default = 2500, required = False, help = "max training steps used when dynamic gradient is active, default: %(default)s")
|
||||
parser.add_argument("--vectors", type = int, default = -1, required = False, help = "number of vectors per token, default: dynamic based on number of input images")
|
||||
parser.add_argument("--batch", type = int, default = 1, required = False, help = "batch size, default: %(default)s")
|
||||
parser.add_argument("--rate", type = str, default = "", required = False, help = "learning rate, default: dynamic")
|
||||
parser.add_argument("--rstart", type = float, default = 0.01, required = False, help = "starting learn rate if using dynamic rate, default: %(default)s")
|
||||
parser.add_argument("--rend", type = float, default = 0.0001, required = False, help = "ending learn rate if using dynamic rate, default: %(default)s")
|
||||
parser.add_argument("--rend", type = float, default = 0.0005, required = False, help = "ending learn rate if using dynamic rate, default: %(default)s")
|
||||
parser.add_argument("--rdescend", type = float, default = 2, required = False, help = "learn rate descend power when using dynamic rate, default: %(default)s")
|
||||
parser.add_argument("--grad", type = int, default = -1, required = False, help = "accumulate gradient over n images, default: : %(default)s")
|
||||
parser.add_argument("--type", type = str, default = 'subject', required = False, help = "training type: subject/style/unknown, default: %(default)s")
|
||||
@@ -444,22 +464,6 @@ async def main():
|
||||
args.train_embedding.learn_rate = params.rate
|
||||
if params.grad > -1:
|
||||
args.train_embedding.gradient_step = params.grad
|
||||
epoch_size = args.train_embedding.batch_size * args.train_embedding.gradient_step
|
||||
if args.train_embedding.create_image_every == -1:
|
||||
args.train_embedding.create_image_every = epoch_size
|
||||
if args.train_embedding.save_embedding_every == -1:
|
||||
args.train_embedding.save_embedding_every = epoch_size
|
||||
if args.train_embedding.learn_rate == -1:
|
||||
loss_args = {
|
||||
"steps": args.train_embedding.steps,
|
||||
"step": epoch_size,
|
||||
"loss_start": params.rstart,
|
||||
"loss_end": params.rend,
|
||||
"loss_type": 'power',
|
||||
"power": params.rdescend
|
||||
}
|
||||
args.train_embedding.learn_rate = gen_loss_rate_str(**loss_args)
|
||||
log.debug({ 'learning rate': args.train_embedding.learn_rate, 'params': loss_args })
|
||||
if params.type == 'subject':
|
||||
if params.skipcaption:
|
||||
args.train_embedding.template_filename = 'subject.txt'
|
||||
|
||||
+2
-1
@@ -128,7 +128,8 @@
|
||||
"PLMS",
|
||||
"DPM++ 2S a",
|
||||
"DPM++ SDE Karras",
|
||||
"DPM2 a Karras"
|
||||
"DPM2 a Karras",
|
||||
"LMS Karras"
|
||||
],
|
||||
"eta_ddim": 0.0,
|
||||
"eta_ancestral": 1.0,
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
"txt2img/Style 1/visible": true,
|
||||
"txt2img/Style 2/value": "None",
|
||||
"txt2img/Style 2/visible": true,
|
||||
"txt2img/Sampling method/value": "Euler a",
|
||||
"txt2img/Sampling method/value": "DPM2 Karras",
|
||||
"txt2img/Sampling method/visible": true,
|
||||
"txt2img/Sampling Steps/visible": true,
|
||||
"txt2img/Sampling Steps/value": 20,
|
||||
@@ -114,7 +114,7 @@
|
||||
"img2img/Output directory/value": "",
|
||||
"img2img/Resize mode/visible": true,
|
||||
"img2img/Resize mode/value": "Just resize",
|
||||
"img2img/Sampling method/value": "Euler a",
|
||||
"img2img/Sampling method/value": "DPM2 Karras",
|
||||
"img2img/Sampling method/visible": true,
|
||||
"img2img/Sampling Steps/visible": true,
|
||||
"img2img/Sampling Steps/value": 20,
|
||||
|
||||
Reference in New Issue
Block a user