multimodalart HF staff commited on
Commit
0e68d2d
1 Parent(s): adcfd5e

Fixes after Slack thread

Browse files
Files changed (4) hide show
  1. README.md +2 -2
  2. app.py +53 -35
  3. convertosd.py +4 -1
  4. train_dreambooth.py +4 -1
README.md CHANGED
@@ -1,10 +1,10 @@
1
  ---
2
  title: Dreambooth Training
3
- emoji: 🌖
4
  colorFrom: pink
5
  colorTo: red
6
  sdk: gradio
7
- sdk_version: 3.10.1
8
  app_file: app.py
9
  pinned: false
10
  license: mit
 
1
  ---
2
  title: Dreambooth Training
3
+ emoji: ☁️
4
  colorFrom: pink
5
  colorTo: red
6
  sdk: gradio
7
+ sdk_version: 3.11
8
  app_file: app.py
9
  pinned: false
10
  license: mit
app.py CHANGED
@@ -11,17 +11,20 @@ import requests
11
  import torch
12
  import zipfile
13
  import urllib.parse
 
14
  from diffusers import StableDiffusionPipeline
 
15
 
16
  css = '''
17
  .instruction{position: absolute; top: 0;right: 0;margin-top: 0px !important}
18
  .arrow{position: absolute;top: 0;right: -110px;margin-top: -8px !important}
19
  #component-4, #component-3, #component-10{min-height: 0}
20
  '''
21
- model_to_load = "multimodalart/sd-fine-tunable"
22
  maximum_concepts = 3
 
23
  #Pre download the files even if we don't use it here
24
- StableDiffusionPipeline.from_pretrained(model_to_load)
 
25
 
26
  def zipdir(path, ziph):
27
  # ziph is zipfile handle
@@ -67,8 +70,14 @@ def count_files(*inputs):
67
  return(gr.update(visible=True, value=f"You are going to train {concept_counter} {type_of_thing}(s), with {file_counter} images for {Training_Steps} steps. This should take around {round(Training_Steps/1.5, 2)} seconds, or {round((Training_Steps/1.5)/3600, 2)} hours. As a reminder, the T4 GPU costs US$0.60 for 1h. Once training is over, don't forget to swap the hardware back to CPU."))
68
 
69
  def train(*inputs):
 
 
 
 
 
70
  if "IS_SHARED_UI" in os.environ:
71
  raise gr.Error("This Space only works in duplicated instances")
 
72
  if os.path.exists("output_model"): shutil.rmtree('output_model')
73
  if os.path.exists("instance_images"): shutil.rmtree('instance_images')
74
  if os.path.exists("diffusers_model.zip"): os.remove("diffusers_model.zip")
@@ -135,19 +144,24 @@ def train(*inputs):
135
  lr_warmup_steps = 0,
136
  max_train_steps=Training_Steps,
137
  )
 
138
  run_training(args_general)
 
139
  torch.cuda.empty_cache()
140
- #convert("output_model", "model.ckpt")
141
- #shutil.rmtree('instance_images')
142
- #shutil.make_archive("diffusers_model", 'zip', "output_model")
 
 
143
  with zipfile.ZipFile('diffusers_model.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
144
  zipdir('output_model/', zipf)
145
- torch.cuda.empty_cache()
146
- return [gr.update(visible=True, value=["diffusers_model.zip"]), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)]
147
 
148
  def generate(prompt):
 
149
  from diffusers import StableDiffusionPipeline
150
-
151
  pipe = StableDiffusionPipeline.from_pretrained("./output_model", torch_dtype=torch.float16)
152
  pipe = pipe.to("cuda")
153
  image = pipe(prompt).images[0]
@@ -180,7 +194,7 @@ def push(model_name, where_to_upload, hf_token):
180
  else:
181
  title_instance_prompt_string = ''
182
  previous_instance_prompt = instance_prompt
183
- image_string = f'''{title_instance_prompt_string}
184
  {image_string}![{instance_prompt} {i}](https://huggingface.co/{model_id}/resolve/main/concept_images/{urllib.parse.quote(image)})'''
185
  readme_text = f'''---
186
  license: creativeml-openrail-m
@@ -189,13 +203,13 @@ tags:
189
  ---
190
  ### {model_name} Dreambooth model trained by {api.whoami(token=hf_token)["name"]} with [Hugging Face Dreambooth Training Space](https://huggingface.co/spaces/multimodalart/dreambooth-training)
191
 
192
- You run your new concept via `diffusers` [Colab Notebook for Inference](https://colab.research.google.com/github/huggingface/notebooks/blob/main/diffusers/sd_dreambooth_inference.ipynb)
193
 
194
- Sample pictures of this concept:
195
  {image_string}
196
  '''
