ما وراء التداخل الكامل: تغطية تكيُّفية للمُعلِّقين في مجموعات البيانات الكبيرة
وضع تسمية مزدوجة لكل شيء مكلف، ووضع تسمية واحدة لكل شيء يجعلك عاجزًا عن الحكم على الجودة. يتيح لك Potato 2.6 إسناد مُعلِّق واحد لمعظم العناصر وثلاثة لعيِّنة طبقية، مع تعزيزات تكيُّفية وتوجيه تلقائي للفصل.
ثمة توتر قياسي في أي مشروع تعليق كبير الحجم. فإن حصل كل عنصر على مُعلِّقَين أو ثلاثة، أمكنك قياس الاتفاق والوثوق بتسمياتك، لكنك تكون قد ضاعفت ميزانيتك مرتين أو ثلاثًا. وإن حصل كل عنصر على مُعلِّق واحد، فإنك تُسمِّي ثلاثة أضعاف البيانات بالمبلغ نفسه، دون أن تكون لديك أدنى فكرة عن مدى موثوقية أيٍّ منها.
الحل الوسط المعتاد معروف لكل من أدار دراسة من قبل: علِّق معظم النصوص تعليقًا فرديًا، وعلِّق عيِّنة صغيرة تعليقًا مزدوجًا أو ثلاثيًا لمراقبة الجودة. كانت المشكلة دائمًا في جعل الأدوات تؤدي ذلك بنظافة، ثم القيام بشيء ما بالتداخل حالما يصبح بين يديك. يبني Potato 2.6 هذا التصميم داخليًا، عبر كتلتي إعداد (num_annotators_per_item وper_annotator_quota) إضافةً إلى التعزيزات التكيُّفية وتوجيه الفصل.
تستعرض هذه المقالة تصميم التغطية من الحالة البسيطة إلى الحالة التكيُّفية. وتجد المرجع الكامل في وثائق التغطية غير المتجانسة.
تغطية تكيُّفية للمُعلِّقين في Potato
حدود قصوى لكل عنصر مع عيِّنة تداخل
تقبل num_annotators_per_item عددًا صحيحًا واحدًا كحدٍّ أقصى موحَّد، أو خريطة مُهيكلة حين تريد تغطية عناصر مختلفة بطرق مختلفة. والشكل الشائع هو افتراض مُعلِّق واحد، مع رفع عيِّنة طبقية إلى ثلاثة:
num_annotators_per_item:
default: 1
overlap_sample:
fraction: 0.1
count: 3
stratify_by: domain
seed: 42
min: 1ترفع كتلة overlap_sample الحدَّ الأقصى على مجموعة فرعية حتمية من العناصر. تجري المعاينة مرة واحدة عند بدء التشغيل، وتُوسَم العناصر المختارة داخليًا بحيث تتعامل معها منطقية الإسناد منذ ذلك الحين كعناصر عالية التغطية. والحقول واضحة: fraction هي النسبة المُعايَنة، وcount هو الحدُّ الأقصى المرفوع (ويجب أن يتجاوز الافتراضي)، وseed يجعل الاختيار قابلًا لإعادة الإنتاج عبر عمليات إعادة التشغيل.
التفصيل الجدير بالتأمل هو stratify_by. وجِّهه إلى حقل في بياناتك (domain هنا)، فتُطبَّق النسبة لكل طبقة بدلًا من تطبيقها على المجموعة بأكملها. تُسهم كل فئة في عيِّنة التداخل بالتناسب، فلا تقيس الاتفاق على عيِّنة يصادف أن 90% منها من مجال واحد. وإن كانت مجموعتك تمزج بين الأخبار ووسائل التواصل الاجتماعي والنصوص السريرية، ظهر كلٌّ منها في عيِّنة الجودة بنسبة حجمه.
التعزيز التكيُّفي: أنفِق أكثر حيث يصعب الأمر
تُختار عيِّنة التداخل الثابتة على نحو أعمى، قبل أن يُعلِّق أحدٌ أيَّ شيء. لكن العناصر التي تحتاج فعلًا إلى نظرة ثانية وثالثة هي تلك التي يختلف عليها المُعلِّقون فعليًا، ولا تعرف أيُّها هي إلا بعد المرور الأول. والتعزيز التكيُّفي يعالج هذا بالضبط:
num_annotators_per_item:
default: 1
adaptive:
enabled: true
disagreement_threshold: 0.5
boost_to: 3حالما يحصل عنصرٌ على تعليقَين على الأقل ويتجاوز معدَّل اختلافه disagreement_threshold، يُرفع حدُّه الأقصى إلى boost_to ويعود العنصر إلى طابور الإسناد لمرور آخر. والتعزيز يحدث مرة واحدة لكل عنصر، فالعنصر المثير للجدل يحصل على تصعيد واحد بدلًا من أن يتفاقم بلا نهاية. هذه تغطية تتبع صعوبة البيانات بدلًا من تخمينها مسبقًا.
حصص لكل مُعلِّق
تتحكم الحدود القصوى للتغطية في عدد المُعلِّقين الذين يحصل عليهم كل عنصر. أما كتلة منفصلة فتتحكم في عدد العناصر التي يحصل عليها كل مُعلِّق، وهو ما تريد عادةً أن يتباين بحسب الخبرة أو العقد:
per_annotator_quota:
default: 100
by_user:
alice: 30
by_user_role:
expert: 30
novice: 200
user_roles:
alice: expert
carol: noviceتجري التسوية من الأكثر تحديدًا أولًا: by_user[uid]، ثم by_user_role[user_roles[uid]]، ثم default. وهكذا يمكنك تحديد سقف خبير بعينه عند 30 عنصرًا، وكل خبير آخر عند 30 بحسب الدور، والمبتدئين عند 200، دون أن يتداخل النظامان مع الحدود القصوى لكل عنصر أعلاه.
تحويل التداخل إلى قرار
جمع التداخل ليس سوى نصف العمل؛ فالمقصود هو التصرف حيال الاختلافات. ومع تفعيل كتلة الفصل، تُسجَّل عناصر عيِّنة التداخل التي تبلغ حدَّها الأقصى تلقائيًا وتُدفع إلى طابور فصل حين يهبط الاتفاق دون عتبتك:
adjudication:
enabled: true
adjudicator_users: [admin]
min_annotations: 2
agreement_threshold: 0.75والأثر أن العناصر منخفضة الاتفاق تطفو إلى السطح لحظة تشبُّع العيِّنة، بدلًا من انتظار أن يتذكر أحدٌ إعادة بناء الطابور يدويًا. يفتح المُحكِّم الطابور فيرى العناصر المتنازَع عليها فعلًا، وقد جرت تصفيتها بالفعل من الكتلة التي اتفق عليها الجميع.
قراءة الاتفاق
حالما تتشبَّع عناصر عيِّنة التداخل، تصبح إحصاءات الاتفاق متاحة عند /admin/iaa. تحسب نقطة النهاية المقياس المناسب لنوع كل مخطَّط بدلًا من فرض رقم واحد على كل شيء: Cohen's وFleiss' kappa للمخطَّطات الاسمية، وweighted kappa للترتيبية، وkappa على مستوى الرمز إضافةً إلى span F1 للنطاقات. وهذا مهم لأن قيمة κ المحسوبة وكأن تقييمات Likert الترتيبية لديك فئات غير مرتَّبة ستقلِّل من شأن الاتفاق الحقيقي.
تجربته
يُشحَن عرضٌ توضيحي قابل للتشغيل مع الإصدار. من جذر المستودع:
python potato/flask_server.py start examples/advanced/heterogeneous-coverage/config.yaml -p 8000يستخدم 20 عنصرًا عبر مجالين، ويُعايِن 20% لتداخل ثلاثي المُعلِّقين مُطبَّقًا طبقيًا حسب المجال، ويُفعِّل تعزيزًا تكيُّفيًا عند عتبة 0.5، ويُعرِّف مستويي خبرة، ويوجِّه العناصر منخفضة الاتفاق إلى الفصل: التصميم بأكمله أعلاه، من بدايته إلى نهايته.
شكل خطة تغطية جيدة
مجتمعةً، يتيح لك هذا التصميم أن تقرِّر إلى أين تذهب ميزانية تعليقك بدلًا من بسطها بالتساوي. تمرُّ معظم العناصر مرة واحدة. وتمرُّ شريحة طبقية ثلاث مرات، فتستطيع الإبلاغ عن الموثوقية عبر المجموعة كلها، لا عبر زاوية واحدة منها فحسب. والعناصر التي تتبيَّن صعوبتها الحقيقية تُصعَّد تلقائيًا، والمتنازَع عليها تُوجَّه إلى مُحكِّم. تنفق الأكثر على البيانات الأكثر ريبة، وتستطيع الدفاع عن كل قرار تغطية في قسم المنهجية.
أما كم مُعلِّقًا تحتاج فعليًا لمهمة بعينها فهي مسألة قائمة بذاتها؛ ومقالة كم عدد المُعلِّقين الذين تحتاجهم تستعرض القواعد التقريبية. هذا الإصدار يدور حول جعل أيِّ إجابة تستقرُّ عليها سهلة التعبير عنها. تُشحَن التغطية غير المتجانسة في Potato 2.6؛ راجع وثائق التغطية غير المتجانسة ومرجع إسناد المهام لكل ما تستطيع الكتل أعلاه فعله.