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.
Files changed (73) hide show
  1. lycoris_lora-3.0.0/PKG-INFO +25 -0
  2. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/README.md +76 -41
  3. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/__init__.py +4 -1
  4. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/config.py +40 -4
  5. lycoris_lora-3.0.0/lycoris/functional/__init__.py +9 -0
  6. lycoris_lora-3.0.0/lycoris/functional/boft.py +99 -0
  7. lycoris_lora-3.0.0/lycoris/functional/diag_oft.py +103 -0
  8. lycoris_lora-3.0.0/lycoris/functional/general.py +106 -0
  9. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/functional/locon.py +13 -35
  10. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/functional/loha.py +53 -38
  11. lycoris_lora-3.0.0/lycoris/functional/lokr.py +240 -0
  12. lycoris_lora-2.3.0.dev11/lycoris/kohya/__init__.py → lycoris_lora-3.0.0/lycoris/kohya.py +83 -346
  13. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/logging.py +16 -0
  14. lycoris_lora-3.0.0/lycoris/modules/__init__.py +46 -0
  15. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/base.py +93 -2
  16. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/boft.py +66 -70
  17. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/diag_oft.py +62 -56
  18. lycoris_lora-3.0.0/lycoris/modules/dylora.py +157 -0
  19. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/full.py +69 -22
  20. lycoris_lora-3.0.0/lycoris/modules/glora.py +263 -0
  21. lycoris_lora-3.0.0/lycoris/modules/ia3.py +143 -0
  22. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/locon.py +54 -45
  23. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/loha.py +53 -40
  24. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/modules/lokr.py +221 -141
  25. lycoris_lora-3.0.0/lycoris/modules/norms.py +159 -0
  26. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/__init__.py +51 -208
  27. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/bnb.py +3 -0
  28. lycoris_lora-3.0.0/lycoris/utils/general.py +5 -0
  29. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/wrapper.py +46 -48
  30. lycoris_lora-3.0.0/lycoris_lora.egg-info/PKG-INFO +25 -0
  31. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/SOURCES.txt +10 -19
  32. lycoris_lora-3.0.0/lycoris_lora.egg-info/requires.txt +4 -0
  33. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/top_level.txt +1 -0
  34. lycoris_lora-3.0.0/setup.py +29 -0
  35. lycoris_lora-3.0.0/test/__init__.py +0 -0
  36. lycoris_lora-3.0.0/test/functional.py +87 -0
  37. lycoris_lora-3.0.0/test/module.py +181 -0
  38. lycoris_lora-3.0.0/test/wrapper.py +128 -0
  39. lycoris_lora-2.3.0.dev11/PKG-INFO +0 -15
  40. lycoris_lora-2.3.0.dev11/lycoris/functional/__init__.py +0 -4
  41. lycoris_lora-2.3.0.dev11/lycoris/functional/general.py +0 -8
  42. lycoris_lora-2.3.0.dev11/lycoris/hcp/__init__.py +0 -4
  43. lycoris_lora-2.3.0.dev11/lycoris/hcp/base.py +0 -153
  44. lycoris_lora-2.3.0.dev11/lycoris/hcp/diag_oft.py +0 -62
  45. lycoris_lora-2.3.0.dev11/lycoris/hcp/loha.py +0 -85
  46. lycoris_lora-2.3.0.dev11/lycoris/hcp/lokr.py +0 -131
  47. lycoris_lora-2.3.0.dev11/lycoris/kohya/model_utils.py +0 -1633
  48. lycoris_lora-2.3.0.dev11/lycoris/kohya/original_unet.py +0 -1760
  49. lycoris_lora-2.3.0.dev11/lycoris/kohya/sdxl_model_util.py +0 -581
  50. lycoris_lora-2.3.0.dev11/lycoris/kohya/sdxl_original_unet.py +0 -1243
  51. lycoris_lora-2.3.0.dev11/lycoris/kohya/test_hyperdream.py +0 -527
  52. lycoris_lora-2.3.0.dev11/lycoris/kohya/utils.py +0 -48
  53. lycoris_lora-2.3.0.dev11/lycoris/modules/__init__.py +0 -137
  54. lycoris_lora-2.3.0.dev11/lycoris/modules/attention.py +0 -259
  55. lycoris_lora-2.3.0.dev11/lycoris/modules/dylora.py +0 -132
  56. lycoris_lora-2.3.0.dev11/lycoris/modules/glokr.py +0 -310
  57. lycoris_lora-2.3.0.dev11/lycoris/modules/glora.py +0 -136
  58. lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/__init__.py +0 -1
  59. lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/generater.py +0 -223
  60. lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/text_encoder.py +0 -266
  61. lycoris_lora-2.3.0.dev11/lycoris/modules/ia3.py +0 -67
  62. lycoris_lora-2.3.0.dev11/lycoris/modules/lilora.py +0 -339
  63. lycoris_lora-2.3.0.dev11/lycoris/modules/norms.py +0 -70
  64. lycoris_lora-2.3.0.dev11/lycoris_lora.egg-info/PKG-INFO +0 -15
  65. lycoris_lora-2.3.0.dev11/lycoris_lora.egg-info/requires.txt +0 -6
  66. lycoris_lora-2.3.0.dev11/setup.py +0 -22
  67. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/LICENSE.md +0 -0
  68. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/logger.py +0 -0
  69. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/preset.py +0 -0
  70. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris/utils/xformers_utils.py +0 -0
  71. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  72. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0}/lycoris_lora.egg-info/not-zip-safe +0 -0
  73. {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
+ ![pypi](https://img.shields.io/pypi/v/lycoris-lora.svg)
3
+ ![versions](https://img.shields.io/pypi/pyversions/lycoris-lora.svg)
4
+ ![PyPI - License](https://img.shields.io/pypi/l/lycoris-lora)
5
+ ![downloads](https://img.shields.io/pypi/dm/lycoris-lora)
6
+ ![commits](https://img.shields.io/github/commit-activity/m/KohakuBlueleaf/LyCORIS/dev)
7
+ ![Discord](https://img.shields.io/discord/1082218577395986452)
8
+
9
+
1
10
  # LyCORIS - Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion. (ICLR'24)
2
11
 
3
- ![banner image](docs/images/banner.png)
12
+ ![banner image](docs/images/banner2.png)
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. <br>
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 <br>
37
- $^†$ It may become more difficult to switch base model or combine multiple concepts in this situation <br>
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 [HCP-Diffusion](https://github.com/IrisRainbowNeko/HCP-Diffusion)
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 lycoris_lora
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
- ## 2024/03/15 update to 2.2.0 - QLyCORIS and DoRA
264
+ ### 2024/06/xx update to 3.0.0 - Brand New Functional API, Parametrize API and Module API
247
265
 
248
- #### New Algo
266
+ #### The reasons of 3.0.0
249
267
 
250
- * DoRA
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
- #### New Features
270
+ We also removed lot of redundant/unused modules.
256
271
 
257
- * Support "bypass" (a.k.a. adapter) mode for LoHa/LoKr/OFT/BOFT
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
- #### Fixes, slight changes
274
+ #### Major Changes
264
275
 
265
- * Refine some details about code quality. Based on the report from GitRoll. (Thx you gitroll!)
266
- * Remove redundant calculation in BOFT
267
- * rank_dropout has been removed from OFT/BOFT temporarily untill we ensure how to apply it.
268
- * Fix bugs in lokr when `lokr_w1_a` not exist.
269
- * Fix bugs in conversion scritps.
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
 
@@ -1,5 +1,8 @@
1
+ try:
2
+ from . import kohya
3
+ except:
4
+ pass
1
5
  from . import (
2
- kohya,
3
6
  modules,
4
7
  utils,
5
8
  )
@@ -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": ["CLIPAttention", "CLIPMLP"],
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": ["CLIPAttention", "CLIPMLP"],
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": ["CLIPAttention", "CLIPMLP"],
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": ["CLIPAttention"],
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,9 @@
1
+ from .general import (
2
+ rebuild_tucker,
3
+ factorization,
4
+ power2factorization,
5
+ FUNC_LIST,
6
+ tucker_weight,
7
+ tucker_weight_from_conv,
8
+ apply_dora_scale,
9
+ )
@@ -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