197
  #Save the readme to a file
198
- readme_file = open("README.md", "w")
199
  readme_file.write(readme_text)
200
  readme_file.close()
201
  #Save the token identifier to a file
@@ -205,7 +219,7 @@ Sample pictures of this concept:
205
  create_repo(model_id,private=True, token=hf_token)
206
  operations = [
207
  CommitOperationAdd(path_in_repo="token_identifier.txt", path_or_fileobj="token_identifier.txt"),
208
- CommitOperationAdd(path_in_repo="README.md", path_or_fileobj="README.md"),
209
  CommitOperationAdd(path_in_repo=f"model.ckpt",path_or_fileobj="model.ckpt")
210
  ]
211
  api.create_commit(
@@ -237,17 +251,17 @@ with gr.Blocks(css=css) as demo:
237
  gr.HTML('''
238
  <div class="gr-prose" style="max-width: 80%">
239
  <h2>Attention - This Space doesn't work in this shared UI</h2>
240
- <p>For it to work, you have to duplicate the Space and run it on your own profile using a (paid) private T4 GPU for training. As each T4 costs US$0,60/h, it should cost < US$1 to train a model with less than 100 images using default settings!</p>
241
- <p>Please, duplicate this Space, then go to the Settings tab and select a T4 or T4 medium instance.</p>
242
  <img class="instruction" src="file/duplicate.png">
243
  <img class="arrow" src="file/arrow.png" />
244
  </div>
245
  ''')
246
  else:
247
- gr.HTML('''
248
  <div class="gr-prose" style="max-width: 80%">
249
- <h2>You have successfully cloned the Dreambooth Training Space</h2>
250
- <p>If you haven't already, attribute a T4 GPU to it (via the Settings tab) and run the training below. You will be billed by the minute from when you activate the GPU until when you turn it off.</p>
251
  </div>
252
  ''')
253
  gr.Markdown("# Dreambooth training")
@@ -277,9 +291,9 @@ with gr.Blocks(css=css) as demo:
277
  visible = False
278
  is_visible.append(gr.State(value=False))
279
 
280
- file_collection.append(gr.File(label=f"Upload the images for your {ordinal(x+1)} concept", file_count="multiple", interactive=True, visible=visible))
281
  with gr.Column(visible=visible) as row[x]:
282
- concept_collection.append(gr.Textbox(label=f"{ordinal(x+1)} concept prompt - use a unique, made up word to avoid collisions"))
283
  with gr.Row():
284
  if(x < maximum_concepts-1):
285
  buttons_collection.append(gr.Button(value="Add +1 concept", visible=visible))
@@ -302,9 +316,7 @@ with gr.Blocks(css=css) as demo:
302
  if(counter_delete < len(delete_collection)+1):
303
  delete_button.click(lambda:[gr.update(visible=False),gr.update(visible=False), gr.update(visible=True), False], None, [file_collection[counter_delete], row[counter_delete], buttons_collection[counter_delete-1], is_visible[counter_delete]], queue=False)
304
  counter_delete += 1
305
-
306
-
307
-
308
  with gr.Accordion("Custom Settings", open=False):
309
  swap_auto_calculated = gr.Checkbox(label="Use custom settings")
310
  gr.Markdown("If not checked, the number of steps and % of frozen encoder will be tuned automatically according to the amount of images you upload and whether you are training an `object`, `person` or `style` as follows: The number of steps is calculated by number of images uploaded multiplied by 20. The text-encoder is frozen after 10% of the steps for a style, 30% of the steps for an object and is fully trained for persons.")
@@ -315,27 +327,33 @@ with gr.Blocks(css=css) as demo:
315
  training_summary = gr.Textbox("", visible=False, label="Training Summary")
316
  steps.change(fn=count_files, inputs=file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[training_summary], queue=False)
317
  perc_txt_encoder.change(fn=count_files, inputs=file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[training_summary], queue=False)
 
318
  for file in file_collection:
319
  file.change(fn=count_files, inputs=file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[training_summary], queue=False)
320
  train_btn = gr.Button("Start Training")
321
- with gr.Box(visible=False) as try_your_model:
322
- gr.Markdown("## Try your model")
323
- with gr.Row():
 
 
 
324
  prompt = gr.Textbox(label="Type your prompt")
325
  result_image = gr.Image()
326
- generate_button = gr.Button("Generate Image")
327
- with gr.Box(visible=False) as push_to_hub:
328
- gr.Markdown("## Push to Hugging Face Hub")
329
- model_name = gr.Textbox(label="Name of your model", placeholder="Tarsila do Amaral Style")
330
- where_to_upload = gr.Dropdown(["My personal profile", "Public Library"], label="Upload to")
331
- gr.Markdown("[A Hugging Face write access token](https://huggingface.co/settings/tokens), go to \"New token\" -> Role : Write. A regular read token won't work here.")
332
- hf_token = gr.Textbox(label="Hugging Face Write Token")
333
- push_button = gr.Button("Push to the Hub")
 
 
334
  result = gr.File(label="Download the uploaded models in the diffusers format", visible=True)
335
  success_message_upload = gr.Markdown(visible=False)
336
  convert_button = gr.Button("Convert to CKPT", visible=False)
337
 
338
- train_btn.click(fn=train, inputs=is_visible+concept_collection+file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[result, try_your_model, push_to_hub, convert_button])
339
  generate_button.click(fn=generate, inputs=prompt, outputs=result_image)
340
  push_button.click(fn=push, inputs=[model_name, where_to_upload, hf_token], outputs=[success_message_upload, result])
341
  convert_button.click(fn=convert_to_ckpt, inputs=[], outputs=result)
 
11
  import torch
12
  import zipfile
13
  import urllib.parse
14
+ import gc
15
  from diffusers import StableDiffusionPipeline
16
+ from huggingface_hub import snapshot_download
17
 
18
  css = '''
19
  .instruction{position: absolute; top: 0;right: 0;margin-top: 0px !important}
20
  .arrow{position: absolute;top: 0;right: -110px;margin-top: -8px !important}
21
  #component-4, #component-3, #component-10{min-height: 0}
22
  '''
 
23
  maximum_concepts = 3
24
+
25
  #Pre download the files even if we don't use it here
26
+ model_to_load = snapshot_download(repo_id="multimodalart/sd-fine-tunable")
27
+ safety_checker = snapshot_download(repo_id="multimodalart/sd-sc")
28
 
29
  def zipdir(path, ziph):
30
  # ziph is zipfile handle
 
70
  return(gr.update(visible=True, value=f"You are going to train {concept_counter} {type_of_thing}(s), with {file_counter} images for {Training_Steps} steps. This should take around {round(Training_Steps/1.5, 2)} seconds, or {round((Training_Steps/1.5)/3600, 2)} hours. As a reminder, the T4 GPU costs US$0.60 for 1h. Once training is over, don't forget to swap the hardware back to CPU."))
71
 
72
  def train(*inputs):
73
+ torch.cuda.empty_cache()
74
+ if 'pipe' in globals():
75
+ del pipe
76
+ gc.collect()
77
+
78
  if "IS_SHARED_UI" in os.environ:
79
  raise gr.Error("This Space only works in duplicated instances")
80
+
81
  if os.path.exists("output_model"): shutil.rmtree('output_model')
82
  if os.path.exists("instance_images"): shutil.rmtree('instance_images')
83
  if os.path.exists("diffusers_model.zip"): os.remove("diffusers_model.zip")
 
144
  lr_warmup_steps = 0,
145
  max_train_steps=Training_Steps,
146
  )
