lycoris-lora 1.8.0.dev6__tar.gz → 1.8.0.dev8__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 (40) hide show
  1. lycoris_lora-1.8.0.dev8/.gitignore +128 -0
  2. lycoris_lora-1.8.0.dev8/Algo.md +134 -0
  3. lycoris_lora-1.8.0.dev8/Change.md +25 -0
  4. lycoris_lora-1.8.0.dev8/Demo.md +53 -0
  5. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/PKG-INFO +1 -1
  6. lycoris_lora-1.8.0.dev8/experiments/better_conv.py +105 -0
  7. lycoris_lora-1.8.0.dev8/experiments/better_conv_extract.py +67 -0
  8. lycoris_lora-1.8.0.dev8/experiments/concept_neuron.py +239 -0
  9. lycoris_lora-1.8.0.dev8/experiments/locon_extract_test.py +34 -0
  10. lycoris_lora-1.8.0.dev8/experiments/locon_merge_test.py +29 -0
  11. lycoris_lora-1.8.0.dev8/experiments/singular_value_test.py +97 -0
  12. lycoris_lora-1.8.0.dev8/experiments/sparse_bias_test.py +71 -0
  13. lycoris_lora-1.8.0.dev8/experiments/time_test.py +88 -0
  14. lycoris_lora-1.8.0.dev8/experiments/weakre_speed.py +14 -0
  15. lycoris_lora-1.8.0.dev6/lycoris/modules/lokr.py → lycoris_lora-1.8.0.dev8/lycoris/modules/glokr.py +1 -4
  16. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/modules/locon.py +32 -8
  17. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/modules/loha.py +3 -3
  18. lycoris_lora-1.8.0.dev8/lycoris/modules/lokr.py +266 -0
  19. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris_lora.egg-info/PKG-INFO +1 -1
  20. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris_lora.egg-info/SOURCES.txt +18 -1
  21. lycoris_lora-1.8.0.dev8/requirements.txt +4 -0
  22. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/setup.py +1 -1
  23. lycoris_lora-1.8.0.dev8/tools/extract_locon.py +129 -0
  24. lycoris_lora-1.8.0.dev8/tools/merge.py +85 -0
  25. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/LICENSE.md +0 -0
  26. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/README.md +0 -0
  27. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/__init__.py +0 -0
  28. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/kohya/__init__.py +0 -0
  29. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/kohya/kohya_model_utils.py +0 -0
  30. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/kohya/kohya_utils.py +0 -0
  31. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/modules/__init__.py +0 -0
  32. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/modules/dylora.py +0 -0
  33. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/modules/glora.py +0 -0
  34. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/modules/ia3.py +0 -0
  35. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris/utils.py +0 -0
  36. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  37. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris_lora.egg-info/not-zip-safe +0 -0
  38. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris_lora.egg-info/requires.txt +0 -0
  39. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/lycoris_lora.egg-info/top_level.txt +0 -0
  40. {lycoris_lora-1.8.0.dev6 → lycoris_lora-1.8.0.dev8}/setup.cfg +0 -0
