Buckets:

hf-doc-build/doc / transformers /main /ar /how_to_hack_models.md
mishig's picture
|
download
raw
8.37 kB
# تخصيص مكوّنات النموذج
طريقة أخرى لتخصيص نموذج هي تعديل مكوّناته، بدلاً من كتابة نموذج جديد بالكامل، مما يتيح لك تكييف النموذج ليناسب حالتك الاستخدامية المحددة. على سبيل المثال، يمكنك إضافة طبقات جديدة أو تحسين آلية الانتباه في بنية معيّنة. تُطبَّق التخصيصات مباشرةً على نموذج Transformers بحيث يمكنك مواصلة استخدام ميزات مثل [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) و[PreTrainedModel](/docs/transformers/main/ar/main_classes/model#transformers.PreTrainedModel) ومكتبة [PEFT](https://huggingface.co/docs/peft/en/index).
ستُظهر لك هذه الدليل كيفية تخصيص آلية الانتباه في نموذج من أجل تطبيق [Low-Rank Adaptation (LoRA)](https://huggingface.co/docs/peft/conceptual_guides/adapter#low-rank-adaptation-lora) عليها.
> [!TIP]
> يُعدّ الأداة [clear_import_cache](https://github.com/huggingface/transformers/blob/9985d06add07a4cc691dc54a7e34f54205c04d40/src/transformers/utils/import_utils.py#L2286) مفيدة للغاية عند تعديلك وتطويرك كود النموذج بشكل متكرر. فهي تحذف جميع وحدات Transformers المخزنة مؤقتاً، وتسمح لـ Python بإعادة تحميل الكود المعدّل دون الحاجة إلى إعادة تشغيل بيئتك باستمرار.
>
> ```py
> from transformers import AutoModel
> from transformers.utils.import_utils import clear_import_cache
>
> model = AutoModel.from_pretrained("bert-base-uncased")
> # modifications to model code
> # clear cache to reload modified code
> clear_import_cache()
> # re-import to use updated code
> model = AutoModel.from_pretrained("bert-base-uncased")
> ```
## فئة الانتباه
[Segment Anything](./model_doc/sam) هو نموذج لتجزئة الصور، ويجمع إسقاط الاستعلام-المفتاح-القيمة (`qkv`) في آليات الانتباه الخاصة به. لتقليل عدد المعلمات القابلة للتدريب والعبء الحسابي، يمكنك تطبيق LoRA على إسقاط `qkv`. ويتطلب ذلك تقسيم إسقاط `qkv` بحيث يمكنك استهداف `q` و`v` بشكل منفصل باستخدام LoRA.
1. أنشئ فئة انتباه مخصصة، `SamVisionAttentionSplit`، عن طريق إنشاء فئة فرعية من فئة `SamVisionAttention` الأصلية. في `__init__`، احذف `qkv` المدمج وأنشئ طبقة خطية منفصلة لكل من `q` و`k` و`v`.
```py
import torch
import torch.nn as nn
from transformers.models.sam.modeling_sam import SamVisionAttention
class SamVisionAttentionSplit(SamVisionAttention, nn.Module):
def __init__(self, config, window_size):
super().__init__(config, window_size)
# remove combined qkv
del self.qkv
# separate q, k, v projections
self.q = nn.Linear(config.hidden_size, config.hidden_size, bias=config.qkv_bias)
self.k = nn.Linear(config.hidden_size, config.hidden_size, bias=config.qkv_bias)
self.v = nn.Linear(config.hidden_size, config.hidden_size, bias=config.qkv_bias)
self._register_load_state_dict_pre_hook(self.split_q_k_v_load_hook)
```
2. تقوم دالة `split_q_k_v_load_hook` بتقسيم أوزان `qkv` المُدرَّبة مسبقًا إلى أوزان منفصلة لـ `q` و`k` و`v` عند تحميل النموذج، لضمان التوافق مع أي نموذج مُدرَّب مسبقًا.
```py
def split_q_k_v_load_hook(self, state_dict, prefix, *args):
keys_to_delete = []
for key in list(state_dict.keys()):
if "qkv." in key:
# split q, k, v from the combined projection
q, k, v = state_dict[key].chunk(3, dim=0)
# replace with individual q, k, v projections
state_dict[key.replace("qkv.", "q.")] = q
state_dict[key.replace("qkv.", "k.")] = k
state_dict[key.replace("qkv.", "v.")] = v
# mark the old qkv key for deletion
keys_to_delete.append(key)
# remove old qkv keys
for key in keys_to_delete:
del state_dict[key]
```
3. في مسار `forward`، يتم حساب `q` و`k` و`v` بشكل منفصل بينما يبقى بقية آلية الانتباه كما هي.
```py
def forward(self, hidden_states: torch.Tensor, output_attentions=False) -> torch.Tensor:
batch_size, height, width, _ = hidden_states.shape
qkv_shapes = (batch_size * self.num_attention_heads, height * width, -1)
query = self.q(hidden_states).reshape((batch_size, height * width,self.num_attention_heads, -1)).permute(0,2,1,3).reshape(qkv_shapes)
key = self.k(hidden_states).reshape((batch_size, height * width,self.num_attention_heads, -1)).permute(0,2,1,3).reshape(qkv_shapes)
value = self.v(hidden_states).reshape((batch_size, height * width,self.num_attention_heads, -1)).permute(0,2,1,3).reshape(qkv_shapes)
attn_weights = (query * self.scale) @ key.transpose(-2, -1)
attn_weights = torch.nn.functional.softmax(attn_weights, dtype=torch.float32, dim=-1).to(query.dtype)
attn_probs = nn.functional.dropout(attn_weights, p=self.dropout, training=self.training)
attn_output = (attn_probs @ value).reshape(batch_size, self.num_attention_heads, height, width, -1)
attn_output = attn_output.permute(0, 2, 3, 1, 4).reshape(batch_size, height, width, -1)
attn_output = self.proj(attn_output)
if output_attentions:
outputs = (attn_output, attn_weights)
else:
outputs = (attn_output, None)
return outputs
```
عيّن الفئة المخصصة `SamVisionAttentionSplit` على وحدة `SamVisionAttention` الأصلية في النماذج لاستبدالها. يتم استبدال جميع حالات `SamVisionAttention` في النموذج بإصدار الانتباه المقسّم.
استبدل الفئة *قبل* استدعاء [from_pretrained()](/docs/transformers/main/ar/main_classes/model#transformers.PreTrainedModel.from_pretrained). يعمل خطاف التحميل فقط أثناء تحميل نقطة التفتيش، لذا فإن استبدال الوحدات في نموذج محمّل بالفعل سيترك طبقات `q` و`k` و`v` الجديدة مهيأة بشكل عشوائي.
```py
from transformers import SamModel
from transformers.models.sam import modeling_sam
# replace the attention class the vision layers instantiate
modeling_sam.SAM_VISION_ATTENTION_CLASSES["eager"] = SamVisionAttentionSplit
# load the pretrained SAM model, the hook splits the qkv weights during loading
model = SamModel.from_pretrained("facebook/sam-vit-base", attn_implementation="eager")
```
## LoRA
عند استخدام إسقاطات منفصلة لـ `q` و`k` و`v`، طبّق LoRA على `q` و`v`.
أنشئ [LoraConfig](https://huggingface.co/docs/peft/package_reference/config#peft.PeftConfig) وحدد الرتبة `r` و`lora_alpha` و`lora_dropout` و`task_type` والأهم من ذلك، الوحدات المستهدفة.
```py
from peft import LoraConfig, get_peft_model
config = LoraConfig(
r=16,
lora_alpha=32,
# apply LoRA to q and v
target_modules=["q", "v"],
lora_dropout=0.1,
task_type="FEATURE_EXTRACTION"
)
```
مرّر النموذج و[LoraConfig](https://huggingface.co/docs/peft/package_reference/config#peft.PeftConfig) إلى [get_peft_model](https://huggingface.co/docs/peft/package_reference/peft_model#peft.get_peft_model) لتطبيق LoRA على النموذج.
```py
model = get_peft_model(model, config)
```
استدعِ [print_trainable_parameters](https://huggingface.co/docs/peft/package_reference/peft_model#peft.PeftMixedModel.print_trainable_parameters) لعرض عدد المعاملات التي يتم تدريبها مقابل إجمالي عدد المعاملات.
```py
model.print_trainable_parameters()
"trainable params: 589,824 || all params: 94,274,096 || trainable%: 0.6256"
```

Xet Storage Details

Size:
8.37 kB
·
Xet hash:
b81d5354c0ed7f23aaf32a372fc910c38731628feb6e7bf4391ad7560f8e37c7

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.