12 نوفمبر 2025
Misraj AI
AI
تهدف هذه المقالة إلى حساب متطلبات الذاكرة للشبكات العصبية العميقة (DNN). لقد كتبت هذه المقالة لتقديم نسخة مبسطة من المقالة السابقة حول استخدام الذاكرة في النماذج اللغوية الكبيرة (LLM). يمكنك فهم هذه ا...
تهدف هذه المقالة إلى حساب متطلبات الذاكرة للشبكات العصبية العميقة (DNN). لقد كتبت هذه المقالة لتقديم نسخة مبسطة من المقالة السابقة حول استخدام الذاكرة في النماذج اللغوية الكبيرة (LLM). يمكنك فهم هذه المقالة إذا كنت تعرف أساسيات الجبر الخطي وأساسيات Pytorch.
سوف نقوم بحساب استخدام الذاكرة على شبكة عصبية بسيطة لجعل حساب LLM أكثر منطقية.
سنبني شبكة عصبية باستخدام إطار عمل PyTorch. سنحسب ذاكرة النموذج البسيط، ونستخدم PyTorch لأن معظم المستخدمين على دراية بهذا الإطار، ولكن بغض النظر عن الإطار الذي ستستخدمه، فإن الحساب هو نفسه.
استيراد نظام التشغيل
استيراد الشعلة
من الشعلة استيراد nn
فئة NeuralNetwork (nn.Module):
def __init__ ( self ):
super ().__init__()
self.gat = nn.Linear( 2048 ، 4096 )
self.up = nn.Linear( 4096 ، 4096 )
self.down = nn.Linear( 4096 ، 2048 )
self.out = nn.Linear( 2048 ، 10 )
def forward ( self، x ):
gat_proj = nn.functional.relu(self.g(x))
up_proj = nn.functional.relu(self.up(gat_proj))
gat_proj = nn.functional.relu(gat_proj + up_proj)
gat_proj = nn.functional.relu(self.down(gat_proj))
gat_proj = gat_proj + x
out = nn.functional.softmax(gat_proj)
يحدد هذا الكود شبكة عصبية باستخدام وحدة PyTorch torch.nn. تم تصميم الشبكة في فئة تسمى NeuralNetwork، والتي ترث من nn.Module، وهي فئة أساسية لجميع وحدات الشبكة العصبية في PyTorch. دعنا نحلل مكونات ووظائف هذا الكود
تعريف الطبقات :
self.gat = nn.Linear(2048, 4096):يحدد طبقة متصلة بالكامل (تحويل خطي) تقوم بربط ميزات الإدخال بحجم 2048 بميزات الإخراج بحجم 4096.self.up = nn.Linear(4096, 4096):يحدد طبقة أخرى متصلة بالكامل تحافظ على حجم الميزة عند 4096.self.down = nn.Linear(4096, 2048):يحدد طبقة متصلة بالكامل تعمل على تقليل حجم الميزة إلى 2048 مرة أخرى.self.out = nn.Linear(2048, 10):يحدد طبقة نهائية متصلة بالكامل تقوم بتعيين ميزات 2048 إلى 10 فئات إخراج (على سبيل المثال، لمشكلة تصنيف تحتوي على 10 فئات).تمثل هذه الطبقات المعلمات القابلة للتعلم في النموذج وتمثل model_memory ، وهو ما نحتاجه في وقت الاستدلال.
دعونا نقسم ذاكرة الشبكة العصبية إلى 4 أجزاء،
استخدام الذاكرة = عدد العناصر × حجم كل عنصر
يتم تعريف حجم كل عنصر من قبل المستخدم على أنه بايت واحد، بايتان، أربعة بايتات. سنعتبر الحجم 2 لجميع العمليات الحسابية 'float32'
لذا، نحتاج إلى الحصول على عدد العناصر داخل هذا النموذج لحساب الذاكرة.
بالنسبة للثلاثة الأولى 'P، G، O' من السهل جدًا حساب الذاكرة لها، أولاً دعنا نحسب P.
من تعريف الطبقات، يمكننا أن نلاحظ أن لدينا 4 مصفوفات على النحو التالي [gat، up، down، out]، لحساب معلمات هذا النموذج، نحتاج فقط إلى حساب عدد العناصر في المصفوفات الأربع السابقة.
P = عدد المعلمات × 2 بايتnum_parameters = gat + up + down + out
num_parameters = ( 2024 * 4096 ) + ( 4096 * 4096 ) + ( 4096 * 2048 ) + ( 2048 * 10 )
num_parameters = 33574912
P = num_parameters * 4
P = 134299648 بايت
P ~= 128 ميجابايتلقد قلنا أن التدرج G هو نفس المعلمات P ،
G = P = 134299648 بايت
G = 128 ميجابايتبالنسبة للمحسن O يعتمد ذلك على المحسن نفسه، على سبيل المثال، إذا ألقيت نظرة على SGD و AdamW ، ستلاحظ أننا نحفظ ضعف عدد المعلمات مع AdamW للزخم، بينما نفس عدد المعلمات مع SGD أيضًا للزخم، سوف نستخدم AdamW لحساباتنا.
O = P * 2
O = 256 ميجابايتالآن وقد انتهينا من الجزء السهل، فلنبدأ في حساب ذاكرة التنشيط. ذاكرة التنشيط هي النسبة الرئيسية للذاكرة في وقت التدريب لبنية نموذج المحولات. ولكن بالنسبة لهذا المثال البسيط، ستكون صغيرة جدًا.
دعونا نشرح ما يحدث مع التنشيط وسنحسب الذاكرة مباشرة. ذاكرة التنشيط هي المعلمات التي ننشئها أثناء التمريرة الأمامية، يتم حفظ هذه المعلمات لحساب الانتشار الخلفي.
الطريقة الأمامية ( forwardالطريقة)
تعرف هذه الطريقة المرور الأمامي للشبكة، وتحدد كيفية xتدفق موتر الإدخال عبر طبقات الشبكة ووظائف التنشيط.
الطبقة الخطية الأولى والتنشيط :
gat_proj = nn.functional.relu(self.gat(x))x: يتم تمرير موتر الإدخال عبر gatالطبقة ويتم تطبيق دالة تنشيط ReLU. يؤدي هذا إلى تحويل ميزات الإدخال من 2048 إلى 4096 بعدًا وتطبيق اللاخطية. gat_projهو متجه به 4096 عنصرًا 'float16'الطبقة الخطية الثانية والتنشيط :
up_proj = nn.functional.relu(self.up(gat_proj)):يتم تمرير الميزات المحولة عبر upالطبقة ويتم تطبيق دالة تنشيط ReLU أخرى. وهذا يحافظ على حجم الميزة عند 4096 بعدًا مع عدم الخطية الإضافية. up_projهو متجه به 4096 'float16'الاتصال المتبقي والتنشيط :
gat_proj = nn.functional.relu(gat_proj + up_proj):يضيف الاتصال المتبقي gat_projويخرج up_projعلى أساس كل عنصر، متبوعًا بتنشيط ReLU. تهدف هذه الخطوة إلى الجمع بين الميزات الأصلية والمحولة، وإضافة اتصال اختصار لتحسين تدفق التدرج وأداء النموذج. سيؤدي هذا أيضًا إلى إضافة 4096 'float16'الطبقة الخطية الثالثة والتنشيط :
gat_proj = nn.functional.relu(self.down(gat_proj)):يتم تمرير الميزات المجمعة عبر downالطبقة، مما يقلل حجم الميزة مرة أخرى إلى 2048 بعدًا، يليه تنشيط ReLU. سيؤدي هذا إلى إضافة 2048 'float16'الاتصال المتبقي الثاني :
gat_proj = gat_proj + x:يضيف اتصال متبقي آخر موتر الإدخال xإلى عناصر الميزات المحولة gat_projعلى أساس كل عنصر على حدة. تعمل هذه الخطوة أيضًا على الجمع بين الميزات الأصلية والمحولة. سيؤدي هذا أيضًا إلى إضافة 2048 'float16'طبقة الإخراج النهائية :
out = self.functional.softmax(gat_proj):يتم تمرير الميزات الناتجة من خلال دالة softmax لإنتاج احتمالات الإخراج النهائية لـ 10 فئات. آخر شيء outمع 10 'float16'الآن نعلم كل خطوة مقدار العناصر التي ستضيفها ولكننا عادةً نستخدم الدفعة الصغيرة أثناء التدريب، لذا لجعل الحساب أكثر عمومية، سنضرب في حجم الدفعة،
ذاكرة التنشيط = حجم البارش * 4096 +
حجم الدفعة * 4096 +
حجم الدفعة * 4096 +
حجم الدفعة * 2048 +
حجم الدفعة * 2048 +
حجم الدفعة * 10
ذاكرة التنشيط = حجم الدفعة * ( 3 * 4096 + 2 * 2048 + 10 )
# حجم الدفعة 128
ذاكرة التنشيط = 128 * ( 16349 ) = 2098432
ذاكرة التنشيط = 2098432 *
ذاكرة التنشيط 4 بايت ~= 8 ميجا بايتمن خلال هذا، أصبحنا الآن نعرف جميع الأجزاء التي نحتاجها لتقدير الذاكرة لتدريب الشبكة العصبية،
إجمالي الذاكرة ~= ذاكرة النموذج + ذاكرة المُحسِّن + ذاكرة التدرج + ذاكرة التنشيط
إجمالي الذاكرة ~= ( 128 + 128 + 256 + 8 ) ميجابايت
إجمالي الذاكرة ~= 520 ميجابايتلمزيد من المعلومات المتقدمة حول الحساب في ماجستير القانون، يمكنك قراءة هذا المقال حول هذا الموضوع،
وفي الختام، نتعلم كيفية حساب متطلبات الذاكرة للشبكة العصبية أثناء مرحلة التدريب، وآمل أن تكون هذه المقالة أبسط من استخدام الذاكرة في LLM وأسهل للقراءة والفهم، وسأكون سعيدًا بالإجابة على أسئلتك ومناقشة أي ملاحظات، فلا تتردد في ترك أي تعليق إما للمناقشة أو إذا لاحظت أي خطأ في المقالة.
خليل حنارة
مهندس ذكاء اصطناعي في مسراج
تواصل معنا لتكتشف كيف يمكن لتقنيات مسراج أن تغيّر طريقة عمل مؤسستك.
لتبدأ رحلتك لحلول أذكى