معالجة الإشارات2006متوسط10 دقيقة قراءة

K-SVD: خوارزمية لتصميم قواميس زائدة الاكتمال للتمثيل المُتفرِّق

K-SVD: An Algorithm for Designing Overcomplete Dictionaries for Sparse Representation

Aharon, M. · Elad, M. · Bruckstein, A. — IEEE Transactions on Signal Processing

المشكلة

لكي نُمثِّل إشارة بشكل مُتفرِّق، نحتاج إلى قاموس — مجموعة من الإشارات النموذجية تُسمّى ذرّات — بحيث نكتب أي إشارة مُدخلة كتركيبة من عدد قليل جدًّا منها. القواميس الثابتة مثل DCT أو المويجات تعمل بشكل معقول للإشارات العامة، لكنها لا تلتقط البنية الفعلية لبيانات بعينها. المشكلة أن تكييف القاموس مع بيانات يُشبه معضلة الدجاجة والبيضة: لإيجاد أفضل قاموس نحتاج الرموز المُتفرِّقة، ولإيجاد الرموز نحتاج القاموس أولاً. الطرق السابقة مثل MOD عالجت هذا لكنها حدّثت جميع الذرّات دفعةً واحدة، فتجاهلت العلاقة المتبادلة بين القاموس والرموز.

الإسهام

خوارزمية K-SVD تعمل بالتناوب بين مرحلتين: الترميز المُتفرِّق — إيجاد أفضل رموز بالنظر إلى القاموس الحالي — ثم تحديث القاموس بتحسين كل ذرّة على حدة عبر تحليل القيمة المفردة. الابتكار الأساسي هو تحديث الذرّة ومعاملاتها معًا عبر تقريب من الرتبة الأولى لمصفوفة الخطأ المتبقّي، مع الحفاظ على تفرُّق الرموز. تُعمِّم عنقدة k-means — لأن k-means حالة خاصة تستخدم فيها كل إشارة ذرّة واحدة فقط. والنتيجة أن K-SVD تتقارب أسرع وتُنتج قواميس أفضل تكيُّفًا من الطرق السابقة.

الأثر

أصبحت K-SVD الأداة الأساسية في تعلّم القواميس. حققت نتائج رائدة في إزالة الضجيج من الصور عبر ترميز مُتفرِّق على قاموس مُتعلَّم، وفي ملء المناطق المفقودة والضغط والتعرّف على الوجوه. تأثيرها امتدّ إلى التعلّم العميق: التمثيلات المُتفرِّقة المُتعلَّمة ألهمت المرمِّزات التلقائية المُتفرِّقة، وفكرة بناء قواميس سمات من البيانات مباشرةً مهّدت الطريق لمرشِّحات الشبكات الالتفافية. تظل من أكثر الأوراق استشهادًا في معالجة الإشارات.

تخيّل أنك طاهٍ يريد تأليف كتاب وصفات. كتاب الوصفات العام (مثل قاموس DCT) يحتوي على وصفات من كل مطابخ العالم — مفيد نظريًّا، لكن إن كنت متخصصًا في المطبخ الإيطالي فمعظم هذه الوصفات لا تخدمك.

K-SVD تعمل كالتالي: تراقب ما تطبخه فعلاً خلال شهر، ثم تكتب كتاب وصفات مُفصَّلًا على مقاسك يحتوي فقط على الوصفات (الذرّات) التي تحتاجها حقًّا. أي طبق تُحضِّره يمكن تركيبه بمزج وصفتين أو ثلاث فقط — وهذا جوهر التمثيل المُتفرِّق.

الحيلة الذكية: في كل جولة تُحسِّن وصفة واحدة بأن تتذوّق جميع الأطباق التي تعتمد عليها، ثم تُعدّلها لتُحسِّنها كلها دفعة واحدة (هذا هو تحديث SVD). بعد عدة جولات يصبح كتابك مُطابقًا تمامًا لاحتياجات مطبخك.

