Buckets:
| import"../chunks/DsnmJJEf.js";import{i as x,h as T,C as k,H as t,D as f,E as B,s as C}from"../chunks/C6Httu04.js";import{p as j,o as N,s as e,f as O,a as g,b as M,c as u,d as _,n,r as y}from"../chunks/jDjavuwI.js";const q='{"title":"Lily: Low-Rank Interconnected Adaptation across Layers","local":"lily-low-rank-interconnected-adaptation-across-layers","sections":[{"title":"Benchmark overview","local":"benchmark-overview","sections":[],"depth":2}],"depth":1}';var I=_('<meta name="hf:doc:metadata"/>'),P=_('<p></p> <!> <!> <p><a href="https://huggingface.co/papers/2407.09946" rel="nofollow">Lily</a> is a parameter-efficient fine-tuning technique that introduces cross-layer weight sharing for adapter matrices. Instead of learning an independent AB pair per layer as in LoRA, Lily uses <strong>locally shared A adapters</strong> (each A is shared across a block of <code>stride_A</code> consecutive layers) and <strong>globally shared B experts</strong> (a small pool of <code>num_B</code> B adapters is shared across all layers). At each forward pass, a lightweight data-dependent router computes a softmax-weighted combination of the B experts to produce the effective B for that layer and input.</p> <p>This sharing can reduce the total number of adapter matrices from <code>2N</code> (standard LoRA) to <code>N / stride_A + num_B</code>, freeing up the parameter budget to use a <strong>much larger rank <code>r</code></strong> — typically <code>2×</code>–<code>4×</code> what you would use in LoRA. Higher rank and better interconnectivity increase the effective rank of the weight update <code>ΔW = A × combined_B</code>, leading to better adaptation performance.</p> <p>Because the B combination is <strong>data-dependent</strong> (the router weights depend on the input activations at runtime), <code>merge</code> and <code>unmerge</code> are <strong>not supported</strong>. If weight merging is required for your deployment, consider other methods such as LoRA instead.</p> <p>Lily currently has the following additional constraints:</p> <ul><li>Only <code>nn.Linear</code> layers are supported.</li> <li>Quantized layers are not supported.</li></ul> <p>If these constraints don’t work for your use case, consider other methods instead.</p> <p>The abstract from the paper is:</p> <blockquote><p>Low-rank adaptation (LoRA) is a widely used parameter-efficient fine-tuning (PEFT) method that learns weight updates ΔW = AB for pretrained weights W through low-rank adapters A and B. While LoRA ensures hardware efficiency, its low-rank weight updates limit adaptation performance. In this paper, we propose low-rank interconnected adaptation across layers (Lily), a novel PEFT method that introduces an interconnected framework with locally shared A and globally shared B experts. This structure eliminates redundant per-layer AB pairs, enabling higher-rank ΔW with equal or fewer parameters. To enhance expressiveness, we use data-dependent routers to determine A-B interconnections, preventing B experts from converging to the same behavior and improving representational power across domains. Experiments across modalities, architectures, and model sizes demonstrate Lily’s superior performance and efficiency.</p></blockquote> <!> <iframe src="https://peft-internal-testing-peft-method-comparison-embed.hf.space/?highlight[type]=LILY" frameborder="0" width="850" height="1000"></iframe> <!> <!> <div class="docstring border-l-2 border-t-2 pl-4 pt-3.5 border-gray-100 rounded-tl-xl mb-6 mt-8"><!> <p>This is the configuration class to store the configuration of a <a href="/docs/peft/pr_3219/en/package_reference/lily#peft.LilyModel">LilyModel</a>.</p></div> <!> <div class="docstring border-l-2 border-t-2 pl-4 pt-3.5 border-gray-100 rounded-tl-xl mb-6 mt-8"><!> <p>Creates a Low-Rank Interconnected Adaptation Across Layers (Lily) model from a pretrained transformers model.</p> <p>The method is described in detail in <a href="https://arxiv.org/abs/2407.09946" rel="nofollow">https://arxiv.org/abs/2407.09946</a>.</p> <p><strong>Attributes</strong>:</p> <ul><li><strong>model</strong> (<a href="https://huggingface.co/docs/transformers/main/en/main_classes/model#transformers.PreTrainedModel" rel="nofollow">PreTrainedModel</a>) — The model to be adapted.</li> <li><strong>peft_config</strong> (<a href="/docs/peft/pr_3219/en/package_reference/lily#peft.LilyConfig">LilyConfig</a>): The configuration of the Lily model.</li></ul></div> <!> <p></p>',1);function E(v,w){j(w,!1),N(()=>{new URLSearchParams(window.location.search).get("fw")}),x();var r=P();T("ghylcc",h=>{var m=I();C(m,"content",q),g(h,m)});var i=e(O(r),2);k(i,{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"});var s=e(i,2);t(s,{title:"Lily: Low-Rank Interconnected Adaptation across Layers",local:"lily-low-rank-interconnected-adaptation-across-layers",headingTag:"h1"});var d=e(s,18);t(d,{title:"Benchmark overview",local:"benchmark-overview",headingTag:"h2"});var l=e(d,4);t(l,{title:"API",local:"api",headingTag:"h1"});var c=e(l,2);t(c,{title:"LilyConfig",local:"peft.LilyConfig",headingTag:"h2"});var o=e(c,2),b=u(o);f(b,{name:"class peft.LilyConfig",anchor:"peft.LilyConfig",source:"https://github.com/huggingface/peft/blob/vr_3219/src/peft/tuners/lily/config.py#L24",parameters:[{name:"task_type",val:": Optional[Union[str, TaskType]] = None"},{name:"peft_type",val:": Optional[Union[str, PeftType]] = None"},{name:"auto_mapping",val:": Optional[dict] = None"},{name:"peft_version",val:": Optional[str] = None"},{name:"base_model_name_or_path",val:": Optional[str] = None"},{name:"revision",val:": Optional[str] = None"},{name:"inference_mode",val:": bool = False"},{name:"r",val:": int = 32"},{name:"stride_A",val:": int = 1"},{name:"num_B",val:": int = 2"},{name:"scaling",val:": float = 1.0"},{name:"target_modules",val:": Optional[Union[list[str], str]] = None"},{name:"exclude_modules",val:": Optional[Union[list[str], str]] = None"},{name:"modules_to_save",val:": Optional[list[str]] = None"},{name:"layers_to_transform",val:": Optional[Union[list[int], int]] = None"},{name:"layers_pattern",val:": Optional[Union[list[str], str]] = None"},{name:"init_weights",val:": bool = True"}],parametersDescription:[{anchor:"peft.LilyConfig.r",description:`<strong>r</strong> (<code>int</code>) — | |
| Lily’s rank. Determines the inner hidden dimension of each adapter and the rank of the weight update <code>A @ B</code>. In Lily, since the number of adapters is typically smaller than in LoRA, each adapter needs to carry | |
| more capacity, so it is recommended to use a larger <code>r</code> than in LoRA — typically <code>2x</code>, <code>3x</code>, or <code>4x</code> the | |
| LoRA rank you would normally use. The total number of trainable parameters scales with <code>r * (total_layers / stride_A + num_B)</code>, so increasing <code>r</code> while keeping <code>stride_A</code> large and <code>num_B</code> small is the recommended | |
| trade-off.`,name:"r"},{anchor:"peft.LilyConfig.stride_A",description:`<strong>stride_A</strong> (<code>int</code>) — | |
| The number of consecutive layers that share one A adapter. For example, if <code>stride_A=4</code>, every 4 adjacent | |
| layers share the same A adapter, resulting in <code>total_layers / stride_A</code> distinct A adapters in total. The A | |
| adapter compresses the input into a low-rank representation of size <code>r</code>. <code>stride_A</code> should be no less than | |
| <ol> | |
| <li>Suggested values: <code>2</code>, <code>3</code>, or <code>4</code> (i.e. sharing every 2, 3, or 4 layers). Keeping <code>stride_A</code> large | |
| (fewer distinct A adapters) and increasing <code>r</code> instead leads to better performance than the opposite | |
| trade-off (small <code>stride_A</code>, small <code>r</code>). Setting <code>stride_A=1</code> means every layer has its own A adapter. | |
| NOTE: the A sharing happens within each target (layers with the same target suffix). For example, if your | |
| target_modules are <code>['q_proj', 'v_proj']</code> and you set <code>stride_A=2</code>, then every 2 adjacent q_proj layers | |
| will share an A adapter, and every 2 adjacent v_proj layers will share another A adapter, but the q_proj | |
| and v_proj layers will not share A adapters with each other since they have different suffixes.</li> | |
| </ol>`,name:"stride_A"},{anchor:"peft.LilyConfig.num_B",description:`<strong>num_B</strong> (<code>int</code>) — | |
| The number of shared B adapters. Unlike A adapters (which are grouped by layer), all B adapters are shared | |
| globally across every layer. For each forward pass, a router computes a weighted combination of all <code>num_B</code> | |
| B adapters (using softmax-normalized weights) to produce a single combined B adapter, which then projects | |
| the low-rank representation back to the original dimension. It is recommended to set <code>num_B</code> to a similar | |
| order as <code>total_layers / stride_A</code>. Suggested values: <code>total_layers / 2</code>, <code>total_layers / 3</code>, or | |
| <code>total_layers / 4</code>. Similar to <code>stride_A</code>, prefer smaller <code>num_B</code> with larger <code>r</code> over larger <code>num_B</code> with | |
| smaller <code>r</code>. NOTE: to train the router, you need at least 2 B adapters (i.e. <code>num_B >= 2</code>), since the | |
| router learns to compute a weighted combination of the B adapters. NOTE: the B sharing happens within each | |
| target (layers with the same target suffix). For example, if your target_modules are <code>['q_proj', 'v_proj']</code> | |
| and you set <code>num_B=4</code>, then there will be 4 B adapters shared across all q_proj layers, and another 4 B | |
| adapters shared across all v_proj layers, but the q_proj and v_proj layers will not share B adapters with | |
| each other since they have different suffixes.`,name:"num_B"},{anchor:"peft.LilyConfig.target_modules",description:`<strong>target_modules</strong> (<code>Union[List[str], str]</code>, <em>optional</em>) — | |
| The names of the modules to apply Lily to. Can be a list of module name strings (e.g. <code>['q_proj', 'v_proj']</code>) or a regex pattern (e.g. <code>'.*decoder.*(SelfAttention|EncDecAttention).*(q|v)$'</code>). If not | |
| specified, Lily will be applied to all supported linear layers.`,name:"target_modules"},{anchor:"peft.LilyConfig.scaling",description:`<strong>scaling</strong> (<code>float</code>) — | |
| A scalar multiplier applied to the combined adapter output (<code>scaling * A @ combined_B</code>) before adding it to | |
| the frozen weight’s forward pass. Unlike LoRA, Lily does not use an <code>alpha / r</code> formulation; instead, | |
| <code>scaling</code> is a direct multiplier. This design makes it straightforward to sweep over values on a log scale | |
| (e.g. <code>0.01</code>, <code>0.1</code>, <code>1.0</code>, <code>10.0</code>). The optimal value is task-dependent and should be treated as a | |
| hyperparameter. We recommend starting with <code>1.0</code>.`,name:"scaling"},{anchor:"peft.LilyConfig.modules_to_save",description:`<strong>modules_to_save</strong> (<code>List[str]</code>, <em>optional</em>) — | |
| List of modules apart from Lily layers to be set as trainable and saved in the final checkpoint. For | |
| example, in Sequence Classification or Token Classification tasks, the final layer <code>classifier/score</code> are | |
| randomly initialized and as such need to be trainable and saved.`,name:"modules_to_save"},{anchor:"peft.LilyConfig.exclude_modules",description:`<strong>exclude_modules</strong> (<code>Union[List[str], str]</code>, <em>optional</em>) — | |
| The names of the modules to not apply the adapter. When passing a string, a regex match will be performed. | |
| When passing a list of strings, either an exact match will be performed or it is checked if the name of the | |
| module ends with any of the passed strings.`,name:"exclude_modules"},{anchor:"peft.LilyConfig.layers_to_transform",description:`<strong>layers_to_transform</strong> (<code>Union[list[int], int]</code>, <em>optional</em>) — | |
| The layer indexes to transform, if this argument is specified, PEFT will transform only the layers indexes | |
| that are specified inside this list. If a single integer is passed, PEFT will transform only the layer at | |
| this index.`,name:"layers_to_transform"},{anchor:"peft.LilyConfig.layers_pattern",description:`<strong>layers_pattern</strong> (<code>Optional[Union[List[str], str]]</code>, <em>optional</em>) — | |
| The layer pattern name, used only if <code>layers_to_transform</code> is different to None and if the layer pattern is | |
| not in the common layers pattern. This should target the <code>nn.ModuleList</code> of the model, which is often | |
| called <code>'layers'</code> or <code>'h'</code>.`,name:"layers_pattern"},{anchor:"peft.LilyConfig.init_weights",description:`<strong>init_weights</strong> (<code>bool</code>) — | |
| Whether to initialize Lily adapter weights using the default initialization scheme: A matrices are | |
| initialized with Kaiming uniform, and B matrices are initialized to zero, ensuring that the adapter output | |
| is zero at the start of training and does not disturb the pretrained model. It is strongly recommended to | |
| keep this as <code>True</code> unless you have a specific reason to change it.`,name:"init_weights"}]}),n(2),y(o);var p=e(o,2);t(p,{title:"LilyModel",local:"peft.LilyModel",headingTag:"h2"});var a=e(p,2),L=u(a);f(L,{name:"class peft.LilyModel",anchor:"peft.LilyModel",source:"https://github.com/huggingface/peft/blob/vr_3219/src/peft/tuners/lily/model.py#L30",parameters:[{name:"model",val:""},{name:"peft_config",val:": Union[PeftConfig, dict[str, PeftConfig]]"},{name:"adapter_name",val:": str"},{name:"low_cpu_mem_usage",val:": bool = False"},{name:"state_dict",val:": Optional[dict[str, torch.Tensor]] = None"}],parametersDescription:[{anchor:"peft.LilyModel.model",description:"<strong>model</strong> (<code>torch.nn.Module</code>) — The model to be adapted.",name:"model"},{anchor:"peft.LilyModel.config",description:'<strong>config</strong> (<a href="/docs/peft/pr_3219/en/package_reference/lily#peft.LilyConfig">LilyConfig</a>) — The configuration of the Lily model.',name:"config"},{anchor:"peft.LilyModel.adapter_name",description:"<strong>adapter_name</strong> (<code>str</code>) — The name of the adapter, defaults to <code>"default"</code>.",name:"adapter_name"}],returnDescription:`<script context="module">export const metadata = 'undefined';<\/script> | |
| <p>The Lily PEFT model.</p> | |
| `,returnType:`<script context="module">export const metadata = 'undefined';<\/script> | |
| <p><code>torch.nn.Module</code></p> | |
| `}),n(8),y(a);var A=e(a,2);B(A,{source:"https://github.com/huggingface/peft/blob/main/docs/source/package_reference/lily.md"}),n(2),g(v,r),M()}export{E as component}; | |
Xet Storage Details
- Size:
- 14.9 kB
- Xet hash:
- f18eae0c29da43bc79bc7b25b22de8e115bf0f959f69992686cfe6a2272a124f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.