lycoris-lora 2.1.0.dev8__tar.gz → 2.1.0.dev9__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.1.0.dev8 → lycoris_lora-2.1.0.dev9}/PKG-INFO +1 -1
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/__init__.py +2 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/kohya/__init__.py +39 -39
- lycoris_lora-2.1.0.dev9/lycoris/logging.py +36 -0
- lycoris_lora-2.1.0.dev9/lycoris/modules/boft.py +211 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/wrapper.py +17 -17
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/PKG-INFO +1 -1
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/SOURCES.txt +2 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/setup.py +1 -1
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/LICENSE.md +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/README.md +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/config.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/hcp/__init__.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/hcp/base.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/hcp/diag_oft.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/hcp/loha.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/hcp/lokr.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/kohya/model_utils.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/kohya/original_unet.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/kohya/sdxl_model_util.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/kohya/sdxl_original_unet.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/kohya/utils.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/__init__.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/attention.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/base.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/diag_oft.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/dylora.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/full.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/glokr.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/glora.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/hypernet/__init__.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/hypernet/generater.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/hypernet/text_encoder.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/ia3.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/locon.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/loha.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/lokr.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/norms.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/utils/__init__.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/utils/logger.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/utils/preset.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/utils/xformers_utils.py +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/dependency_links.txt +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/not-zip-safe +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/requires.txt +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/top_level.txt +0 -0
- {lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lycoris_lora
|
|
3
|
-
Version: 2.1.0.
|
|
3
|
+
Version: 2.1.0.dev9
|
|
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
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
9
|
import sys
|
|
10
|
-
from warnings import warn
|
|
11
10
|
from typing import List
|
|
12
11
|
|
|
13
12
|
sys.setrecursionlimit(10000)
|
|
@@ -26,11 +25,13 @@ from ..modules.glora import GLoRAModule
|
|
|
26
25
|
from ..modules.norms import NormModule
|
|
27
26
|
from ..modules.full import FullModule
|
|
28
27
|
from ..modules.diag_oft import DiagOFTModule
|
|
28
|
+
from ..modules.boft import ButterflyOFTModule
|
|
29
29
|
from ..modules import make_module
|
|
30
30
|
|
|
31
31
|
from ..config import PRESET
|
|
32
32
|
from ..utils.preset import read_preset
|
|
33
33
|
from ..utils import get_module, str_bool
|
|
34
|
+
from ..logging import logger
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
network_module_dict = {
|
|
@@ -43,6 +44,7 @@ network_module_dict = {
|
|
|
43
44
|
"glora": GLoRAModule,
|
|
44
45
|
"full": FullModule,
|
|
45
46
|
"diag-oft": DiagOFTModule,
|
|
47
|
+
"boft": ButterflyOFTModule,
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
|
|
@@ -64,7 +66,7 @@ def create_network(
|
|
|
64
66
|
or kwargs.get("use_tucker", False)
|
|
65
67
|
)
|
|
66
68
|
if "disable_conv_cp" in kwargs or "use_cp" in kwargs or "use_conv_cp" in kwargs:
|
|
67
|
-
|
|
69
|
+
logger.warning(
|
|
68
70
|
"disable_conv_cp and use_cp are deprecated. Please use use_tucker instead.",
|
|
69
71
|
stacklevel=2,
|
|
70
72
|
)
|
|
@@ -76,7 +78,7 @@ def create_network(
|
|
|
76
78
|
|
|
77
79
|
if algo == "glora" and conv_dim > 0:
|
|
78
80
|
conv_dim = 0
|
|
79
|
-
|
|
81
|
+
logger.info("Disable conv layer for GLoRA")
|
|
80
82
|
|
|
81
83
|
preset = kwargs.get("preset", "full")
|
|
82
84
|
if preset not in PRESET:
|
|
@@ -86,22 +88,20 @@ def create_network(
|
|
|
86
88
|
assert preset is not None
|
|
87
89
|
LycorisNetworkKohya.apply_preset(preset)
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
logger.info(f"Using rank adaptation algo: {algo}")
|
|
90
92
|
|
|
91
93
|
if (
|
|
92
94
|
(algo == "loha")
|
|
93
95
|
and not kwargs.get("no_dim_warn", False)
|
|
94
96
|
and (network_dim > 64 or conv_dim > 64)
|
|
95
97
|
):
|
|
96
|
-
print("=" * 20 + "WARNING" + "=" * 20)
|
|
97
98
|
warning_type = {"loha": "Hadamard Product representation"}
|
|
98
99
|
warning_msg = f"""You are not supposed to use dim>64 (64*64 = 4096, it already has enough rank)\n
|
|
99
100
|
in {warning_type[algo]}!\n
|
|
100
101
|
Please consider use lower dim or disable this warning with --network_args no_dim_warn=True\n
|
|
101
102
|
If you just want to use high dim {algo}, please consider use lower lr.
|
|
102
103
|
"""
|
|
103
|
-
|
|
104
|
-
print("=" * 20 + "WARNING" + "=" * 20)
|
|
104
|
+
logger.warning(warning_msg, stacklevel=2)
|
|
105
105
|
|
|
106
106
|
if algo == "ia3":
|
|
107
107
|
network = IA3Network(
|
|
@@ -241,7 +241,7 @@ def create_hypernetwork(
|
|
|
241
241
|
or kwargs.get("use_tucker", False)
|
|
242
242
|
)
|
|
243
243
|
if "disable_conv_cp" in kwargs or "use_cp" in kwargs or "use_conv_cp" in kwargs:
|
|
244
|
-
|
|
244
|
+
logger.warning(
|
|
245
245
|
"disable_conv_cp and use_cp are deprecated. Please use use_tucker instead.",
|
|
246
246
|
stacklevel=2,
|
|
247
247
|
)
|
|
@@ -255,7 +255,7 @@ def create_hypernetwork(
|
|
|
255
255
|
"locon": LoConModule,
|
|
256
256
|
}[algo]
|
|
257
257
|
|
|
258
|
-
|
|
258
|
+
logger.info(f"Using rank adaptation algo: {algo}")
|
|
259
259
|
|
|
260
260
|
return HyperDreamNetwork(
|
|
261
261
|
text_encoder,
|
|
@@ -353,19 +353,19 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
353
353
|
|
|
354
354
|
self.conv_lora_dim = int(conv_lora_dim)
|
|
355
355
|
if self.conv_lora_dim and self.conv_lora_dim != self.lora_dim:
|
|
356
|
-
|
|
357
|
-
|
|
356
|
+
logger.info("Apply different lora dim for conv layer")
|
|
357
|
+
logger.info(f"Conv Dim: {conv_lora_dim}, Linear Dim: {lora_dim}")
|
|
358
358
|
elif self.conv_lora_dim == 0:
|
|
359
|
-
|
|
359
|
+
logger.info("Disable conv layer")
|
|
360
360
|
|
|
361
361
|
self.alpha = alpha
|
|
362
362
|
self.conv_alpha = float(conv_alpha)
|
|
363
363
|
if self.conv_lora_dim and self.alpha != self.conv_alpha:
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
logger.info("Apply different alpha value for conv layer")
|
|
365
|
+
logger.info(f"Conv alpha: {conv_alpha}, Linear alpha: {alpha}")
|
|
366
366
|
|
|
367
367
|
if 1 >= dropout >= 0:
|
|
368
|
-
|
|
368
|
+
logger.info(f"Use Dropout value: {dropout}")
|
|
369
369
|
self.dropout = dropout
|
|
370
370
|
self.rank_dropout = rank_dropout
|
|
371
371
|
self.module_dropout = module_dropout
|
|
@@ -466,7 +466,7 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
466
466
|
target_replace_modules,
|
|
467
467
|
target_replace_names=[],
|
|
468
468
|
) -> List:
|
|
469
|
-
|
|
469
|
+
logger.info("Create LyCORIS Module")
|
|
470
470
|
loras = []
|
|
471
471
|
next_config = {}
|
|
472
472
|
for name, module in root_module.named_modules():
|
|
@@ -503,7 +503,7 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
503
503
|
return loras
|
|
504
504
|
|
|
505
505
|
if network_module == GLoRAModule:
|
|
506
|
-
|
|
506
|
+
logger.info("GLoRA enabled, only train transformer")
|
|
507
507
|
# only train transformer (for GLoRA)
|
|
508
508
|
LycorisNetworkKohya.UNET_TARGET_REPLACE_MODULE = [
|
|
509
509
|
"Transformer2DModel",
|
|
@@ -529,7 +529,7 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
529
529
|
LycorisNetworkKohya.TEXT_ENCODER_TARGET_REPLACE_NAME,
|
|
530
530
|
)
|
|
531
531
|
)
|
|
532
|
-
|
|
532
|
+
logger.info(
|
|
533
533
|
f"create LyCORIS for Text Encoder: {len(self.text_encoder_loras)} modules."
|
|
534
534
|
)
|
|
535
535
|
|
|
@@ -539,14 +539,14 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
539
539
|
LycorisNetworkKohya.UNET_TARGET_REPLACE_MODULE,
|
|
540
540
|
LycorisNetworkKohya.UNET_TARGET_REPLACE_NAME,
|
|
541
541
|
)
|
|
542
|
-
|
|
542
|
+
logger.info(f"create LyCORIS for U-Net: {len(self.unet_loras)} modules.")
|
|
543
543
|
|
|
544
544
|
algo_table = {}
|
|
545
545
|
for lora in self.text_encoder_loras + self.unet_loras:
|
|
546
546
|
algo_table[lora.__class__.__name__] = (
|
|
547
547
|
algo_table.get(lora.__class__.__name__, 0) + 1
|
|
548
548
|
)
|
|
549
|
-
|
|
549
|
+
logger.info(f"module type table: {algo_table}")
|
|
550
550
|
|
|
551
551
|
self.weights_sd = None
|
|
552
552
|
|
|
@@ -580,12 +580,12 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
580
580
|
), f"internal error: flag not set"
|
|
581
581
|
|
|
582
582
|
if apply_text_encoder:
|
|
583
|
-
|
|
583
|
+
logger.info("enable LyCORIS for text encoder")
|
|
584
584
|
else:
|
|
585
585
|
self.text_encoder_loras = []
|
|
586
586
|
|
|
587
587
|
if apply_unet:
|
|
588
|
-
|
|
588
|
+
logger.info("enable LyCORIS for U-Net")
|
|
589
589
|
else:
|
|
590
590
|
self.unet_loras = []
|
|
591
591
|
|
|
@@ -598,7 +598,7 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
598
598
|
if self.weights_sd:
|
|
599
599
|
# if some weights are not in state dict, it is ok because initial LoRA does nothing (lora_up is initialized by zeros)
|
|
600
600
|
info = self.load_state_dict(self.weights_sd, False)
|
|
601
|
-
|
|
601
|
+
logger.info(f"weights are loaded: {info}")
|
|
602
602
|
|
|
603
603
|
# TODO refactor to common function with apply_to
|
|
604
604
|
def merge_to(self, text_encoder, unet, weights_sd, dtype, device):
|
|
@@ -610,12 +610,12 @@ class LycorisNetworkKohya(LycorisNetwork):
|
|
|
610
610
|
apply_unet = True
|
|
611
611
|
|
|
612
612
|
if apply_text_encoder:
|
|
613
|
-
|
|
613
|
+
logger.info("enable LoRA for text encoder")
|
|
614
614
|
else:
|
|
615
615
|
self.text_encoder_loras = []
|
|
616
616
|
|
|
617
617
|
if apply_unet:
|
|
618
|
-
|
|
618
|
+
logger.info("enable LoRA for U-Net")
|
|
619
619
|
else:
|
|
620
620
|
self.unet_loras = []
|
|
621
621
|
|
|
@@ -717,12 +717,12 @@ class HyperDreamNetwork(torch.nn.Module):
|
|
|
717
717
|
self.alpha = alpha
|
|
718
718
|
|
|
719
719
|
if 1 >= dropout >= 0:
|
|
720
|
-
|
|
720
|
+
logger.info(f"Use Dropout value: {dropout}")
|
|
721
721
|
if network_module != LoConModule:
|
|
722
|
-
|
|
722
|
+
logger.info("HyperDreamBooth only support LoRA at this time")
|
|
723
723
|
raise NotImplementedError
|
|
724
724
|
if lora_dim * (down_dim + up_dim) > 4096:
|
|
725
|
-
|
|
725
|
+
logger.info(
|
|
726
726
|
"weight elements > 4096 (dim * (down_dim + up_dim)) is not recommended!"
|
|
727
727
|
)
|
|
728
728
|
|
|
@@ -737,7 +737,7 @@ class HyperDreamNetwork(torch.nn.Module):
|
|
|
737
737
|
target_replace_modules,
|
|
738
738
|
target_replace_names=[],
|
|
739
739
|
) -> List[network_module]:
|
|
740
|
-
|
|
740
|
+
logger.info("Create LyCORIS Module")
|
|
741
741
|
loras = []
|
|
742
742
|
for name, module in root_module.named_modules():
|
|
743
743
|
if module.__class__.__name__ in target_replace_modules:
|
|
@@ -832,7 +832,7 @@ class HyperDreamNetwork(torch.nn.Module):
|
|
|
832
832
|
LycorisNetworkKohya.TEXT_ENCODER_TARGET_REPLACE_MODULE,
|
|
833
833
|
)
|
|
834
834
|
)
|
|
835
|
-
|
|
835
|
+
logger.info(
|
|
836
836
|
f"create LyCORIS for Text Encoder: "
|
|
837
837
|
f"{len(self.text_encoder_loras)} modules."
|
|
838
838
|
)
|
|
@@ -842,7 +842,7 @@ class HyperDreamNetwork(torch.nn.Module):
|
|
|
842
842
|
unet,
|
|
843
843
|
LycorisNetworkKohya.UNET_TARGET_REPLACE_MODULE,
|
|
844
844
|
)
|
|
845
|
-
|
|
845
|
+
logger.info(f"create LyCORIS for U-Net: {len(self.unet_loras)} modules.")
|
|
846
846
|
|
|
847
847
|
self.loras: list[LoConModule] = self.text_encoder_loras + self.unet_loras
|
|
848
848
|
self.img_weight_generater = ImgWeightGenerator(
|
|
@@ -968,12 +968,12 @@ class HyperDreamNetwork(torch.nn.Module):
|
|
|
968
968
|
), f"internal error: flag not set"
|
|
969
969
|
|
|
970
970
|
if apply_text_encoder:
|
|
971
|
-
|
|
971
|
+
logger.info("enable LyCORIS for text encoder")
|
|
972
972
|
else:
|
|
973
973
|
self.text_encoder_loras = []
|
|
974
974
|
|
|
975
975
|
if apply_unet:
|
|
976
|
-
|
|
976
|
+
logger.info("enable LyCORIS for U-Net")
|
|
977
977
|
else:
|
|
978
978
|
self.unet_loras = []
|
|
979
979
|
|
|
@@ -1125,7 +1125,7 @@ class IA3Network(torch.nn.Module):
|
|
|
1125
1125
|
target_replace_names=[],
|
|
1126
1126
|
target_train_input=[],
|
|
1127
1127
|
) -> List[IA3Module]:
|
|
1128
|
-
|
|
1128
|
+
logger.info("Create LyCORIS Module")
|
|
1129
1129
|
loras = []
|
|
1130
1130
|
for name, module in root_module.named_modules():
|
|
1131
1131
|
if module.__class__.__name__ in target_replace_modules:
|
|
@@ -1174,7 +1174,7 @@ class IA3Network(torch.nn.Module):
|
|
|
1174
1174
|
IA3Network.TRAIN_INPUT,
|
|
1175
1175
|
)
|
|
1176
1176
|
)
|
|
1177
|
-
|
|
1177
|
+
logger.info(
|
|
1178
1178
|
f"create LyCORIS for Text Encoder: {len(self.text_encoder_loras)} modules."
|
|
1179
1179
|
)
|
|
1180
1180
|
|
|
@@ -1185,7 +1185,7 @@ class IA3Network(torch.nn.Module):
|
|
|
1185
1185
|
IA3Network.UNET_TARGET_REPLACE_NAME,
|
|
1186
1186
|
IA3Network.TRAIN_INPUT,
|
|
1187
1187
|
)
|
|
1188
|
-
|
|
1188
|
+
logger.info(f"create LyCORIS for U-Net: {len(self.unet_loras)} modules.")
|
|
1189
1189
|
|
|
1190
1190
|
self.weights_sd = None
|
|
1191
1191
|
|
|
@@ -1238,12 +1238,12 @@ class IA3Network(torch.nn.Module):
|
|
|
1238
1238
|
), f"internal error: flag not set"
|
|
1239
1239
|
|
|
1240
1240
|
if apply_text_encoder:
|
|
1241
|
-
|
|
1241
|
+
logger.info("enable LyCORIS for text encoder")
|
|
1242
1242
|
else:
|
|
1243
1243
|
self.text_encoder_loras = []
|
|
1244
1244
|
|
|
1245
1245
|
if apply_unet:
|
|
1246
|
-
|
|
1246
|
+
logger.info("enable LyCORIS for U-Net")
|
|
1247
1247
|
else:
|
|
1248
1248
|
self.unet_loras = []
|
|
1249
1249
|
|
|
@@ -1254,7 +1254,7 @@ class IA3Network(torch.nn.Module):
|
|
|
1254
1254
|
if self.weights_sd:
|
|
1255
1255
|
# if some weights are not in state dict, it is ok because initial LoRA does nothing (lora_up is initialized by zeros)
|
|
1256
1256
|
info = self.load_state_dict(self.weights_sd, False)
|
|
1257
|
-
|
|
1257
|
+
logger.info(f"weights are loaded: {info}")
|
|
1258
1258
|
|
|
1259
1259
|
def enable_gradient_checkpointing(self):
|
|
1260
1260
|
# not supported
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import copy
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ColoredFormatter(logging.Formatter):
|
|
7
|
+
COLORS = {
|
|
8
|
+
"DEBUG": "\033[0;36m", # CYAN
|
|
9
|
+
"INFO": "\033[0;32m", # GREEN
|
|
10
|
+
"WARNING": "\033[0;33m", # YELLOW
|
|
11
|
+
"ERROR": "\033[0;31m", # RED
|
|
12
|
+
"CRITICAL": "\033[0;37;41m", # WHITE ON RED
|
|
13
|
+
"RESET": "\033[0m", # RESET COLOR
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
def format(self, record):
|
|
17
|
+
colored_record = copy.copy(record)
|
|
18
|
+
levelname = colored_record.levelname
|
|
19
|
+
seq = self.COLORS.get(levelname, self.COLORS["RESET"])
|
|
20
|
+
colored_record.levelname = f"{seq}{levelname}{self.COLORS['RESET']}"
|
|
21
|
+
return super().format(colored_record)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger("LyCORIS")
|
|
25
|
+
logger.propagate = False
|
|
26
|
+
logger.setLevel(logging.INFO)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if not logger.handlers:
|
|
30
|
+
handler = logging.StreamHandler(sys.stdout)
|
|
31
|
+
handler.setFormatter(
|
|
32
|
+
ColoredFormatter(
|
|
33
|
+
"%(asctime)s|[%(name)s]-%(levelname)s: %(message)s", "%Y-%m-%d %H:%M:%S"
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
logger.addHandler(handler)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
from functools import cache
|
|
2
|
+
from math import log2, ceil
|
|
3
|
+
|
|
4
|
+
import torch
|
|
5
|
+
import torch.nn as nn
|
|
6
|
+
import torch.nn.functional as F
|
|
7
|
+
|
|
8
|
+
from einops import rearrange
|
|
9
|
+
|
|
10
|
+
from .base import ModuleCustomSD
|
|
11
|
+
from lycoris.logging import logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@cache
|
|
15
|
+
def log_butterfly_factorize(dim, factor, result):
|
|
16
|
+
logger.info(
|
|
17
|
+
f"Use BOFT({int(log2(result[1]))}, {result[0]//2})"
|
|
18
|
+
f" (equivalent to factor={result[0]}) "
|
|
19
|
+
f"for {dim=} and {factor=}"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def butterfly_factor(dimension: int, factor: int = -1) -> tuple[int, int]:
|
|
24
|
+
"""
|
|
25
|
+
m = 2k
|
|
26
|
+
n = 2**p
|
|
27
|
+
m*n = dim
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
# Find the first solution and check if it is even doable
|
|
31
|
+
m = n = 0
|
|
32
|
+
while m <= factor:
|
|
33
|
+
m += 2
|
|
34
|
+
while dimension % m != 0 and m < dimension:
|
|
35
|
+
m += 2
|
|
36
|
+
if m > factor:
|
|
37
|
+
break
|
|
38
|
+
if sum(int(i) for i in f"{dimension//m:b}") == 1:
|
|
39
|
+
n = dimension // m
|
|
40
|
+
|
|
41
|
+
if n == 0:
|
|
42
|
+
raise ValueError(
|
|
43
|
+
f"It is impossible to decompose {dimension} with factor {factor} under BOFT constrains."
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
log_butterfly_factorize(dimension, factor, (dimension // n, n))
|
|
47
|
+
return dimension // n, n
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ButterflyOFTModule(ModuleCustomSD):
|
|
51
|
+
"""
|
|
52
|
+
modifed from kohya-ss/sd-scripts/networks/lora:LoRAModule
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
lora_name,
|
|
58
|
+
org_module: nn.Module,
|
|
59
|
+
multiplier=1.0,
|
|
60
|
+
lora_dim=4,
|
|
61
|
+
alpha=1,
|
|
62
|
+
dropout=0.0,
|
|
63
|
+
rank_dropout=0.0,
|
|
64
|
+
module_dropout=0.0,
|
|
65
|
+
use_tucker=False,
|
|
66
|
+
use_scalar=False,
|
|
67
|
+
rank_dropout_scale=False,
|
|
68
|
+
constrain=0,
|
|
69
|
+
rescaled=False,
|
|
70
|
+
**kwargs,
|
|
71
|
+
):
|
|
72
|
+
"""if alpha == 0 or None, alpha is rank (no scaling)."""
|
|
73
|
+
super().__init__()
|
|
74
|
+
self.lora_name = lora_name
|
|
75
|
+
|
|
76
|
+
if isinstance(org_module, nn.Linear):
|
|
77
|
+
self.op = F.linear
|
|
78
|
+
self.dim = org_module.out_features
|
|
79
|
+
self.kw_dict = {}
|
|
80
|
+
elif isinstance(org_module, nn.Conv2d):
|
|
81
|
+
self.op = F.conv2d
|
|
82
|
+
self.dim = org_module.out_channels
|
|
83
|
+
self.kw_dict = {
|
|
84
|
+
"stride": org_module.stride,
|
|
85
|
+
"padding": org_module.padding,
|
|
86
|
+
"dilation": org_module.dilation,
|
|
87
|
+
"groups": org_module.groups,
|
|
88
|
+
}
|
|
89
|
+
else:
|
|
90
|
+
raise NotImplementedError
|
|
91
|
+
|
|
92
|
+
out_dim = org_module.weight.shape[0]
|
|
93
|
+
b, m_exp = butterfly_factor(out_dim, lora_dim)
|
|
94
|
+
self.block_size = b
|
|
95
|
+
self.block_num = m_exp
|
|
96
|
+
#BOFT(m, b)
|
|
97
|
+
self.boft_b = b
|
|
98
|
+
self.boft_m = sum(int(i) for i in f"{m_exp-1:b}") + 1
|
|
99
|
+
# block_num > block_size
|
|
100
|
+
self.rescaled = rescaled
|
|
101
|
+
self.constrain = constrain * out_dim
|
|
102
|
+
self.oft_blocks = nn.Parameter(
|
|
103
|
+
torch.zeros(self.boft_m, self.block_num, self.block_size, self.block_size)
|
|
104
|
+
)
|
|
105
|
+
if rescaled:
|
|
106
|
+
self.rescale = nn.Parameter(torch.ones(self.block_num, self.block_size, 1))
|
|
107
|
+
|
|
108
|
+
self.rank_dropout = rank_dropout
|
|
109
|
+
self.rank_dropout_scale = rank_dropout_scale
|
|
110
|
+
self.module_dropout = module_dropout
|
|
111
|
+
|
|
112
|
+
self.multiplier = multiplier
|
|
113
|
+
self.org_module = [org_module]
|
|
114
|
+
self.org_forward = self.org_module[0].forward
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def I(self):
|
|
118
|
+
return torch.eye(self.block_size, device=next(self.parameters()).device)
|
|
119
|
+
|
|
120
|
+
def apply_to(self, **kwargs):
|
|
121
|
+
self.org_forward = self.org_module[0].forward
|
|
122
|
+
self.org_module[0].forward = self.forward
|
|
123
|
+
|
|
124
|
+
def restore(self):
|
|
125
|
+
self.org_module[0].forward = self.org_forward
|
|
126
|
+
|
|
127
|
+
def merge_to(self, multiplier=1.0):
|
|
128
|
+
weight = self.make_weight(scale=multiplier)
|
|
129
|
+
self.org_module[0].weight.data.copy_(weight)
|
|
130
|
+
|
|
131
|
+
def custom_state_dict(self):
|
|
132
|
+
return {"oft_diag": self.get_r()}
|
|
133
|
+
|
|
134
|
+
def get_r(self):
|
|
135
|
+
I = self.I
|
|
136
|
+
# for Q = -Q^T
|
|
137
|
+
q = self.oft_blocks - self.oft_blocks.transpose(-1, -2)
|
|
138
|
+
normed_q = q
|
|
139
|
+
# Diag OFT style constrain
|
|
140
|
+
if self.constrain > 0:
|
|
141
|
+
q_norm = torch.norm(q) + 1e-8
|
|
142
|
+
if q_norm > self.constrain:
|
|
143
|
+
normed_q = q * self.constrain / q_norm
|
|
144
|
+
# use float() to prevent unsupported type
|
|
145
|
+
r = (I + normed_q) @ (I - normed_q).float().inverse()
|
|
146
|
+
return r
|
|
147
|
+
|
|
148
|
+
def make_weight(self, scale=1, device=None):
|
|
149
|
+
if self.rank_dropout and self.training:
|
|
150
|
+
drop = torch.rand(self.dim, device=device) < self.rank_dropout
|
|
151
|
+
drop = drop.to(self.oft_blocks.dtype)
|
|
152
|
+
if self.rank_dropout_scale:
|
|
153
|
+
drop /= drop.mean()
|
|
154
|
+
else:
|
|
155
|
+
drop = 1
|
|
156
|
+
|
|
157
|
+
m = self.boft_m
|
|
158
|
+
b = self.boft_b
|
|
159
|
+
r_b = b // 2
|
|
160
|
+
r = self.get_r()
|
|
161
|
+
inp = self.org_module[0].weight.to(device, dtype=r.dtype)
|
|
162
|
+
|
|
163
|
+
for i in range(m):
|
|
164
|
+
bi = r[i] # b_num, b_size, b_size
|
|
165
|
+
if i == 0:
|
|
166
|
+
# Apply multiplier/scale and rescale into first weight
|
|
167
|
+
bi = bi * scale + (1 - scale) * self.I
|
|
168
|
+
if self.rescaled:
|
|
169
|
+
bi = bi * self.rescale
|
|
170
|
+
inp = rearrange(inp, "(c g k) ... -> (c k g) ...", g=2, k=2**i * r_b)
|
|
171
|
+
inp = rearrange(inp, "(d b) ... -> d b ...", b=b)
|
|
172
|
+
inp = torch.einsum("b i j, b j ... -> b i ...", bi, inp)
|
|
173
|
+
inp = rearrange(inp, "d b ... -> (d b) ...")
|
|
174
|
+
inp = rearrange(inp, "(c k g) ... -> (c g k) ...", g=2, k=2**i * r_b)
|
|
175
|
+
|
|
176
|
+
weight = inp
|
|
177
|
+
return weight*drop
|
|
178
|
+
|
|
179
|
+
@torch.no_grad()
|
|
180
|
+
def apply_max_norm(self, max_norm, device=None):
|
|
181
|
+
orig_norm = self.oft_blocks.to(device).norm()
|
|
182
|
+
norm = torch.clamp(orig_norm, max_norm / 2)
|
|
183
|
+
desired = torch.clamp(norm, max=max_norm)
|
|
184
|
+
ratio = desired / norm
|
|
185
|
+
|
|
186
|
+
scaled = ratio.item() != 1.0
|
|
187
|
+
if scaled:
|
|
188
|
+
self.oft_blocks *= ratio
|
|
189
|
+
|
|
190
|
+
return scaled, orig_norm * ratio
|
|
191
|
+
|
|
192
|
+
def forward(self, x):
|
|
193
|
+
if self.module_dropout and self.training:
|
|
194
|
+
if torch.rand(1) < self.module_dropout:
|
|
195
|
+
return self.org_forward(x)
|
|
196
|
+
scale = self.multiplier
|
|
197
|
+
|
|
198
|
+
w = self.make_weight(scale, x.device)
|
|
199
|
+
kw_dict = self.kw_dict | {"weight": w, "bias": self.org_module[0].bias}
|
|
200
|
+
return self.op(x, **kw_dict)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
if __name__ == '__main__':
|
|
204
|
+
dim = 320
|
|
205
|
+
test_layer = nn.Linear(dim, dim)
|
|
206
|
+
test_layer.weight = nn.Parameter(torch.eye(dim))
|
|
207
|
+
test_boft = ButterflyOFTModule('test', test_layer, lora_dim=16)
|
|
208
|
+
test_boft.oft_blocks = nn.Parameter(torch.randn_like(test_boft.oft_blocks))
|
|
209
|
+
|
|
210
|
+
print(test_boft.make_weight(1, 'cpu').shape)
|
|
211
|
+
print(torch.count_nonzero(test_boft.make_weight(1, 'cpu')), dim*dim)
|
|
@@ -7,7 +7,6 @@ import sys
|
|
|
7
7
|
|
|
8
8
|
sys.setrecursionlimit(10000)
|
|
9
9
|
from typing import List
|
|
10
|
-
from warnings import warn
|
|
11
10
|
|
|
12
11
|
import torch
|
|
13
12
|
|
|
@@ -20,11 +19,13 @@ from .modules.glora import GLoRAModule
|
|
|
20
19
|
from .modules.norms import NormModule
|
|
21
20
|
from .modules.full import FullModule
|
|
22
21
|
from .modules.diag_oft import DiagOFTModule
|
|
22
|
+
from .modules.boft import ButterflyOFTModule
|
|
23
23
|
from .modules import make_module
|
|
24
24
|
|
|
25
25
|
from .config import PRESET
|
|
26
26
|
from .utils.preset import read_preset
|
|
27
27
|
from .utils import get_module, str_bool
|
|
28
|
+
from .logging import logger
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
network_module_dict = {
|
|
@@ -36,6 +37,7 @@ network_module_dict = {
|
|
|
36
37
|
"glora": GLoRAModule,
|
|
37
38
|
"full": FullModule,
|
|
38
39
|
"diag-oft": DiagOFTModule,
|
|
40
|
+
"boft": ButterflyOFTModule,
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
|
|
@@ -55,7 +57,7 @@ def create_lycoris(module, multiplier, linear_dim, linear_alpha, **kwargs):
|
|
|
55
57
|
or kwargs.get("use_tucker", False)
|
|
56
58
|
)
|
|
57
59
|
if "disable_conv_cp" in kwargs or "use_cp" in kwargs or "use_conv_cp" in kwargs:
|
|
58
|
-
|
|
60
|
+
logger.warning(
|
|
59
61
|
"disable_conv_cp and use_cp are deprecated. Please use use_tucker instead.",
|
|
60
62
|
stacklevel=2,
|
|
61
63
|
)
|
|
@@ -67,7 +69,7 @@ def create_lycoris(module, multiplier, linear_dim, linear_alpha, **kwargs):
|
|
|
67
69
|
|
|
68
70
|
if algo == "glora" and conv_dim > 0:
|
|
69
71
|
conv_dim = 0
|
|
70
|
-
|
|
72
|
+
logger.info("Disable conv layer for GLoRA")
|
|
71
73
|
|
|
72
74
|
preset = kwargs.get("preset", "full")
|
|
73
75
|
if preset not in PRESET:
|
|
@@ -77,14 +79,13 @@ def create_lycoris(module, multiplier, linear_dim, linear_alpha, **kwargs):
|
|
|
77
79
|
assert preset is not None
|
|
78
80
|
LycorisNetwork.apply_preset(preset)
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
logger.info(f"Using rank adaptation algo: {algo}")
|
|
81
83
|
|
|
82
84
|
if (
|
|
83
85
|
(algo == "loha")
|
|
84
86
|
and not kwargs.get("no_dim_warn", False)
|
|
85
87
|
and (linear_dim > 64 or conv_dim > 64)
|
|
86
88
|
):
|
|
87
|
-
print("=" * 20 + "WARNING" + "=" * 20)
|
|
88
89
|
warning_type = {"loha": "Hadamard Product representation"}
|
|
89
90
|
warning_msg = (
|
|
90
91
|
"You are not supposed to use dim>64 (64*64 = 4096, it already has enough rank)\n"
|
|
@@ -92,8 +93,7 @@ def create_lycoris(module, multiplier, linear_dim, linear_alpha, **kwargs):
|
|
|
92
93
|
"Please consider use lower dim or disable this warning with --network_args no_dim_warn=True\n"
|
|
93
94
|
f"If you just want to use high dim {algo}, please consider use lower lr."
|
|
94
95
|
)
|
|
95
|
-
|
|
96
|
-
print("=" * 20 + "WARNING" + "=" * 20)
|
|
96
|
+
logger.warning(warning_msg, stacklevel=2)
|
|
97
97
|
|
|
98
98
|
network = LycorisNetwork(
|
|
99
99
|
module,
|
|
@@ -230,19 +230,19 @@ class LycorisNetwork(torch.nn.Module):
|
|
|
230
230
|
|
|
231
231
|
self.conv_lora_dim = int(conv_lora_dim)
|
|
232
232
|
if self.conv_lora_dim and self.conv_lora_dim != self.lora_dim:
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
logger.info("Apply different lora dim for conv layer")
|
|
234
|
+
logger.info(f"Conv Dim: {conv_lora_dim}, Linear Dim: {lora_dim}")
|
|
235
235
|
elif self.conv_lora_dim == 0:
|
|
236
|
-
|
|
236
|
+
logger.info("Disable conv layer")
|
|
237
237
|
|
|
238
238
|
self.alpha = alpha
|
|
239
239
|
self.conv_alpha = float(conv_alpha)
|
|
240
240
|
if self.conv_lora_dim and self.alpha != self.conv_alpha:
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
logger.info("Apply different alpha value for conv layer")
|
|
242
|
+
logger.info(f"Conv alpha: {conv_alpha}, Linear alpha: {alpha}")
|
|
243
243
|
|
|
244
244
|
if 1 >= dropout >= 0:
|
|
245
|
-
|
|
245
|
+
logger.info(f"Use Dropout value: {dropout}")
|
|
246
246
|
self.dropout = dropout
|
|
247
247
|
self.rank_dropout = rank_dropout
|
|
248
248
|
self.module_dropout = module_dropout
|
|
@@ -341,7 +341,7 @@ class LycorisNetwork(torch.nn.Module):
|
|
|
341
341
|
target_replace_modules,
|
|
342
342
|
target_replace_names=[],
|
|
343
343
|
) -> List:
|
|
344
|
-
|
|
344
|
+
logger.info("Create LyCORIS Module")
|
|
345
345
|
loras = []
|
|
346
346
|
next_config = {}
|
|
347
347
|
for name, module in root_module.named_modules():
|
|
@@ -383,14 +383,14 @@ class LycorisNetwork(torch.nn.Module):
|
|
|
383
383
|
LycorisNetwork.TARGET_REPLACE_MODULE,
|
|
384
384
|
LycorisNetwork.TARGET_REPLACE_NAME,
|
|
385
385
|
)
|
|
386
|
-
|
|
386
|
+
logger.info(f"create LyCORIS: {len(self.loras)} modules.")
|
|
387
387
|
|
|
388
388
|
algo_table = {}
|
|
389
389
|
for lora in self.loras:
|
|
390
390
|
algo_table[lora.__class__.__name__] = (
|
|
391
391
|
algo_table.get(lora.__class__.__name__, 0) + 1
|
|
392
392
|
)
|
|
393
|
-
|
|
393
|
+
logger.info(f"module type table: {algo_table}")
|
|
394
394
|
|
|
395
395
|
self.weights_sd = None
|
|
396
396
|
|
|
@@ -430,7 +430,7 @@ class LycorisNetwork(torch.nn.Module):
|
|
|
430
430
|
if self.weights_sd:
|
|
431
431
|
# if some weights are not in state dict, it is ok because initial LoRA does nothing (lora_up is initialized by zeros)
|
|
432
432
|
info = self.load_state_dict(self.weights_sd, False)
|
|
433
|
-
|
|
433
|
+
logger.info(f"weights are loaded: {info}")
|
|
434
434
|
|
|
435
435
|
def is_mergeable(self):
|
|
436
436
|
return True
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lycoris-lora
|
|
3
|
-
Version: 2.1.0.
|
|
3
|
+
Version: 2.1.0.dev9
|
|
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
|
|
@@ -3,6 +3,7 @@ README.md
|
|
|
3
3
|
setup.py
|
|
4
4
|
lycoris/__init__.py
|
|
5
5
|
lycoris/config.py
|
|
6
|
+
lycoris/logging.py
|
|
6
7
|
lycoris/wrapper.py
|
|
7
8
|
lycoris/hcp/__init__.py
|
|
8
9
|
lycoris/hcp/base.py
|
|
@@ -18,6 +19,7 @@ lycoris/kohya/utils.py
|
|
|
18
19
|
lycoris/modules/__init__.py
|
|
19
20
|
lycoris/modules/attention.py
|
|
20
21
|
lycoris/modules/base.py
|
|
22
|
+
lycoris/modules/boft.py
|
|
21
23
|
lycoris/modules/diag_oft.py
|
|
22
24
|
lycoris/modules/dylora.py
|
|
23
25
|
lycoris/modules/full.py
|
|
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
|
|
|
4
4
|
setup(
|
|
5
5
|
name="lycoris_lora",
|
|
6
6
|
packages=find_packages(),
|
|
7
|
-
version="2.1.0.
|
|
7
|
+
version="2.1.0.dev9",
|
|
8
8
|
url="https://github.com/KohakuBlueleaf/LyCORIS",
|
|
9
9
|
description="Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion",
|
|
10
10
|
author="Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris/modules/hypernet/text_encoder.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lycoris_lora-2.1.0.dev8 → lycoris_lora-2.1.0.dev9}/lycoris_lora.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|