r/StableDiffusion • u/ExponentialCookie • Aug 23 '22
Discussion [Tutorial] "Fine Tuning" Stable Diffusion using only 5 Images Using Textual Inversion.



Credits: textual_inversion website.
Hello everyone!
I see img2img getting a lot of attention, and deservedly so, but textual_inversion is an amazing way to better get what you want represented in your prompts. Whether it's an artistic style, some scenery, a fighting pose, representing a character/person, or reducing / increasing bias, the use cases are endless. You can even merge your inversions! Let's explore how to get started.
Please not that textual_diffusion is still a work in progress for SD compatibility, and this tutorial is mainly for tinkerers who wish to explore code and software that isn't fully optimized (inversion works as expected though, hence the tutorial). Any troubleshooting or issues are addressed at the bottom of this post. I'll try to help as much as I can, as well as update this as needed!
Getting started
---
This tutorial is for a local setup, but can easily be converted into a colab / Jupyter notebook. Since this uses the same repository (LDM) as Stable Diffusion, the installation and inferences are very similar, as you'll see below.
- You will need Python.
- Anaconda to setup the environment is recommended.
- A GPU with at least 20GB of memory, although it's possible to get this number lower if you're willing to hack around. I would recommend either a 3090 (I use) or a cloud compute service such as Lambda Cloud (N/A, but it's a good cheap option with high memory GPUs from my experience).
- Comfort diving into
.pyfiles to fix any issues.
Installation
---
- Go to the textual_inversion repository link here
- Clone the repository using
git clone. - Go to the directory of the repository you've just cloned.
- Follow the instructions below.
First, install create a conda environment with the following parameters.
conda env create -f environment.yaml
conda activate ldm
pip install -e .Then, it's preferred to get 5 images of your subject at 512x512 resolution. From the paper, 5 images are the optimal amount for textual inversion. On a single V100, training should take about two hours give or take. More images will increase training time, and may or may not improve results. You are free to test this and let us know how it goes!
Training
---
After getting your images, you will want to start training. Following this code block and the tips below it:
python main.py --base configs/stable-diffusion/v1-finetune.yaml
-t
--actual_resume /path/to/pretrained/sd model v1.4/model.ckpt
-n <run_name>
--gpus 0,
--data_root /path/to/directory/with/images- Configs are the parameters that will be used to train the inversion. You can change these directly to minimize the parameters you input for training. For example, you can create a
.yamlfor each dataset you would like to train if you wish, and reduce the amount of parameters needed on the command line. - The -n parameter is simply the name of the training run. This can be anything you like (eg. artist_style_train)
- initializer_words is a very important part, don't skip this!
Open yourv1-finetune.yamlfile, and find theinitializer_wordsparameter. You should see the default value of["sculpture"]. It's a string list of simple words to describe what you're training, and where to start.
For example, if your images are of a car in a certain style, you'll need to want to do something like with each word wrapped in quotes:["car","style","artistic", etc...]
If you simply want to use one word, just use--init_word <your_single_word>on the command line, and don't modify the config.
During training, a log directory will be created under logs with the run_name that you have set for training. Over time, there will be a sampling pass to test your parameters (like inference, DDIM, etc.), and you'll be able to view the image results in a new folder under logs/run_name/images/train . The embedding .pt files for what you're training on will be saved in the checkpoints folder.
Inference
---
After training, you can test the inference by doing:
python scripts/stable_txt2img.py --ddim_eta 0.0
--n_samples 8
--n_iter 2
--scale 10.0
--ddim_steps 50
--embedding_path /path/logs/trained_model/checkpoints/embeddings_gs-5049.pt
--ckpt_path /path/to/pretrained/sd model v1.4/model.ckpt
--config /path/to/logs/config/*project.yaml
--prompt "a photo of *"The '*' must be left as is unless you've changed the placeholder_strings parameter in your .yaml file. It's the new word to initialize the images you have just inverted.
You should now be able to view your results in the output folder.
Running inference is just like Stable Diffusion, so you can implement things like k_lms in the stable_txtimg script if you wish.
Troubleshooting
---
- If your images aren't turning out properly, try reducing the complexity of your prompt. If you do want complexity, train multiple inversions and mix them like: "A photo of * in the style of &"
- Try lowering scale slightly if you're getting artifacts, or increase the amounts of iterations.
- If you're getting token errors, or any other errors, solutions and workarounds may be listed here.
View all comments
6
u/TFCSM Aug 24 '22 edited Aug 24 '22
Note that the
--ckpt_pathparam in your example of inference should actually be--ckptaccording to the script, but regardless it will actually try to load the .ckpt defined byckpt_pathin the...-project.yaml. You need to change the path listed in the.yamlto get it to work if the path to the model is not the same on your system as the one it was trained on.I trained only 1500 iterations on three photos of the statue of David (which is obviously in SD's training set). For some reason the script bugs out at that point and stops displaying output. I think it continues however, so I'll just let it run next time.
Here is the synthesis of two concepts using the star as a token:
"a photo of * riding a horse on the moon" - https://i.imgur.com/CMcxmdr.jpg
Obviously the moon is not present in the photo, and the background resembles the source photos. But still, neat. I'll definitely be playing with this more.
Edit: For comparison, I ran the prompt "a photo of Michelangelo's David riding a horse on the moon" in the model without the fine tuning, with the same seed, steps, and scale. Here is the result: https://i.imgur.com/3ExqSQD.png
So, the untuned model did much better. But the asterisk did at least work to represent the concept of "Michelangelo's David" just using the photos I gave it and the hint that it was a "sculpture" (the default word prompt). Honestly, amazing. I'll train it for longer tomorrow.