147
+ print("Starting training...")
148
  run_training(args_general)
149
+ gc.collect()
150
  torch.cuda.empty_cache()
151
+ print("Adding Safety Checker to the model...")
152
+ shutil.copytree(f"{safety_checker}/feature_extractor", "output_model/feature_extractor")
153
+ shutil.copytree(f"{safety_checker}/safety_checker", "output_model/safety_checker")
154
+ shutil.copy(f"model_index.json", "output_model/model_index.json")
155
+ print("Zipping model file...")
156
  with zipfile.ZipFile('diffusers_model.zip', 'w', zipfile.ZIP_DEFLATED) as zipf:
157
  zipdir('output_model/', zipf)
158
+ print("Training completed!")
159
+ return [gr.update(visible=True, value=["diffusers_model.zip"]), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)]
160
 
161
  def generate(prompt):
162
+ torch.cuda.empty_cache()
163
  from diffusers import StableDiffusionPipeline
164
+ global pipe
165
  pipe = StableDiffusionPipeline.from_pretrained("./output_model", torch_dtype=torch.float16)
166
  pipe = pipe.to("cuda")
167
  image = pipe(prompt).images[0]
 
194
  else:
195
  title_instance_prompt_string = ''
196
  previous_instance_prompt = instance_prompt
197
+ image_string = f'''{title_instance_prompt_string} (use that on your prompt)
198
  {image_string}![{instance_prompt} {i}](https://huggingface.co/{model_id}/resolve/main/concept_images/{urllib.parse.quote(image)})'''
