Skip to content
دروس تعليميةمدة القراءة 9 دقيقة

مهام مقارنة الصور والتفضيل

ابنِ في Potato مهمة لمقارنة الصور تعرض صورتين جنباً إلى جنب مع مخطط للتفضيل وترتيب عرض عشوائي وإعداد للترتيب عند وجود مجموعات أكبر من الصور.

Potato Team

يبني هذا الدليل التعليمي في Potato مهمة لمقارنة الصور تعرض صورتين مولّدتين جنباً إلى جنب، مع مقياس تفضيل من خمس نقاط، وأسئلة متابعة لكل معيار على حدة، ثم صيغتي الترتيب وBest-Worst Scaling للمجموعات التي تضم أكثر من صورتين. ويصلح البناء نفسه لبيانات التفضيل في RLHF، ولمقارنات الضغط وتحسين الصور، ولاختبارات A/B في التصميم.

تطلب المقارنة من المُوسِّم أن يختار بين صورتين بدلاً من أن يضع صورة واحدة على مقياس، وهذا يُغني عن اشتراك جميع المُوسِّمين في معايرة واحدة لمعنى الدرجة 4 من 5. والثمن أن مجموعة من n صورة تحتاج إلى أحكام أكثر بكثير للوصول إلى ترتيب كامل، وهذا ما تعالجه قسما الترتيب وBest-Worst Scaling في آخر المقال.

ملف البيانات

يحمل كل صف معرّفاً ومساري الصورتين وأي سياق يحتاجه المُوسِّم للحكم عليهما. يقرأ Potato أسماء الحقول من item_properties، ولذلك فاختيار الأسماء نفسها متروك لك:

json
{"id": "pair_001", "prompt": "A sunset over mountains", "image_a": "/media/model_a_001.png", "image_b": "/media/model_b_001.png"}
{"id": "pair_002", "prompt": "A cat on a windowsill", "image_a": "/media/model_a_002.png", "image_b": "/media/model_b_002.png"}

عرض صورتين جنباً إلى جنب

يُضبط المحتوى والأسئلة في Potato كلٌّ على حدة. تحدد الكتلة instance_display ما ينظر إليه المُوسِّم، وتحدد annotation_schemes ما يُسأل عنه. يضع حقلان من نوع image مع تخطيط أفقي الصورتين إحداهما بجانب الأخرى، ويتيح zoomable للمُوسِّم فحص العيوب التي لا تظهر بحجم العرض العادي:

yaml
instance_display:
  layout:
    direction: horizontal
    gap: 24px
  fields:
    - key: image_a
      type: image
      label: "Image A"
      display_options:
        max_height: 512
        zoomable: true
        alt_text: "First generated image"
    - key: image_b
      type: image
      label: "Image B"
      display_options:
        max_height: 512
        zoomable: true
        alt_text: "Second generated image"

هذا ما يراه المُوسِّم بعد ضبط العرض والمخطط كليهما:

صورتان جنباً إلى جنب وتحتهما مقياس للتفضيلمهمة مقارنة تعرض المرشّحَين وتحتهما سؤال التفضيل

سؤال التفضيل

يميّز المقياس ذو النقاط الخمس بين التفضيل القوي والتفضيل الضعيف، وهذا مهم عندما تدرّب نموذجاً على النتيجة، لأن الزوج الذي انقسم حوله المُوسِّمون بالتساوي يحمل إشارة تدريب مختلفة عن زوج حكموا عليه جميعاً بوضوح. يربط sequential_key_binding الخيارات الخمسة بالمفاتيح من 1 إلى 5، وهذا هو الفرق بين مقارنة تستغرق أربع ثوانٍ وأخرى تستغرق اثنتي عشرة ثانية.

yaml
annotation_schemes:
  - annotation_type: radio
    name: preference
    description: "Which image better matches the prompt?"
    labels:
      - name: "A is clearly better"
      - name: "A is slightly better"
      - name: "About equal"
      - name: "B is slightly better"
      - name: "B is clearly better"
    sequential_key_binding: true
    label_requirement:
      required: true

أضف هذه الكتلة إلى الإعداد السابق. اجعل الخيار الأوسط "About equal" وليس "No preference"، لأن العبارتين تصفان حكمين مختلفين، ولأن المُوسِّمين يستخدمون خيار "no preference" زراً للتخطي.

تحيّز الموضع

يختار المُوسِّمون الخيار الأيسر أكثر مما ينبغي، ولذلك يجب أن يتغير الجانب الذي تظهر فيه كل صورة. اجعل ذلك عشوائياً عند بناء ملف البيانات، بتبديل image_a وimage_b في نصف عشوائي من الصفوف وتسجيل اتجاه كل صف، ثم أعِد الأحكام المسجلة إلى اتجاهها الأصلي قبل تحليلها. تُعرض حقول العرض في Potato بالترتيب الذي تسردها به، ولذلك لا يستطيع الإعداد أن يقوم بهذا نيابة عنك.