لماذا نتعلّم القاموس بدلاً من استخدام قاموس جاهز؟

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

السؤال الطبيعي: أي قاموس نستخدم؟ القواميس الثابتة — أسس فورييه والمويجات وتحويل الجيب التمامي المنفصل — أنيقة رياضيًّا وتؤدي غرضها مع فئات واسعة من الإشارات. لكن مشكلتها أنها تُعامل جميع البيانات بالطريقة نفسها: قاموس مويجات مُصمَّم للصور الطبيعية يُهدر ذرّات على أنماط لا تظهر أبدًا في صور الأشعة الطبية، والعكس صحيح. فيصبح السؤال المحوري: هل يمكننا تعلُّم قاموس من البيانات نفسها بحيث تكتسب كل ذرّة مكانها بجدارة؟

القاموس زائد الاكتمال يحتوي على ذرّات أكثر من أبعاد الإشارة (K>nK > n). هذه الوفرة تعني أن لكل إشارة طرقًا عديدة لتفكيكها — لكن قيد التفرُّق يفرض اختيار التفكيك الذي يستعمل أقل عدد ممكن من الذرّات. الأمر أشبه بصندوق أدوات واسع: كلما زادت الأدوات المتاحة، استطعت اختيار الأنسب لكل مهمة وتقليل ما تحتاجه فعلاً.

افتح في المختبر
اليسار: ذرّات DCT الثابتة. اليمين: ذرّات تعلّمتها K-SVD من رُقع صور حقيقية. لاحظ كيف تلتقط الذرّات المُتعلَّمة اتجاهات الحواف والنسيج والتدرّجات الخاصة بهذه البيانات تحديدًا.
تستيقظ التجربة عند وصولك…

الصياغة الرياضية: ماذا نُحسِّن بالضبط؟

نبدأ من المعطيات: لدينا NN إشارة تدريب {yi}\{y_i\}، كل منها بـnn بُعدًا. المطلوب إيجاد قاموس DD مكوّن من KK ذرّة (أعمدة المصفوفة) ومصفوفة معاملات مُتفرِّقة XX بحيث YDXY \approx DX، وكل عمود في XX يحتوي على عدد قليل جدًّا من القيم غير الصفرية. بعبارة أخرى، نريد تقليل الإجمالي مع فرض قيد تفرُّق على كل متجه معاملات.

minD,XYDXF2s.t.i,  xi0T0\min_{D, X} \|Y - DX\|_F^2 \quad \text{s.t.} \quad \forall i,\; \|x_i\|_0 \leq T_0
دالة هدف تعلّم القاموسY = مصفوفة جميع إشارات التدريب · D = القاموس بذرّاته الـK · X = المعاملات المُتفرِّقة · T₀ = أقصى عدد مسموح للمعاملات غير الصفرية لكل إشارة · ‖·‖_F = مقياس فروبينيوس (مجموع مربعات الخطأ) · ‖·‖₀ = عدد القيم غير الصفرية

هذه المسألة صعبة لأن DD وXX معًا مسألة غير محدّبة — لا يوجد حل مباشر. الحيلة التي تستخدمها K-SVD هي التناوب: نُثبِّت القاموس DD ونبحث عن أفضل رموز XX (الترميز المُتفرِّق)، ثم نُثبِّت XX ونُحسِّن DD عمودًا عمودًا (تحديث القاموس). هذا الأسلوب التناوبي مألوف — فهو يُشبه خوارزمية EM ويُشبه k-means نفسها.

من K-means إلى K-SVD: تعميم طبيعي

أسهل طريقة لفهم K-SVD هي أن نراها تعميمًا طبيعيًّا لـ بأسلوب K-means. في K-means، كل نقطة بيانات تُنسب إلى مركز عنقود واحد — أقرب نقطة مركزية إليها. وهذا يعني عمليًّا أننا نُمثِّل كل إشارة بذرّة واحدة فقط بمعامل قدره 1، أي أقصى درجات التفرُّق (T0=1T_0 = 1).

