add lora support

This commit is contained in:
Sourab Mangrulkar
2022-11-30 14:51:26 +05:30
parent 513630dbc7
commit e816037024
5 changed files with 41 additions and 14 deletions
+6 -2
View File
@@ -1,7 +1,8 @@
# 🤗 pets
Parameter-Efficient Tuning at Scale with 🤗 Accelerate
# 🤗 PET
Parameter-Efficient Tuning. Intergrated with 🤗 Accelerate to scale seamlessly to large models using PyTorch FSDP.
Supported methods:
1. Prefix Tuning
2. P-Tuning
3. Prompt Tuning
@@ -38,4 +39,7 @@ Supported methods:
| BART | ✅ | ✅ | ✅ | |
## Caveats:
1. Doesn't work currently with DeeSpeed ZeRO Stage-3. Extending support with DeeSpeed ZeRO Stage-3 is in backlog.
+1 -1
View File
@@ -22,7 +22,7 @@ extras["dev"] = extras["quality"]
setup(
name="pets",
version="0.1.0.dev0",
description="Parameter-Efficient Tuning at Scale (PETS)",
description="Parameter-Efficient Tuning (PET)",
long_description=open("README.md", "r", encoding="utf-8").read(),
long_description_content_type="text/markdown",
keywords="deep learning",
+2
View File
@@ -15,5 +15,7 @@ from .tuners import (
PromptEncoderReparameterizationType,
PromptTuningConfig,
PromptTuningInit,
LoRAModel,
LoRAConfig,
)
from .utils import PETConfig, PETType, PromptLearningConfig, TaskType
+1
View File
@@ -5,3 +5,4 @@
from .p_tuning import PromptEncoder, PromptEncoderConfig, PromptEncoderReparameterizationType
from .prefix_tuning import PrefixEncoder, PrefixTuningConfig
from .prompt_tuning import PromptEmbedding, PromptTuningConfig, PromptTuningInit
from .lora import LoRAModel, LoRAConfig
+31 -11
View File
@@ -1,8 +1,29 @@
# todo
from typing import Callable, Optional
import torch
from transformers import Conv1D
from transformers.pytorch_utils import Conv1D
from dataclasses import dataclass, asdict, field
import loralib as lora
from loralib import mark_only_lora_as_trainable, lora_state_dict # flake8: noqa
from ..utils import PETConfig
@dataclass
class LoRAConfig(PETConfig):
r: int = field(default=None, metadata={"help": "LoRA attention dimension"})
lora_alpha: int = field(default=None, metadata={"help": "LoRA alpha"})
lora_dropout: float = field(default=None, metadata={"help": "LoRA dropout"})
merge_weights: bool = field(
default=False, metadata={"help": "Merge weights of the original model and the LoRA model"}
)
fan_in_fan_out: bool = field(
default=False,
metadata={"help": "Set this to True if the layer to replace stores weight like (fan_in, fan_out)"},
)
target_modules: Optional[list] = field(default=None, metadata={"help": "List of modules to replace with LoRA"})
bias: str = field(default="none", metadata={"help": "Bias type for LoRA. Can be 'none', 'all' or 'lora_only'"})
class LoRAModel(torch.nn.Module):
@@ -10,27 +31,26 @@ class LoRAModel(torch.nn.Module):
super().__init__()
self.config = config
self.model = model
self.find_and_replace()
mark_only_lora_as_trainable(self.model, self.config.bias)
def find_and_replace(self):
key_list = [key for key, _ in self.model.named_modules()]
for key in key_list:
if any(key.endswith(target_key) for target_key in self.config["target_module_keys"]):
parent, target_name, target = self.get_submodules(key)
if any(key.endswith(target_key) for target_key in self.config.target_module_keys):
parent, target, target_name = self.get_submodules(key)
if isinstance(target, torch.nn.Linear):
new_module = lora.Linear(
target.in_features, target.out_features, **self.config["prompt_encoder_config"]
)
elif isinstance(target, torch.nn.Conv1d, Conv1D):
new_module = lora.LoRAConv1d(
target.in_channels, target.out_channels, target.kernel_size, bias=target.bias is not None
)
new_module = lora.Linear(target.in_features, target.out_features, **asdict(self.config))
elif isinstance(target, Conv1D):
in_features, out_features = target.weight.shape
new_module = lora.MergedLinear(in_features, out_features, **asdict(self.config))
self.replace_module(parent, target_name, new_module)
def get_submodules(self, key):
parent = self.model.get_submodule(".".join(key.split(".")[:-1]))
target_name = key.split(".")[:-1]
target = self.model.get_submodule(key)
return parent, target_name, target
return parent, target, target_name
def replace_module(self, parent_module, child_name, new_module, old_module):
setattr(parent_module, child_name, new_module)