أما مقارنات النصوص فمختلفة. يأخذ المخطط pairwise مرشّحَيه من حقل واحد في بيانات العنصر، ولذلك يستطيع randomize_order أن يبدّل ترتيبهما، ويسجّل Potato الترتيب الذي رآه كل مُوسِّم فعلاً. تُشتق البذرة من المُوسِّم والعنصر والمخطط معاً، وهذا ما يجعل ميل الشخص إلى الموضع الأول يقع على مرشّحين مختلفين من عنصر إلى آخر بدلاً من أن يرتبط بجانب واحد طوال الدراسة. راجع توثيق المقارنة الثنائية عندما يكون ما تقارنه نصوصاً.

السؤال عن معايير محددة

يخبرك التفضيل العام بالصورة التي فازت ولا يخبرك بشيء عن السبب. وإضافة سؤالين أو ثلاثة أسئلة ضيقة تحته تجعل الخلافات قابلة للفهم، إذ كثيراً ما يتفق المُوسِّمون المختلفون في الحكم العام على مدى الالتزام بالموجِّه ويختلفون في الجانب الجمالي.

yaml
  - annotation_type: radio
    name: prompt_adherence
    description: "Which image better matches the prompt?"
    labels:
      - name: A
      - name: Tie
      - name: B
 
  - annotation_type: multiselect
    name: issues_a
    description: "Problems in Image A (select all that apply)"
    labels:
      - name: "Distorted faces or hands"
      - name: "Text rendering errors"
      - name: "Unnatural lighting"
      - name: "Missing elements from the prompt"
      - name: "Blurry or low quality"
      - name: "None"

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

المقارنة قبل وبعد

تستخدم مهام التحسين والترميم والتحرير البناء نفسه ذا الصورتين، مع تسمية الجانبين بدلاً من جعلهما عشوائيين، لأن معرفة أي الجانبين هو الأصل جزء من السؤال:

yaml
instance_display:
  layout:
    direction: horizontal
    gap: 24px
  fields:
    - key: original
      type: image
      label: "Original"
      display_options:
        max_height: 512
        zoomable: true
    - key: enhanced
      type: image
      label: "Enhanced"
      display_options:
        max_height: 512
        zoomable: true
 
annotation_schemes:
  - annotation_type: radio
    name: enhancement_quality
    description: "How did the edit change the image?"
    labels:
      - name: "Clearly improved"
      - name: "Slightly improved"
      - name: "No noticeable change"
      - name: "Made worse"
    label_requirement:
      required: true
 
  - annotation_type: multiselect
    name: problems_introduced
    description: "Problems the edit introduced (select all that apply)"
    labels:
      - name: "Over-sharpening or halos"
      - name: "Color shift"
      - name: "Loss of detail"
      - name: "New artifacts"
      - name: "None"

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

أكثر من صورتين

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

yaml
item_properties:
  id_key: id
  text_key: prompt
 
instance_display:
  fields:
    - key: prompt
      type: text
      label: "Prompt"
    - key: images
      type: gallery
      display_options:
        layout: grid
        columns: 2
        thumbnail_size: 320
        zoomable: true
 
annotation_schemes:
  - annotation_type: ranking
    name: preference_rank
    description: "Drag the image numbers to rank them from best at the top to worst at the bottom."
    labels:
      - "Image 1"
      - "Image 2"
      - "Image 3"
      - "Image 4"
    allow_ties: false
    label_requirement:
      required: true

تسمّي labels المواضع في المعرض، ولذلك يجب أن تحمل القائمة مدخلاً واحداً لكل صورة، وأن يكون لكل عنصر العدد نفسه من المرشّحين. يناسب الترتيب المجموعات الصغيرة، لأن المُوسِّم يقارن كل مرشّح بكل مرشّح آخر في آن واحد. وفوق ثمانية مرشّحين تقريباً يزداد الجهد المبذول في كل عنصر أسرع مما تزداد المعلومات التي تحصل عليها.

المجموعات الأكبر

يكون Best-Worst Scaling هو الخيار عندما تكون المجموعة أكبر من أن تُرتَّب في شاشة واحدة. يرى المُوسِّمون مجموعة صغيرة من العناصر، أربعة في العادة، ويختارون الأفضل والأسوأ فقط، ثم تُحسب الدرجات عبر مجموعات كثيرة متداخلة:

yaml
  - annotation_type: bws
    name: quality
    description: "Select the BEST and the WORST image in this set."
    tuple_size: 4
    best_description: "Best"
    worst_description: "Worst"

أضف هذا المخطط إلى الإعداد السابق. يجري حساب الدرجات بعد الجمع، من تبويب BWS في لوحة الإدارة أو من سطر الأوامر، ويكتب bws_scores.tsv في مجلد الإخراج:

bash
python -m potato.bws_scoring --config config.yaml --method bradley_terry