K-SVD ترفع هذا القيد وتسمح لكل إشارة باستخدام حتى T0T_0 ذرّة بأوزان مختلفة. الفرق جوهري: K-means تُقسّم البيانات إلى مجموعات منفصلة، بينما K-SVD تسمح بتمثيلات مرنة متداخلة. مثلاً، صورة وجه يمكن أن تستخدم ذرّة لمنطقة العينين وأخرى للأنف وثالثة للفك — وهذا مستحيل مع K-means التي تُجبرك على اختيار «أقرب وجه واحد» فقط.

اسم «K-SVD» يعكس هذا الأصل: K ذرّة يجري تحديثها بتحليل القيمة المفردة.

افتح في المختبر
بدّل بين K-means (ذرّة واحدة لكل إشارة) وK-SVD (عدة ذرّات لكل إشارة). لاحظ كيف تلتقط K-SVD بنية أغنى بكثير.
تستيقظ التجربة عند وصولك…

الخطوة الأولى: الترميز المُتفرِّق بالمُطاردة المتعامدة الجشعة

في هذه المرحلة لدينا القاموس الحالي DD ونريد إيجاد أكثر تمثيل مُتفرِّق ممكن لكل إشارة تدريب. تستخدم K-SVD لهذا الغرض خوارزمية (OMP) — وهي خوارزمية جشعة تبني التمثيل ذرّة تلو الأخرى.

آلية عمل OMP واضحة: انظر إلى إشارتك وجِد ذرّة القاموس الأكثر توافقًا معها — أي الذرّة التي يُطابق «اتجاهها» الجزء الذي لم يُفسَّر بعد — ثم أضفها إلى مجموعة الذرّات النشطة. بعد ذلك أسقِط الإشارة على الذرّات المختارة إسقاطًا متعامدًا لتحسين المعاملات، وكرّر العملية مع المتبقّي. تتوقف حين تستخدم T0T_0 ذرّة أو يصبح الخطأ مقبولاً.

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

افتح في المختبر
شاهد كيف تبني OMP الترميز المُتفرِّق خطوة بخطوة. في كل تكرار تختار الذرّة الأكثر توافقًا وتُقلِّص المتبقّي.
تستيقظ التجربة عند وصولك…

الخطوة الثانية: تحديث القاموس — قلب خوارزمية K-SVD

هنا نصل إلى الابتكار الجوهري الذي يُميّز K-SVD. بعد مرحلة الترميز المُتفرِّق أصبح لدينا معاملات XX ونريد تحسين كل ذرّة dkd_k (العمود kk في القاموس DD).

الملاحظة المفتاحية: حين نُحدّث ذرّة معيّنة dkd_k، يمكننا عزل مساهمتها وحدها. الكلي DXDX عبارة عن مجموع حدود من الرتبة الأولى — كل ذرّة مضروبة في صف معاملاتها. إذا أزلنا مساهمة الذرّة kk، نحصل على خطأ المتبقّي EkE_k:

Ek=YjkdjxTjE_k = Y - \sum_{j \neq k} d_j x_T^j
خطأ المتبقّي بعد إزالة مساهمة الذرّة kE_k = ما تبقّى بلا تفسير بعد أن أدّت جميع الذرّات الأخرى دورها · نريد أن يُقرِّب حاصل ضرب d_k في x_T^k هذا المتبقّي قدر الإمكان

المطلوب الآن إيجاد أفضل dkd_k وصف معاملاتها xTkx_T^k اللذين يُقلِّلان EkdkxTkF2\|E_k - d_k x_T^k\|_F^2. هذه في جوهرها مسألة تقريب مصفوفة بمصفوفة من الرتبة الأولى — وأفضل تقريب من هذا النوع يُعطيه مباشرةً تحليل القيمة المفردة (SVD).

