انتقل إلى المحتوى الرئيسي

الوحدة 7 — التكييف بالنصّ

نموذج الانتشار في الوحدة السابقة يُنتج صورًا عشوائيّة من التوزيع المتعلَّم: أرقام MNIST أو وجوه CelebA. الفتح الحقيقيّ لـStable Diffusion وDALL-E وImagen جاء حين استطعنا أن نُخبر النموذج ما نريد بالضبط بجملة عاديّة. هذه الوحدة تُفصّل الآلة التي تصل النصّ بالانتشار.

المسألة: كيف نُدخل نصًّا في شبكة تعالج صورًا؟

النصّ سلسلة من الرموز اللغويّة، والصورة شبكة من البكسلات. لا يمكن مباشرة أن نجمع نصًّا بصورة أو نمرّرهما في الطبقة نفسها. المسألة تنقسم إلى قسمين مستقلّين:

  1. تحويل النصّ إلى تمثيل رقميّ ذي معنى دلاليّ: أي متّجه (أو سلسلة متّجهات) بحيث تكون جملتان قريبتان في المعنى قريبتين في الفضاء.
  2. حقن هذا التمثيل داخل U-Net الانتشار بطريقة تسمح لكلّ خطوة إزالة تشويش بأن «ترى» النصّ.

القسم الأوّل تحلّه شبكة مرمّز نصّيّ مُدرَّبة مسبقًا. الأشهر هي CLIP. القسم الثاني يحلّه الانتباه المتقاطع.

CLIP: تمثيل مشترك للنصّ والصورة

CLIP (Contrastive Language-Image Pre-training) لـRadford وآخرين (OpenAI, 2021) شبكة زوجيّة: شبكة تُشفّر النصّ إلى متّجه، وأخرى تُشفّر الصورة إلى متّجه، وتُدرَّبان على 400 مليون زوج (نصّ، صورة) مأخوذ من الإنترنت. الخسارة تُقرّب متّجه الصورة من متّجه نصّها، وتُبعده عن متّجهات النصوص الأخرى في الدفعة.

النتيجة بنية مشتركة: «صورة قطّة» في CLIP تُنتج متّجهًا قريبًا من الصورة الفعليّة لقطّة. هذا يجعل CLIP أداة قويّة لأشياء ما دُرِّبت عليها صراحة: التصنيف بأصفار مُشاهَدات (تعطيه الأصناف بالكلمات، لا بالتسميات)، والبحث بالنصّ في مكتبة صور، وطبعًا التكييف في نماذج الانتشار.

في Stable Diffusion، نستعمل مرمّز CLIP النصّيّ (النسخة L/14 أو H/14) لتحويل الجملة إلى سلسلة من متّجهات (رمز واحد يُنتج متّجهًا، وليس متّجهًا واحدًا للجملة كلّها). هذه السلسلة هي «مفاتيح» النصّ التي ستراها U-Net.

الانتباه المتقاطع: كيف تستمع الصورة إلى النصّ

الانتباه المتقاطع (Cross-Attention) عمليّة انتباه بين مصدرين مختلفين: خرائط متغيّرات U-Net من جهة، وتضمينات النصّ من جهة أخرى. صيغته:

Attention(Q,K,V)=softmax ⁣(QKdk)V\mathrm{Attention}(Q, K, V) = \mathrm{softmax}\!\left(\frac{Q K^{\top}}{\sqrt{d_k}}\right) V

مع QQ محسوبة من خرائط الصورة، وK,VK, V محسوبتين من تضمينات النصّ. النتيجة: كلّ موضع في خارطة المتغيّرات يُقرّر ديناميكيًّا أيّ كلمات في الجملة الأكثر صلة به، ويستقبل مزيجًا من تضميناتها.

عمليًّا، تُدرَج طبقات الانتباه المتقاطع بين كتل U-Net (بعد كلّ كتلة نزول أو صعود). النصّ يدخل مرّة واحدة في بداية أخذ العيّنة، ويُستهلك في كلّ خطوة من الخطوات الخمسين. لا يعاد حسابه، مجرّد ضربه في المصفوفات الخاصّة بكلّ طبقة.

class AttentionCroisee(nn.Module):
def __init__(self, dim_image, dim_texte, dim_tete=64, nb_tetes=8):
super().__init__()
dim_inner = dim_tete * nb_tetes
self.to_q = nn.Linear(dim_image, dim_inner, bias=False)
self.to_k = nn.Linear(dim_texte, dim_inner, bias=False)
self.to_v = nn.Linear(dim_texte, dim_inner, bias=False)
self.to_out = nn.Linear(dim_inner, dim_image)
self.echelle = dim_tete ** -0.5

def forward(self, x, texte):
# x : (B, N_image, dim_image) خرائط U-Net مُسطَّحة
# texte : (B, N_texte, dim_texte) تضمينات CLIP
Q, K, V = self.to_q(x), self.to_k(texte), self.to_v(texte)
poids = torch.softmax(Q @ K.transpose(-1, -2) * self.echelle, dim=-1)
return self.to_out(poids @ V)

هذه الآلة تشبه أذنًا: كلّ منطقة من الصورة تسأل النصّ «ماذا تقول عنّي؟» وتستمع للجواب.

التوجيه بدون مصنِّف: سلاح البساطة

