اعرف متى تكون مجموعة البيانات جاهزة
اجعل بدء أول عملية تدريب مشروطًا بثمانية اختبارات نجاح أو إخفاق، وأتمتة الاختبارات الثلاثة التي يمكن لبرنامج التحقق منها، واعرف الإصلاح الذي يتطلبه كل إخفاق.
يصل كل مشروع إلى مرحلة يرغب فيها الفريق ببدء التدريب. أحيانًا تكون مجموعة البيانات جاهزة، وأحيانًا أخرى لا تزال تتضمن تسربًا بين التقسيمات أو فئة غير موسومة بما يكفي، ما يهدر أسبوعًا من وقت GPU وينتج رقمًا لا ينبغي لأحد الوثوق به. تجعل ثمانية اختبارات، يُسجَّل لكل منها نجاح أو إخفاق أو استثناء موثّق، هذا القرار موضوعيًا بدلًا من أن يكون رهينًا للمزاج.
عملي
الاختبارات الثمانية#
| # | الفحص | معايير النجاح | إذا أخفق الاختبار، فارجع إلى |
|---|---|---|---|
| 1 | هدف واضح | الهدف والمهمة والفئات واختبار القبول موثّقة ومتفق عليها | ابدأ بهدف العمل |
| 2 | فئات محددة | لكل فئة تعريف، ومثال مسمّى لشيء مشابه لا يشمله التعريف | الهدف ودليل وضع الوسوم |
| 3 | صور ممثلة | تستوفي كل حالة في المواصفات حصتها، وتأتي معظم الصور من مصادر الإنتاج | جمع بيانات عالية الجودة وممثلة |
| 4 | حجم كافٍ | ≥ 1,500 صورة و≥ 10,000 حالة لكل فئة، أو استثناء موثّق | المواصفات والجمع |
| 5 | وسوم متسقة | الدليل مكتوب، وجولة المعايرة مكتملة، ومستوى الاتفاق ≥ 90% | أفضل ممارسات وضع الوسوم |
| 6 | اكتمل ضبط الجودة | اجتاز برنامج التدقيق الفحص، ورُوجعت الحالات المشتبه بها، ودُوّنت ملاحظات ضبط الجودة | ضبط جودة مجموعة البيانات |
| 7 | تقسيمات سليمة | تقسيم مُجمّع، ولا تظهر أي مجموعة في تقسيمين، وكل فئة موجودة في كل تقسيم | قسّم مجموعة البيانات على نحو صحيح |
| 8 | صور الخلفية | 0–10% من الصور إطارات فارغة من الوسوم | المواصفات والجمع |
تضبط قائمة التحقق القرارات نفسها التي يتناولها دليل جمع البيانات ووضع الوسوم واحدًا تلو الآخر؛ وهنا تُجمع في قرار واحد بالمضي أو عدمه.
أتمتة الاختبارات القابلة للعد#
الاختبارات 4 و7 و8 حسابية، لذا يقيّمها البرنامج بالطريقة نفسها في كل مرة. يقرأ هذا البرنامج مجموعة التدريب التجريبية وقوائم التقسيمات التي أنشأها group_split.py في الدرس السابق:
from collections import Counter
from pathlib import Path
root = Path("datasets/practice") # images/, labels/, and the train/val/test.txt lists from group_split.py
splits = {s: [Path(p).stem for p in (root / f"{s}.txt").read_text().split()] for s in ("train", "val", "test")}
def classes(stem):
label = root / "labels" / f"{stem}.txt"
return [int(r.split()[0]) for r in label.read_text().splitlines() if r.strip()] if label.exists() else []
stems = [s for split in splits.values() for s in split]
instances = Counter(c for s in stems for c in classes(s))
images = Counter(c for s in stems for c in set(classes(s)))
background = sum(not classes(s) for s in stems) / len(stems)
groups = {split: {s.rsplit("_", 1)[0] for s in names} for split, names in splits.items()}
per_split = {split: {c for s in names for c in classes(s)} for split, names in splits.items()}
shared = (groups["train"] & groups["val"]) | (groups["train"] & groups["test"]) | (groups["val"] & groups["test"])
weakest = min(instances, key=lambda c: (images[c], instances[c]))
checks = {
"4 volume": (images[weakest] >= 1500 and instances[weakest] >= 10_000,
f"weakest class {weakest}: {images[weakest]} images, {instances[weakest]} instances"),
"7 no shared groups": (not shared, f"{len(shared)} groups appear in more than one split"),
"7 every class in every split": (all(per_split[s] == set(instances) for s in splits),
", ".join(f"{s} misses {len(set(instances) - per_split[s])}" for s in splits)),
"8 background 0-10%": (background <= 0.10, f"{background:.1%} background images"),
}
for name, (ok, detail) in checks.items():
print(f"{'PASS' if ok else 'FAIL'} {name:<29} {detail}")FAIL 4 volume weakest class 30: 1 images, 1 instances
PASS 7 no shared groups 0 groups appear in more than one split
FAIL 7 every class in every split train misses 5, val misses 36, test misses 41
PASS 8 background 0-10% 1.6% background imagesعالج التقسيم المُجمّع مشكلة التسرب، لكن مجموعة التدريب التجريبية لا تقترب من الجاهزية: فالفئة الأضعف فيها (30، skis) لا تحتوي إلا على حالة واحدة موسومة، ولا يستطيع val تقييم نصف الفئات. وهذه هي النتيجة المتوقعة لـ128 صورة تجريبية، وهي بالضبط النتيجة التي صُمم هذا الاختبار لإظهارها قبل قضاء أسبوع في التدريب.
يغطي البرنامج النصي ما يمكن عده. أما عمليات التحقق 1 و2 و3 و5 و6 فتحتاج إلى شخص: هدف متفق عليه، وتعريفات مكتوبة، وتغطية للمواصفات، ودرجة اتفاق مقاسة، وملاحظات مراقبة الجودة. قيّمها يدويًا، مع سطر واحد من الأدلة لكل منها.
اتخذ القرار: درّب، أو امضِ مع وجود فجوة، أو أصلح#
عند إخفاق أحد الاختبارات، تكون الخطوة التالية المغرية في الغالب أي شيء سوى إصلاح البيانات:
| الاختصار المغري | سبب عدم جدواه |
|---|---|
| "جرّب نموذجًا أكبر." | يتعلم النموذج الأكبر ضوضاء الوسوم بالكفاءة نفسها. |
| "اضبط معدل التعلّم." | لا يضيف أي إعداد للمحسّن فئة أو حالة مفقودة. |
| "درّب لعدد أكبر من الحقب." | يؤدي التدريب لحقب إضافية على بيانات محدودة إلى فرط التكيّف بسرعة أكبر. |
| "أضف مزيدًا من التعزيز." | لا يستطيع التعزيز إنشاء حالات لم تتضمنها البيانات قط. |
ثلاثة أنماط تكاد تكون جاهزة#
| النمط | الاختبار الذي أخفق | ما يبدو عليه | الحل |
|---|---|---|---|
| حجم كبير دون تنوع | 3 | 5,000 صورة، وكاميرا واحدة، ولا حالات طرفية | اجمع الصور من كاميرات ومواقع وأوقات أكثر قبل التدريب |
| تنوع دون اتساق | 5 | يختلف واضعو الوسوم في امتداد الصندوق والتعامل مع الحجب | أكمل الدليل، وأجرِ المعايرة، وأعد وضع الوسوم للعينات المتأثرة |
| تسرب خفي | 7 | تقسيم عشوائي لكل صورة على حدة لإطارات الفيديو | أعِد التقسيم حسب المقطع أو الكاميرا أو اليوم؛ وتوقّع انخفاض mAP التحقق، لأن هذا الانخفاض يعكس الواقع |
أطلق مع فجوة معروفة#
غالبًا ما يكون القرار الصائب هو البدء بنموذج أولي مركّز قبل اجتياز جميع الفحوص: تجربة تجريبية، أو نموذج أولي، أو إصدار أول على مجموعة فرعية من الكاميرات. يكشف النموذج المستخدم في الإنتاج ما هو خاطئ فعليًا بسرعة أكبر من تنقيح مجموعة البيانات في الظلام. عند الإطلاق مع وجود فجوة، دوّن ثلاثة أمور:
- الفحص الذي لم يجتز الاختبار.
- الأثر المتوقع، مثل «لا توجد بيانات ليلية؛ توقّع انخفاض الاستدعاء بعد حلول الظلام».
- خطة جمع البيانات التي تسد الفجوة أثناء تشغيل الإصدار الأول.
عبارة «الحجم: استثناء» لا تخبر الشخص التالي بشيء. أما «الحجم: pallet عند 700 حالة، توقّع انخفاض استدعاء المنصات النقالة في الممرات المزدحمة؛ ستتم تسمية 2,000 حالة إضافية بحلول يونيو» فهي تعبّر عن مخاطرة مُدارة. يجب أن يذكر كل استثناء أثره المتوقع على اختبار القبول.
أعِد الفحوص قبل كل إعادة تدريب#

