البرمجة باستخدام PyTorch: بناء تطبيقات التعلم العميق

صورةمرحبا سكان! سيساعدك Ian Poynter في معرفة كيفية إعداد PyTorch في السحابة ، وكيفية إنشاء بنى عصبية تسهل العمل مع الصور والصوت والنص. يغطي هذا الكتاب المفاهيم الأساسية لتعلم النقل ، وتصحيح الأخطاء ، واستخدام مكتبة PyTorch. سوف تتعلم ما يلي: - تنفيذ نماذج التعلم العميق - استخدام PyTorch في المشاريع الكبيرة - تطبيق نقل التعلم - استخدام نماذج PyTorch torchaudio والتلافيفية لتصنيف البيانات الصوتية - تطبيق أحدث تقنيات البرمجة اللغوية العصبية باستخدام نموذج تم تدريبه على ويكيبيديا - نماذج تصحيح PyTorch باستخدام TensorBoard و Flamegraph - نشر تطبيقات PyTorch في الحاويات "تعد PyTorch واحدة من أسرع مكتبات التعلم العميق نموًا ، وتنافس عملاق Google TensorFlow - على قدم المساواة تقريبًا.





تصنيف الصور باستخدام PyTorch



تمتلئ كتب التعلم العميق بالمصطلحات المهنية وغير المفهومة. أحاول أن أبقيه عند الحد الأدنى وأقدم دائمًا مثالًا واحدًا يمكن تمديده بسهولة عندما تعتاد على العمل مع PyTorch. نستخدم هذا المثال في جميع أنحاء الكتاب لتوضيح كيفية تصحيح نموذج (الفصل 7) أو نشره في الإنتاج (الفصل 8).



من الآن فصاعدًا حتى نهاية الفصل 4 ، سنقوم بتجميع مصنف الصور. تستخدم الشبكات العصبية بشكل شائع كمصنفات للصور ؛ تعرض الشبكات صورة وتطرح سؤالاً بسيطًا: "ما هذا؟"



لنبدأ بإنشاء تطبيقنا في PyTorch.



مشكلة التصنيف



سننشئ هنا مصنفًا بسيطًا يمكنه تمييز السمكة عن القطة. سنقوم بتكرار عملية تصميم وتطوير نموذجنا لجعله أكثر دقة.

في التين. يصور الشكل 2.1 و 2.2 سمكة وقطة بكل مجدهم. لست متأكدًا مما إذا كانت السمكة تحمل اسمًا ، لكن اسم القطة هو Helvetica.



لنبدأ بمناقشة بعض مشاكل التصنيف القياسية.



صورة صورة



الصعوبات القياسية



كيف تكتب برنامجًا يمكنه تمييز سمكة من قطة؟ ربما تكتب مجموعة من القواعد التي تصف ما إذا كانت القطة لها ذيل أو أن السمكة بها مقاييس ، وتطبق تلك القواعد على الصورة حتى يتمكن البرنامج من تصنيف الصورة. لكن هذا سيستغرق وقتًا وجهدًا ومهارة. ماذا لو صادفت قطة مانكس؟ على الرغم من أنها قطة بوضوح ، إلا أنها لا تملك ذيلًا.



تزداد هذه القواعد تعقيدًا عندما تحاول وصف جميع السيناريوهات المحتملة باستخدامها. أيضًا ، يجب أن أعترف أن البرمجة المرئية سيئة بالنسبة لي ، لذا فإن التفكير في الاضطرار إلى كتابة التعليمات البرمجية يدويًا لجميع هذه القواعد أمر مرعب.



أنت بحاجة إلى وظيفة تقوم بإرجاع قطة أو سمكة عند إدخال صورة. من الصعب إنشاء مثل هذه الوظيفة بمجرد سرد جميع المعايير بالكامل. لكن التعلم العميق يجبر الكمبيوتر بشكل أساسي على القيام بالعمل الجاد لإنشاء كل هذه القواعد التي تحدثنا عنها للتو ، بشرط أن نقوم بإنشاء الهيكل ، وتزويد الشبكة بالكثير من البيانات ، وإعلامها إذا كانت تعطي الإجابة الصحيحة. هذا ما سنفعله. بالإضافة إلى ذلك ، سوف تتعلم بعض التقنيات الأساسية لاستخدام PyTorch.