@@ -0,0 +1,128 @@
1
+ # test
2
+ test_model/
3
+
4
+ # Editors
5
+ .vscode/
6
+ .idea/
7
+
8
+ # Vagrant
9
+ .vagrant/
10
+
11
+ # Mac/OSX
12
+ .DS_Store
13
+
14
+ # Windows
15
+ Thumbs.db
16
+
17
+ # Source for the following rules: https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore
18
+ # Byte-compiled / optimized / DLL files
19
+ __pycache__/
20
+ *.py[cod]
21
+ *$py.class
22
+
23
+ # C extensions
24
+ *.so
25
+
26
+ # Distribution / packaging
27
+ .Python
28
+ build/
29
+ develop-eggs/
30
+ dist/
31
+ downloads/
32
+ eggs/
33
+ .eggs/
34
+ lib/
35
+ lib64/
36
+ parts/
37
+ sdist/
38
+ var/
39
+ wheels/
40
+ *.egg-info/
41
+ .installed.cfg
42
+ *.egg
43
+ MANIFEST
44
+
45
+ # PyInstaller
46
+ # Usually these files are written by a python script from a template
47
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
48
+ *.manifest
49
+ *.spec
50
+
51
+ # Installer logs
52
+ pip-log.txt
53
+ pip-delete-this-directory.txt
54
+
55
+ # Unit test / coverage reports
56
+ htmlcov/
57
+ .tox/
58
+ .nox/
59
+ .coverage
60
+ .coverage.*
61
+ .cache
62
+ nosetests.xml
63
+ coverage.xml
64
+ *.cover
65
+ .hypothesis/
66
+ .pytest_cache/
67
+
68
+ # Translations
69
+ *.mo
70
+ *.pot
71
+
72
+ # Django stuff:
73
+ *.log
74
+ local_settings.py
75
+ db.sqlite3
76
+
77
+ # Flask stuff:
78
+ instance/
79
+ .webassets-cache
80
+
81
+ # Scrapy stuff:
82
+ .scrapy
83
+
84
+ # Sphinx documentation
85
+ docs/_build/
86
+
87
+ # PyBuilder
88
+ target/
89
+
90
+ # Jupyter Notebook
91
+ .ipynb_checkpoints
92
+
93
+ # IPython
94
+ profile_default/
95
+ ipython_config.py
96
+
97
+ # pyenv
98
+ .python-version
99
+
100
+ # celery beat schedule file
101
+ celerybeat-schedule
102
+
103
+ # SageMath parsed files
104
+ *.sage.py
105
+
106
+ # Environments
107
+ .env
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+ .dmypy.json
128
+ dmypy.json
@@ -0,0 +1,134 @@
1
+ # Algorithm explanation
2
+
3
+
4
+ ## Basic Idea
5
+ Linear Layer:
6
+
7
+ $Y = W \cdot X$
8
+
9
+ finetuning is to get the $W'$
10
+
11
+ $Y = W \cdot X + W' \cdot X$
12
+
13
+ and normally $shape(W') = shape(W)$
14
+
15
+ ---
16
+
17
+ ## Conventional Methods
18
+ [Ref](https://arxiv.org/abs/2106.09685)
19
+
20
+ Linear:
21
+
22
+ $Y_{out \times batch} = W_{out \times in} \cdot X_{in \times batch}$
23
+
24
+ $\xrightarrow{} Y_{out \times batch} = W_{out \times in} \cdot X_{in \times batch} + Wa_{out \times dim} \cdot Wb_{dim \times in} \cdot X_{in \times batch}$
25
+
26
+
27
+ LoRA for Convolution:
28
+ Consider im2col of matmul first:
29
+
30
+ ![image](https://user-images.githubusercontent.com/59680068/221547963-c821b9fa-2825-4b8d-8192-c3109268417f.png)
31
+ ![image](https://user-images.githubusercontent.com/59680068/221547996-4be14700-1392-4859-9e29-e3e669142a09.png)
32
+ $X:[channel, width, height]$
33
+
34
+ $\xrightarrow{reorder}[c \times kw \times kh, outw \times outh]$
35
+
36
+ $Kernels: [out, c, kw, kh] \xrightarrow{reshape} [out, c \times kw \times kh]$
37
+
38
+ $Conv(X, Kernels) = Kernels \times X \xrightarrow{reshape} [out, outw, outh]$
39
+
40
+ and then write down this conventional LoRA for conv layer
41
+ $Conv(in, out, ksize, padding, stride)$
42
+
43
+ $\xrightarrow{}Conv(dim, out, 1)\circ Conv(in, dim, ksize, padding, stride)$
44
+
45
+
46
+ In this method, we can get that
47
+ $W' = Wa \cdot Wb$ with $rank(W') \le dim$
48
+
49
+ ---
50
+
51
+ ## Hadamard Product
52
+ [Ref](https://arxiv.org/abs/2108.06098)
53
+ ![image](https://user-images.githubusercontent.com/59680068/223942143-05b5ebff-06c4-4d07-a0eb-037fd6f04e77.png)
54
+
55
+
56
+ consider $W' = Wa \odot Wb$, we can get $rank(W') \le rank(Wa) \times rank(Wb)$.
57
+ And then we use conventional method on $Wa$ and $Wb$. Which means it can use 2x dim to get square rank.
58
+
59
+ **Rank != Information capacity, but they are relative**
60
+
61
+ based on the experiment result from the paper, it seems like although the rank(Wa) * rank(Wb) is just upper bound, but almost everytime it will produce W' with rank = rank(Wa)*rank(Wb).
62
+
63
+ ### Why custom backward
64
+ with $W' = (Wa_1 \cdot Wa_2) \odot (Wb_1 \cdot Wb_2)$, when you need to calc the backpropogation, you will need $\Delta{W'}$ and $Wa$ to calc $\Delta{Wb}$, also $Wb$ for $\Delta{Wa}$.
65
+
66
+ With pytorch's autograd, this kind of operation will cache the $Wa$ and $Wb$ for calc the backward, which means it will cache 2x size of weight for backward.
67
+
68
+ To avoid this terrible situation, I impl a custom backward which will reconstruct $Wa$ and $Wb$ when actually needed, this method saved tons of memory.
69
+
70
+ ### CP-Decomposition
71
+ [Ref](https://arxiv.org/abs/1412.6553)
72
+
73
+ As mentioned before, the weight shape for convolution layer is $[out, in, kw, kh]$. And we just unfold it to $[out, in \times kw \times kh]$ for decomposition.
74
+
75
+ But actually there is a method to decomposition any shape ot tensor called cp decomposition.
76
+
77
+ Using cp-decomposition in Covolution will be something like:
78
+
79
+ $\tau: [dim, dim, kw, kh]$ <br>
80
+ $x_1: [dim, out]$<br>
81
+ $x_2: [dim, in]$<br>
82
+ $W' = \tau \times_1 x_1 \times_2 x_2$<br>
83
+ $W': [out, in, kw, kh]$
84
+
85
+ Or write this thing as multiple conv layer:
86
+
87
+ Conv(in, dim, (1, 1))<br>
88
+ ↓<br>
89
+ Conv(dim, dim, (kw, kh), stride, padding)<br>
90
+ ↓<br>
91
+ conv(dim, out, (1, 1))<br>
92
+
93
+ For hadamard product implementation, just use 2 different $W'$ and multiply them together.
94
+
95
+ ---
96
+
97
+ ## Kronercker Product
98
+
99
+ ### Definition
100
+
101
+ If $W_1$ is an a x b matrix and $W_2$ is a c x d matrix, then the Kronecker Product of two matrices is
102
+
103
+ $W' = W_1 \otimes W_2$ and an ac x bd matrix.
104
+
105
+ In meaning of matrix, $W_2$ becomes weight and $W_1$ becomes weight scale of $W_2$
106
+
107
+ ### About rank
108
+
109
+ And we can decompose $W_2$ using LoRA with rank, r.
110
+
111
+ $W_2 = Wa_2 \cdot Wb_2$ then $W' = W_1 \otimes (Wa_2 \cdot Wb_2)$
112
+
113
+ we can get $rank(W') \le rank(W_1) \times rank(Wa_2 \cdot Wb_2)$ and $rank(W_1) \le min(a, b), rank(Wa_2 \cdot Wb_2) \le r$
114
+
115
+ => $rank(W') \le min(a, b) \times r$
116
+
117
+ Remember that $min(a, b) \times r$ is upper bound. $rank(W') = min(a, b) \times r$ does not guarantee. Experiment needs.
118
+
119
+ ### Number of parameters
120
+
121
+ We decompose matrix, $W' = W_1 \otimes (Wa_2 \cdot Wb_2)$.
122
+
123
+ (# of parameters) = $(a \times b) + (c \times r + r \times d) = a \times b + r \times (c + d)$, m = ac, n = bd.
124
+
125
+ and suppose best case $a=c= \sqrt{m}, b=d= \sqrt{n}$
126
+
127
+ then, (# of parameters) = $\sqrt{mn} + r \times (\sqrt{m} + \sqrt{n})$
128
+
129
+ We can reduce the number of parameters to order of square root maximally.
130
+
131
+ ---
132
+
133
+ ## Sparse Bias
134
+ Todo...
@@ -0,0 +1,25 @@
1
+ # Change Log
2
+
3
+ ## 2023/06/28 update to 1.7.1
4
+ * **rearrange the version format, previous 0.1.7 should be 1.7.0**
5
+ * fix the bug in scale weight norm
6
+
7
+ ## 2023/06/26 Update to 0.1.7
8
+ * Add support for rank_dropout and module_dropout on LoCon/LoHa/LoKr
9
+ * Add support for scale_weight_norms on LoCon/LoHa/LoKr
10
+ * Will support SDXL on 0.1.8 (you can follow the dev branch)
11
+
12
+ ## 2023/06/04 update to 0.1.6
13
+ * add dylora and IA^3 algorithm
14
+
15
+ ## 2023/03/29 Update to 0.1.4
16
+ * cp decomposition is default to disable now
17
+ * add 4 more layer to train (conv_in/out, time_embedding)
18
+
19
+ ## 2023/03/12 Update to 0.1.0
20
+ * Add cp-decomposition implementation for convolution layer
21
+ * Both LoRA(LoCon) and LoHa can use this more parameter-efficient decomposition
22
+ * Add sparse bias for extracted LoRA
23
+ * Will add to training in the future (Maybe)
24
+ * Change weight initialization method in LoHa
25
+ * Use lower std to avoid loss to go high or NaN when using normal lr (like 0.5 in Dadap)
@@ -0,0 +1,53 @@
1
+ # Demo, Example, Comparing
2
+
3
+
4
+ ## expand LoRA to Convolution Layer
5
+ lora for transformer only
6
+ vs
7
+ lora for whole model
8
+
9
+ Yog-Sothoth LoRA/LoCon:
10
+ https://civitai.com/models/14878/loconlora-yog-sothoth-depersonalization
11
+
12
+ LoRA rank=1:
13
+ ![00159](https://user-images.githubusercontent.com/59680068/222422792-b37648c3-af2e-4bee-9f82-b14a5d8e5f5d.png)
14
+ LoCon rank=1
15
+ ![00164](https://user-images.githubusercontent.com/59680068/222422830-4ec9f550-cdff-4314-b694-1658bf9f1c83.png)
16
+
17
+ xy grid:
18
+ ![image](https://user-images.githubusercontent.com/59680068/222424002-5ce2572c-9102-4e2d-83f2-100bc41ec272.png)
19
+
20
+
21
+ With some experiments from community, finetuning whole model can learn "More". But in some case this means it will overfit heavily.
22
+
23
+ ---
24
+
25
+ ## Hadamard product vs Conventional
26
+ We introduced LoRA finetuning with Hadamard Product representation from FedPara.
27
+ And based on this [experiments](https://civitai.com/models/17336/roukin8-character-lohaloconfullckpt-8), LoHa with same size (and dim>2, or rank>4) can get better result in some situation.
28
+
29
+ ![Image](https://i.imgur.com/l3P0TgM.jpg)
30
+
31
+ This is some comments from the experiments:
32
+ ```
33
+ Why LoHa?
34
+
35
+ The following comparison should be quite convincing.
36
+
37
+ (Left 4 LoHa with different number of training steps; Right 4 same thing but for LoCon; same seed same training parameters for the two training)
38
+
39
+
40
+ In addition to the five characters I also train a bunch of style into the model (what I have always been doing actually).
41
+
42
+ However, LoRa and LoCon do not combine styles with characters that well (characters are only trained with anime images) and this capacity gets largely improved in LoHa.
43
+
44
+ Note that the two files have almost the same size (around 30mb). For this I set (linear_dim, conv_dim) to (16,8) for LoCon and (8,4) for LoHa. However with Hadamard product the resulting matrix could now be of rank 8x8=64 for linear layers and 4x4=16 for convolutional layers.
45
+ ```
46
+
47
+ And there is more example about LoHA vs LoCon in same file size. (diff < 200KB)
48
+ ![xyz_grid-0330-2023-03-08_d4d1ef62c3_KBlueLeaf_KBlueLeaf-v1 1_4114224331_c2af89d9-2160x2789](https://user-images.githubusercontent.com/59680068/223930255-a1e4b91e-25da-41ce-9dd2-12bd0e976afc.jpg)
49
+ ![xyz_grid-0324-2023-03-08_d4d1ef62c3_KBlueLeaf_KBlueLeaf-v1 1_2496183095_a91c0526-2160x2789](https://user-images.githubusercontent.com/59680068/223930265-f1f1d658-3722-46ce-93e6-fdec18a58c19.jpg)
50
+
51
+ ![xyz_grid-0300-2023-03-08_b38775f1cf_download_谈秋-v2_3652865965_ed37959c-2640x2047](https://user-images.githubusercontent.com/59680068/223930346-c32a062c-4b3a-40a6-83e3-853127129b7d.jpg)
52
+ ![xyz_grid-0296-2023-03-08_d4d1ef62c3_KBlueLeaf_KBlueLeaf-v1 1_4001890147_ed37959c-2640x2047](https://user-images.githubusercontent.com/59680068/223930351-45653f67-7b0c-42e6-9a81-cc691d2b9dbf.jpg)
53
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 1.8.0.dev6
3
+ Version: 1.8.0.dev8
4
4
  Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
5
5
  Home-page: https://github.com/KohakuBlueleaf/LyCORIS
6
6
  Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
@@ -0,0 +1,105 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+
6
+ class HadaWeightCP(torch.autograd.Function):
7
+ @staticmethod
8
+ def forward(ctx, orig_weight, t1, w1a, w1b, t2, w2a, w2b, scale=torch.tensor(1)):
9
+ ctx.save_for_backward(t1, w1a, w1b, t2, w2a, w2b, scale)
10
+
11
+ temp = torch.einsum('i j k l, j r -> i r k l', t1, w1b)
12
+ rebuild1 = torch.einsum('i j k l, i r -> r j k l', temp, w1a)
13
+
14
+ temp = torch.einsum('i j k l, j r -> i r k l', t2, w2b)
15
+ rebuild2 = torch.einsum('i j k l, i r -> r j k l', temp, w2a)
16
+
17
+ return orig_weight + rebuild1*rebuild2*scale
18
+
19
+ @staticmethod
20
+ def backward(ctx, grad_out):
21
+ (t1, w1a, w1b, t2, w2a, w2b, scale) = ctx.saved_tensors
22
+
23
+ grad_out = grad_out*scale
24
+
25
+ temp = torch.einsum('i j k l, j r -> i r k l', t2, w2b)
26
+ rebuild = torch.einsum('i j k l, i r -> r j k l', temp, w2a)
27
+
28
+ grad_w = rebuild*grad_out
29
+ del rebuild
30
+
31
+ grad_w1a = torch.einsum('r j k l, i j k l -> r i', temp, grad_w)
32
+ grad_temp = torch.einsum('i j k l, i r -> r j k l', grad_w, w1a.T)
33
+ del grad_w, temp
34
+
35
+ grad_w1b = torch.einsum('i r k l, i j k l -> r j', t1, grad_temp)
36
+ grad_t1 = torch.einsum('i j k l, j r -> i r k l', grad_temp, w1b.T)
37
+ del grad_temp
38
+
39
+ temp = torch.einsum('i j k l, j r -> i r k l', t1, w1b)
40
+ rebuild = torch.einsum('i j k l, i r -> r j k l', temp, w1a)
41
+
42
+ grad_w = rebuild*grad_out
43
+ del rebuild
44
+
45
+ grad_w2a = torch.einsum('r j k l, i j k l -> r i', temp, grad_w)
46
+ grad_temp = torch.einsum('i j k l, i r -> r j k l', grad_w, w2a.T)
47
+ del grad_w, temp
48
+
49
+ grad_w2b = torch.einsum('i r k l, i j k l -> r j', t2, grad_temp)
50
+ grad_t2 = torch.einsum('i j k l, j r -> i r k l', grad_temp, w2b.T)
51
+ del grad_temp
52
+ return grad_out, grad_t1, grad_w1a, grad_w1b, grad_t2, grad_w2a, grad_w2b, None
53
+
54
+
55
+ def make_weight_cp(orig_weight, t1, w1a, w1b, t2, w2a, w2b, scale=torch.tensor(0.25)):
56
+ return HadaWeightCP.apply(orig_weight, t1, w1a, w1b, t2, w2a, w2b, scale)
57
+
58
+
59
+ def make_cp(orig_weight, t1, w1a, w1b, t2, w2a, w2b, scale=torch.tensor(0.25)):
60
+ temp = torch.einsum('i j k l, j r -> i r k l', t1, w1b)
61
+ rebuild1 = torch.einsum('i j k l, i r -> r j k l', temp, w1a)
62
+
63
+ temp = torch.einsum('i j k l, j r -> i r k l', t2, w2b)
64
+ rebuild2 = torch.einsum('i j k l, i r -> r j k l', temp, w2a)
65
+
66
+ return orig_weight + rebuild1*rebuild2 * scale
67
+
68
+
69
+ KERNEL_SIZE = 3
70
+ STRIDE = 1
71
+ PADDING = 1
72
+ IN_CH = 1280
73
+ OUT_CH = 1208
74
+ LORA_RANK = 4
75
+ SIZE = 32
76
+
77
+
78
+ t1 = nn.Parameter(torch.randn(LORA_RANK, LORA_RANK, 3, 3))
79
+ w1a = nn.Parameter(torch.randn(LORA_RANK, OUT_CH))
80
+ w1b = nn.Parameter(torch.randn(LORA_RANK, IN_CH))
81
+
82
+ t2 = nn.Parameter(torch.randn(LORA_RANK, LORA_RANK, 3, 3))
83
+ w2a = nn.Parameter(torch.randn(LORA_RANK, OUT_CH))
84
+ w2b = nn.Parameter(torch.randn(LORA_RANK, IN_CH))
85
+
86
+ orig = nn.Parameter(torch.randn(OUT_CH, IN_CH, 3, 3))
87
+
88
+ test_x = torch.randn(1, 4, 64, 64)
89
+ test_t = torch.randn(1, 4, 64, 64)
90
+
91
+
92
+ w1 = make_cp(orig, t1, w1a, w1b, t2, w2a, w2b)
93
+ w2 = make_weight_cp(orig, t1, w1a, w1b, t2, w2a, w2b)
94
+
95
+ torch.mean(w1).backward()
96
+ grad1 = t1.grad.clone()
97
+ t1.grad = None
98
+
99
+ torch.mean(w2).backward()
100
+ grad2 = t1.grad.clone()
101
+
102
+
103
+ print('MSE Loss: ', F.mse_loss(grad1, grad2))
104
+ print('L1 Loss : ', F.l1_loss(grad1, grad2))
105
+ print('Distance: ', torch.dist(grad1, grad2))
@@ -0,0 +1,67 @@
1
+ import os, sys
2
+ sys.path.insert(0, os.getcwd())
3
+ import torch
4
+ import torch.nn as nn
5
+ import torch.nn.functional as F
6
+
7
+ from lycoris.utils import extract_conv
8
+ from pytorch_lightning import seed_everything
9
+
10
+
11
+ def make_sparse(t, sparsity=0.95):
12
+ sparse_t = t.masked_fill(
13
+ torch.abs(t) < torch.quantile(torch.abs(t), sparsity),
14
+ 0
15
+ )
16
+ return sparse_t
17
+
18
+ def make_cp(t, x1, x2):
19
+ x1 = x1.reshape(x1.size(0), -1)
20
+ x2 = x2.reshape(x2.size(0), -1)
21
+
22
+ # [rank, rank, k, k] * [rank, out]
23
+ temp = torch.einsum('n m k l, i n -> i m k l', t, x2)
24
+
25
+ # [out, rank, k, k] * [rank, in]
26
+ result = torch.einsum('i m k l, m j -> i j k l', temp, x1)
27
+ print(result.shape)
28
+ return result
29
+
30
+
31
+ seed_everything(0)
32
+
33
+ KERNEL_SIZE = 3
34
+ STRIDE = 1
35
+ PADDING = 1
36
+ IN_CH = 1280
37
+ OUT_CH = 640
38
+ LORA_RANK = 32
39
+ SIZE = 32
40
+
41
+ conv_orig = nn.Conv2d(IN_CH, OUT_CH, 3, 1, 1, bias=False).cuda()
42
+ conv_orig.weight = nn.Parameter(
43
+ (torch.randn(OUT_CH, LORA_RANK)
44
+ @ torch.randn(LORA_RANK, IN_CH*9)
45
+ * 0.05
46
+ ).reshape(conv_orig.weight.shape).cuda()
47
+ )
48
+ conv_rebd = nn.Conv2d(IN_CH, OUT_CH, 3, 1, 1, bias=False).cuda()
49
+
50
+ extract_a, extract_b, diff = extract_conv(conv_orig.weight, 'fixed', LORA_RANK, 'cuda')
51
+ out_weight = extract_b.reshape(OUT_CH, -1) @ extract_a.reshape(LORA_RANK, -1)
52
+ out_weight = out_weight.reshape(conv_orig.weight.shape)
53
+
54
+ extract_a, extract_c, diff = extract_conv(extract_a.transpose(0, 1), 'fixed', LORA_RANK, 'cuda')
55
+ extract_a = extract_a.transpose(0, 1)
56
+ extract_c = extract_c.transpose(0, 1)
57
+ print(extract_a.shape, extract_b.shape, extract_c.shape)
58
+
59
+
60
+ conv_rebd.weight = nn.Parameter(make_cp(
61
+ extract_a, extract_c, extract_b
62
+ ))
63
+ print()
64
+ print('without sparse bias')
65
+ print('MSE Loss: ', F.mse_loss(conv_orig.weight, conv_rebd.weight))
66
+ print('L1 Loss : ', F.l1_loss(conv_orig.weight, conv_rebd.weight))
67
+ print('Distance: ', torch.dist(conv_orig.weight, conv_rebd.weight))