مجموعة البيانات التي كانت جاهزة للإصدار الأول ليست بالضرورة جاهزة للإصدار الثالث. قد تؤدي الفئات الجديدة والمصادر الجديدة والموسومون الجدد، كلٌّ على حدة، إلى إخفاق فحص كان يجتازه سابقًا، كما تنحرف بيانات الإنتاج بينما تتراكم الوسوم الجديدة. أعد تشغيل readiness.py وأعِد تقييم الفحوص اليدوية قبل كل إعادة تدريب؛ فهذا يستغرق دقائق، وقد يكلفك تخطيه أسبوعًا من التدريب على مجموعة بيانات معطوبة.
عرض الحل
قائمة تحقق مُقيَّمة لمجموعة التدريب:
| # | الفحص | الدرجة | الدليل |
|---|---|---|---|
| 1 | هدف واضح | نعم | objective.md وacceptance_test.py من الدرس 1 |
| 2 | فئات محددة | لا | لا توجد تعريفات مكتوبة لأسماء COCO الثمانين أو أمثلة مشابهة مستبعدة |
| 3 | صور ممثّلة | لا | coverage.py: الكاميرات cam2–cam4 دون الحد المطلوب |
| 4 | حجم كافٍ | لا | readiness.py: أضعف فئة لها صورة واحدة |
| 5 | وسوم متسقة | لا | نسبة الاتفاق 47% في جولة المعايرة |
| 6 | اكتملت مراقبة الجودة | جزئي | أُجريت المراجعة؛ وما زالت الحالات المشتبه بها في 000000000438.jpg دون حسم |
| 7 | تقسيمات سليمة | لا | لا توجد مجموعات مشتركة، لكن مجموعة التحقق تفتقد 36 فئة من أصل 71 |
| 8 | صور الخلفية | نعم | 1.6% |
القرار: الإصلاح أولًا. الترتيب حسب المخاطر التي تهدد اختبار القبول: (1) تقليص قائمة الفئات إلى الفئات التي يحتاج إليها الهدف، ما يقلّص الفحوص 2 و4 و7 دفعةً واحدة؛ (2) جمع مزيد من المجموعات لتلك الفئات؛ (3) استكمال القاعدة الإرشادية المتعلقة بالأشخاص البعيدين وإعادة وسمهم. تفشل مجموعة العرض التوضيحي في هذا الفحص، وينبغي لها ذلك.