لكن أولاً البيانات



أولا ، نحن بحاجة إلى البيانات. ما مقدار البيانات؟ يعتمد على عوامل مختلفة. كما سترى في الفصل 4 ، فإن فكرة أن أي تقنية تعلم عميق تتطلب كميات هائلة من البيانات لتدريب شبكة عصبية ليست صحيحة بالضرورة. ومع ذلك ، سنبدأ الآن من نقطة الصفر ، الأمر الذي يتطلب عادةً الوصول إلى الكثير من البيانات. مطلوب العديد من صور الأسماك والقطط.



يمكن للمرء أن يقضي بعض الوقت في تنزيل مجموعة من الصور من بحث الصور على Google ، ولكن هناك طريقة أسهل: المجموعة القياسية من الصور المستخدمة لتدريب الشبكات العصبية هي ImageNet. يحتوي على أكثر من 14 مليون صورة و 20 ألف فئة صور. هذا هو المعيار الذي تقارن به جميع مصنّفات الصور. لذلك ، ألتقط الصور من هناك ، على الرغم من أنه يمكنك اختيار خيارات أخرى إذا كنت تريد ذلك.



إلى جانب البيانات ، يجب أن يكون لدى PyTorch طريقة لتحديد ماهية القط وما هي السمكة. إنه سهل بما فيه الكفاية بالنسبة لنا ، ولكنه أصعب بالنسبة لجهاز الكمبيوتر (لهذا السبب قمنا بإنشاء برنامج!). نستخدم العلامات المرفقة بالبيانات وهذا ما يسمى التعلم الخاضع للإشراف. (إذا لم يكن لديك حق الوصول إلى أي من الملصقات ، فقد خمنت ذلك ،



فسيتم استخدام التعلم الآلي غير الخاضع للإشراف.) إذا استخدمنا بيانات ImageNet ، فلن تكون تسمياتها مفيدة لأنها تحتوي على الكثير من المعلومات. لا يعد وضع علامة على قطة أو سمك السلمون المرقط لجهاز كمبيوتر مثل قطة أو سمكة.