لكن هناك نقطة دقيقة وحاسمة: لا يمكننا تطبيق SVD على EkE_k بالكامل. لماذا؟ لأن ذلك سيُولِّد معاملات غير صفرية لإشارات لم تكن تستخدم الذرّة kk أصلاً، فيتحطّم التفرُّق الذي اجتهدنا لبنائه. الحل: تُقيّد K-SVD التحديث بالإشارات التي تستخدم الذرّة kk فعلاً فقط — أي المجموعة ωk={i:xki0}\omega_k = \{i : x_k^i \neq 0\}. نبني مصفوفة مقيَّدة EkRE_k^R من هذه الأعمدة وحدها، ونُطبّق عليها SVD، فنُحدِّث الذرّة ومعاملاتها غير الصفرية معًا في خطوة واحدة.

افتح في المختبر
انقر على أي ذرّة لترى خطوة تحديثها: المتبقّي المُقيَّد وتحليل SVD والذرّة والمعاملات بعد التحديث.
تستيقظ التجربة عند وصولك…

خوارزمية K-SVD كاملة

بتجميع المرحلتين تعمل K-SVD كالتالي: أولاً، الترميز المُتفرِّق — نستخدم OMP لإيجاد أفضل تمثيل مُتفرِّق لكل إشارة تدريب بالقاموس الحالي. ثانيًا، تحديث القاموس — لكل ذرّة k=1,,Kk = 1, \ldots, K نحسب المتبقّي المُقيَّد EkRE_k^R ونُطبّق SVD من الرتبة الأولى ونُحدِّث الذرّة ومعاملاتها معًا. ثم نُكرّر حتى يتحقق .

النقطة المهمة: كل تكرار مضمون أن يُقلِّل خطأ التمثيل الكلي أو يُبقيه كما هو على الأقل. عمليًّا تتقارب الخوارزمية في حدود 10 إلى 50 تكرارًا.

افتح في المختبر
تابع خوارزمية K-SVD خطوة بخطوة: ترميز مُتفرِّق ← تحديث القاموس ← تقارب. راقب كيف ينخفض خطأ التمثيل مع كل تكرار.
تستيقظ التجربة عند وصولك…

الخوارزمية في شيفرة برمجية

خوارزمية K-SVD (نسخة مبسَّطة بـ NumPy)python

مبسَّط لإظهار الفكرة — ليس التنفيذ الحقيقي.

import numpy as np

def omp(D, y, T0):
    """المُطاردة المتعامدة الجشعة: أوجد الترميز المُتفرِّق للإشارة y."""
    residual = y.copy()
    indices = []
    for _ in range(T0):
        # جد الذرّة الأكثر ارتباطًا بالمتبقّي
        correlations = D.T @ residual
        best = np.argmax(np.abs(correlations))
        indices.append(best)
        # حل المربعات الصغرى على الذرّات المختارة
        Ds = D[:, indices]
        coeffs = np.linalg.lstsq(Ds, y, rcond=None)[0]
        residual = y - Ds @ coeffs
    x = np.zeros(D.shape[1])
    x[indices] = coeffs
    return x

def ksvd(Y, K, T0, n_iter=50):
    """تعلّم قاموس بـ K ذرّة من إشارات التدريب Y."""
    n, N = Y.shape
    # هيّئ القاموس بإشارات تدريب عشوائية
    D = Y[:, np.random.choice(N, K, replace=False)]
    D = D / np.linalg.norm(D, axis=0)  # طبّع الذرّات

    for iteration in range(n_iter):
        # المرحلة 1: الترميز المُتفرِّق بـ OMP
        X = np.zeros((K, N))
        for i in range(N):
            X[:, i] = omp(D, Y[:, i], T0)

        # المرحلة 2: تحديث القاموس (ذرّة واحدة في كل مرة)
        for k in range(K):
            # جد الإشارات التي تستخدم الذرّة k
            omega_k = np.nonzero(X[k, :])[0]
            if len(omega_k) == 0:
                continue  # تخطَّ الذرّات غير المستخدمة
            # احسب المتبقّي المُقيَّد
            E_k = Y - D @ X + np.outer(D[:, k], X[k, :])
            E_k_R = E_k[:, omega_k]
            # تحديث SVD من الرتبة الأولى
            U, S, Vt = np.linalg.svd(E_k_R, full_matrices=False)
            D[:, k] = U[:, 0]              # الذرّة الجديدة
            X[k, omega_k] = S[0] * Vt[0]   # المعاملات الجديدة

        error = np.linalg.norm(Y - D @ X, 'fro')
        print(f"تكرار {iteration}: الخطأ = {error:.4f}")
    return D, X