199
  readme_text = f'''---
200
  license: creativeml-openrail-m
 
203
  ---
204
  ### {model_name} Dreambooth model trained by {api.whoami(token=hf_token)["name"]} with [Hugging Face Dreambooth Training Space](https://huggingface.co/spaces/multimodalart/dreambooth-training)
205
 
206
+ You run your new concept via `diffusers` [Colab Notebook for Inference](https://colab.research.google.com/github/huggingface/notebooks/blob/main/diffusers/sd_dreambooth_inference.ipynb). Don't forget to use the concept prompts!
207
 
208
+ Sample pictures of:
209
  {image_string}
210
  '''
211
  #Save the readme to a file
212
+ readme_file = open("model.README.md", "w")
213
  readme_file.write(readme_text)
214
  readme_file.close()
215
  #Save the token identifier to a file
 
219
  create_repo(model_id,private=True, token=hf_token)
220
  operations = [
221
  CommitOperationAdd(path_in_repo="token_identifier.txt", path_or_fileobj="token_identifier.txt"),
222
+ CommitOperationAdd(path_in_repo="README.md", path_or_fileobj="model.README.md"),
223
  CommitOperationAdd(path_in_repo=f"model.ckpt",path_or_fileobj="model.ckpt")
224
  ]
225
  api.create_commit(
 
251
  gr.HTML('''
252
  <div class="gr-prose" style="max-width: 80%">
253
  <h2>Attention - This Space doesn't work in this shared UI</h2>
254
+ <p>For it to work, you have to duplicate the Space and run it on your own profile using a (paid) private T4 GPU for training. As each T4 costs US$0.60/h, it should cost < US$1 to train a model with less than 100 images using default settings!</p>
255
+ <p>Please, duplicate this Space, then go to the Settings tab and select a T4 instance.</p>
256
  <img class="instruction" src="file/duplicate.png">
257
  <img class="arrow" src="file/arrow.png" />
258
  </div>
259
  ''')
260
  else:
261
+ gr.HTML(f'''
262
  <div class="gr-prose" style="max-width: 80%">
263
+ <h2>You have successfully duplicated the Dreambooth Training Space</h2>
264
+ <p>If you haven't already, <a href="https://huggingface.co/spaces/{os.environ['SPACE_ID']}/settings">attribute a T4 GPU to it (via the Settings tab)</a> and run the training below. You will be billed by the minute from when you activate the GPU until when you turn it off.</p>
265
  </div>
266
  ''')
267
  gr.Markdown("# Dreambooth training")
 
291
  visible = False
292
  is_visible.append(gr.State(value=False))
293
 
294
+ file_collection.append(gr.File(label=f'''Upload the images for your {ordinal(x+1) if (x>0) else ""} concept''', file_count="multiple", interactive=True, visible=visible))
295
  with gr.Column(visible=visible) as row[x]:
296
+ concept_collection.append(gr.Textbox(label=f'''{ordinal(x+1) if (x>0) else ""} concept prompt - use a unique, made up word to avoid collisions'''))
297
  with gr.Row():
298
  if(x < maximum_concepts-1):
299
  buttons_collection.append(gr.Button(value="Add +1 concept", visible=visible))
 
316
  if(counter_delete < len(delete_collection)+1):
317
  delete_button.click(lambda:[gr.update(visible=False),gr.update(visible=False), gr.update(visible=True), False], None, [file_collection[counter_delete], row[counter_delete], buttons_collection[counter_delete-1], is_visible[counter_delete]], queue=False)
318
  counter_delete += 1
319
+
 
 
320
  with gr.Accordion("Custom Settings", open=False):
321
  swap_auto_calculated = gr.Checkbox(label="Use custom settings")
322
  gr.Markdown("If not checked, the number of steps and % of frozen encoder will be tuned automatically according to the amount of images you upload and whether you are training an `object`, `person` or `style` as follows: The number of steps is calculated by number of images uploaded multiplied by 20. The text-encoder is frozen after 10% of the steps for a style, 30% of the steps for an object and is fully trained for persons.")
 
327
  training_summary = gr.Textbox("", visible=False, label="Training Summary")
328
  steps.change(fn=count_files, inputs=file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[training_summary], queue=False)
329
  perc_txt_encoder.change(fn=count_files, inputs=file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[training_summary], queue=False)
330
+
331
  for file in file_collection:
332
  file.change(fn=count_files, inputs=file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[training_summary], queue=False)
333
  train_btn = gr.Button("Start Training")
334
+
335
+ completed_training = gr.Markdown("# Training completed", visible=False)
336
+
337
+ with gr.Row():
338
+ with gr.Box(visible=False) as try_your_model:
339
+ gr.Markdown("## Try your model")
340
  prompt = gr.Textbox(label="Type your prompt")
341
  result_image = gr.Image()
342
+ generate_button = gr.Button("Generate Image")
343
+
344
+ with gr.Box(visible=False) as push_to_hub:
345
+ gr.Markdown("## Push to Hugging Face Hub")
346
+ model_name = gr.Textbox(label="Name of your model", placeholder="Tarsila do Amaral Style")
347
+ where_to_upload = gr.Dropdown(["My personal profile", "Public Library"], label="Upload to")
348
+ gr.Markdown("[A Hugging Face write access token](https://huggingface.co/settings/tokens), go to \"New token\" -> Role : Write. A regular read token won't work here.")
349
+ hf_token = gr.Textbox(label="Hugging Face Write Token")
350
+ push_button = gr.Button("Push to the Hub")
351
+
352
  result = gr.File(label="Download the uploaded models in the diffusers format", visible=True)
353
  success_message_upload = gr.Markdown(visible=False)
354
  convert_button = gr.Button("Convert to CKPT", visible=False)
355
 
356
+ train_btn.click(fn=train, inputs=is_visible+concept_collection+file_collection+[type_of_thing]+[steps]+[perc_txt_encoder]+[swap_auto_calculated], outputs=[result, try_your_model, push_to_hub, convert_button, completed_training])
357
  generate_button.click(fn=generate, inputs=prompt, outputs=result_image)
358
  push_button.click(fn=push, inputs=[model_name, where_to_upload, hf_token], outputs=[success_message_upload, result])
359
  convert_button.click(fn=convert_to_ckpt, inputs=[], outputs=result)
convertosd.py CHANGED
@@ -7,7 +7,7 @@ import argparse
7
  import os.path as osp
8
 
9
  import torch
10
-
11
 
12
  # =================#
13
  # UNet Conversion #
@@ -221,3 +221,6 @@ def convert(model_path, checkpoint_path):
221
  state_dict = {k:v.half() for k,v in state_dict.items()}
222
  state_dict = {"state_dict": state_dict}
223
  torch.save(state_dict, checkpoint_path)
 
 
 
 
7
  import os.path as osp
8
 
9
  import torch
10
+ import gc
11
 
12
  # =================#
13
  # UNet Conversion #
 
221
  state_dict = {k:v.half() for k,v in state_dict.items()}
222
  state_dict = {"state_dict": state_dict}
223
  torch.save(state_dict, checkpoint_path)
224
+ del state_dict, text_enc_dict, vae_state_dict, unet_state_dict
225
+ torch.cuda.empty_cache()
226
+ gc.collect()
train_dreambooth.py CHANGED
@@ -6,6 +6,7 @@ from pathlib import Path
6
  from typing import Optional
7
  import subprocess
8
  import sys
 
9
 
10
  import torch
11
  import torch.nn.functional as F
@@ -812,7 +813,9 @@ def run_training(args_imported):
812
  repo.push_to_hub(commit_message="End of training", blocking=False, auto_lfs_prune=True)
813
 
814
  accelerator.end_training()
815
-
 
 
816
  if __name__ == "__main__":
817
  pass
818
  #main()
 
6
  from typing import Optional
7
  import subprocess
8
  import sys
9
+ import gc
10
 
11
  import torch
12
  import torch.nn.functional as F
 
813
  repo.push_to_hub(commit_message="End of training", blocking=False, auto_lfs_prune=True)
814
 
815
  accelerator.end_training()
816
+ del pipeline
817
+ torch.cuda.empty_cache()
818
+ gc.collect()
819
  if __name__ == "__main__":
820
  pass
821
  #main()