مطلوب لإعادة تسميتها. نظرًا لأن ImageNet عبارة عن مجموعة كبيرة من الصور ، فقد قمت بتجميع الصورة ووضع علامات على عناوين URL للأسماك والقطط (https://oreil.ly/NbtEU).



يمكنك تشغيل download.py script في هذا الدليل وسيقوم بتنزيل الصور من عناوين url ووضعها في مواقع التدريب المناسبة. إعادة وضع العلامات أمر بسيط ؛ يخزن البرنامج النصي صور القطط في دليل القطارات / القط وصور الأسماك في دليل القطارات / الأسماك. إذا كنت لا تريد استخدام برنامج نصي للتنزيل ، فما عليك سوى إنشاء هذه الأدلة ووضع الصور المقابلة في الأماكن الصحيحة. لدينا الآن بيانات ، لكننا نحتاج إلى تحويلها إلى تنسيق يمكن لـ PyTorch فهمه.



PyTorch ومحمل البيانات



غالبًا ما يكون تحميل البيانات وتحويلها إلى تنسيقات جاهزة للتدريب أحد مجالات علم البيانات التي تستغرق وقتًا طويلاً. طورت PyTorch متطلبات تفاعل البيانات الراسخة التي تجعلها واضحة جدًا ، سواء كنت تعمل مع الصور أو النصوص أو الصوت.



الشرطان الرئيسيان للعمل مع البيانات هما مجموعات البيانات ومحمل البيانات. مجموعة البيانات هي فئة بايثون تسمح لنا بتلقي البيانات التي نرسلها إلى الشبكة العصبية.



أداة تحميل البيانات هي ما ينقل البيانات من مجموعة البيانات إلى الشبكة. (قد يشمل ذلك معلومات مثل: كم عدد عمليات العاملين التي تقوم بتحميل البيانات إلى الشبكة؟ كم عدد الصور التي نقوم بتحميلها في نفس الوقت؟)



دعنا نلقي نظرة على مجموعة البيانات أولاً. يمكن لكل مجموعة بيانات ، سواء كانت تحتوي على صور أو صوت أو نص أو مناظر طبيعية ثلاثية الأبعاد أو معلومات سوق الأوراق المالية أو أي شيء آخر ، التفاعل مع PyTorch إذا كانت تفي بمتطلبات فئة Python المجردة هذه:



class Dataset(object):
     def __getitem__(self, index):
          raise NotImplementedError

     def __len__(self):
          raise NotImplementedError


الأمر بسيط جدًا: علينا استخدام طريقة تُرجع حجم مجموعة البيانات الخاصة بنا (len) ، وطريقة يمكنها استخراج عنصر من مجموعة البيانات في زوج (التسمية ، الموتر). وهذا ما يسمى بمحمل البيانات لأنه يمرر البيانات إلى الشبكة العصبية للتدريب. لذلك علينا كتابة جسم لطريقة getitem التي يمكنها التقاط صورة وتحويلها إلى موتر وإعادة وضعها ووضع علامة عليها مرة أخرى حتى تتمكن PyTorch من العمل معها. كل شيء واضح ، ولكن من الواضح أن هذا السيناريو يحدث كثيرًا ، فربما تجعل PyTorch المهمة أسهل؟



إنشاء مجموعة بيانات تدريبية



تتضمن حزمة torchvision فئة ImageFolder تقوم بكل شيء تقريبًا ، بافتراض أن صورنا في هيكل حيث يكون كل دليل عبارة عن تسمية (على سبيل المثال ، جميع القطط موجودة في دليل باسم cat). إليك ما تحتاجه لمثال القطة والأسماك:



import torchvision
from torchvision import transforms

train_data_path = "./train/"
transforms = transforms.Compose([
      transforms.Resize(64),
      transforms.ToTensor(),
      transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                std=[0.229, 0.224, 0.225] )
      ])

train_data = torchvision.datasets.ImageFolder
(root=train_data_path,transform=transforms)