التطبيق الأبرز: إزالة الضجيج من الصور

أشهر تطبيقات K-SVD وأكثرها تأثيرًا هو إزالة الضجيج من الصور. المبدأ بسيط وأنيق: الصورة النظيفة يمكن تمثيلها بتفرُّق على قاموس جيد، لكن العشوائي لا يملك بنية مُتفرِّقة. لذلك حين نتعلّم قاموسًا من الصورة المُشوّشة نفسها (أو من رُقع تدريب نظيفة)، ثم نُرمِّز كل رقعة متداخلة بتفرُّق، فإن الرموز المُتفرِّقة تلتقط الإشارة الحقيقية وتترك الضجيج في المتبقّي — لأنه ببساطة لا يتناسب مع أي تركيبة مُتفرِّقة من ذرّات القاموس.

أظهر الأد وأهارون (2006) أن إزالة الضجيج بـ K-SVD حققت أعلى نسبة إشارة إلى ضجيج ذروية (PSNR) على المعايير القياسية، متفوّقةً على المويجات والطرق المنافسة المتاحة حينها.

افتح في المختبر
أضف ضجيجًا إلى صورة وشاهد كيف تستعيد K-SVD الإشارة النظيفة بالترميز المُتفرِّق على ذرّات مُتعلَّمة.
تستيقظ التجربة عند وصولك…

لماذا كانت هذه الورقة مؤثرة؟

  1. 1999

    طريقة الاتجاهات المثلى (MOD)

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

  2. 2006

    K-SVD (هذه الورقة)

    تحديث تتابعي ذرّةً بذرّة عبر تحليل القيمة المفردة، مع تحسين الذرّة ومعاملاتها معًا والحفاظ على التفرُّق. أصبحت المعيار في تعلّم القواميس.

  3. 2006

    إزالة الضجيج بـ K-SVD (الأد وأهارون)

    طُبِّقت K-SVD على إزالة الضجيج من الصور وحققت نتائج رائدة، فأثبتت الفاعلية العملية للتمثيلات المُتفرِّقة المُتعلَّمة.

  4. 2009

    تعلّم القواميس التدريجي (ميرال وآخرون)

    وسّعت نطاق تعلّم القواميس ليشمل مجموعات بيانات ضخمة عبر معالجة عيّنة واحدة في كل مرة، متغلّبةً على قيد المعالجة الدفعية في K-SVD.

  5. 2010

    K-SVD التمييزية (تشانغ ولي)

    أضافت حدًّا تصنيفيًّا إلى دالة الهدف، فأصبح القاموس المُتعلَّم قادرًا على إعادة البناء والتمييز بين الفئات في آن واحد.

  6. 2012

    المرمّزات التلقائية المُتفرِّقة في التعلّم العميق

    تبنّى التعلّم العميق المبدأ ذاته: تعلّم سمات مُتفرِّقة من البيانات. الصلة بين K-SVD والمرمّزات التلقائية المُتفرِّقة واضحة ومباشرة — كلاهما يتعلّم قواميس سمات زائدة الاكتمال ومُتفرِّقة.

المرجعAharon, M., Elad, M. & Bruckstein, A.. K-SVD: An Algorithm for Designing Overcomplete Dictionaries for Sparse Representation. IEEE Transactions on Signal Processing, 2006.

مصطلحات هذه الورقة