PEFT documentation
AdaLoRA
AdaLoRA
AdaLoRA(Adaptive LoRA)は、LoRAがすべてのモジュールにパラメータを均等に割り当てるのとは異なり、重み行列やレイヤーに割り当てる学習可能なパラメータの数を最適化する方法です。重要な重み行列やレイヤーには多くのパラメータが割り当てられ、重要度の低いものには少ないパラメータが割り当てられます。行列の平均的な望ましいrankまたはr、およびAdaLoRAを適用するモジュールはtarget_modulesで制御できます。設定する他の重要なパラメータには、lora_alpha(スケーリング係数)とmodules_to_save(AdaLoRAレイヤー以外で学習および保存されるモジュール)があります。これらのパラメータ、およびそれ以外のパラメータはすべて、AdaLoraConfigにあります。
論文の抄録は以下の通りです:
下流タスクに対する大規模事前学習言語モデルのファインチューニングは、NLPにおいて重要なパラダイムとなっています。しかし、一般的な手法では事前学習モデルのすべてのパラメータをファインチューニングするため、下流タスクの数が多くなると計算コストが prohibitive になります。そのため、低ランク増分など、事前学習重みの増分更新をパラメータ効率よく学習する多くのファインチューニング手法が提案されています。これらの手法は、事前学習重み行列全体に増分更新の予算を均等に割り当て、異なる重みパラメータの重要性の違いを無視しがちです。その結果、ファインチューニングの性能が最適になりません。このギャップを埋めるために、我々は AdaLoRA を提案します。AdaLoRA は、重み行列の重要性スコアに基づいて、パラメータ予算を適応的に割り当てます。具体的には、AdaLoRA は増分更新を特異値分解の形式でパラメータ化します。この新しいアプローチにより、重要でない更新の特異値を効果的に剪定することが可能になり、これは本質的にそれらのパラメータ予算を削減するものですが、計算コストの高い厳密な SVD 計算を回避します。自然言語処理、質問応答、自然言語生成における複数の事前学習モデルを用いて広範な実験を行い、AdaLoRA の有効性を検証しました。結果は、AdaLoRA がベースラインと比較して顕著な改善を示すことを示しており、特に低予算設定において顕著です。コードは https://github.com/QingruZhang/AdaLoRA で公開されています。
AdaLoRAには、パラメータの予算とマスクを更新するために各トレーニングステップで呼び出すべきupdate_and_allocate()メソッドがあります。これを呼び出さないと、適応ステップが実行されません。そのため、このメソッドを組み込むために、カスタムなトレーニングループを作成するか、Trainerをサブクラス化する必要があります。例として、このカスタムなトレーニングループをご覧ください。
AdaLoRA は、LoRA で導入されたパラメータ予算を管理し、タスクに適した重要な重み行列にはより多くのパラメータ、つまりより高いランク r - を割り当て、重要度の低いものは削減します。ランクは、特異値分解(SVD)に類似した方法で制御されます。 は、2 つの直交行列と特異値を含む対角行列でパラメータ化されます。このパラメータ化方法により、計算コストの高い SVD を反復的に適用することを回避できます。この方法に基づき、 のランクは重要度スコアに応じて調整されます。 はトリプレットに分割され、各トリプレットはモデル性能への貢献度に基づいてスコアリングされます。重要度スコアが低いトリプレットは削減され、スコアが高いトリプレットはファインチューニングのために保持されます。
AdaLoRA による学習には、init フェーズ、budgeting フェーズ、final フェーズの3つの段階があります。init フェーズでは、budgeting は適用されないため、rank は変更されません。budgeting フェーズでは、上記で説明したプロセスが適用され、budget に基づいて rank が再分配されます。これにより、より重要なアダプターにはより多くの rank を、より重要度の低いレイヤーには少ない rank を割り当てることを目指します。final フェーズに到達すると、budgeting は終了し、rank は再分配されますが、再分配された rank でしばらく学習を継続することで、パフォーマンスをさらに向上させることができます。
貢献を歓迎します:このセクションは明確化が必要です。
重要度の測定方法が不明確です。また、説明がやや冗長であり、統合すると良いかもしれません。 貢献方法については、こちらをご覧ください。
ベンチマーク概要
使用方法
from peft import AdaLoraConfig, get_peft_model
config = AdaLoraConfig(
r=8,
init_r=12,
tinit=200,
tfinal=1000,
deltaT=10,
target_modules=["query", "value"],
modules_to_save=["classifier"],
)
model = get_peft_model(model, config)
model.print_healthcheck()
[... training code ...]
model.update_and_allocate(step_idx)API
AdaLoraConfig
クラス peft.AdaLoraConfig
< source >( task_type: Optional[Union[str, TaskType]] = Nonepeft_type: Optional[Union[str, PeftType]] = Noneauto_mapping: Optional[dict] = Nonepeft_version: Optional[str] = Nonebase_model_name_or_path: Optional[str] = Nonerevision: Optional[str] = Noneinference_mode: bool = Falser: int = 8target_modules: Optional[Union[list[str], str]] = Noneexclude_modules: Optional[Union[list[str], str]] = Nonelora_alpha: int = 8lora_dropout: float = 0.0fan_in_fan_out: bool = Falsebias: Literal['none', 'all', 'lora_only'] = 'none'use_rslora: bool = Falsemodules_to_save: Optional[list[str]] = Noneinit_lora_weights: bool | Literal['gaussian', 'eva', 'olora', 'pissa', 'pissa_niter_[number of iters]', 'corda', 'astra', 'loftq', 'orthogonal', 'mica', 'nora'] = Truelayers_to_transform: Optional[Union[list[int], int]] = Nonelayers_pattern: Optional[Union[list[str], str]] = Nonerank_pattern: dict | None = Nonealpha_pattern: Optional[dict] = <factory>megatron_config: Optional[dict] = Nonemegatron_core: Optional[str] = 'megatron.core'trainable_token_indices: Optional[Union[list[int], dict[str, list[int]]]] = Noneloftq_config: Union[LoftQConfig, dict] = <factory>eva_config: Optional[EvaConfig] = Nonecorda_config: Optional[CordaConfig] = Noneastra_config: Optional[AstraConfig] = Nonelora_ga_config: Optional[LoraGAConfig] = Noneuse_dora: bool = Falsevelora_config: Optional[Union[VeloraConfig, dict]] = Nonealora_invocation_tokens: Optional[list[int]] = Noneuse_qalora: bool = Falseqalora_group_size: int = 16monteclora_config: Optional[MontecloraConfig] = Nonelayer_replication: Optional[list[tuple[int, int]]] = Noneruntime_config: LoraRuntimeConfig = <factory>lora_bias: bool = Falsetarget_parameters: Optional[list[str]] = Noneuse_bdlora: Optional[BdLoraConfig] = Nonearrow_config: Optional[ArrowConfig] = Nonekasa_config: Optional[KasaConfig] = Noneensure_weight_tying: bool = Falsetarget_r: int = 8init_r: int = 12tinit: int = 0tfinal: int = 0deltaT: int = 1beta1: float = 0.85beta2: float = 0.85orth_reg_weight: float = 0.5total_step: int | None = None )
パラメータ
- target_r (
int) — 増分行列の目標平均ランク。 - init_r (
int) — 各増分行列の初期ランク。 - tinit (
int) — 初期ファインチューニングのウォームアップステップ数。 - tfinal (
int) — 最終ファインチューニングのステップ数。 - deltaT (
int) — 2回の予算割当の間隔時間。 - beta1 (
float) — 感度の平滑化のための EMA のハイパーパラメータ。 - beta2 (
float) — 不確実性の定量化のためのEMAのハイパーパラメータ。 - orth_reg_weight (
float) — 直交正則化の係数。 - total_step (
int) — 学習前に指定すべき、学習の総ステップ数です。 - rank_pattern (
list) — RankAllocator によって各重み行列に割り当てられたランクです。
これはAdaLoraModelの設定を保存するための設定クラスです。
AdaLoRAには、tinit、tfinal、total_stepによって定義される3つのフェーズがあります。
初期フェーズは、アダプタの事前学習のステップとして理解できます。これにより、ランクを削減する際に、ランダムな行列の代わりに削減できる情報がすでにエンコードされている状態になります。このフェーズは、tinitを指定することによって定義されます。
初期フェーズが終了し(tinit ステップが経過し)、最終フェーズが始まっていない場合、AdaLoRA は各ステップごとに、各レイヤーが持つことのできるランクの予算を削減します。ランクの削減はこの段階で行われます。このプロセスは、total_step - tfinal ステップに達するまで続きます。
total_step - tfinal ステップに達した時点で始まる最終フェーズでは、レイヤーのランクは変更されず、前フェーズで生成された低ランクのレイヤーをファインチューニングします。
実用的な例として、tinitが10、tfinalが20、total_stepが100の場合を挙げます。予算が一定であるため(initフェーズ)、最初の10ステップはランク削減なしで事前学習を行います。次に、80ステップ(100-20)をかけて、予算がステップごとに減少する削減フェーズを行います。最後に、削減なしで20ステップかけて最終的なファインチューニングを行います。
AdaLoraModel
クラス peft.AdaLoraModel
< source >( modelconfigadapter_name**kwargs ) → torch.nn.Module
パラメータ
- model (transformers.PreTrainedModel) — 適応させる対象のモデル。
- config (AdaLoraConfig) — AdaLoraモデルの設定です。
- adapter_name (
str) — アダプターの名前。デフォルトは"default"です。 - low_cpu_mem_usage (
bool、optional、デフォルトはFalse) — メタデバイス上に空のアダプター重みを生成します。読み込みプロセスを高速化するために有用です。
戻り値
torch.nn.Module
AdaLoraモデル。
事前学習済みのtransformersモデルからAdaLoRA(Adaptive LoRA)モデルを作成します。論文: https://openreview.net/forum?id=lq62uWRJjiY
例:
>>> from transformers import AutoModelForSeq2SeqLM
>>> from peft import AdaLoraConfig, get_peft_model
>>> config = AdaLoraConfig(
... peft_type="ADALORA",
... task_type="SEQ_2_SEQ_LM",
... init_r=12,
... lora_alpha=32,
... target_modules=["q", "v"],
... lora_dropout=0.01,
... total_step=1000,
... )
>>> model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")
>>> adalora_model = get_peft_model(model, config)属性:
- model (transformers.PreTrainedModel) — 適応させる対象のモデル。
- peft_config (AdaLoraConfig): AdaLoraモデルの設定です。
このメソッドはAdaLoRAではサポートされていません。代わりにLoRAを使用してください。
update_and_allocate
< source >( global_step )
このメソッドは、Adaloraの予算とマスクを更新します。
これは、loss.backward() の後で、zero_grad() の前に、すべての学習ステップで呼び出す必要があります。
tinit、tfinal、deltaT はメソッド内で処理されます。