الضبط الدقيق الخاص تفاضلياً باستخدام Opacus
اضبط مصنِّف نصوص أو صور على تصنيفات دراستك ضبطاً دقيقاً بـDP-SGD، وحدّد epsilon وdelta، واقرأ الخصوصية المستهلكة في سجل التشغيلة وبطاقة النموذج.
جديد في v2.14.0
يدرّب هذا الدرس مصنِّفاً على تصنيفات دراسة بعينها بخصوصية تفاضلية، فلا يكشف النموذج المنشور إلا القليل عن أي عنصر معلَّق بمفرده. الصفحة لأصحاب الدراسات التي تكون عناصرها أو تصنيفاتها حساسة (كالسجلات الصحية أو الرسائل الخاصة) ويخططون لمشاركة النموذج أو نشره. ستضيف كتلة dp إلى معاملات hf-text-classification، وتشغّل المُدرِّب على مثال مراجعات المنتجات، وتقرأ الخصوصية المستهلكة من سجل التشغيلة وبطاقة النموذج. وتعمل الكتلة نفسها على hf-image-classification، ولا يقبل dp أي مُدرِّب آخر.
epsilon وdelta في الخصوصية التفاضلية
الخصوصية التفاضلية ضمان رياضي بشأن حساب يجري على مجموعة بيانات. فإضافة سجل واحد أو حذفه تغيّر احتمال أي ناتج بمقدار محدود، ولذلك لا يكشف الناتج إلا القليل عن وجود ذلك السجل. وepsilon (ε) هو هذا الحد. وكلما صغر epsilon صار التمييز بين النواتج مع السجل وبدونه أصعب، فيعطي epsilon الأصغر خصوصية أقوى. وdelta (δ) هو احتمال أن يفشل حدّ epsilon، وتصف وثائق Potato دلتا بأنها "the chance the guarantee does not hold".
يدرّب DP-SGD شبكة عصبية تحت هذا الضمان، بطريقة Abadi وآخرين (2016). تقتطع كل خطوة تدريب تدرّج كل عنصر عند معيار أقصى، وتضيف ضجيجاً غاوسياً إلى المجموع. يحدّ الاقتطاع من مقدار ما يستطيع عنصر واحد أن يحرّك به النموذج، ويحجب الضجيج هذه الحركة المحدودة. وOpacus مكتبة PyTorch تنفّذ DP-SGD، ويسلّم Potato حلقة التدريب إلى Opacus كلما حملت تشغيلة dp. ويجمع محاسب RDP في Opacus epsilon الذي تستهلكه كل خطوة.
ثبّت المُدرِّب وOpacus
تحتاج مُدرِّبات المحوّلات إلى torch وtransformers من إضافات التدريب في Potato. ولا تضم أي إضافة في Potato مكتبة Opacus، لأن Opacus يثبّت إصدارات محددة من torch. ثبّت الاثنين على الجهاز الذي تتدرّب عليه التشغيلة:
pip install "potato-annotation[train-text]" # [train-vision] for hf-image-classification
pip install opacusتتحقق التشغيلة التي فيها dp من وجود Opacus على جهاز التدريب قبل أن يبدأ التدريب. ولذلك يوضع Opacus، على خلفية ssh أو SLURM أو وكيل، على خادم GPU أو عقدة الحوسبة التي تتدرّب، لا على خادم التعليق. يتناول التدريب عن بُعد هذه الخلفيات.
هيّئ المُدرِّب
التهيئة أدناه هي مثال مراجعات المنتجات من درّب نموذجك الأول، مع ضبط التدريب الخاص افتراضياً لـhf-text-classification. انسخ data/reviews.json وdata/gold.json من examples/ai-assisted/model-training/ في Potato إلى مجلد مشروع، واحفظ هذه التهيئة فيه باسم config.yaml:
annotation_task_name: "Review Sentiment (private training)"
data_files:
- "data/reviews.json"
item_properties:
id_key: "id"
text_key: "text"
task_dir: "."
output_annotation_dir: "annotation_output"
require_password: false
admin_api_key: "demo-admin-key"
num_annotators_per_item: 1
annotation_schemes:
- annotation_type: "radio"
name: "sentiment"
description: "Is this review positive or negative?"
labels:
- "positive"
- "negative"
sequential_key_binding: true
model_training:
enabled: true
trainer_params:
hf-text-classification:
epochs: 5
batch_size: 16
dp:
epsilon: 8
max_grad_norm: 1.0
writeback:
schemas: ["sentiment"]
include_unlabeled: true
min_confidence: 0.6تضبط trainer_params القيم الافتراضية لكل تشغيلة من hf-text-classification، ولذلك يُفتح حقل Parameters في صفحة التدريب ومدخل dp مملوء أصلاً. ويقع epsilon: 8 ضمن المدى من 1 إلى 10 الذي تسمّيه وثائق Potato معتاداً. وقد تُرك delta، فيضبط Potato دلتا على 1 / (10 × عناصر train). ويكرّر max_grad_norm: 1.0 الاقتطاع الافتراضي. ويكرّر epochs وbatch_size القيمتين الافتراضيتين للمُدرِّب، لأن Opacus يحدّد حجم الضجيج من كليهما. ولا يناسب require_password: false ومفتاح المشرف البسيط إلا تجربة محلية.
يأخذ dp ثلاثة مفاتيح:
| المفتاح | الافتراضي | المعنى |
|---|---|---|
epsilon | مطلوب | ميزانية الخصوصية للتشغيلة كلها. epsilon الأصغر أكثر خصوصية ويضيف ضجيجاً أكثر. |
delta | 1 / (10 × عناصر train) | احتمال ألا يصمد الضمان. يجب أن تكون delta أقل من 1 / عناصر train. |
max_grad_norm | 1.0 | يُقتطع تدرّج كل عنصر عند هذا المعيار قبل إضافة الضجيج. |
تجتاز التهيئة python -m potato.validate_cli config.yaml --strict. يقبل المُدقِّق تخطيطاً أو null أو false للمفتاح dp ويرفض dp: true. ويفحص المُدقِّق أيضاً كل مفتاح داخل dp ومداه. ويجري Opacus والفحوص المعتمدة على عدد عناصر train عند بدء التشغيلة، على الجهاز الذي يتدرّب، كما يسرد أخطاء عند بدء التشغيلة.
صنّف العناصر وابدأ تشغيلة
يرفض hf-text-classification الضبط على أقل من 20 عنصر train (min_instances). شغّل الخادم، ثم صنّف المراجعات يدوياً أو بثلاثة معلّقين محاكين من المحاكي يجيبون من ملف المعيار الذهبي:
potato start config.yaml -p 8000
python -m potato.simulator --server http://localhost:8000 --users 3 \
--strategy gold_standard --competence good=1.0 --max-annotations 40 \
--gold-file data/gold.json --sequential --fast-mode --no-exportيصنّف المحاكي 120 من 160 مراجعة. ومع splits الافتراضية (70% train و15% val و15% test) وsplit_seed: 0، وضعت تشغيلتنا 76 مراجعة مصنّفة في train و19 في val و25 في test. وتصبح delta الافتراضية إذن 1 / 760، أي نحو 0.00132، ويجب أن تكون أي delta تضبطها أقل من 1 / 76، أي نحو 0.0132.
افتح http://localhost:8000/admin/training بمفتاح المشرف، واختر hf-text-classification والمخطط sentiment، وتحقق من أن حقل Parameters يعرض مدخل dp، وانقر Train now. وتبدأ التشغيلة نفسها من API:
curl -X POST -H "X-API-Key: demo-admin-key" -H "Content-Type: application/json" \
http://localhost:8000/admin/training/api/runs \
-d '{"trainer": "hf-text-classification", "schemas": ["sentiment"]}'يحمل الرد run_id. تتجاوز params الخاصة بالتشغيلة trainer_params، ولذلك يدرّب "params": {"dp": {"epsilon": 2}} تشغيلة واحدة بميزانية أصغر، ويدرّب "params": {"dp": null} أو "params": {"dp": false} تشغيلة واحدة دون DP. أبقِ split_seed دون تغيير بين التشغيلتين، ليتدرّب كلاهما ويُقيَّم على العناصر نفسها وتقارَن درجتا العناصر المحجوزة مباشرة.
أسطر سجل التشغيلة تحت DP
تسرد صفحة التشغيلة في /admin/training/runs/<run_id> أحداث التشغيلة ومقاييسها. وتضيف تشغيلة DP ثلاثة أنواع من الأسطر إلى الأحداث.
يسمّي السطر الأول جداول التضمين التي يجمّدها Potato. يأخذ تضمينا الموضع ونوع الرمز في محوّل نصي صفاً واحداً تشترك فيه الدفعة كلها، ولا يستطيع Opacus حساب تدرّج لكل عنصر عبر صف مشترك. وفي النموذج الافتراضي distilbert/distilroberta-base تكون الجداول المجمّدة roberta.embeddings.position_embeddings وroberta.embeddings.token_type_embeddings. والجداول المجمّدة لا تتدرّب ولا تستهلك خصوصية، وتتدرّب تضمينات الكلمات وكل طبقة أخرى مع ذلك.
يبدأ السطر الثاني بـDP-SGD: ويذكر epsilon المستهدف وdelta والحقب المخططة ومضاعِف الضجيج الذي اختاره Opacus والاقتطاع لكل عنصر ومعدل أخذ العيّنات. تسحب كل خطوة دفعة بأخذ عيّنات بواسون، فينضم كل عنصر train إلى دفعة باستقلال باحتمال 1 / الدفعات في الحقبة. ومع 76 عنصر train في دفعات من 16، تضم الحقبة 5 دفعات ويعطي السجل معدل أخذ عيّنات 0.2000. ويحدّد مضاعِف الضجيج الانحراف المعياري للضجيج، ويعطي الأسئلة الشائعة في Opacus المدى من 0.1 إلى 2 معتاداً.
وبعد كل حقبة يبلّغ سطر بالصيغة Epoch <n>/<epochs>: loss <loss>, epsilon spent <epsilon> عن متوسط خسارة الحقبة وepsilon المستهلك حتى الآن. وتُسجَّل القيمة نفسها لكل حقبة بوصفها المقياس dp_epsilon، وتحمل المقاييس النهائية للتشغيلة dp_epsilon للتشغيلة كلها. يحدّد Opacus حجم الضجيج بحيث لا تستهلك الحقب المخططة أكثر من epsilon المستهدف. والتشغيلة التي تتوقف مبكراً بسبب patience (حقبتان دون درجة val أفضل افتراضياً) تستهلك أقل من المستهدف.
مدخل dp في بطاقة النموذج
تكتب التشغيلة model_card.json في artifacts/ داخل مجلد التشغيلة، <task_dir>/<output_annotation_dir>/training/runs/<run_id>/. وفي بطاقة تشغيلة DP مدخل dp:
| الحقل | القيمة |
|---|---|
epsilon_target | قيمة epsilon التي طلبتها |
epsilon_spent | ما استهلكته التشغيلة، من محاسب RDP في Opacus |
delta | قيمة delta التي استخدمتها التشغيلة، قيمتك أو الافتراضية |
max_grad_norm | الاقتطاع لكل عنصر |
noise_multiplier | مضاعِف الضجيج الذي اختاره Opacus |
accountant | rdp |
covers | train split |
يحتسب epsilon_spent كل حقبة تدرّبت التشغيلة عليها. وتدخل الحقب التي تلي نقطة الحفظ المحتفَظ بها في المجموع. ويرفع النشر على Hugging Face Hub ملف model_card.json مع النموذج، مع استبدال المسارات المحلية بأسماء الملفات، فيسافر مدخل dp مع الأوزان. وفي بطاقة النموذج README.md على Hub صفٌّ "Differential privacy" فيه epsilon المستهلك مقابل المستهدف وdelta وقسم train الذي يغطيه الضمان. ويحذف الصف الهدف أو delta حين لا تكون التشغيلة قد سجّلت القيمة.
اختيار ميزانية الخصوصية والاقتطاع
تعطي وثائق Potato المدى من 1 إلى 10 معتاداً لـepsilon، وتشترط أن تكون delta أقل من 1 / عناصر train. وتعطي الأسئلة الشائعة في Opacus قاعدة الإبهام نفسها لـdelta، وتوصي بثابت صغير لـepsilon مع delta ضئيلة جداً. وتقع delta الافتراضية 1 / (10 × عناصر train) تحت السقف 1 / عناصر train، ولذلك تستطيع معظم الدراسات ترك delta.
يوازن الاقتطاع max_grad_norm بين خطأين. فالاقتطاع يغيّر كل تدرّج أكبر من العتبة، وتقول الأسئلة الشائعة في Opacus إن الاقتطاع يضعف التقارب. ويتناسب الضجيج مع الاقتطاع، فالاقتطاع الأكبر يضيف ضجيجاً أكثر. وتضيف الأسئلة الشائعة أن العتبة الخاطئة تضر النماذج الخطية أكثر من العميقة. ابدأ من الافتراضي 1.0 وقارن درجات العناصر المحجوزة قبل ضبط الاقتطاع.
يحدّد Opacus حجم الضجيج للحقب المخططة epochs، ولذلك فإن epsilon نفسه موزعاً على حقب أقل يعني ضجيجاً أقل في كل خطوة. وتشير الأسئلة الشائعة في Opacus إلى أن الدفعة الأكبر ترفع معدل أخذ العيّنات، ومعه كلفة الخصوصية. وتقترح الأسئلة الشائعة معدل تعلّم أكبر وإيقافاً أبكر لتعويض الكلفة. قارن درجة العناصر المحجوزة لتشغيلة DP بدرجة تشغيلة بلا dp على التقسيم نفسه. والفجوة بين الدرجتين تقيس ما يكلّفه الضمان على بياناتك.
نطاق الضمان
يغطي الضمان قسم train. فتغيير عنصر train واحد يغيّر ما يمكن أن يكونه النموذج المنشور بمقدار epsilon المذكور على الأكثر. ويُحتسب العنصر مع التصنيف المحسوم من معلّقيه. ويذكر Potato الضمان لكل عنصر، ولا تذكر الوثائق ضماناً لكل معلّق.
قسم val خارج الضمان. فبعد كل حقبة يقيّم المُدرِّب النموذج على عناصر val ويحتفظ بنقطة الحفظ من الحقبة ذات أفضل درجة. وهذا الاختيار يقرأ تصنيفات عناصر val دون ضجيج، ولذلك لا تعد epsilon في بطاقة النموذج بشيء بشأن عناصر val. وحين تحتاج عناصر val إلى الحماية نفسها لعناصر train، اضبط كسر val على 0 وانقل الكسر إلى test، مثل splits: {train: 0.7, val: 0, test: 0.3}. وبدون عناصر val يحتفظ المُدرِّب بآخر حقبة، ولا توقف patience التشغيلة مبكراً، وتأتي درجة العناصر المحجوزة من test. وترك كسر train دون تغيير يُبقي العناصر نفسها في train، لأن Potato يسند الأقسام بتجزئة ببذرة لمعرّف كل عنصر.
قائمة تصنيفات النموذج خارج الضمان. يقرأ Potato قائمة التصنيفات من التصنيفات التي تظهر في البيانات، ولذلك يظهر تصنيف استخدمه المعلّقون على عنصر واحد بين مخرجات النموذج.
فروق التدريب تحت DP
يحتاج DP-SGD إلى تدرّج لكل عنصر، ولذلك تختلف تشغيلة DP عن تشغيلة عادية للمُدرِّب نفسه في ما يلي:
- يجري التدريب بدقة كاملة، أياً كان ما يقوله
precision، لأن الدقة المختلطة معطلة تحت DP. - يجب أن يكون
gradient_accumulationمساوياً 1. تدرّب كل خطوة دفعة واحدة مأخوذة بعيّنات بواسون. - يُرفض النموذج الأساسي المكمَّم (
lora.quantize). - تُجمَّد جداول تضمين الموضع ونوع الرمز في المحوّل النصي، كما يبلّغ سجل التشغيلة.
- النموذج الذي فيه طبقة لا يدعمها Opacus، مثل BatchNorm، يفشل عند بدء التدريب مع تسمية الطبقة.
لا يقبل dp إلا hf-text-classification وhf-image-classification. ويرفض كل مُدرِّب آخر معاملاً لا يقبله، ولذلك يفشل dp على sklearn-text أو setfit أو hf-token-classification عند الإقلاع تحت trainer_params وبخطأ 409 عند بدء التشغيلة.
أخطاء عند بدء التشغيلة
يبلّغ potato validate عن مفتاح لا يقبله dp وعن قيمة خارج المدى قبل بدء الخادم. وتفحص التشغيلة كتلة dp مرة أخرى عند بدئها، مع Opacus والحدود المعتمدة على قسم train. وتنتهي التشغيلة التي تفشل في هذه الفحوص بخطأ قبل التدريب، برمز validation_failed وكل المشكلات في رسالة واحدة. وتأتي الرسائل من فحوص Potato:
| المشكلة | الرسالة |
|---|---|
| Opacus غير مثبّت | dp needs opacus, which is not installed (pip install opacus). |
لا epsilon | dp needs epsilon, the privacy budget for the run (1 to 10 is usual). |
مفتاح لا يقبله dp | dp does not take bogus; it takes epsilon, delta and max_grad_norm. |
delta عند 1 / عناصر train أو فوقه | dp.delta is 0.05, at least 1 / 76 train items: at that delta one item's data could be released outright. Use less than 0.0131579. |
gradient_accumulation أكبر من 1 | dp trains one sampled batch per step; set gradient_accumulation to 1. |
ضبط lora.quantize | dp cannot train a quantized (4bit or 8bit) base model; drop lora.quantize. |
التخطيط الفارغ dp: {} يطلب DP بلا ميزانية ويفشل برسالة غياب epsilon. وحين تضبط trainer_params الكتلة dp، فإن "dp": null أو "dp": false في تشغيلة يوقف DP لتلك التشغيلة. ويسرد مسار الحالة GET /admin/training/api/status الرسائل نفسها تحت errors.
قراءات إضافية
- نظرة عامة على تدريب النماذج، لصفحة التدريب والنشر على Hub
- المُدرِّبات، لما يضبطه
hf-text-classificationوhf-image-classification - تهيئة تدريب النماذج، للتقسيمات ودرجات العناصر المحجوزة والكتابة الراجعة
- درّب نموذجك الأول، للمشروع نفسه دون GPU ودون DP
- التدريب عن بُعد، لتشغيل الضبط الدقيق الخاص تفاضلياً على خادم GPU
- الخصوصية التفاضلية (
dp) في مرجع تدريب النماذج في Potato
المراجع
- Abadi, M., Chu, A., Goodfellow, I., McMahan, H. B., Mironov, I., Talwar, K., and Zhang, L. (2016). Deep learning with differential privacy. Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security, 308-318. https://doi.org/10.1145/2976749.2978318
- Opacus. FAQ. https://opacus.ai/docs/faq