تتم إضافة شيء آخر هنا لأن torchvision يتيح لك أيضًا تحديد قائمة من التحولات ليتم تطبيقها على الصورة قبل أن تدخل الشبكة العصبية. يتمثل التحويل الافتراضي في أخذ بيانات الصورة وتحويلها إلى موتر (طريقة التحويل (الأشكال المتحولة. ToTensor () الموضحة في الكود السابق) ، ولكنها تقوم أيضًا ببعض الأشياء الأخرى التي قد لا تكون واضحة.



أولاً ، تم تصميم وحدات معالجة الرسومات لأداء عمليات حسابية سريعة ذات حجم قياسي. لكن ربما لدينا مجموعة متنوعة من الصور بدقة عالية. لتحسين أداء المعالجة ، نقوم بقياس كل صورة إدخال بنفس دقة 64 × 64 باستخدام تحويل تغيير الحجم (64). ثم نقوم بتحويل الصور إلى موتر وأخيراً نقوم بتسوية الموتر حول مجموعة معينة من المتوسطات ونقاط الانحراف المعياري.



التطبيع مهم لأنه من المتوقع إجراء عدد كبير من المضاعفات أثناء مرور المدخلات عبر طبقات الشبكة العصبية ؛ يمنع الاحتفاظ بقيم الإدخال بين 0 و 1 زيادات كبيرة في القيم أثناء مرحلة التعلم (المعروفة باسم مشكلة التدرج المتفجر). هذا التجسيد السحري هو فقط المتوسط ​​والانحراف المعياري لمجموعة بيانات ImageNet ككل. يمكنك حسابه على وجه التحديد لمجموعة فرعية من الأسماك والقطط ، لكن هذه القيم موثوقة إلى حد ما. (إذا كنت تعمل على مجموعة بيانات مختلفة تمامًا ، فيجب حساب هذا المتوسط ​​والتباين ، على الرغم من أن الكثيرين يستخدمون ببساطة ثوابت ImageNet ويبلغون عن نتائج مقبولة.)



تسهل التحويلات القابلة للتركيب أيضًا تنفيذ إجراءات مثل تدوير الصورة وتحويل الصورة لزيادة البيانات ، وهو ما سنعود إليه في الفصل 4.



في هذا المثال ، نقوم بتغيير حجم الصور إلى 64 × 64. لقد قمت بهذا الاختيار العشوائي لتسريع عملية الحساب على شبكتنا الأولى. تستخدم معظم الأبنية الحالية ، التي ستراها في الفصل 3 ، 224 × 224 أو 299 × 299 لصور الإدخال الخاصة بهم .. بشكل عام ، كلما زاد حجم ملف الإدخال ، زادت البيانات التي يمكن للشبكة التعلم منها. الوجه الآخر للعملة هو يمكنك عادةً احتواء مجموعة أصغر من الصور في ذاكرة وحدة معالجة الرسومات.


هناك الكثير من المعلومات الأخرى حول مجموعات البيانات ، وهذا ليس كل شيء. ولكن لماذا نحتاج إلى معرفة أكثر مما نحتاج إليه إذا كنا نعرف بالفعل مجموعة بيانات التدريب؟



التحقق من صحة ومجموعات البيانات المرجعية



تم إعداد مجموعة بيانات التدريب الخاصة بنا ، لكننا الآن بحاجة إلى تكرار نفس الخطوات مع مجموعة بيانات التحقق. ما الفرق هنا؟ إحدى عيوب التعلم العميق (وفي الواقع كل التعلم الآلي) هو الإفراط في التجهيز: فالنموذج جيد حقًا في التعرف على ما تم تدريبه عليه ، لكنه لا يعمل على أمثلة لم يراها. يرى النموذج صورة قطة ، وإذا لم تكن جميع صور القطط الأخرى متشابهة جدًا مع هذا ، فإن النموذج يقرر أنها ليست قطة ، على الرغم من أن العكس واضح. لمنع الشبكة العصبية من التصرف على هذا النحو ، نقوم بتحميل عينة التحكم في download.py ، أي في سلسلة من صور القطط والأسماك غير الموجودة في مجموعة بيانات التدريب. في نهاية كل دورة تدريبية (تُعرف أيضًا بالحقبة) ، نقارن هذه المجموعة للتأكد من أن الشبكة ليست خاطئة. لا تنزعج ، رمز هذا الفحص بسيط للغاية:هذا هو نفس الرمز مع تغيير العديد من أسماء المتغيرات:



val_data_path = "./val/"
val_data = torchvision.datasets.ImageFolder(root=val_data_path,
                                                                  transform=transforms)


استخدمنا فقط سلسلة المحولات بدلاً من تعريفها مرة أخرى.



بالإضافة إلى مجموعة بيانات التحقق ، نحتاج أيضًا إلى إنشاء مجموعة بيانات للتحقق. يتم استخدامه لاختبار النموذج بعد الانتهاء من جميع التدريبات:



test_data_path = "./test/"
test_data = torchvision.datasets.ImageFolder(root=test_data_path,
                                                                   transform=transforms)


للوهلة الأولى ، يمكن أن تكون الأنواع المختلفة من المجموعات معقدة ومربكة ، لذلك قمت بتجميع جدول للإشارة إلى أي جزء من التدريب يستخدم كل مجموعة (الجدول 2.1).



صورة


يمكننا الآن إنشاء برامج تحميل بيانات ببضعة سطور أخرى من كود Python:



batch_size=64
train_data_loader = data.DataLoader(train_data, batch_size=batch_size)
val_data_loader = data.DataLoader(val_data, batch_size=batch_size)
test_data_loader = data.DataLoader(test_data, batch_size=batch_size)


الجديد والجدير بالملاحظة في هذا الرمز هو أمر batch_size. تقول عدد الصور التي ستمر عبر الشبكة قبل أن نتدرب ونحدثها. من الناحية النظرية ، يمكننا تعيين حجم_دفعة لسلسلة من الصور في مجموعات بيانات الاختبار والتدريب بحيث ترى الشبكة كل صورة قبل التحديث. من الناحية العملية ، لا يتم ذلك عادةً لأن الحزم الأصغر (المعروفة بشكل أكثر شيوعًا في الأدبيات باسم الحزم الصغيرة) تتطلب ذاكرة أقل ولا توجد حاجة لتخزين جميع المعلومات حول كل صورة في مجموعة البيانات ، ويؤدي حجم الحزمة الأصغر إلى تعلم أسرع مثل الشبكة التحديثات بشكل أسرع. بالنسبة إلى برامج تحميل بيانات PyTorch ، يتم تعيين حجم الدفعة على القيمة 1 افتراضيًا ، وستحتاج على الأرجح إلى تغييره. على الرغم من أنني اخترت 64 ، يمكنك تجربة الفهمكم عدد الحزم المصغرة التي يمكن استخدامها دون نفاد ذاكرة وحدة معالجة الرسومات. جرب بعض المعلمات الإضافية: على سبيل المثال ، يمكنك تحديد كيفية جلب مجموعات البيانات ، وما إذا كان سيتم تبديل مجموعة البيانات بالكامل عشوائيًا في كل مرة يتم تشغيلها ، وعدد مهام سير العمل المتضمنة لاسترداد البيانات من مجموعة البيانات. كل هذا يمكن العثور عليه فيوثائق PyTorch .



يتعلق الأمر بنقل البيانات إلى PyTorch ، لذلك دعونا الآن نتخيل شبكة عصبية بسيطة ستبدأ في تصنيف صورنا.



أخيرًا ، شبكة عصبية!



سنبدأ بأبسط شبكة تعلم عميق - طبقة إدخال ستعمل مع موترات الإدخال (صورنا) ؛ طبقة مخرجات بحجم عدد فئات الإخراج لدينا (2) ؛ وطبقة مخفية بينهما. في المثال الأول ، سنستخدم الطبقات المرتبطة بالكامل. في التين. يوضح الشكل 2.3 طبقة إدخال من ثلاث عقد ،

وطبقة مخفية من ثلاث عقد ومخرج من عقدتين.



في هذا المثال ، تؤثر كل عقدة في طبقة واحدة على عقدة في الطبقة التالية ، ولكل اتصال وزن يحدد قوة الإشارة من تلك العقدة إلى الطبقة التالية. (هذه هي الأوزان التي سيتم تحديثها عندما نقوم بتدريب الشبكة ، عادةً من التهيئة العشوائية.) عندما يمر الإدخال عبر الشبكة ، يمكننا (أو PyTorch) ببساطة مضاعفة أوزان وتحيزات تلك الطبقة عن طريق الإدخال. قبل تمريرها إلى الوظيفة التالية ، تدخل هذه النتيجة في وظيفة التنشيط ، وهي ببساطة طريقة لإدخال اللاخطية في نظامنا.



صورة


وظائف التنشيط



تبدو وظيفة التنشيط صعبة ، ولكن وظيفة التنشيط الأكثر شيوعًا التي يمكنك العثور عليها الآن هي ReLU ، أو الوحدة الخطية المصححة. ذكي مرة أخرى! لكن هذه مجرد وظيفة تنفذ max (0 ، x) ، وبالتالي تكون النتيجة 0 إذا كان الإدخال سالبًا ، أو مجرد الإدخال (x) إذا كانت x موجبة. بكل بساطة!



وظيفة التنشيط الأخرى التي من المرجح أن تصادفها هي الوظيفة اللوجيستية متعددة المتغيرات (softmax) ، وهي أكثر تعقيدًا من الناحية الرياضية. بشكل أساسي ، يولد مجموعة من القيم من 0 إلى 1 ، والتي تضيف ما يصل إلى 1 (الاحتمالات!) ، وتزن القيم بطريقة تزيد من الاختلاف ، أي أنها تنتج نتيجة واحدة في متجه سيكون أكبر من كل الآخرين. سترى غالبًا أنها تستخدم في نهاية شبكة التصنيف للتأكد من أن الشبكة ستقوم ببعض التنبؤات حول الفئة التي تعتقد أن بيانات الإدخال هي.



الآن بعد أن أصبح لدينا كل هذه اللبنات ، يمكننا البدء في بناء شبكتنا العصبية الأولى.



إنشاء الشبكة العصبية



يشبه بناء شبكة عصبية في PyTorch البرمجة في Python. نحن نرث من فئة تسمى torch.nn.Network ونملأ __init__ وطرق إعادة التوجيه:



class SimpleNet(nn.Module):

def __init__(self):
     super(Net, self).__init__()
     self.fc1 = nn.Linear(12288, 84)
     self.fc2 = nn.Linear(84, 50)
     self.fc3 = nn.Linear(50,2)

def forward(self):
     x = x.view(-1, 12288)
     x = F.relu(self.fc1(x))
     x = F.relu(self.fc2(x))
     x = F.softmax(self.fc3(x))
     return x
simplenet = SimpleNet()


مرة أخرى ، هذا ليس بالأمر الصعب. نقوم بإجراء الإعدادات اللازمة في init () ، وفي هذه الحالة نسمي مُنشئ الطبقة الفائقة وثلاث طبقات متصلة بالكامل (تسمى Linear in PyTorch ، وتسمى Dense in Keras). تصف طريقة forward () كيفية نقل البيانات عبر الشبكة ، سواء في التدريب أو في التنبؤ (الاستدلال). أولاً ، علينا تحويل الموتر ثلاثي الأبعاد (x و y بالإضافة إلى معلومات الألوان ثلاثية القنوات - الأحمر والأخضر والأزرق) في الصورة - انتباه! - في موتر أحادي البعد بحيث يمكن تمريره إلى الطبقة الخطية الأولى ، ونقوم بذلك باستخدام view (). وبالتالي ، فإننا نطبق الطبقات ووظائف التنشيط بالترتيب ، ونعيد إخراج softmax للحصول على التنبؤ لهذه الصورة.



الأرقام في الطبقات المخفية عشوائية ، باستثناء ناتج الطبقة الأخيرة ، وهي 2 ، والتي تتطابق مع فئتين - قطة أو سمكة. يتطلب بيانات في طبقات لتقليص حيث تتقلص في المكدس. إذا انتقلت الطبقة ، على سبيل المثال ، من 50 مدخلًا إلى 100 مخرجات ، فيمكن للشبكة أن تتعلم ببساطة عن طريق تمرير 50 ​​اتصالًا إلى خمسين من أصل مائة ناتج ، واعتبار عملها مكتملًا. من خلال تقليل حجم المخرجات فيما يتعلق بالمدخلات ، فإننا نجبر هذا الجزء من الشبكة على معرفة تمثيل المدخلات الأصلية بموارد أقل ، مما يعني على الأرجح أن الشبكة تحدد بعض السمات المميزة للصور: على سبيل المثال ، تعلمت التعرف على زعنفة أو ذيل.



لدينا توقعات ويمكن مقارنتها بالتسمية الفعلية للصورة الأصلية لمعرفة ما إذا كانت صحيحة. ولكنه يحتاج إلى طريقة ما للسماح لـ PyTorch بتحديد ليس فقط صحة أو عدم صحة التنبؤ ، ولكن أيضًا مدى صحته أو عدم صحته. تقوم وظيفة الخسارة بهذا.



نبذة عن الكاتب



Ian Poynter (Ian Pointer) - مهندس علم البيانات ، متخصص في حلول التعلم الآلي (بما في ذلك طرق التدريس المتعمقة) لعدد من العملاء في Fortune 100. في الوقت الحاضر ، يعمل Yang في Lucidworks ، التي تشارك في تطوير التطبيقات المتقدمة ومعالجة اللغات الطبيعية.



»يمكن العثور على مزيد من التفاصيل حول الكتاب على الموقع الإلكتروني لدار النشر

» فهرس المحتويات

» مقتطفات



لـ Habitants خصم 25٪ على القسيمة - PyTorch



عند الدفع مقابل النسخة الورقية من الكتاب ، يتم إرسال كتاب إلكتروني إلى البريد الإلكتروني.



All Articles