lycoris-lora 2.3.0.dev11__tar.gz → 3.0.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-3.0.0/PKG-INFO +25 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/README.md +76 -41
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/__init__.py +4 -1
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/config.py +40 -4
- lycoris_lora-3.0.0/lycoris/functional/__init__.py +9 -0
- lycoris_lora-3.0.0/lycoris/functional/boft.py +99 -0
- lycoris_lora-3.0.0/lycoris/functional/diag_oft.py +103 -0
- lycoris_lora-3.0.0/lycoris/functional/general.py +106 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/functional/locon.py +13 -35
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/functional/loha.py +53 -38
- lycoris_lora-3.0.0/lycoris/functional/lokr.py +240 -0
- lycoris_lora-2.3.0.dev11/lycoris/kohya/__init__.py → lycoris_lora-3.0.0/lycoris/kohya.py +83 -346
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/logging.py +16 -0
- lycoris_lora-3.0.0/lycoris/modules/__init__.py +46 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/base.py +93 -2
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/boft.py +66 -70
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/diag_oft.py +62 -56
- lycoris_lora-3.0.0/lycoris/modules/dylora.py +157 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/full.py +69 -22
- lycoris_lora-3.0.0/lycoris/modules/glora.py +263 -0
- lycoris_lora-3.0.0/lycoris/modules/ia3.py +143 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/locon.py +54 -45
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/loha.py +53 -40
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/lokr.py +221 -141
- lycoris_lora-3.0.0/lycoris/modules/norms.py +159 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/__init__.py +51 -208
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/bnb.py +3 -0
- lycoris_lora-3.0.0/lycoris/utils/general.py +5 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/wrapper.py +46 -48
- lycoris_lora-3.0.0/lycoris_lora.egg-info/PKG-INFO +25 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/SOURCES.txt +10 -19
- lycoris_lora-3.0.0/lycoris_lora.egg-info/requires.txt +4 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/top_level.txt +1 -0
- lycoris_lora-3.0.0/setup.py +29 -0
- lycoris_lora-3.0.0/test/__init__.py +0 -0
- lycoris_lora-3.0.0/test/functional.py +87 -0
- lycoris_lora-3.0.0/test/module.py +181 -0
- lycoris_lora-3.0.0/test/wrapper.py +128 -0
- lycoris_lora-2.3.0.dev11/PKG-INFO +0 -15
- lycoris_lora-2.3.0.dev11/lycoris/functional/__init__.py +0 -4
- lycoris_lora-2.3.0.dev11/lycoris/functional/general.py +0 -8
- lycoris_lora-2.3.0.dev11/lycoris/hcp/__init__.py +0 -4
- lycoris_lora-2.3.0.dev11/lycoris/hcp/base.py +0 -153
- lycoris_lora-2.3.0.dev11/lycoris/hcp/diag_oft.py +0 -62
- lycoris_lora-2.3.0.dev11/lycoris/hcp/loha.py +0 -85
- lycoris_lora-2.3.0.dev11/lycoris/hcp/lokr.py +0 -131
- lycoris_lora-2.3.0.dev11/lycoris/kohya/model_utils.py +0 -1633
- lycoris_lora-2.3.0.dev11/lycoris/kohya/original_unet.py +0 -1760
- lycoris_lora-2.3.0.dev11/lycoris/kohya/sdxl_model_util.py +0 -581
- lycoris_lora-2.3.0.dev11/lycoris/kohya/sdxl_original_unet.py +0 -1243
- lycoris_lora-2.3.0.dev11/lycoris/kohya/test_hyperdream.py +0 -527
- lycoris_lora-2.3.0.dev11/lycoris/kohya/utils.py +0 -48
- lycoris_lora-2.3.0.dev11/lycoris/modules/__init__.py +0 -137
- lycoris_lora-2.3.0.dev11/lycoris/modules/attention.py +0 -259
- lycoris_lora-2.3.0.dev11/lycoris/modules/dylora.py +0 -132
- lycoris_lora-2.3.0.dev11/lycoris/modules/glokr.py +0 -310
- lycoris_lora-2.3.0.dev11/lycoris/modules/glora.py +0 -136
- lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/__init__.py +0 -1
- lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/generater.py +0 -223
- lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/text_encoder.py +0 -266
- lycoris_lora-2.3.0.dev11/lycoris/modules/ia3.py +0 -67
- lycoris_lora-2.3.0.dev11/lycoris/modules/lilora.py +0 -339
- lycoris_lora-2.3.0.dev11/lycoris/modules/norms.py +0 -70
- lycoris_lora-2.3.0.dev11/lycoris_lora.egg-info/PKG-INFO +0 -15
- lycoris_lora-2.3.0.dev11/lycoris_lora.egg-info/requires.txt +0 -6
- lycoris_lora-2.3.0.dev11/setup.py +0 -22
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/LICENSE.md +0 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/logger.py +0 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/preset.py +0 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/xformers_utils.py +0 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/dependency_links.txt +0 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/not-zip-safe +0 -0
- {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/setup.cfg +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: lycoris_lora
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
|
|
5
|
+
Home-page: https://github.com/KohakuBlueleaf/LyCORIS
|
|
6
|
+
Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
|
|
7
|
+
Author-email: apolloyeh0123@gmail.com
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Environment :: GPU :: NVIDIA CUDA :: 11.8
|
|
10
|
+
Classifier: Environment :: GPU :: NVIDIA CUDA :: 12
|
|
11
|
+
Classifier: Environment :: GPU :: NVIDIA CUDA :: 12 :: 12.1
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
License-File: LICENSE.md
|
|
22
|
+
Requires-Dist: torch
|
|
23
|
+
Requires-Dist: einops
|
|
24
|
+
Requires-Dist: toml
|
|
25
|
+
Requires-Dist: tqdm
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+

|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
|
|
1
10
|
# LyCORIS - Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion. (ICLR'24)
|
|
2
11
|
|
|
3
|
-

|
|
4
13
|
|
|
5
14
|
A project that implements different parameter-efficient fine-tuning algorithms for Stable Diffusion.
|
|
6
15
|
|
|
@@ -20,21 +29,21 @@ Please check [List of Implemented Algorithms](docs/Algo-List.md) and [Guidelines
|
|
|
20
29
|
|
|
21
30
|
A simple comparison of some of these methods are provided below (to be taken with a grain of salt)
|
|
22
31
|
|
|
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 | ● | ★ | ▲ | ● | ●
|
|
32
|
+
| | Full | LoRA | LoHa | LoKr low factor | LoKr high factor$^+$ |
|
|
33
|
+
| --------------------- | ---- | ---- | ---- | --------------- | ---------------------- |
|
|
34
|
+
| Fidelity | ★ | ● | ▲ | ◉ | ▲ |
|
|
35
|
+
| Flexibility$^*$ | ★ | ● | ◉ | ▲ | ●$^†$ |
|
|
36
|
+
| Diversity | ▲ | ◉ | ★ | ● | ★ |
|
|
37
|
+
| Size | ▲ | ● | ● | ● | ★ |
|
|
38
|
+
| Training Speed Linear | ★ | ● | ● | ★ | ★ |
|
|
39
|
+
| Training Speed Conv | ● | ★ | ▲ | ● | ● |
|
|
31
40
|
|
|
32
41
|
★ > ◉ > ● > ▲
|
|
33
42
|
[> means better and smaller size is better]
|
|
34
43
|
|
|
35
|
-
$^+$ Usually we take `factor <= 0.5 * sqrt(dim)` as low factor and `factor >= sqrt(dim` as high factor. For example, factor<=8 for SD1.x/SD2.x/SDXL can be seen as low factor, and, factor>=16 can be seen as high factor.
|
|
36
|
-
$^*$ 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
|
|
37
|
-
$^†$ It may become more difficult to switch base model or combine multiple concepts in this situation
|
|
44
|
+
$^+$ Usually we take `factor <= 0.5 * sqrt(dim)` as low factor and `factor >= sqrt(dim` as high factor. For example, factor<=8 for SD1.x/SD2.x/SDXL can be seen as low factor, and, factor>=16 can be seen as high factor. `<br>`
|
|
45
|
+
$^*$ 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 `<br>`
|
|
46
|
+
$^†$ It may become more difficult to switch base model or combine multiple concepts in this situation `<br>`
|
|
38
47
|
|
|
39
48
|
**The actual performance may vary depending on the datasets, tasks, and hyperparameters used. It is recommended to experiment with different settings to achieve optimal results.**
|
|
40
49
|
|
|
@@ -66,7 +75,7 @@ However, newer model types may not always be supported. If you encounter this is
|
|
|
66
75
|
There are three different ways to train LyCORIS models.
|
|
67
76
|
|
|
68
77
|
- 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)
|
|
69
|
-
- With [
|
|
78
|
+
- With [Naifu-Diffusion](https://github.com/Mikubill/naifu)
|
|
70
79
|
- With your own script by using LyCORIS as standalone wrappers for **ANY** pytorch modules.
|
|
71
80
|
|
|
72
81
|
In any case, please install this package in the corresponding virtual environment. You can either install it
|
|
@@ -74,7 +83,7 @@ In any case, please install this package in the corresponding virtual environmen
|
|
|
74
83
|
- through pip
|
|
75
84
|
|
|
76
85
|
```bash
|
|
77
|
-
pip install
|
|
86
|
+
pip install lycoris-lora
|
|
78
87
|
```
|
|
79
88
|
- or from source
|
|
80
89
|
|
|
@@ -111,6 +120,8 @@ You can use this package's kohya module to run kohya's training script to train
|
|
|
111
120
|
|
|
112
121
|
#### HCP-Diffusion
|
|
113
122
|
|
|
123
|
+
**The support for HCP-Diffusion has been dropped on LyCORIS3.0.0, we will wait until HCP side finish the implementation of new wrapper**
|
|
124
|
+
|
|
114
125
|
You can use this package's hcp module to run HCP-Diffusion's training script to train lycoris module for SD models
|
|
115
126
|
|
|
116
127
|
```bash
|
|
@@ -156,6 +167,13 @@ forward_with_lyco = your_model(x)
|
|
|
156
167
|
|
|
157
168
|
You can check my [HakuPhi](https://github.com/KohakuBlueleaf/HakuPhi) project to see how I utilize LyCORIS to finetune the Phi-1.5 models.
|
|
158
169
|
|
|
170
|
+
#### Other method
|
|
171
|
+
|
|
172
|
+
After LyCORIS3.0.0, Parametrize API and Functional API have been added, which provide more different ways on utilizing LyCORIS library.
|
|
173
|
+
|
|
174
|
+
Check API reference for more informations.
|
|
175
|
+
You can also take the [test suites](test/) as a kind of examples.
|
|
176
|
+
|
|
159
177
|
#### Bitsandbytes support
|
|
160
178
|
|
|
161
179
|
See [bnb_example.py](bnb_example.py) for example. Basically as same as standalone wrapper.
|
|
@@ -243,44 +261,61 @@ See [docs/Conversion-scripts.md](docs/Conversion-scripts.md) for more informatio
|
|
|
243
261
|
|
|
244
262
|
For full log, please see [Change.md](Change.md)
|
|
245
263
|
|
|
246
|
-
|
|
264
|
+
### 2024/06/xx update to 3.0.0 - Brand New Functional API, Parametrize API and Module API
|
|
247
265
|
|
|
248
|
-
####
|
|
266
|
+
#### The reasons of 3.0.0
|
|
249
267
|
|
|
250
|
-
|
|
251
|
-
* Ref: [DoRA: Weight-Decomposed Low-Rank Adaptation](https://github.com/KohakuBlueleaf/LyCORIS)
|
|
252
|
-
* Weight decompose for LoHa and LoKr. (A.K.A DoHa/DoKr)
|
|
253
|
-
* DoRA/DoHa/DoKr will require smaller Learning rate!
|
|
268
|
+
We reconstruct the whole library with new Class definition and brand new Functional API system.
|
|
254
269
|
|
|
255
|
-
|
|
270
|
+
We also removed lot of redundant/unused modules.
|
|
256
271
|
|
|
257
|
-
|
|
258
|
-
* LoHa will require 2xFLOPs since we rebuild full diff weight and then do one more forward.
|
|
259
|
-
* LoKr, OFT, BOFT should be more efficient than LoHa in bypass mode.
|
|
260
|
-
* Support [bnb 8bit/4bit Linear layer](https://github.com/TimDettmers/bitsandbytes) (a.k.a. QLyCORIS) with LoHa/LoKr/OFT/BOFT.
|
|
261
|
-
* This will force module to enable bypass mode.
|
|
272
|
+
Since the whole library are changed significantly. We decide to call it 3.0.0 as a new major version.
|
|
262
273
|
|
|
263
|
-
####
|
|
274
|
+
#### Major Changes
|
|
264
275
|
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
276
|
+
* New Module API
|
|
277
|
+
* Add Parametrize API
|
|
278
|
+
* Add Functional API
|
|
279
|
+
* LoCon/LoHa/LoKr/Diag-OFT/BOFT only.
|
|
280
|
+
* Remove optional deps from install_requires
|
|
281
|
+
* Remove lot of redundant/deprecated modules
|
|
282
|
+
* Better testing
|
|
283
|
+
* HunYuan DiT Support ([PR](https://github.com/kohya-ss/sd-scripts/pull/1378) in kohya-ss/sd-scripts)
|
|
284
|
+
|
|
285
|
+
#### Full change log
|
|
286
|
+
|
|
287
|
+
##### New Features
|
|
288
|
+
|
|
289
|
+
* LyCORIS now have consistent API for different algorithm like `bypass_forward_diff` or `get_diff_weight` method. Developers of other project can utilize these API to do more tricks or integrate LyCORIS into their framework more easily.
|
|
290
|
+
* LyCORIS now have parametrize API which utilize `torch.nn.utils.parametrize.register_parametrization` to directly patch individual parameters. Which can be useful for MHA layer or other tricky modules.
|
|
291
|
+
* Currently only support 2~5D tensors. And LyCORIS will pretend these weights are weight of Linear/Conv1,2,3D then send it into LyCORIS modules
|
|
292
|
+
* More native implementation or more detailed control will be added in the future.
|
|
293
|
+
* LyCORIS now have functional API. Developers who prefer functional more than Module things can utilize this feature.
|
|
294
|
+
* Functional API also allow developers who don't want to introduce new dependencies. Just copy-paste the source code and utilizing it. (with Apache-2 License, directly copy-paste is totally allowed)
|
|
295
|
+
* Add support for Conv1d and Conv3d module on LoCon/LoHa/LoKr/Full/OFT/BOFT/GLoRA (not All algo in LyCORIS support them, you may receive error when apply unsopported algo), support inherited module (for example: `LoRACompatibleConv` or `LoRACompatibleLinear` from [`huggingface/diffusers`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/lora.py))
|
|
296
|
+
* HunYuan DiT support.
|
|
297
|
+
|
|
298
|
+
##### Improvements, Fixes, Slight Changes
|
|
299
|
+
|
|
300
|
+
* Drop dependencies related to kohya-ss/sd-scripts:
|
|
301
|
+
* We now take kohya-ss/sd-scripts as optional dependency
|
|
302
|
+
* Which means `transformers`, `diffusers` and anything related to kohya are all optional deps now.
|
|
303
|
+
* The definition of dropout and rank_dropout in each algorithm are changed. Since some concept of original rank_dropout in the lora of kohya-ss/sd-script is hard to applied to other algorithm. We can only design the dropout for each module seperatedly.
|
|
304
|
+
* `apply_max_norm` issue are all fixed.
|
|
305
|
+
* DyLoRA, (IA)^3, GLoRA are all rewritten and support Linear/Conv1,2,3d.
|
|
306
|
+
* (IA)^3, GLoRA, Diag-OFT, BOFT are supported in `create_lycoris_from_weights`
|
|
307
|
+
* `lycoris.kohya.create_network_from_weights` also support them as well.
|
|
308
|
+
* Fix wrong implementation of BOFT.
|
|
309
|
+
* `create_lycoris_from_weights` and `create_network_from_weights` now have correct logging infos.
|
|
310
|
+
* `get_module` and `make_module` are moved into modules' API.
|
|
270
311
|
|
|
271
312
|
## Todo list
|
|
272
313
|
|
|
273
|
-
- [X] Module and Document for using LyCORIS in any other model, Not only SD.
|
|
274
|
-
- [X] Proposition3 in [FedPara](https://arxiv.org/abs/2108.06098)
|
|
275
|
-
* also need custom backward to save the vram
|
|
276
|
-
- [ ] Low rank + sparse representation
|
|
277
|
-
- [X] For extraction
|
|
278
|
-
- [ ] For training
|
|
279
|
-
- [ ] Support more operation, not only linear and conv2d.
|
|
280
|
-
- [X] Configure varying ranks or dimensions for specific modules as needed.
|
|
281
314
|
- [ ] Automatically selecting an algorithm based on the specific rank requirement.
|
|
282
|
-
- [ ] Explore other low-rank representations or parameter-efficient methods to fine-tune either the entire model or specific parts of it.
|
|
283
315
|
- [ ] More experiments for different task, not only diffusion models.
|
|
316
|
+
- [X] LoKr and LoHa have been proven to be useful for Large Language Model.
|
|
317
|
+
- [ ] Explore other low-rank representations or parameter-efficient methods to fine-tune either the entire model or specific parts of it.
|
|
318
|
+
- [ ] Documentation for whole library.
|
|
284
319
|
|
|
285
320
|
## Citation
|
|
286
321
|
|
|
@@ -6,6 +6,7 @@ PRESET = {
|
|
|
6
6
|
"ResnetBlock2D",
|
|
7
7
|
"Downsample2D",
|
|
8
8
|
"Upsample2D",
|
|
9
|
+
"HunYuanDiTBlock",
|
|
9
10
|
],
|
|
10
11
|
"unet_target_name": [
|
|
11
12
|
"conv_in",
|
|
@@ -13,7 +14,12 @@ PRESET = {
|
|
|
13
14
|
"time_embedding.linear_1",
|
|
14
15
|
"time_embedding.linear_2",
|
|
15
16
|
],
|
|
16
|
-
"text_encoder_target_module": [
|
|
17
|
+
"text_encoder_target_module": [
|
|
18
|
+
"CLIPAttention",
|
|
19
|
+
"CLIPMLP",
|
|
20
|
+
"MT5Block",
|
|
21
|
+
"BertLayer",
|
|
22
|
+
],
|
|
17
23
|
"text_encoder_target_name": [],
|
|
18
24
|
},
|
|
19
25
|
"full-lin": {
|
|
@@ -21,30 +27,47 @@ PRESET = {
|
|
|
21
27
|
"unet_target_module": [
|
|
22
28
|
"Transformer2DModel",
|
|
23
29
|
"ResnetBlock2D",
|
|
30
|
+
"HunYuanDiTBlock",
|
|
24
31
|
],
|
|
25
32
|
"unet_target_name": [
|
|
26
33
|
"time_embedding.linear_1",
|
|
27
34
|
"time_embedding.linear_2",
|
|
28
35
|
],
|
|
29
|
-
"text_encoder_target_module": [
|
|
36
|
+
"text_encoder_target_module": [
|
|
37
|
+
"CLIPAttention",
|
|
38
|
+
"CLIPMLP",
|
|
39
|
+
"MT5Block",
|
|
40
|
+
"BertLayer",
|
|
41
|
+
],
|
|
30
42
|
"text_encoder_target_name": [],
|
|
31
43
|
},
|
|
32
44
|
"attn-mlp": {
|
|
33
45
|
"enable_conv": False,
|
|
34
46
|
"unet_target_module": [
|
|
35
47
|
"Transformer2DModel",
|
|
48
|
+
"HunYuanDiTBlock",
|
|
36
49
|
],
|
|
37
50
|
"unet_target_name": [],
|
|
38
|
-
"text_encoder_target_module": [
|
|
51
|
+
"text_encoder_target_module": [
|
|
52
|
+
"CLIPAttention",
|
|
53
|
+
"CLIPMLP",
|
|
54
|
+
"MT5Block",
|
|
55
|
+
"BertLayer",
|
|
56
|
+
],
|
|
39
57
|
"text_encoder_target_name": [],
|
|
40
58
|
},
|
|
41
59
|
"attn-only": {
|
|
42
60
|
"enable_conv": False,
|
|
43
61
|
"unet_target_module": [
|
|
44
62
|
"CrossAttention",
|
|
63
|
+
"SelfAttention",
|
|
45
64
|
],
|
|
46
65
|
"unet_target_name": [],
|
|
47
|
-
"text_encoder_target_module": [
|
|
66
|
+
"text_encoder_target_module": [
|
|
67
|
+
"CLIPAttention",
|
|
68
|
+
"BertAttention",
|
|
69
|
+
"MT5LayerSelfAttention",
|
|
70
|
+
],
|
|
48
71
|
"text_encoder_target_name": [],
|
|
49
72
|
},
|
|
50
73
|
"unet-only": {
|
|
@@ -54,6 +77,7 @@ PRESET = {
|
|
|
54
77
|
"ResnetBlock2D",
|
|
55
78
|
"Downsample2D",
|
|
56
79
|
"Upsample2D",
|
|
80
|
+
"HunYuanDiTBlock",
|
|
57
81
|
],
|
|
58
82
|
"unet_target_name": [
|
|
59
83
|
"conv_in",
|
|
@@ -68,6 +92,7 @@ PRESET = {
|
|
|
68
92
|
"enable_conv": False,
|
|
69
93
|
"unet_target_module": [
|
|
70
94
|
"Transformer2DModel",
|
|
95
|
+
"HunYuanDiTBlock",
|
|
71
96
|
],
|
|
72
97
|
"unet_target_name": [],
|
|
73
98
|
"text_encoder_target_module": [],
|
|
@@ -83,4 +108,15 @@ PRESET = {
|
|
|
83
108
|
"text_encoder_target_module": [],
|
|
84
109
|
"text_encoder_target_name": [],
|
|
85
110
|
},
|
|
111
|
+
"ia3": {
|
|
112
|
+
"enable_conv": False,
|
|
113
|
+
"unet_target_module": [],
|
|
114
|
+
"unet_target_name": ["to_k", "to_v", "ff.net.2"],
|
|
115
|
+
"text_encoder_target_module": [],
|
|
116
|
+
"text_encoder_target_name": ["k_proj", "v_proj", "mlp.fc2"],
|
|
117
|
+
"name_algo_map": {
|
|
118
|
+
"mlp.fc2": {"train_on_input": True},
|
|
119
|
+
"ff.net.2": {"train_on_input": True},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
86
122
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
import torch.nn as nn
|
|
5
|
+
import torch.nn.functional as F
|
|
6
|
+
|
|
7
|
+
from einops import rearrange
|
|
8
|
+
|
|
9
|
+
from .general import power2factorization, FUNC_LIST
|
|
10
|
+
from .diag_oft import get_r
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def weight_gen(org_weight, max_block_size, boft_m=-1, rescale=False):
|
|
14
|
+
"""### boft_weight_gen
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
org_weight (torch.Tensor): the weight tensor
|
|
18
|
+
max_block_size (int): max block size
|
|
19
|
+
rescale (bool, optional): whether to rescale the weight. Defaults to False.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
torch.Tensor: oft_blocks[, rescale_weight]
|
|
23
|
+
"""
|
|
24
|
+
out_dim, *rest = org_weight.shape
|
|
25
|
+
block_size, block_num = power2factorization(out_dim, max_block_size)
|
|
26
|
+
max_boft_m = sum(int(i) for i in f"{block_num-1:b}") + 1
|
|
27
|
+
if boft_m == -1:
|
|
28
|
+
boft_m = max_boft_m
|
|
29
|
+
boft_m = min(boft_m, max_boft_m)
|
|
30
|
+
oft_blocks = torch.zeros(boft_m, block_num, block_size, block_size)
|
|
31
|
+
if rescale is not None:
|
|
32
|
+
return oft_blocks, torch.ones(out_dim, *[1] * len(rest))
|
|
33
|
+
else:
|
|
34
|
+
return oft_blocks, None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
|
|
38
|
+
"""### boft_diff_weight
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
TODO
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
torch.Tensor: ΔW
|
|
45
|
+
"""
|
|
46
|
+
m, num, b, _ = oft_blocks.shape
|
|
47
|
+
r_b = b // 2
|
|
48
|
+
I = torch.eye(b, device=oft_blocks.device)
|
|
49
|
+
r = get_r(oft_blocks, I, constraint)
|
|
50
|
+
inp = org = org_weight.to(dtype=r.dtype)
|
|
51
|
+
|
|
52
|
+
for i in range(m):
|
|
53
|
+
bi = r[i] # b_num, b_size, b_size
|
|
54
|
+
inp = rearrange(inp, "(c g k) ... -> (c k g) ...", g=2, k=2**i * r_b)
|
|
55
|
+
inp = rearrange(inp, "(d b) ... -> d b ...", b=b)
|
|
56
|
+
inp = torch.einsum("b i j, b j ... -> b i ...", bi, inp)
|
|
57
|
+
inp = rearrange(inp, "d b ... -> (d b) ...")
|
|
58
|
+
inp = rearrange(inp, "(c k g) ... -> (c g k) ...", g=2, k=2**i * r_b)
|
|
59
|
+
|
|
60
|
+
if rescale is not None:
|
|
61
|
+
inp = inp * rescale
|
|
62
|
+
|
|
63
|
+
return inp - org
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def bypass_forward_diff(
|
|
67
|
+
org_out, oft_blocks, rescale=None, constraint=None, need_transpose=False
|
|
68
|
+
):
|
|
69
|
+
"""### boft_bypass_forward_diff
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
TODO
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
torch.Tensor: output tensor
|
|
76
|
+
"""
|
|
77
|
+
m, num, b, _ = oft_blocks.shape
|
|
78
|
+
r_b = b // 2
|
|
79
|
+
I = torch.eye(b, device=oft_blocks.device)
|
|
80
|
+
r = get_r(oft_blocks, I, constraint)
|
|
81
|
+
inp = org = org_out.to(dtype=r.dtype)
|
|
82
|
+
if need_transpose:
|
|
83
|
+
inp = org = inp.transpose(1, -1)
|
|
84
|
+
|
|
85
|
+
for i in range(m):
|
|
86
|
+
bi = r[i] # b_num, b_size, b_size
|
|
87
|
+
inp = rearrange(inp, "... (c g k) ->... (c k g)", g=2, k=2**i * r_b)
|
|
88
|
+
inp = rearrange(inp, "... (d b) -> ... d b", b=b)
|
|
89
|
+
inp = torch.einsum("b i j, ... b j -> ... b i", bi, inp)
|
|
90
|
+
inp = rearrange(inp, "... d b -> ... (d b)")
|
|
91
|
+
inp = rearrange(inp, "... (c k g) -> ... (c g k)", g=2, k=2**i * r_b)
|
|
92
|
+
|
|
93
|
+
if rescale is not None:
|
|
94
|
+
inp = inp * rescale.transpose(0, -1)
|
|
95
|
+
|
|
96
|
+
inp = inp - org
|
|
97
|
+
if need_transpose:
|
|
98
|
+
inp = inp.transpose(1, -1)
|
|
99
|
+
return inp
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
import torch.nn as nn
|
|
5
|
+
import torch.nn.functional as F
|
|
6
|
+
|
|
7
|
+
from .general import factorization, FUNC_LIST
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_r(oft_blocks, I=None, constraint=0):
|
|
11
|
+
if I is None:
|
|
12
|
+
I = torch.eye(oft_blocks.shape[-1], device=oft_blocks.device)
|
|
13
|
+
if I.ndim < oft_blocks.ndim:
|
|
14
|
+
for _ in range(oft_blocks.ndim - I.ndim):
|
|
15
|
+
I = I.unsqueeze(0)
|
|
16
|
+
# for Q = -Q^T
|
|
17
|
+
q = oft_blocks - oft_blocks.transpose(-1, -2)
|
|
18
|
+
normed_q = q
|
|
19
|
+
if constraint is not None and constraint > 0:
|
|
20
|
+
q_norm = torch.norm(q) + 1e-8
|
|
21
|
+
if q_norm > constraint:
|
|
22
|
+
normed_q = q * constraint / q_norm
|
|
23
|
+
# use float() to prevent unsupported type
|
|
24
|
+
r = (I + normed_q) @ (I - normed_q).float().inverse()
|
|
25
|
+
return r
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def weight_gen(org_weight, max_block_size, rescale=False):
|
|
29
|
+
"""### weight_gen
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
org_weight (torch.Tensor): the weight tensor
|
|
33
|
+
max_block_size (int): max block size
|
|
34
|
+
rescale (bool, optional): whether to rescale the weight. Defaults to False.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
torch.Tensor: oft_blocks[, rescale_weight]
|
|
38
|
+
"""
|
|
39
|
+
out_dim, *rest = org_weight.shape
|
|
40
|
+
block_size, block_num = factorization(out_dim, max_block_size)
|
|
41
|
+
oft_blocks = torch.zeros(block_num, block_size, block_size)
|
|
42
|
+
if rescale:
|
|
43
|
+
return oft_blocks, torch.ones(out_dim, *[1] * len(rest))
|
|
44
|
+
else:
|
|
45
|
+
return oft_blocks, None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
|
|
49
|
+
"""### diff_weight
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
TODO
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
torch.Tensor: ΔW
|
|
56
|
+
"""
|
|
57
|
+
I = torch.eye(oft_blocks.shape[1], device=oft_blocks.device)
|
|
58
|
+
r = get_r(oft_blocks, I, constraint)
|
|
59
|
+
|
|
60
|
+
block_num, block_size, _ = oft_blocks.shape
|
|
61
|
+
_, *shape = org_weight.shape
|
|
62
|
+
org_weight = org_weight.to(dtype=r.dtype)
|
|
63
|
+
org_weight = org_weight.view(block_num, block_size, *shape)
|
|
64
|
+
# Init R=0, so add I on it to ensure the output of step0 is original model output
|
|
65
|
+
weight = torch.einsum(
|
|
66
|
+
"k n m, k n ... -> k m ...",
|
|
67
|
+
r - I,
|
|
68
|
+
org_weight,
|
|
69
|
+
).view(-1, *shape)
|
|
70
|
+
if rescale is not None:
|
|
71
|
+
weight = rescale * weight
|
|
72
|
+
weight = weight + (rescale - 1) * org_weight
|
|
73
|
+
return weight
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def bypass_forward_diff(
|
|
77
|
+
org_out, oft_blocks, rescale=None, constraint=None, need_transpose=False
|
|
78
|
+
):
|
|
79
|
+
"""### bypass_forward_diff
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
TODO
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
torch.Tensor: output tensor
|
|
86
|
+
"""
|
|
87
|
+
block_num, block_size, _ = oft_blocks.shape
|
|
88
|
+
I = torch.eye(block_size, device=oft_blocks.device)
|
|
89
|
+
r = get_r(oft_blocks, I, constraint)
|
|
90
|
+
if need_transpose:
|
|
91
|
+
org_out = org_out.transpose(1, -1)
|
|
92
|
+
org_out = org_out.to(dtype=r.dtype)
|
|
93
|
+
*shape, _ = org_out.shape
|
|
94
|
+
oft_out = torch.einsum(
|
|
95
|
+
"k n m, ... k n -> ... k m", r - I, org_out.view(*shape, block_num, block_size)
|
|
96
|
+
)
|
|
97
|
+
out = oft_out.view(*shape, -1)
|
|
98
|
+
if rescale is not None:
|
|
99
|
+
out = rescale.transpose(-1, 0) * out
|
|
100
|
+
out = out + (rescale - 1).transpose(-1, 0) * org_out
|
|
101
|
+
if need_transpose:
|
|
102
|
+
out = out.transpose(1, -1)
|
|
103
|
+
return out
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import torch.nn as nn
|
|
3
|
+
import torch.nn.functional as F
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
FUNC_LIST = [None, None, F.linear, F.conv1d, F.conv2d, F.conv3d]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def rebuild_tucker(t, wa, wb):
|
|
10
|
+
rebuild2 = torch.einsum("i j ..., i p, j r -> p r ...", t, wa, wb)
|
|
11
|
+
return rebuild2
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def factorization(dimension: int, factor: int = -1) -> tuple[int, int]:
|
|
15
|
+
"""
|
|
16
|
+
return a tuple of two value of input dimension decomposed by the number closest to factor
|
|
17
|
+
second value is higher or equal than first value.
|
|
18
|
+
|
|
19
|
+
In LoRA with Kroneckor Product, first value is a value for weight scale.
|
|
20
|
+
second value is a value for weight.
|
|
21
|
+
|
|
22
|
+
Because of non-commutative property, A⊗B ≠ B⊗A. Meaning of two matrices is slightly different.
|
|
23
|
+
|
|
24
|
+
examples)
|
|
25
|
+
factor
|
|
26
|
+
-1 2 4 8 16 ...
|
|
27
|
+
127 -> 1, 127 127 -> 1, 127 127 -> 1, 127 127 -> 1, 127 127 -> 1, 127
|
|
28
|
+
128 -> 8, 16 128 -> 2, 64 128 -> 4, 32 128 -> 8, 16 128 -> 8, 16
|
|
29
|
+
250 -> 10, 25 250 -> 2, 125 250 -> 2, 125 250 -> 5, 50 250 -> 10, 25
|
|
30
|
+
360 -> 8, 45 360 -> 2, 180 360 -> 4, 90 360 -> 8, 45 360 -> 12, 30
|
|
31
|
+
512 -> 16, 32 512 -> 2, 256 512 -> 4, 128 512 -> 8, 64 512 -> 16, 32
|
|
32
|
+
1024 -> 32, 32 1024 -> 2, 512 1024 -> 4, 256 1024 -> 8, 128 1024 -> 16, 64
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
if factor > 0 and (dimension % factor) == 0:
|
|
36
|
+
m = factor
|
|
37
|
+
n = dimension // factor
|
|
38
|
+
if m > n:
|
|
39
|
+
n, m = m, n
|
|
40
|
+
return m, n
|
|
41
|
+
if factor < 0:
|
|
42
|
+
factor = dimension
|
|
43
|
+
m, n = 1, dimension
|
|
44
|
+
length = m + n
|
|
45
|
+
while m < n:
|
|
46
|
+
new_m = m + 1
|
|
47
|
+
while dimension % new_m != 0:
|
|
48
|
+
new_m += 1
|
|
49
|
+
new_n = dimension // new_m
|
|
50
|
+
if new_m + new_n > length or new_m > factor:
|
|
51
|
+
break
|
|
52
|
+
else:
|
|
53
|
+
m, n = new_m, new_n
|
|
54
|
+
if m > n:
|
|
55
|
+
n, m = m, n
|
|
56
|
+
return m, n
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def power2factorization(dimension: int, factor: int = -1) -> tuple[int, int]:
|
|
60
|
+
"""
|
|
61
|
+
m = 2k
|
|
62
|
+
n = 2**p
|
|
63
|
+
m*n = dim
|
|
64
|
+
"""
|
|
65
|
+
if factor == -1:
|
|
66
|
+
factor = dimension
|
|
67
|
+
|
|
68
|
+
# Find the first solution and check if it is even doable
|
|
69
|
+
m = n = 0
|
|
70
|
+
while m <= factor:
|
|
71
|
+
m += 2
|
|
72
|
+
while dimension % m != 0 and m < dimension:
|
|
73
|
+
m += 2
|
|
74
|
+
if m > factor:
|
|
75
|
+
break
|
|
76
|
+
if sum(int(i) for i in f"{dimension//m:b}") == 1:
|
|
77
|
+
n = dimension // m
|
|
78
|
+
|
|
79
|
+
return dimension // n, n
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def tucker_weight_from_conv(up, down, mid):
|
|
83
|
+
up = up.reshape(up.size(0), up.size(1))
|
|
84
|
+
down = down.reshape(down.size(0), down.size(1))
|
|
85
|
+
return torch.einsum("m n ..., i m, n j -> i j ...", mid, up, down)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def tucker_weight(wa, wb, t):
|
|
89
|
+
temp = torch.einsum("i j ..., j r -> i r ...", t, wb)
|
|
90
|
+
return torch.einsum("i j ..., i r -> r j ...", temp, wa)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def apply_dora_scale(org_weight, rebuild, dora_scale, scale):
|
|
94
|
+
dora_norm_dims = org_weight.dim() - 1
|
|
95
|
+
weight = org_weight + rebuild
|
|
96
|
+
weight = weight.to(dora_scale.dtype)
|
|
97
|
+
weight_norm = (
|
|
98
|
+
weight.transpose(0, 1)
|
|
99
|
+
.reshape(weight.shape[1], -1)
|
|
100
|
+
.norm(dim=1, keepdim=True)
|
|
101
|
+
.reshape(weight.shape[1], *[1] * dora_norm_dims)
|
|
102
|
+
.transpose(0, 1)
|
|
103
|
+
)
|
|
104
|
+
merged_scale1 = weight / weight_norm * dora_scale
|
|
105
|
+
diff_weight = merged_scale1 - org_weight
|
|
106
|
+
return org_weight + diff_weight * scale
|