lycoris-lora 2.0.0.dev7__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/PKG-INFO +1 -1
- lycoris_lora-2.1.0/README.md +289 -0
- lycoris_lora-2.1.0/lycoris/__init__.py +23 -0
- lycoris_lora-2.1.0/lycoris/config.py +86 -0
- lycoris_lora-2.1.0/lycoris/hcp/__init__.py +4 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/hcp/base.py +57 -32
- lycoris_lora-2.1.0/lycoris/hcp/diag_oft.py +62 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/hcp/loha.py +40 -22
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/hcp/lokr.py +60 -35
- lycoris_lora-2.1.0/lycoris/kohya/__init__.py +1327 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/kohya/model_utils.py +409 -110
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/kohya/original_unet.py +220 -67
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/kohya/sdxl_model_util.py +64 -20
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/kohya/sdxl_original_unet.py +150 -48
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/kohya/utils.py +1 -1
- lycoris_lora-2.1.0/lycoris/logging.py +36 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/__init__.py +40 -29
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/attention.py +85 -72
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/base.py +27 -6
- lycoris_lora-2.1.0/lycoris/modules/boft.py +210 -0
- lycoris_lora-2.1.0/lycoris/modules/diag_oft.py +168 -0
- lycoris_lora-2.1.0/lycoris/modules/dylora.py +132 -0
- lycoris_lora-2.1.0/lycoris/modules/full.py +134 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/glokr.py +112 -84
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/glora.py +39 -20
- lycoris_lora-2.1.0/lycoris/modules/hypernet/__init__.py +1 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/hypernet/generater.py +71 -50
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/hypernet/text_encoder.py +79 -52
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/ia3.py +13 -13
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/locon.py +92 -54
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/loha.py +120 -88
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/lokr.py +136 -97
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/modules/norms.py +29 -12
- lycoris_lora-2.1.0/lycoris/utils/__init__.py +611 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/utils/logger.py +2 -4
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/utils/preset.py +2 -2
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris/utils/xformers_utils.py +1 -0
- lycoris_lora-2.1.0/lycoris/wrapper.py +514 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris_lora.egg-info/PKG-INFO +1 -1
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris_lora.egg-info/SOURCES.txt +4 -0
- lycoris_lora-2.1.0/setup.py +14 -0
- lycoris_lora-2.0.0.dev7/README.md +0 -194
- lycoris_lora-2.0.0.dev7/lycoris/__init__.py +0 -5
- lycoris_lora-2.0.0.dev7/lycoris/config.py +0 -98
- lycoris_lora-2.0.0.dev7/lycoris/hcp/__init__.py +0 -6
- lycoris_lora-2.0.0.dev7/lycoris/kohya/__init__.py +0 -1135
- lycoris_lora-2.0.0.dev7/lycoris/modules/diag_oft.py +0 -127
- lycoris_lora-2.0.0.dev7/lycoris/modules/dylora.py +0 -120
- lycoris_lora-2.0.0.dev7/lycoris/modules/full.py +0 -36
- lycoris_lora-2.0.0.dev7/lycoris/modules/hypernet/__init__.py +0 -5
- lycoris_lora-2.0.0.dev7/lycoris/utils/__init__.py +0 -535
- lycoris_lora-2.0.0.dev7/setup.py +0 -18
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/LICENSE.md +0 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris_lora.egg-info/dependency_links.txt +0 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris_lora.egg-info/not-zip-safe +0 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris_lora.egg-info/requires.txt +0 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/lycoris_lora.egg-info/top_level.txt +0 -0
- {lycoris_lora-2.0.0.dev7 → lycoris_lora-2.1.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lycoris_lora
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
|
|
5
5
|
Home-page: https://github.com/KohakuBlueleaf/LyCORIS
|
|
6
6
|
Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# LyCORIS - Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion.
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
A project that implements different parameter-efficient fine-tuning algorithms for Stable Diffusion.
|
|
6
|
+
|
|
7
|
+
This project originated from LoCon (see archive branch).
|
|
8
|
+
|
|
9
|
+
**If you are interested in discussing more details, you can join [our Discord server](https://discord.gg/VtTFKrj9gJ)**
|
|
10
|
+
|
|
11
|
+
[](https://discord.gg/VtTFKrj9gJ)
|
|
12
|
+
|
|
13
|
+
**If you want to check more in-depth experiment results and discussions for LyCORIS, you can check our [paper](https://arxiv.org/abs/2309.14859)**
|
|
14
|
+
|
|
15
|
+
## Algorithm Overview
|
|
16
|
+
|
|
17
|
+
LyCORIS currently contains LoRA (LoCon), LoHa, LoKr, (IA)^3, DyLoRA, Native fine-tuning (aka dreambooth).
|
|
18
|
+
GLoRA and GLoKr are coming soon.
|
|
19
|
+
Please check [List of Implemented Algorithms](docs/Algo-List.md) and [Guidelines](docs/Guidelines.md) for more details.
|
|
20
|
+
|
|
21
|
+
A simple comparison of some of these methods are provided below (to be taken with a grain of salt)
|
|
22
|
+
|
|
23
|
+
| | Full | LoRA | LoHa | LoKr low factor | LoKr high factor |
|
|
24
|
+
| --------------------- | ---- | ---- | ---- | --------------- | ---------------- |
|
|
25
|
+
| Fidelity | ★ | ● | ▲ | ◉ | ▲ |
|
|
26
|
+
| Flexibility$^*$ | ★ | ● | ◉ | ▲ | ●$^†$ |
|
|
27
|
+
| Diversity | ▲ | ◉ | ★ | ● | ★ |
|
|
28
|
+
| Size | ▲ | ● | ● | ● | ★ |
|
|
29
|
+
| Training Speed Linear | ★ | ● | ● | ★ | ★ |
|
|
30
|
+
| Training Speed Conv | ● | ★ | ▲ | ● | ● |
|
|
31
|
+
|
|
32
|
+
★ > ◉ > ● > ▲
|
|
33
|
+
[> means better and smaller size is better]
|
|
34
|
+
|
|
35
|
+
$^*$ Flexibility means anything related to generating images not similar to those in the training set, and combination of multiple concepts, whether they are trained together or not
|
|
36
|
+
$^†$ It may become more difficult to switch base model or combine multiple concepts in this situation
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### Image Generation
|
|
41
|
+
|
|
42
|
+
#### [a1111/sd-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
|
|
43
|
+
|
|
44
|
+
After sd-webui 1.5.0, LyCORIS models are officially supported by the built-in LoRA system. You can put them in either `models/Lora` or `models/LyCORIS` and use the default syntax `<lora:filename:multiplier>` to trigger it.
|
|
45
|
+
|
|
46
|
+
When we add new model types, we will always make sure they can be used with the newest version of sd-webui.
|
|
47
|
+
|
|
48
|
+
As for sd-webui with version < 1.5.0, please check this [extension](https://github.com/KohakuBlueleaf/a1111-sd-webui-lycoris).
|
|
49
|
+
|
|
50
|
+
#### Others
|
|
51
|
+
|
|
52
|
+
As far as we are aware, LyCORIS models are also supported in the following interfaces / online generation services (please help us complete the list!)
|
|
53
|
+
|
|
54
|
+
- [ComfyUI](https://github.com/comfyanonymous/ComfyUI)
|
|
55
|
+
- [InvokeAI](https://github.com/invoke-ai/InvokeAI)
|
|
56
|
+
- [CivitAI](https://civitai.com/)
|
|
57
|
+
- [Tensor.Art](https://tensor.art/)
|
|
58
|
+
|
|
59
|
+
However, newer model types may not always be supported. If you encounter this issue, consider requesting the developers of the corresponding interface or website to include support for the new type.
|
|
60
|
+
|
|
61
|
+
### Training
|
|
62
|
+
|
|
63
|
+
There are three different ways to train LyCORIS models.
|
|
64
|
+
|
|
65
|
+
- With [kohya-ss/sd-scripts](https://github.com/kohya-ss/sd-scripts) (see a list of compatible graphical interfaces and colabs at the end of the section)
|
|
66
|
+
- With [HCP-Diffusion](https://github.com/IrisRainbowNeko/HCP-Diffusion)
|
|
67
|
+
- With your own script by using LyCORIS as standalone wrappers for any pytorch modules.
|
|
68
|
+
|
|
69
|
+
In any case, please install this package in the corresponding virtual environment. You can either install it
|
|
70
|
+
|
|
71
|
+
- through pip
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install lycoris_lora
|
|
75
|
+
```
|
|
76
|
+
- or from source
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git clone https://github.com/KohakuBlueleaf/LyCORIS
|
|
80
|
+
cd LyCORIS
|
|
81
|
+
pip install .
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A detilaed description of the network arguments is provided in [docs/Network-Args.md](docs/Network-Args.md).
|
|
85
|
+
|
|
86
|
+
#### kohya script
|
|
87
|
+
|
|
88
|
+
You can use this package's kohya module to run kohya's training script to train lycoris module for SD models
|
|
89
|
+
|
|
90
|
+
- with command line arguments
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
accelerate launch train_network.py \
|
|
94
|
+
--network_module lycoris.kohya \
|
|
95
|
+
--network_dim "DIM_FOR_LINEAR" --network_alpha "ALPHA_FOR_LINEAR"\
|
|
96
|
+
--network_args "conv_dim=DIM_FOR_CONV" "conv_alpha=ALPHA_FOR_CONV" \
|
|
97
|
+
"dropout=DROPOUT_RATE" "algo=locon" \
|
|
98
|
+
```
|
|
99
|
+
- with `toml` files
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
accelerate launch train_network.py \
|
|
103
|
+
--config_file example_configs/training_configs/kohya/loha_config.toml \
|
|
104
|
+
--dataset_config example_configs/training_configs/kohya/dataset_config.toml
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For your convenience, some example `toml` files for kohya LyCORIS training are provided in [example/training_configs/kohya](example_configs/training_configs/kohya).
|
|
108
|
+
|
|
109
|
+
#### HCP-Diffusion
|
|
110
|
+
|
|
111
|
+
You can use this package's hcp module to run HCP-Diffusion's training script to train lycoris module for SD models
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
accelerate launch -m hcpdiff.train_ac_single \
|
|
115
|
+
--cfg example_configs/training_configs/hcp/hcp_diag_oft.yaml
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
For your convenience, some example `yaml` files for HCP LyCORIS training are provided in [example/training_configs/hcp](example_configs/training_configs/hcp).
|
|
119
|
+
|
|
120
|
+
For the moment being the outputs of HCP-Diffusion are not directly compatible with a1111/sdwebui.
|
|
121
|
+
You can perform conversion with [tools/batch_hcp_convert.py](tools/batch_hcp_convert.py).
|
|
122
|
+
|
|
123
|
+
In the case of pivotal tuning, [tools/batch_bundle_convert.py](tools/batch_bundle_convert.py) can be further used to convert to and from bundle formats.
|
|
124
|
+
Check [docs/Conversion-scripts.md](docs/Conversion-scripts.md) for more information.
|
|
125
|
+
|
|
126
|
+
#### As standalone wrappers
|
|
127
|
+
|
|
128
|
+
See [standalone_example.py](standalone_example.py) for full example.
|
|
129
|
+
|
|
130
|
+
Import `create_lycoris` and `LycorisNetwork` from `lycoris` library, put your preset to `LycorisNetwork` and then use `create_lycoris` to create LyCORIS module for your pytorch module.
|
|
131
|
+
|
|
132
|
+
For example:
|
|
133
|
+
|
|
134
|
+
```py
|
|
135
|
+
from lycoris import create_lycoris, LycorisNetwork
|
|
136
|
+
|
|
137
|
+
LycorisNetwork.apply_preset(
|
|
138
|
+
{"target_name": [".*attn.*"]}
|
|
139
|
+
)
|
|
140
|
+
lycoris_net = create_lycoris(
|
|
141
|
+
your_model,
|
|
142
|
+
1.0,
|
|
143
|
+
linear_dim=16,
|
|
144
|
+
linear_alpha=2.0,
|
|
145
|
+
algo="lokr"
|
|
146
|
+
)
|
|
147
|
+
lycoris_net.apply_to()
|
|
148
|
+
|
|
149
|
+
# after apply_to(), your_model() will run with LyCORIS net
|
|
150
|
+
lycoris_param = lycoris_net.parameters()
|
|
151
|
+
forward_with_lyco = your_model(x)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
You can check my [HakuPhi](https://github.com/KohakuBlueleaf/HakuPhi) project to see how I utilize LyCORIS to finetune the Phi-1.5 models.
|
|
155
|
+
|
|
156
|
+
#### Graphical interfaces and Colabs (via kohya trainer)
|
|
157
|
+
|
|
158
|
+
You can also train LyCORIS with the following graphical interfaces
|
|
159
|
+
|
|
160
|
+
* [bmaltais/kohya_ss](https://github.com/bmaltais/kohya_ss)
|
|
161
|
+
* [derrian-distro/LoRA_Easy_Training_Scripts](https://github.com/derrian-distro/LoRA_Easy_Training_Scripts)
|
|
162
|
+
* [Akegarasu/lora-scripts](https://github.com/Akegarasu/lora-scripts)
|
|
163
|
+
|
|
164
|
+
and colabs (please help us complete the list!)
|
|
165
|
+
|
|
166
|
+
* [hollowstrawberry/kohya-colab](https://github.com/hollowstrawberry/kohya-colab)
|
|
167
|
+
* [Linaqruf/kohya-trainer](https://github.com/Linaqruf/kohya-trainer)
|
|
168
|
+
|
|
169
|
+
However, they are not guaranteed to be up-to-date. In particular, newer types may not be supported. Consider requesting the developers for support or simply use the original kohya script in this case.
|
|
170
|
+
|
|
171
|
+
## Utilities
|
|
172
|
+
|
|
173
|
+
### Extract LoCon
|
|
174
|
+
|
|
175
|
+
You can extract LoCon from a dreambooth model with its base model.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python3 extract_locon.py <settings> <base_model> <db_model> <output>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Use --help to get more info
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
$ python3 extract_locon.py --help
|
|
185
|
+
usage: extract_locon.py [-h] [--is_v2] [--is_sdxl] [--device DEVICE] [--mode MODE] [--safetensors] [--linear_dim LINEAR_DIM]
|
|
186
|
+
[--conv_dim CONV_DIM] [--linear_threshold LINEAR_THRESHOLD] [--conv_threshold CONV_THRESHOLD]
|
|
187
|
+
[--linear_ratio LINEAR_RATIO] [--conv_ratio CONV_RATIO] [--linear_quantile LINEAR_QUANTILE]
|
|
188
|
+
[--conv_quantile CONV_QUANTILE] [--use_sparse_bias] [--sparsity SPARSITY] [--disable_cp]
|
|
189
|
+
base_model db_model output_name
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Merge LyCORIS back to model
|
|
193
|
+
|
|
194
|
+
You can merge your LyCORIS model back to your checkpoint (base model).
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
python3 merge.py <settings> <base_model> <lycoris_model> <output>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Use --help to get more info
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
$ python3 merge.py --help
|
|
204
|
+
usage: merge.py [-h] [--is_v2] [--is_sdxl] [--device DEVICE] [--dtype DTYPE] [--weight WEIGHT] base_model lycoris_model output_name
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Conversion of LoRA, LyCORIS and full models between HCP and sd-webui format
|
|
208
|
+
|
|
209
|
+
This script allows you to use the LyCORIS models trained with HCP-Diffusion in sd-webui.
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
python3 batch_hcp_convert.py \
|
|
213
|
+
--network_path /path/to/ckpts \
|
|
214
|
+
--dst_dir /path/to/stable-diffusion-webui/models/Lora \
|
|
215
|
+
--output_prefix something \
|
|
216
|
+
--auto_scale_alpha --to_webui
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
See [docs/Conversion-scripts.md](docs/Conversion-scripts.md) for more information.
|
|
220
|
+
|
|
221
|
+
### Conversion from and to bundle format
|
|
222
|
+
|
|
223
|
+
This script is particularly useful in the case of pivotal tuning.
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
python3 batch_bundle_convert.py \
|
|
227
|
+
--network_path /path/to/sd-webui-ssd/models/Lora \
|
|
228
|
+
--emb_path /path/to/ckpts \
|
|
229
|
+
--dst_dir /path/to/sd-webui-ssd/models/Lora/bundle \
|
|
230
|
+
--to_bundle --verbose 2
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
See [docs/Conversion-scripts.md](docs/Conversion-scripts.md) for more information.
|
|
234
|
+
|
|
235
|
+
## Change Log
|
|
236
|
+
|
|
237
|
+
For full log, please see [Change.md](Change.md)
|
|
238
|
+
|
|
239
|
+
## 2024/02/18 update to 2.1.0
|
|
240
|
+
|
|
241
|
+
#### New Algo
|
|
242
|
+
|
|
243
|
+
* [BOFT (Butterfly OFT)](https://arxiv.org/abs/2311.06243)
|
|
244
|
+
|
|
245
|
+
#### Improvements
|
|
246
|
+
|
|
247
|
+
* Faster, better extract script
|
|
248
|
+
* support kohya-ss/sd-scripts image gen
|
|
249
|
+
* support regex name in kohya-ss/sd-scripts
|
|
250
|
+
* support resume on:
|
|
251
|
+
* full
|
|
252
|
+
* loha
|
|
253
|
+
* oft
|
|
254
|
+
* boft
|
|
255
|
+
* Add logger into LyCORIS
|
|
256
|
+
|
|
257
|
+
#### Fixes, slight changes
|
|
258
|
+
|
|
259
|
+
* Update HCP convert for the case where only UNet or TE is trained.
|
|
260
|
+
* Change arg names for conversion scripts.
|
|
261
|
+
* Fix wrong TE prefix in merge scripts.
|
|
262
|
+
* Fix warnings and confusing logging.
|
|
263
|
+
|
|
264
|
+
## Todo list
|
|
265
|
+
|
|
266
|
+
- [X] Module and Document for using LyCORIS in any other model, Not only SD.
|
|
267
|
+
- [X] Proposition3 in [FedPara](https://arxiv.org/abs/2108.06098)
|
|
268
|
+
* also need custom backward to save the vram
|
|
269
|
+
- [ ] Low rank + sparse representation
|
|
270
|
+
- [X] For extraction
|
|
271
|
+
- [ ] For training
|
|
272
|
+
- [ ] Support more operation, not only linear and conv2d.
|
|
273
|
+
- [X] Configure varying ranks or dimensions for specific modules as needed.
|
|
274
|
+
- [ ] Automatically selecting an algorithm based on the specific rank requirement.
|
|
275
|
+
- [ ] Explore other low-rank representations or parameter-efficient methods to fine-tune either the entire model or specific parts of it.
|
|
276
|
+
- [ ] More experiments for different task, not only diffusion models.
|
|
277
|
+
|
|
278
|
+
## Citation
|
|
279
|
+
|
|
280
|
+
```bibtex
|
|
281
|
+
@inproceedings{
|
|
282
|
+
yeh2024navigating,
|
|
283
|
+
title={Navigating Text-To-Image Customization: From Ly{CORIS} Fine-Tuning to Model Evaluation},
|
|
284
|
+
author={SHIH-YING YEH and Yu-Guan Hsieh and Zhidong Gao and Bernard B W Yang and Giyeong Oh and Yanmin Gong},
|
|
285
|
+
booktitle={The Twelfth International Conference on Learning Representations},
|
|
286
|
+
year={2024},
|
|
287
|
+
url={https://openreview.net/forum?id=wfzXa8e783}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from . import (
|
|
2
|
+
kohya,
|
|
3
|
+
modules,
|
|
4
|
+
utils,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from .modules.locon import LoConModule
|
|
8
|
+
from .modules.loha import LohaModule
|
|
9
|
+
from .modules.lokr import LokrModule
|
|
10
|
+
from .modules.dylora import DyLoraModule
|
|
11
|
+
from .modules.glora import GLoRAModule
|
|
12
|
+
from .modules.norms import NormModule
|
|
13
|
+
from .modules.full import FullModule
|
|
14
|
+
from .modules.diag_oft import DiagOFTModule
|
|
15
|
+
from .modules import make_module
|
|
16
|
+
|
|
17
|
+
from .wrapper import (
|
|
18
|
+
LycorisNetwork,
|
|
19
|
+
create_lycoris,
|
|
20
|
+
create_lycoris_from_weights,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .logging import logger
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
PRESET = {
|
|
2
|
+
"full": {
|
|
3
|
+
"enable_conv": True,
|
|
4
|
+
"unet_target_module": [
|
|
5
|
+
"Transformer2DModel",
|
|
6
|
+
"ResnetBlock2D",
|
|
7
|
+
"Downsample2D",
|
|
8
|
+
"Upsample2D",
|
|
9
|
+
],
|
|
10
|
+
"unet_target_name": [
|
|
11
|
+
"conv_in",
|
|
12
|
+
"conv_out",
|
|
13
|
+
"time_embedding.linear_1",
|
|
14
|
+
"time_embedding.linear_2",
|
|
15
|
+
],
|
|
16
|
+
"text_encoder_target_module": ["CLIPAttention", "CLIPMLP"],
|
|
17
|
+
"text_encoder_target_name": [],
|
|
18
|
+
},
|
|
19
|
+
"full-lin": {
|
|
20
|
+
"enable_conv": False,
|
|
21
|
+
"unet_target_module": [
|
|
22
|
+
"Transformer2DModel",
|
|
23
|
+
"ResnetBlock2D",
|
|
24
|
+
],
|
|
25
|
+
"unet_target_name": [
|
|
26
|
+
"time_embedding.linear_1",
|
|
27
|
+
"time_embedding.linear_2",
|
|
28
|
+
],
|
|
29
|
+
"text_encoder_target_module": ["CLIPAttention", "CLIPMLP"],
|
|
30
|
+
"text_encoder_target_name": [],
|
|
31
|
+
},
|
|
32
|
+
"attn-mlp": {
|
|
33
|
+
"enable_conv": False,
|
|
34
|
+
"unet_target_module": [
|
|
35
|
+
"Transformer2DModel",
|
|
36
|
+
],
|
|
37
|
+
"unet_target_name": [],
|
|
38
|
+
"text_encoder_target_module": ["CLIPAttention", "CLIPMLP"],
|
|
39
|
+
"text_encoder_target_name": [],
|
|
40
|
+
},
|
|
41
|
+
"attn-only": {
|
|
42
|
+
"enable_conv": False,
|
|
43
|
+
"unet_target_module": [
|
|
44
|
+
"CrossAttention",
|
|
45
|
+
],
|
|
46
|
+
"unet_target_name": [],
|
|
47
|
+
"text_encoder_target_module": ["CLIPAttention"],
|
|
48
|
+
"text_encoder_target_name": [],
|
|
49
|
+
},
|
|
50
|
+
"unet-only": {
|
|
51
|
+
"enable_conv": True,
|
|
52
|
+
"unet_target_module": [
|
|
53
|
+
"Transformer2DModel",
|
|
54
|
+
"ResnetBlock2D",
|
|
55
|
+
"Downsample2D",
|
|
56
|
+
"Upsample2D",
|
|
57
|
+
],
|
|
58
|
+
"unet_target_name": [
|
|
59
|
+
"conv_in",
|
|
60
|
+
"conv_out",
|
|
61
|
+
"time_embedding.linear_1",
|
|
62
|
+
"time_embedding.linear_2",
|
|
63
|
+
],
|
|
64
|
+
"text_encoder_target_module": [],
|
|
65
|
+
"text_encoder_target_name": [],
|
|
66
|
+
},
|
|
67
|
+
"unet-transformer-only": {
|
|
68
|
+
"enable_conv": False,
|
|
69
|
+
"unet_target_module": [
|
|
70
|
+
"Transformer2DModel",
|
|
71
|
+
],
|
|
72
|
+
"unet_target_name": [],
|
|
73
|
+
"text_encoder_target_module": [],
|
|
74
|
+
"text_encoder_target_name": [],
|
|
75
|
+
},
|
|
76
|
+
"unet-convblock-only": {
|
|
77
|
+
"enable_conv": True,
|
|
78
|
+
"unet_target_module": ["ResnetBlock2D", "Downsample2D", "Upsample2D"],
|
|
79
|
+
"unet_target_name": [
|
|
80
|
+
"conv_in",
|
|
81
|
+
"conv_out",
|
|
82
|
+
],
|
|
83
|
+
"text_encoder_target_module": [],
|
|
84
|
+
"text_encoder_target_name": [],
|
|
85
|
+
},
|
|
86
|
+
}
|
|
@@ -11,8 +11,8 @@ try:
|
|
|
11
11
|
from hcpdiff.utils.utils import isinstance_list
|
|
12
12
|
except ImportError:
|
|
13
13
|
print(
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
"HCP-Diffusion is not installed, hcp feature will be disabled. "
|
|
15
|
+
"Use `pip install hcpdiff` to install hcpdiff."
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
from ..utils.logger import logger
|
|
@@ -21,70 +21,88 @@ from ..utils.logger import logger
|
|
|
21
21
|
class LycorisPluginContainer(PatchPluginContainer):
|
|
22
22
|
def __init__(self, host_name: str, host: nn.Module, parent_block: nn.Module):
|
|
23
23
|
super(LycorisPluginContainer, self).__init__(host_name, host, parent_block)
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
self.op = None
|
|
26
|
-
self.module_type =
|
|
26
|
+
self.module_type = ""
|
|
27
27
|
self.extra_args = {}
|
|
28
28
|
if isinstance(host, nn.Conv2d):
|
|
29
29
|
self.op = F.conv2d
|
|
30
|
-
self.module_type =
|
|
30
|
+
self.module_type = "conv"
|
|
31
31
|
self.extra_args = {
|
|
32
32
|
"stride": host.stride,
|
|
33
33
|
"padding": host.padding,
|
|
34
34
|
"dilation": host.dilation,
|
|
35
|
-
"groups": host.groups
|
|
35
|
+
"groups": host.groups,
|
|
36
36
|
}
|
|
37
37
|
elif isinstance(host, nn.Linear):
|
|
38
38
|
self.op = F.linear
|
|
39
|
-
self.module_type =
|
|
39
|
+
self.module_type = "linear"
|
|
40
40
|
self.extra_args = {}
|
|
41
41
|
elif isinstance(host, nn.LayerNorm):
|
|
42
42
|
self.op = F.layer_norm
|
|
43
|
-
self.module_type =
|
|
43
|
+
self.module_type = "norm"
|
|
44
44
|
self.extra_args = {
|
|
45
45
|
"normalized_shape": host.normalized_shape,
|
|
46
|
-
"eps": host.eps
|
|
46
|
+
"eps": host.eps,
|
|
47
47
|
}
|
|
48
48
|
elif isinstance(host, nn.GroupNorm):
|
|
49
49
|
self.op = F.group_norm
|
|
50
|
-
self.module_type =
|
|
51
|
-
self.extra_args = {
|
|
52
|
-
"num_groups": host.num_groups,
|
|
53
|
-
"eps": host.eps
|
|
54
|
-
}
|
|
50
|
+
self.module_type = "norm"
|
|
51
|
+
self.extra_args = {"num_groups": host.num_groups, "eps": host.eps}
|
|
55
52
|
else:
|
|
56
53
|
logger.warning(
|
|
57
54
|
f"Unsupported host type: '{type(host)}' for LyCORIS plugin. "
|
|
58
55
|
"Will ignore this block."
|
|
59
56
|
)
|
|
60
|
-
|
|
57
|
+
|
|
61
58
|
def forward(self, *args, **kwargs):
|
|
62
59
|
if self.op is None:
|
|
63
60
|
return self._host(*args, **kwargs)
|
|
64
|
-
|
|
65
|
-
if
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
isinstance(self._host, (LoRACompatibleLinear, LoRACompatibleConv))
|
|
64
|
+
and len(args) == 2
|
|
65
|
+
):
|
|
66
66
|
scale = args[1]
|
|
67
67
|
args = [args[0]]
|
|
68
68
|
else:
|
|
69
69
|
scale = 1
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
org_weight = self._host.weight
|
|
72
72
|
org_bias = getattr(self._host, "bias", None)
|
|
73
73
|
new_weight = org_weight
|
|
74
74
|
new_bias = org_bias
|
|
75
75
|
total_diff_output = 0
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
for name in self.plugin_names:
|
|
78
78
|
lyco_plugin_block = getattr(self, name)
|
|
79
|
-
|
|
79
|
+
(
|
|
80
|
+
diff_weight,
|
|
81
|
+
diff_bias,
|
|
82
|
+
diff_output,
|
|
83
|
+
update_weight,
|
|
84
|
+
update_bias,
|
|
85
|
+
) = lyco_plugin_block(
|
|
86
|
+
org_weight, org_bias, new_weight, new_bias, *args, **kwargs
|
|
87
|
+
)
|
|
80
88
|
# logger.debug(f'diff weight norm: {torch.norm(diff_weight).detach().cpu().item()}')
|
|
81
89
|
if diff_weight is not None:
|
|
82
|
-
|
|
90
|
+
if update_weight:
|
|
91
|
+
new_weight = new_weight + diff_weight * scale
|
|
92
|
+
else:
|
|
93
|
+
new_weight = diff_weight
|
|
83
94
|
if diff_bias is not None:
|
|
84
|
-
|
|
95
|
+
if update_bias:
|
|
96
|
+
new_bias = (
|
|
97
|
+
diff_bias * scale
|
|
98
|
+
if new_bias is None
|
|
99
|
+
else new_bias + diff_bias * scale
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
new_bias = diff_bias
|
|
85
103
|
if diff_output is not None:
|
|
86
104
|
total_diff_output = total_diff_output + diff_output * scale
|
|
87
|
-
|
|
105
|
+
|
|
88
106
|
weight_dict = {
|
|
89
107
|
"weight": new_weight,
|
|
90
108
|
"bias": new_bias,
|
|
@@ -95,10 +113,17 @@ class LycorisPluginContainer(PatchPluginContainer):
|
|
|
95
113
|
|
|
96
114
|
class LycorisPluginBlock(PatchPluginBlock):
|
|
97
115
|
container_cls = LycorisPluginContainer
|
|
116
|
+
|
|
98
117
|
def __init__(
|
|
99
|
-
self,
|
|
100
|
-
|
|
101
|
-
|
|
118
|
+
self,
|
|
119
|
+
*args,
|
|
120
|
+
dim=4,
|
|
121
|
+
alpha=1.0,
|
|
122
|
+
dropout=0.0,
|
|
123
|
+
rank_dropout=0.0,
|
|
124
|
+
module_dropout=0.0,
|
|
125
|
+
use_tucker=False,
|
|
126
|
+
**kwargs,
|
|
102
127
|
):
|
|
103
128
|
super(LycorisPluginBlock, self).__init__(*args, **kwargs)
|
|
104
129
|
self.module_type = self.container().module_type
|
|
@@ -108,21 +133,21 @@ class LycorisPluginBlock(PatchPluginBlock):
|
|
|
108
133
|
self.rank_dropout = rank_dropout
|
|
109
134
|
self.module_dropout = module_dropout
|
|
110
135
|
self.tucker = False
|
|
111
|
-
|
|
112
|
-
if self.module_type ==
|
|
136
|
+
|
|
137
|
+
if self.module_type == "conv":
|
|
113
138
|
self.out_dim = self.host().out_channels
|
|
114
139
|
self.in_dim = self.host().in_channels
|
|
115
140
|
self.k_size = self.host().kernel_size
|
|
116
141
|
self.tucker = use_tucker
|
|
117
142
|
self.shape = [self.out_dim, self.in_dim, *self.k_size]
|
|
118
|
-
elif self.module_type ==
|
|
143
|
+
elif self.module_type == "linear":
|
|
119
144
|
self.out_dim = self.host().out_features
|
|
120
145
|
self.in_dim = self.host().in_features
|
|
121
146
|
self.shape = [self.out_dim, self.in_dim]
|
|
122
|
-
elif self.module_type ==
|
|
147
|
+
elif self.module_type == "norm":
|
|
123
148
|
self.dim = self.host().weight.shape[0]
|
|
124
149
|
else:
|
|
125
150
|
raise NotImplementedError
|
|
126
|
-
|
|
151
|
+
|
|
127
152
|
def forward(self, org_weight, org_bias, new_weight, new_bias, *args, **kwargs):
|
|
128
|
-
raise NotImplementedError
|
|
153
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import torch.nn as nn
|
|
3
|
+
import torch.nn.functional as F
|
|
4
|
+
|
|
5
|
+
from einops import rearrange
|
|
6
|
+
|
|
7
|
+
from .base import LycorisPluginBlock
|
|
8
|
+
from ..modules.lokr import factorization
|
|
9
|
+
from ..modules.diag_oft import DiagOFTModule, log_oft_factorize
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DiagOFTBlock(DiagOFTModule, LycorisPluginBlock):
|
|
13
|
+
wrapable_classes = (nn.Conv2d, nn.Linear)
|
|
14
|
+
|
|
15
|
+
def __init__(self, *args, constrain=0, rescaled=False, **kwargs):
|
|
16
|
+
LycorisPluginBlock.__init__(self, *args, **kwargs)
|
|
17
|
+
|
|
18
|
+
out_dim = self.shape[0]
|
|
19
|
+
self.block_size, self.block_num = factorization(out_dim, self.dim)
|
|
20
|
+
self.scale = 1.0
|
|
21
|
+
# block_num > block_size
|
|
22
|
+
self.rescaled = rescaled
|
|
23
|
+
self.constrain = constrain * out_dim
|
|
24
|
+
self.oft_blocks = nn.Parameter(
|
|
25
|
+
torch.zeros(self.block_num, self.block_size, self.block_size)
|
|
26
|
+
)
|
|
27
|
+
if rescaled:
|
|
28
|
+
self.rescale = nn.Parameter(torch.ones(out_dim))
|
|
29
|
+
log_oft_factorize(
|
|
30
|
+
dim=out_dim,
|
|
31
|
+
factor=self.dim,
|
|
32
|
+
num=self.block_num,
|
|
33
|
+
bdim=self.block_size,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def forward(self, orig_weight, org_bias, new_weight, new_bias, *args, **kwargs):
|
|
37
|
+
device = self.oft_blocks.device
|
|
38
|
+
if self.rank_dropout and self.training:
|
|
39
|
+
drop = (torch.rand(self.oft_blocks, device=device) < self.rank_dropout).to(
|
|
40
|
+
self.oft_blocks.dtype
|
|
41
|
+
)
|
|
42
|
+
if self.rank_dropout_scale:
|
|
43
|
+
drop /= drop.mean()
|
|
44
|
+
else:
|
|
45
|
+
drop = 1
|
|
46
|
+
|
|
47
|
+
r = self.get_r()
|
|
48
|
+
org_weight = orig_weight.to(device, dtype=r.dtype)
|
|
49
|
+
org_weight = rearrange(
|
|
50
|
+
org_weight, "(k n) ... -> k n ...", k=self.block_num, n=self.block_size
|
|
51
|
+
)
|
|
52
|
+
# Init R=0, so add I on it to ensure the output of step0 is original model output
|
|
53
|
+
weight = torch.einsum(
|
|
54
|
+
"k n m, k n ... -> k m ...",
|
|
55
|
+
r * self.scale + (1 - self.scale) * self.I,
|
|
56
|
+
org_weight,
|
|
57
|
+
)
|
|
58
|
+
weight = rearrange(weight, "k m ... -> (k m) ...")
|
|
59
|
+
if self.rescaled:
|
|
60
|
+
weight = self.rescale.to(weight) * weight
|
|
61
|
+
# disable update weight for replace the weight directly
|
|
62
|
+
return weight, None, None, False, False
|