البحث عن الالتهاب الرئوي في الأشعة السينية مع Fast.ai

صادفت مقالًا على مدونة شركة School of Data وقررت التحقق من قدرة مكتبة Fast.ai على نفس مجموعة البيانات المذكورة في المقالة. لن تجد هنا حججًا حول مدى أهمية تشخيص الالتهاب الرئوي في الوقت المناسب وبشكل صحيح ، وما إذا كانت هناك حاجة لأخصائيي الأشعة في ظروف التطور التكنولوجي ، وما إذا كان التنبؤ بشبكة عصبية يمكن اعتباره تشخيصًا طبيًا ، إلخ. الهدف الرئيسي هو إظهار أن التعلم الآلي في المكتبات الحديثة يمكن أن يكون بسيطًا جدًا (يتطلب حرفيًا بضعة أسطر من التعليمات البرمجية) ويعطي نتائج ممتازة. دعنا نتذكر نتيجة المقال (الدقة = 0.84 ، أذكر = 0.96) ونرى ما يحدث معنا.

نحن نأخذ البيانات للتدريب من هنا . البيانات هي 5856 من الأشعة السينية موزعة على فئتين - مع أو بدون علامات الالتهاب الرئوي. تتمثل مهمة الشبكة العصبية في تزويدنا بتصنيف ثنائي للأشعة السينية عالي الجودة لتحديد علامات الالتهاب الرئوي.

نبدأ باستيراد المكتبات وبعض الإعدادات القياسية:

%reload_ext autoreload %autoreload 2 %matplotlib inline from fastai.vision import * from fastai.metrics import error_rate import os 

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

 bs = 64 

تحديث مهم:
كما هو موضح بحق في التعليقات أدناه ، من المهم أن نراقب بوضوح البيانات التي سيتم تدريب النموذج عليها والتي سنختبر فعاليتها. سنقوم بتدريب النموذج في الصور في مجلدات القطار و val ، والتحقق من صحة الصور الموجودة في مجلد الاختبار ، على غرار ما تم القيام به هنا .

نحدد مسارات البيانات الخاصة بنا

 path = Path('storage/chest_xray') path.ls() 

وتحقق من أن جميع المجلدات في مكانها (تم نقل المجلد val للتدريب):

 Out: [PosixPath('storage/chest_xray/train'), PosixPath('storage/chest_xray/test')] 

نحن نعد بياناتنا لـ "التحميل" في الشبكة العصبية. من المهم ملاحظة أنه في Fast.ai هناك عدة طرق لمطابقة تسمية الصورة. تخبرنا طريقة from_folder أن التسميات يجب أن تؤخذ من اسم المجلد الذي توجد به الصورة.

تعني المعلمة size أننا نغير حجم كل الصور إلى حجم 299 × 299 (تعمل الخوارزميات لدينا مع صور مربعة). تعطينا وظيفة get_transforms زيادة الصورة لزيادة مقدار بيانات التدريب (نترك الإعدادات الافتراضية هنا).

 np.random.seed(5) data = ImageDataBunch.from_folder(path, train = 'train', valid = 'test', size=299, bs=bs, ds_tfms=get_transforms()).normalize(imagenet_stats) 

لنلقِ نظرة على البيانات:

 data.show_batch(rows=3, figsize=(6,6)) 



للتحقق ، نلقي نظرة على الفئات التي حصلنا عليها والتوزيع الكمي للصور بين القطار والتحقق من الصحة:

 data.classes, data.c, len(data.train_ds), len(data.valid_ds) 

 Out: (['NORMAL', 'PNEUMONIA'], 2, 5232, 624) 

نحدد نموذج التدريب بناءً على بنية Resnet50:

 learn = cnn_learner(data, models.resnet50, metrics=error_rate) 

وابدأ التعلم في 8 عصور بناءً على سياسة دورة واحدة :

 learn.fit_one_cycle(8) 



نرى أننا حصلنا بالفعل على دقة بنسبة 89 ٪ في عينة التحقق من الصحة. سنقوم بتدوين أوزان نموذجنا في الوقت الحالي وسنحاول تحسين النتيجة.

 learn.save('step-1-50') 

"تذويب" النموذج بأكمله ، لأنه قبل ذلك ، قمنا بتدريب النموذج فقط على المجموعة الأخيرة من الطبقات ، وتم أخذ أوزان البقية من النموذج المدربين مسبقًا على Imagenet و "مجمدة":

 learn.unfreeze() 

نحن نبحث عن معدل التعلم الأمثل لمواصلة التعلم:

 learn.lr_find() learn.recorder.plot() 



نبدأ التدريب لمدة 10 عصور مع معدلات التعلم المختلفة لكل مجموعة من الطبقات.

 learn.fit_one_cycle(10, max_lr=slice(1e-6, 1e-4)) 



نرى أن دقة نموذجنا زادت قليلاً إلى 89.4٪ في عينة التحقق من الصحة.

نكتب الأوزان.

 learn.save('step-2-50') 

بناء مصفوفة الارتباك:
 interp = ClassificationInterpretation.from_learner(learn) interp.plot_confusion_matrix() 


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

هذا هو المكان الذي تدخل فيه مقاييس الدقة والاستدعاء في الاعتبار:

  • TP - التنبؤ الإيجابي الحقيقي ؛
  • TN - التنبؤ السلبي الحقيقي ؛
  • FP - التنبؤ الإيجابي الخاطئ ؛
  • FN - التنبؤ السلبي الكاذب.

الدقة $ = TP / (TP + FP) = 385/446 = 0.863 $


أذكر $ = TP / (TP + FN) = 385/390 = 0.987 دولار



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

Source: https://habr.com/ru/post/ar471282/


All Articles