update interrogate and train

This commit is contained in:
Vladimir Mandic
2023-01-19 17:55:31 -05:00
parent 1f173f8123
commit 832c24c24d
8 changed files with 66 additions and 37 deletions
+5 -6
View File
@@ -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
View File
@@ -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
+20 -3
View File
@@ -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__":
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,