نمرّر النصّ إلى الشبكة، فتُنتج صورة تحترمه بشكل ما، لكن ليس دائمًا بقوّة. التوجيه بدون مصنِّف (Classifier-Free Guidance، اختصارًا CFG) لـHo وSalimans (2022) حيلة بسيطة عبقريّة تُضخِّم الاحترام للنصّ.

الفكرة: أثناء التدريب، نُلغي النصّ في 10% من الحالات ونستبدله بتضمين فارغ. النموذج يتعلّم إذًا التنبّؤ بالضجيج في وضعين: مشروط بالنصّ ϵθ(xt,t,c)\epsilon_{\theta}(x_t, t, c)، وغير مشروط ϵθ(xt,t,)\epsilon_{\theta}(x_t, t, \varnothing).

عند أخذ العيّنة، ندمج التنبّؤين في اتّجاه يُضخِّم أثر النصّ:

ϵ~(xt,t,c)=ϵθ(xt,t,)+s[ϵθ(xt,t,c)ϵθ(xt,t,)]\tilde\epsilon(x_t, t, c) = \epsilon_{\theta}(x_t, t, \varnothing) + s \cdot \left[\epsilon_{\theta}(x_t, t, c) - \epsilon_{\theta}(x_t, t, \varnothing)\right]

المعامل ss يُدعى سلّم التوجيه (guidance scale). قيمة s=1s = 1 توليد شرطيّ عاديّ، وs=0s = 0 توليد غير مشروط. قيم بين 5 و10 هي المعتادة في Stable Diffusion، وتعطي صورًا تتبع النصّ بصرامة.

الثمن: أخذ العيّنة يتضاعف كلفةً لأنّه يحتاج نداءين على U-Net في كلّ خطوة (واحد مشروط وواحد غير مشروط). لكنّه يبقى الطريقة القياسية اليوم لجودتها الاستثنائية.

سلّم التوجيه: مفاضلة بين الوفاء والواقعيّة

قيمة ss ليست تفصيلًا. جرّب نفس النصّ بقيم مختلفة:

  • s=1s = 1: صور واقعيّة جدًّا، لكنّها قد تتجاهل تفاصيل النصّ.
  • s=3s = 3 إلى 55: توازن جيّد بين الوفاء للنصّ وطبيعيّة الصورة، وهو ما يُستعمل في التوليد الفنّيّ.
  • s=7s = 7 إلى 1010: صور تحترم النصّ بصرامة، لكن مع «فنّيّة زائدة» أحيانًا (تشبع الألوان، أشكال محاطة بحدود واضحة).
  • s>15s > 15: تدهور واضح، صور مشوّهة تبدو مصنوعة.

الاختيار الأمثل يعتمد على المهمّة: نصّ قصير ملموس (s=5s = 5 يكفي)، نصّ طويل مع كثير من التفاصيل (s=7s = 7 إلى 88)، فنّ تجريديّ (ss منخفض للاحتفاظ بالحرّية).

التوجيه السلبيّ: توليد ما لا تريد

Stable Diffusion يضيف مفهومًا عمليًّا مفيدًا: النصّ السلبيّ. بدل التضمين الفارغ في CFG، نستعمل تضمين نصّ نريد تفاديه. هكذا صيغة مثل «صورة وجه، سلبيّ: يدان مشوّهتان، شفاه غير متماثلة» تُضخِّم الفارق بعيدًا عن العيوب الشائعة. هذه الحيلة الصغيرة تحسّن الجودة بشكل ملحوظ دون أيّ تدريب إضافيّ.

مثال عمليّ: توليد بـStable Diffusion

مكتبة diffusers من Hugging Face تُوفّر كلّ ما نحتاجه في بضعة أسطر:

from diffusers import StableDiffusionPipeline
import torch

pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
).to("cuda")

prompt = "portrait of a Moroccan woman, high detail, natural lighting"
negative_prompt = "blurry, deformed hands, extra fingers"

image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=30, # DDIM/DPM-Solver خطوة كافية
guidance_scale=7.5, # سلّم CFG قياسيّ
).images[0]

يعمل هذا في بضع ثوانٍ على بطاقة رسوميّات RTX 3060 مع 12 جيغابايت. المكتبة تُخفي كثيرًا من التعقيد (مرمّز النصّ، مُخطِّط، U-Net، مرمّز تلقائيّ)، لكن كلّ قطعة منه رأيناها في هذه الوحدة والسابقة.

في الخلاصة

  • CLIP يُوفّر مرمّزًا نصّيًّا مدرَّبًا على 400 مليون زوج نصّ-صورة، ويعطي تضمينات ذات معنى دلاليّ يمكن حقنها في نماذج الرؤية.
  • الانتباه المتقاطع هو الآلة التي تسمح لكلّ موضع في U-Net أن يستمع إلى كلّ كلمات النصّ ديناميكيًّا.
  • التوجيه بدون مصنِّف يُضخِّم أثر النصّ عبر دمج تنبّؤين (مشروط وغير مشروط) بمعامل ss؛ الأسعار المعتادة بين 5 و10.
  • النصّ السلبيّ يُتيح تفادي عيوب معلومة (يدان مشوّهتان مثلًا) بلا تدريب إضافيّ، ويحسّن الجودة بشكل عمليّ.

الوحدة التالية تفتح سؤال التقييم: كيف نعرف موضوعيًّا هل نموذج يُنتج صورًا أفضل من آخر؟ وتُدخل مقياس FID وحدوده.