لا تحتاج الطريقة counting إلى أي اعتماديات إضافية، وهي خط الأساس الشفاف. أما bradley_terry فيلائم نموذجاً على المقارنات الثنائية الضمنية ويحتاج إلى pip install choix. ويُنمذج plackett_luce كل اختيار للأفضل والأسوأ مباشرةً، ولا يحتاج إلى شيء غير Potato نفسه. ويشرح توثيق Best-Worst Scaling توليد المجموعات الذي يجب أن يسبق كل هذا.

التعليمات وفحوصات الانتباه

اذكر في التعليمات ما يعنيه "أفضل" في هذه المهمة، لأن المُوسِّمين سيضعون تعريفهم الخاص إن لم تفعل، ولن تكتشف ذلك إلا في مرحلة قياس الاتفاق. يضع annotation_instructions النص في كل صفحة توسيم:

yaml
annotation_instructions: |
  Judge each pair on how well it matches the prompt first, then on visual
  quality, then on how appealing it looks. Zoom in before deciding: hands,
  text, and fine texture are where generation failures show up. Mark "About
  equal" only when you have looked at both and cannot separate them.

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

yaml
attention_checks:
  enabled: true
  items_file: "data/attention_checks.json"
  frequency: 20
  min_response_time: 3.0
  failure_handling:
    warn_threshold: 2
    block_threshold: 5

أضف الكتلتين إلى الإعداد السابق. يلتقط min_response_time نمط الإخفاق الأكثر تهديداً لمهمة المقارنة، وهو مُوسِّم ينقر بسرعة لا تترك له وقتاً للنظر إلى الصورة الثانية.

الإعداد الكامل

يشغّل هذا الإعداد عملية جمع تفضيلات لـ RLHF بمخرَجين من النموذج لكل عنصر، وتفضيل من خمس نقاط، وسؤال واحد عن معيار، وتقدير للثقة. يرى ثلاثة مُوسِّمين كل زوج، وهذا يكفي للإبلاغ عن الاتفاق ولأخذ تسمية الأغلبية.

yaml
annotation_task_name: "Generative Model Comparison"
task_description: "Compare two generated images against the prompt that produced them."
 
data_files:
  - data/model_outputs.json
 
item_properties:
  id_key: id
  text_key: prompt
 
instance_display:
  layout:
    direction: horizontal
    gap: 24px
  fields:
    - key: image_a
      type: image
      label: "Image A"
      display_options:
        max_height: 512
        zoomable: true
        alt_text: "First generated image"
    - key: image_b
      type: image
      label: "Image B"
      display_options:
        max_height: 512
        zoomable: true
        alt_text: "Second generated image"
 
annotation_instructions: |
  Judge each pair on prompt match first, then visual quality, then appeal.
  Zoom in before deciding. Mark "About equal" only when you cannot separate them.
 
annotation_schemes:
  - annotation_type: radio
    name: preference
    description: "Which image better represents the prompt?"
    labels:
      - name: "A is clearly better"
      - name: "A is slightly better"
      - name: "About equal"
      - name: "B is slightly better"
      - name: "B is clearly better"
    sequential_key_binding: true
    label_requirement:
      required: true
 
  - annotation_type: radio
    name: prompt_adherence
    description: "Which image matches the prompt more closely?"
    labels:
      - name: A
      - name: Tie
      - name: B
 
  - annotation_type: likert
    name: confidence
    description: "How confident are you in this judgment?"
    size: 5
    min_label: "Guessing"
    max_label: "Certain"
 
attention_checks:
  enabled: true
  items_file: "data/attention_checks.json"
  frequency: 20
  min_response_time: 3.0
  failure_handling:
    warn_threshold: 2
    block_threshold: 5
 
num_annotators_per_item: 3
output_annotation_dir: annotation_output/image-comparison/
export_annotation_format: jsonl

شغّله بالأمر potato start config.yaml -p 8000، وافتح المنفذ في المتصفح، وسجّل الدخول لتتأكد من أن الزوج يُعرض كما تتوقع قبل أن ترسل الرابط إلى أي أحد. ووسِّم بعض العناصر بنفسك أيضاً، لأن المخطط الذي يبدو واضحاً في الإعداد كثيراً ما يتبين أنه غامض عند الزوج الحقيقي الثالث.

ما يحتويه الإخراج

يكتب Potato ملفات لكل مُوسِّم تحت output_annotation_dir، ويضيف export_annotation_format تصديراً دورياً تحت <output_annotation_dir>/exports/<format>/. يذكر كل سجل مُصدَّر المثيل والمُوسِّم والتسمية المختارة لكل مخطط:

json
{"instance_id": "pair_001", "user_id": "rater_01", "labels": {"preference": {"A is slightly better": "A is slightly better"}, "confidence": {"4": "4"}}, "spans": {}, "links": {}}

اربط ذلك بملف بياناتك عبر instance_id لتعرف أي نموذج أنتج كل جانب، وألغِ تبديل اليسار واليمين الذي طبقته عند بناء الملف قبل أن تجمّع أي شيء. تأجيل هذه الخطوة إلى النهاية، بدلاً من تنفيذها في إعداد التوسيم، هو ما يحفظ السجل الخام لما رآه كل مُوسِّم فعلاً.

الخطوات التالية