PEFT 文档

可训练词元 (Trainable Tokens)

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

可训练词元 (Trainable Tokens)

可训练词元 (Trainable Tokens) 方法提供了一种针对特定词元嵌入进行微调的方式,而无需训练整个嵌入矩阵或在嵌入矩阵上使用适配器。它基于此处的初始实现

该方法只针对特定的词元,并选择性地训练您指定的词元索引。因此,所需的内存 (RAM) 会更低,磁盘存储空间也显著低于存储完整的微调嵌入矩阵。

通过此脚本获取的一些初步基准测试表明,对于 gemma-2-2b(它有一个相当大的嵌入矩阵),使用可训练词元 (Trainable Tokens) 比完全微调嵌入矩阵可以节省约 4 GiB 的显存。虽然 LoRA 会使用相当数量的显存,但它也可能针对您不希望更改的词元。请注意,这些只是指示性数据,不同的嵌入矩阵大小可能会使这些数字有所偏差。

请注意,此方法不会为您添加词元,您必须自己将词元添加到分词器 (tokenizer) 中,并相应地调整模型的嵌入矩阵大小。此方法只会重新训练您指定的词元的嵌入。此方法也可以与 LoRA 层结合使用!请参阅 LoRA 开发者指南

在使用 save_pretrained() 保存模型或使用 get_peft_model_state_dict() 检索状态字典时,如果添加了新词元,可能会保存完整的嵌入矩阵而不是仅保存差异,这是一种预防措施,因为嵌入矩阵的大小已更改。为节省空间,您可以在调用 save_pretrained 时通过设置 save_embedding_layers=False 来禁用此行为。只要您不同时通过其他方式修改嵌入矩阵,这样做是安全的,因为此类更改不会被可训练词元追踪到。

TrainableTokensConfig

class peft.TrainableTokensConfig

< >

( task_type: typing.Union[str, peft.utils.peft_types.TaskType, NoneType] = None peft_type: typing.Union[str, peft.utils.peft_types.PeftType, NoneType] = None auto_mapping: typing.Optional[dict] = None base_model_name_or_path: typing.Optional[str] = None revision: typing.Optional[str] = None inference_mode: bool = False token_indices: list[int] = <factory> target_modules: Optional[Union[list[str], str]] = None init_weights: bool = True )

参数

  • token_indices (list[int]) — 整数列表,表示您希望可训练的词元的索引。要查找词元的索引,您可以使用分词器对字符串进行分词,并查看返回的 input_ids。索引数量越接近词元总数,此方法的效率就越低。
  • target_modules (Optional[Union[list[str], str]]) — 要替换为我们的 TrainableTokensLayer 的模块名称列表或模块名称的正则表达式。如果未定义,它将尝试获取模型的输入嵌入层(如果模型有 get_input_embeddings 方法,transformer 模型通常有),如果失败,则默认为 ‘embed_tokens’。其他示例目标是 embeddingencoder.embeddingsdecoder.embeddings
  • init_weights (bool) — 默认情况下,新词元的权重初始化为与相应词元嵌入相同。这使得 TrainableTokens 在未训练时是无操作的。如果设置为 False,权重将是随机值。除非您确切知道自己在做什么,否则不要更改此设置。

TrainableTokens 方法的配置。

允许训练新词元(并重新训练现有词元)而无需训练完整的嵌入矩阵。通过将少数选定的词元(通过其索引识别)标记为可训练,并保持其余部分不变,此方法可用于添加新词元或更改现有词元的嵌入,同时节省内存。与完全训练嵌入矩阵相比,存储和工作内存的使用都减少了。

请注意,使用 FSDP/DeepSpeed 进行训练可能尚未完全支持。

TrainableTokensModel

class peft.TrainableTokensModel

< >

( model peft_config: Union[PeftConfig, dict[str, PeftConfig]] adapter_name: str low_cpu_mem_usage: bool = False state_dict: Optional[dict[str, torch.Tensor]] = None )

disable_adapter_layers

< >

( )

禁用所有适配器。

禁用所有适配器后,模型输出对应于基础模型的输出。

enable_adapter_layers

< >

( )

启用所有适配器。

如果您之前禁用了所有适配器并希望重新启用它们,请调用此函数。

merge_and_unload

< >

( progressbar: bool = False safe_merge: bool = False adapter_names: Optional[list[str]] = None )

参数

  • progressbar (bool) — 是否显示指示卸载和合并过程的进度条
  • safe_merge (bool) — 是否激活安全合并检查,以检查适配器权重中是否存在潜在的 Nan 值
  • adapter_names (List[str], 可选) — 应该合并的适配器名称列表。如果为 None,则将合并所有活动的适配器。默认为 None

此方法将训练过的词元合并到基础模型的目标嵌入层中。如果有人想将基础模型用作独立模型,则需要这样做。

set_adapter

< >

( adapter_name: str | list[str] )

参数

  • adapter_name (strlist[str]) — 要激活的适配器的名称。

设置活动的适配器。

此外,此函数将把指定的适配器设置为可训练的(即 requires_grad=True)。如果不希望如此,请使用以下代码。

>>> for name, param in model_peft.named_parameters():
...     if ...:  # some check on name (ex. if 'lora' in name)
...         param.requires_grad = False

unload

< >

( )

通过移除所有可训练词元模块来恢复基础模型,而不进行合并。

< > 在 GitHub 上更新