MZ
The Null Hypothesis
→ العودة إلى المقالات

الجبر الخطي

قراءة معمقة في SVD

من تركيب المصفوفات إلى الهندسة والبرهان والبنية منخفضة الرتبة وتحليل المركبات الرئيسية.

كلمات مفتاحية: تحليل القيم المفردة · SVD · الجبر الخطي · التقريب منخفض الرتبة · تحليل المركبات الرئيسية · تحليل المصفوفات

A matrix is factored into singular vectors and values, alongside its transformation of a unit circle into an ellipse.
في هذا المقال

قمة الجبل

قد يبدو الحديث عن SVD في عالم الجبر الخطي كالقفز مباشرةً إلى قمة جبل. لماذا نبدأ من أعلى النظرية قبل أن نعرف الطريق إليها؟

لا تقلق. لن نحفظ القمة ولن نضيع وسط متاهات البراهين. سنفعل شيئًا أبسط: سنقف فوقها قليلًا، ثم نبدأ في ها حتى نرى ممَّا تكوَّن الجبل.

من ال إلى التفكيك

وبما أننا نتحدث عن التفكيك — Decomposition، فلنبدأ من الاتجاه المعاكس: التجميع — Composition.

أمامنا ثلاث مصفوفات، AA وBB وCC. أبعادها متوافقة، ولذلك نستطيع أن نصلها ببعضها:

W=ABC.W=ABC.

هذه هي الفكرة في أبسط صورة: نعرف القطع، نجمعها، فيظهر شيء جديد. وإذا دخل متجه xx إلى هذه السلسلة فإن العمل يبدأ من اليمين: Wx=ABCx=A(B(Cx))Wx=ABCx=A(B(Cx))، أي

x→CCx→BBCx→AABCx.x\xrightarrow{C}Cx\xrightarrow{B}BCx\xrightarrow{A}ABCx.

لنأخذ مثالًا صغيرًا:

A=[1201],B=[20012],C=[0−110].A= \begin{bmatrix} 1&2\\ 0&1 \end{bmatrix}, \qquad B= \begin{bmatrix} 2&0\\ 0&\tfrac12 \end{bmatrix}, \qquad C= \begin{bmatrix} 0&-1\\ 1&0 \end{bmatrix}.

وعند جمع هذه التحويلات نحصل على

W=ABC=[1−2120].W=ABC= \begin{bmatrix} 1&-2\\ \tfrac12&0 \end{bmatrix}.
تتابع التحويلاتx → Cx → BCx → ABCx
x₁x₂(1, 1)
المتجهة الحالية · الدخل[1, 1]

الشكل 1: تركيب المصفوفات بوصفه تحويلات متتابعة. يعمل حاصل الضرب ABC على x من اليمين إلى اليسار: يحوّل C المدخل أولًا، ثم يتبعه B وA.

التجميع في Python

python

هذا هو الاتجاه السهل في القصة: القطع معروفة، ولذلك نبني منها ال النهائية.

هنا تلمس التجميع بدل أن تقرأ تعريفه فقط. غيّر xx، واضغط على المصفوفات، وراقب كيف تمر ال من CC إلى BB ثم إلى AA.

والآن اقلب السؤال: بدل أن أعطيك القطع، أضع أمامك مصفوفة واحدة اسمها DD. نرى صفوفها وأعمدتها، ونستطيع أن نحسب رتبتها وكل ما يظهر لنا منها. ثم أقول لك: افتحها. أرني البنية التي تختبئ في داخلها.

لو لم تكن لدينا أدوات، لاستطعنا التخمين حتى تحترق النجوم. لكن هذا بالضبط هو السبب الذي جعل علماء الجبر الخطي يبنون نظريات الـdecomposition: لا نريد أي عوامل عشوائية؛ نريد قطعًا لها معنى وبنية نستطيع الاستفادة منها.

قد تكون القطع مثلثية كما في LU، أو اتجاهات orthonormal ومعاملات مثلثية كما في QR، أو عاملًا مثلثيًا وانعكاسه كما في Cholesky. وقد نغيّر زاوية النظر نفسها كما في Spectral decomposition وSchur، أو نفصل الدوران عن التمدد كما في Polar decomposition. ثم نصل إلى SVD، الذي سيأخذ المسرح من هنا.

أطلس التفكيك

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

في العنصر التالي اختر LU أو QR أو Cholesky أو Spectral أو SVD. افتح العوامل، ثم أعد بناء المصفوفة الأصلية. لا تحفظ الصيغ؛ راقب النمط وهو يتكرر.

LU يحول Gaussian elimination إلى عاملين يمكن إعادة استخدامهما.

المصفوفة الأصلية
43
63
10
1.51
43
0-1.5
دور العامل · L

مثلثية سفلية: تحفظ معاملات elimination.

الشكل 2: طرق تفكيك المصفوفات. تمثل خمسة تفكيكات المصفوفة نفسها ببنى مختلفة، وتوفر عوامل كل تفكيك مسارًا لإعادة بناء A.

أطلس تفكيك صغير في Python

python

وباستخدام SciPy يمكن حساب بعض التفكيكات مباشرة:

python

ومن هنا لا يعود SVD قفزة غريبة. أصبح مجرد التفكيك الذي سنقترب منه أكثر من أي تفكيك آخر.


الجوهر فقط

لأي مصفوفة حقيقية A∈Rm×nA\in\mathbb R^{m\times n}، يمكننا كتابة

A=UΣVT.\boxed{A=U\Sigma V^T}.

في الصورة الكاملة يكون UU مصفوفة ة من الحجم m×mm\times m، وVV مصفوفة متعامدة من الحجم n×nn\times n، بينما Σ\Sigma مستطيلة من الحجم m×nm\times n.

على قطر Σ\Sigma توجد القيم المفردة:

σ1≥σ2≥⋯≥0.\sigma_1\ge\sigma_2\ge\cdots\ge0.

أعمدة VV هي right singular vectors، وأعمدة UU هي left singular vectors. ولو كانت العناصر مركبة نستبدل TT بالـconjugate transpose ∗^*.

متجه الإدخال

المتجه الحالي · متجه x(1, 0.25)

اختر متجهًا لتحويله.

الشكل 3: تحويل المتجه وفق SVD. يفصل التفكيك تحويل المتجه إلى تغيير متعامد للإحداثيات بواسطة Vᵀ، وتمدد بواسطة Σ، وإعادة توجيه بواسطة U.

هذه هي الصيغة. أمّا المعنى فيظهر عندما نرى وظيفة كل قطعة.

احسب SVD وتحقق منه

python

ولمصفوفة مستطيلة استخدم

python

إذا كانت نسخة compact/economy هي كل ما تحتاجه.


من اليمين تبدأ الحكاية

إذا أدخلنا متجهة xx، فلدينا Ax=UΣVTxAx=U\Sigma V^Tx.

ابدأ من VTV^T. هذه القطعة لا “تشوّه” المتجهة كيفما اتفق؛ هي تسأل: كم تحتوي xx من كل اتجاه خاص viv_i؟ فعلًا، إذا كتبنا V=[v1 v2 ⋯ vn]V=[v_1\ v_2\ \cdots\ v_n]، فإن

VTx=[v1Txv2Tx⋮].V^Tx= \begin{bmatrix} v_1^Tx\\ v_2^Tx\\ \vdots \end{bmatrix}.

إذن VTV^T يحلل المدخل في إحداثيات صُممت خصيصًا لهذه المصفوفة.

ثم تصل الإحداثيات إلى Σ\Sigma. لا توجد هنا مزاوجة معقدة بين المحاور؛ كل اتجاه يُضرب في رقم واحد:

Σ[a1a2⋮]=[σ1a1σ2a2⋮].\Sigma \begin{bmatrix} a_1\\a_2\\\vdots \end{bmatrix} = \begin{bmatrix} \sigma_1a_1\\ \sigma_2a_2\\ \vdots \end{bmatrix}.

وهنا تكمن بساطة SVD: التحويل المعقد صار في هذه الإحداثيات مجرد stretch/shrink مستقل لكل محور.

وأخيرًا تأتي UU لتضع هذه المركبات بعد تمددها في اتجاهاتها المناسبة داخل فضاء الخرج.

لذلك يمكن أن نحفظ القصة لا الحروف:

VT⟶Σ⟶U\boxed{ V^T\longrightarrow\Sigma\longrightarrow U }

يحلّل (V^T) المدخل، ثم تمدّد (Sigma) مركباته أو تقلّصها، وأخيرًا يوجّه (U) الخرج.

والجملة التي تختصر كل ذلك هي

Avi=σiui.\boxed{Av_i=\sigma_i u_i.}

أدخل الاتجاه الخاص viv_i، فتخرج في اتجاه uiu_i بعد أن يتغير طولها بمقدار σi\sigma_i.


سر الجمال

هنا يظهر أول سبب يجعل SVD جميلًا: الـeigendecomposition التقليدي يريد مصفوفة مربعة، لأن معادلة

Av=λvAv=\lambda v

تحتاج أن يعيش vv وAvAv في الفضاء نفسه.

لكن إذا كانت A:Rn→RmA:\mathbb R^n\to\mathbb R^m وm≠nm\neq n، فليس هناك سبب لأن يكون فضاء المدخل هو فضاء الخرج.

SVD لا يحاول إجبار الفضاءين على أن يكونا واحدًا. يعطي المدخل ه الخاص VV، ويعطي الخرج أساسه الخاص UU. هذا ليس حلًا التفافيًا للمشكلة؛ هذه هي الفكرة التي تجعل SVD طبيعيًا للمصفوفات المستطيلة.


حين تتحول الدائرة

تخيل دائرة الوحدة في بعدين. كل نقطة عليها تمثل متجهة طولها واحد. عندما نطبّق VTV^T، تتغير الإحداثيات دون أن تتغير الأطوال لأن VV orthogonal. ثم تأتي Σ\Sigma فتمد محورًا أكثر من الآخر، فتحول الدائرة إلى ellipse. بعدها تدور UU النتيجة أو تعكسها لتضعها في الاتجاه النهائي.

x₁x₂

دائرة الوحدةيبدأ كل اتجاه بالطول الوحدي نفسه.

الشكل 4: الأثر الهندسي لتفكيك SVD. تعيد Vᵀ تمثيل دائرة الوحدة في أساس متعامد جديد، ثم تمددها Σ إلى قطع ناقص، ويحدد U اتجاهها النهائي؛ وتحدد القيم المفردة أطوال المحاور.

دع الهندسة تتحرك

python

للتعليم من الأفضل متابعة circle ثم after_vt ثم after_sigma ثم after_u مرحلةً بعد مرحلة. وفي النسخة التفاعلية نتابع الجسم نفسه وهو يتغير بدل الاعتماد على صور منفصلة.

لهذا يقال كثيرًا إن SVD هو “دوران/انعكاس، ثم تمدد، ثم دوران/انعكاس”. العبارة مفيدة، لكن النسخة الأدق هي أن VTV^T يختار نظام إحداثيات المدخل، وΣ\Sigma يقوم بالفعل المستقل على كل محور، وUU يختار نظام إحداثيات الخرج.


من أين تأتي هذه القطع؟

الآن وصلنا إلى سؤال مهم: هل اخترعنا هذه الاتجاهات لأنها تبدو جميلة؟ لا. ابدأ من المعادلة Avi=σiuiAv_i=\sigma_i u_i.

اضرب من اليسار بـATA^T:

ATAvi=σiATui.A^TAv_i=\sigma_i A^Tu_i.

وفي SVD نحصل أيضًا على ATui=σiviA^Tu_i=\sigma_i v_i، إذن ATAvi=σi2viA^TAv_i=\sigma_i^2v_i.

ها هو السر: الـ هي للمصفوفة ATAA^TA، ومربعات هي لها.

وبالمثل AATui=σi2uiAA^Tu_i=\sigma_i^2u_i، فتكون eigenvectors لـAATAA^T.

وهذا يفسر لماذا القيم المفردة غير سالبة: ATAA^TA موجبة شبه محددة، وبالتالي eigenvalues الخاصة بها غير سالبة، ثم نأخذ الجذر σi=λi\sigma_i=\sqrt{\lambda_i}.


أول خيط: ATAA^TA

إذا أردت أن تبني SVD للتعلم لا للحساب العددي الاحترافي، ابدأ بـATAA^TA. استخرج eigenvectors متعامدة معيارية viv_i ورتب eigenvalues تنازليًا. من كل eigenvalue λi\lambda_i اصنع

σi=λi.\sigma_i=\sqrt{\lambda_i}.

وحين تكون σi≠0\sigma_i\neq0، مرر viv_i داخل AA، ثم اقسم على مقدار التمدد:

ui=Aviσi.u_i=\frac{Av_i}{\sigma_i}.

بهذه الطريقة لا نسحب UU وΣ\Sigma وVV من قبعة ساحر. ATAA^TA تخبرنا بالاتجاهات المهمة في فضاء المدخل، eigenvalues تخبرنا بقوة التمدد، وAA نفسها تخبرنا أين تصل هذه الاتجاهات في فضاء الخرج.

هذا الطريق ممتاز للفهم. أما في العمل العددي الحقيقي فسنعتمد على خوارزميات SVD مستقرة مباشرة بدل تكوين ATAA^TA دائمًا، لأن تربيع condition number قد يزيد المشكلات العددية.

ابنِ SVD من ATAA^TA

هذا مفيد لفهم النظرية. أما في العمل العددي الحقيقي فالأفضل استخدام np.linalg.svd مباشرة.

python

برهان الوجود

ما الذي نريد إثباته فعلًا؟

حتى الآن عرفنا كيف نفهم SVD وكيف نبنيه بطريقة تعليمية. لكن تبقى قفزة مهمة: لماذا نضمن أن كل مصفوفة تملك SVD أصلًا؟

لنفترض A∈Cm×nA\in\mathbb C^{m\times n}، وr=rank⁡(A)r=\operatorname{rank}(A).

نريد أن نثبت وجود صيغة condensed SVD:

A=XΣrY∗,\boxed{A=X\Sigma_rY^*},

بحيث أعمدة XX وأعمدة YY orthonormal، و

Σr=diag⁡(σ1,…,σr),σ1≥⋯≥σr>0.\Sigma_r= \operatorname{diag}(\sigma_1,\ldots,\sigma_r), \qquad \sigma_1\ge\cdots\ge\sigma_r>0.

إذا كانت الرموز المركبة مزعجة، تذكر فقط أن A∗=ATA^*=A^T في الحالة الحقيقية.

الأداة التي سنستعملها هي spectral theorem: كل مصفوفة تملك أساسًا orthonormal من eigenvectors، ويمكن كتابتها في صورة

W=ZΛZ∗.W=Z\Lambda Z^*.

المشكلة الة أن AA قد لا تكون مربعة ولا Hermitian. إذن بدل أن نحاول إجبار AA على شيء ليست عليه، سنبني مصفوفة أكبر تحمل AA داخلها.


الحيلة التي تفتح الباب

عرّف

W=[0AA∗0].\boxed{ W= \begin{bmatrix} 0&A\\ A^*&0 \end{bmatrix}. }

حجمها (m+n)×(m+n)(m+n)\times(m+n)، فهي مربعة. والأهم أن W∗=WW^*=W، إذن WW Hermitian، وبالتالي مفتوح لنا.

خذ eigenvector لـWW واكتبه على قطعتين:

z=[xy],Wz=σz.z= \begin{bmatrix} x\\y \end{bmatrix}, \qquad Wz=\sigma z.

بتوسيع الضرب الكتلي نحصل على

[AyA∗x]=[σxσy].\begin{bmatrix} Ay\\A^*x \end{bmatrix} = \begin{bmatrix} \sigma x\\\sigma y \end{bmatrix}.

أي Ay=σxAy=\sigma x وA∗x=σyA^*x=\sigma y.

انظر إلى أول معادلة. إنها تقريبًا التعريف الذي كنا نبحث عنه: yy يتصرف كـright singular vector، وxx كـleft singular vector، وσ\sigma كـsingular value.

A∈Cm×nA \in \mathbb{C}^{m \times n}

قد تكون A مستطيلة، لذلك eigendecomposition المباشر ليس متاحًا.

الشكل 5: برهان وجود تفكيك القيم المفردة. تُضمّن المصفوفة المستطيلة في مصفوفة هيرميتية أكبر، ثم تُستخدم المبرهنة الطيفية لاستخراج أزواج المتجهات المفردة المتعامدة التي تكوّن تفكيك SVD.

افحص برهان الـblock matrix عدديًا

python

هذه التجربة العددية تعرض ما يتنبأ به البرهان تمامًا:

spec⁡(W)={−σi,0,+σi}.\operatorname{spec}(W) = \{-\sigma_i,0,+\sigma_i\}.

هذه هي الحيلة المركزية للبرهان كله: نحول مشكلة SVD لمصفوفة ربما تكون مستطيلة إلى eigenvalue problem لمصفوفة Hermitian أكبر.


لماذا تأتي القيم أزواجًا؟

إذا كان

[xy]\begin{bmatrix}x\\y\end{bmatrix}

eigenvector بقيمة +σ+\sigma، فانظر إلى

[x−y].\begin{bmatrix}x\\-y\end{bmatrix}.

باستخدام Ay=σxAy=\sigma x وA∗x=σyA^*x=\sigma y نجد

W[x−y]=−σ[x−y].W \begin{bmatrix}x\\-y\end{bmatrix} =-\sigma \begin{bmatrix}x\\-y\end{bmatrix}.

إذن القيم غير الصفرية تأتي في أزواج +σi,−σi+\sigma_i,-\sigma_i.

وبما أن WW Hermitian، فإن eigenvectors المرتبطة بقيم eigenvalues مختلفة يمكن اختيارها متعامدة. هذه المعلومة هي التي ستعطينا لاحقًا للاتجاهات المفردة.


نجمع القطع

نختار

zi=[xiyi]z_i= \begin{bmatrix}x_i\\y_i\end{bmatrix}

بحيث يكون zi∗zi=2z_i^*z_i=2.

قد يبدو الرقم 2 غريبًا، لكنه مقصود: نريد في النهاية أن يكون لكل من xix_i وyiy_i طول يساوي 1.

لدينا xi∗xi+yi∗yi=2x_i^*x_i+y_i^*y_i=2.

ومن تعامد eigenvector المرتبط بـ+σi+\sigma_i مع النظير المرتبط بـ−σi-\sigma_i نحصل على

xi∗xi−yi∗yi=0.x_i^*x_i-y_i^*y_i=0.

نجمع المعادلتين فنحصل على xi∗xi=1x_i^*x_i=1، ونطرحهما فنحصل على yi∗yi=1y_i^*y_i=1.

الآن نجمع المتجهات في مصفوفتين:

X=[x1 ⋯ xr],Y=[y1 ⋯ yr],X=[x_1\ \cdots\ x_r], \qquad Y=[y_1\ \cdots\ y_r],

ونضع القيم المفردة في Σr=diag⁡(σ1,…,σr)\Sigma_r=\operatorname{diag}(\sigma_1,\ldots,\sigma_r).

وباستخدام spectral decomposition للمصفوفة WW، ثم ضرب الكتل ومقارنة الجزء العلوي الأيمن، نحصل على ما أردناه:

A=XΣrY∗.\boxed{A=X\Sigma_rY^*.}

لماذا تبقى الاتجاهات نظيفة؟

وحدة الطول حصلنا عليها بالفعل. بقي أن نثبت أن الأعمدة المختلفة متعامدة.

لـi≠ji\neq j، تعامد eigenvectors لـWW يعطينا

xi∗xj+yi∗yj=0.x_i^*x_j+y_i^*y_j=0.

وعندما نقارن eigenvector الموجب للأول مع النظير ذي الإشارة السالبة للثاني نحصل على

xi∗xj−yi∗yj=0.x_i^*x_j-y_i^*y_j=0.

اجمع المعادلتين: 2xi∗xj=0⟹xi∗xj=02x_i^*x_j=0 \Longrightarrow x_i^*x_j=0. واطرحهما: 2yi∗yj=0⟹yi∗yj=02y_i^*y_j=0 \Longrightarrow y_i^*y_j=0. وهكذا X∗X=IrX^*X=I_r وY∗Y=IrY^*Y=I_r.

لم نعد نملك حدسًا فقط. لقد أثبتنا وجود الـcondensed SVD.


البرهان في نفس واحد

إذا ضاعت التفاصيل، لا تحفظ الصفحات. احفظ الحركة.

نبدأ بـAA، ثم نخفيها داخل

W=[0AA∗0].W= \begin{bmatrix} 0&A\\A^*&0 \end{bmatrix}.

WW Hermitian، لذلك تعطينا spectral theorem eigenvectors متعامدة معيارية. نقسم كل eigenvector إلى جزأين xix_i وyiy_i، فتخرج لنا المعادلتان

Ayi=σixi,A∗xi=σiyi.Ay_i=\sigma_i x_i, \qquad A^*x_i=\sigma_i y_i.

نجمع xix_i في XX، وyiy_i في YY، والقيم σi\sigma_i في Σr\Sigma_r، فنستعيد

A=XΣrY∗.\boxed{A=X\Sigma_rY^*.}

الـsingular vectors لم تظهر من العدم. كانت مختبئة داخل eigenvectors لمصفوفة Hermitian صممناها بعناية.


من حاصل ضرب إلى طبقات

حتى الآن رأينا SVD كآلة من ثلاث مراحل. الآن سنديرها قليلًا لنرى صورة ثانية لا تقل أهمية. اكتب U=[u1 u2 ⋯ ]U=[u_1\ u_2\ \cdots] وV=[v1 v2 ⋯ ]V=[v_1\ v_2\ \cdots].

لأن Σ\Sigma قطرية، يمكن فتح حاصل الضرب إلى مجموع:

A=∑i=1min⁡(m,n)σiuiviT.\boxed{ A= \sum_{i=1}^{\min(m,n)} \sigma_i u_i v_i^T. }

كل uiviTu_iv_i^T مصفوفة ، لأن كل أعمدتها مضاعفات عددية من uiu_i.

إذن SVD يقول شيئًا مدهشًا وبسيطًا في الوقت نفسه:

المصفوفة طبقات rank-1 مرتبة من الأقوى إلى الأضعف.
الطبقة المحددة · R1
R1=9.35 u1v1TR_{1} = 9.35\,u_{1}v_{1}^T
اتجاه الخرج u
0.680.680.240.08
اتجاه الدخل vᵀ
0.680.680.240.08
4.384.381.530.484.384.381.530.481.531.530.540.170.480.480.170.05
مجموع الطبقات الحالي · 2 في المجموعخطأ فروبينيوس: 1.33
4.494.491.06-0.054.494.491.06-0.051.061.062.542.43-0.05-0.052.432.6

الشكل 6: كتابة المصفوفة كمجموع حدود من الرتبة الأولى. تُكتب A مجموعًا لحدود من الشكل σᵢuᵢvᵢᵀ. وتؤدي إضافة الحدود تباعًا إلى تحسين إعادة البناء وتقليل الباقي.

انظر إلى المصفوفة

حتى heatmap بسيطة للمصفوفة قد تكفي لكي تصبح البنية مرئية:

python

استعمل العرض نفسه كسرد متصل: ابدأ بالمصفوفة الأصلية AA، ثم اعزل طبقة rank-1، ثم اعرض truncated reconstruction AkA_k، وفي النهاية انظر إلى residual A−AkA-A_k. هكذا يصبح matrix decomposition شيئًا نراه يتحرك بدل أن يكون مجرد رموز.

اسحب طبقات rank-1 واحدةً واحدة

python

كل layer_i رتبتها لا تتجاوز 1.

ولعرض إحدى الطبقات:

python

القيمة σi\sigma_i هي قوة الطبقة. إذا كانت صفرًا، فالطبقة لا تضيف شيئًا. ومن هنا نحصل على حقيقة مهمة:

rank⁡(A)=#{i:σi≠0}.\boxed{ \operatorname{rank}(A) = \#\{i:\sigma_i\ne0\}. }

كم قطعة نحتاج؟

يمكن أيضًا فهم rank من زاوية البناء. إذا كانت

rank⁡(A)=k,\operatorname{rank}(A)=k,

فيمكن بناء AA من kk قطع rank-1، ولا يمكن فعل ذلك باستخدام k−1k-1 قطع rank-1 فقط.

هذه ليست مجرد صورة جميلة؛ إنها تعيد تفسير معنى الرتبة نفسه: كم اتجاهًا مستقلًا نحتاج حتى نبني المصفوفة؟

وهذا يقود طبيعيًا إلى rank factorization. إذا

A=YZTA=YZ^T

وكان لـYY عدد kk من الأعمدة، فإن كل أعمدة AA تعيش داخل span لتلك الأعمدة، ولذلك

rank⁡(A)≤k.\operatorname{rank}(A)\le k.

إذا كانت rank الفعلية تساوي rr، فلن تستطيع ضغط البعد الداخلي تحت rr مع الحفاظ على المساواة التامة.

SVD يعطينا rank factorization خاصة جدًا، لكنها لا تكتفي بأي أساس؛ تختار اتجاهات orthonormal وترتبها حسب القوة.


حين نقبل أن نفقد قليلًا

لنفترض أن

A=σ1u1v1T+σ2u2v2T+⋯ .A= \sigma_1u_1v_1^T+ \sigma_2u_2v_2^T+ \cdots.

إذا كانت أول عدة قيم مفردة كبيرة والبقية صغيرة، قد نقرر الاحتفاظ بأول kk طبقات فقط:

Ak=∑i=1kσiuiviT=UkΣkVkT.\boxed{ A_k= \sum_{i=1}^{k}\sigma_i u_i v_i^T =U_k\Sigma_kV_k^T. }

نحن هنا لا نزعم أن Ak=AA_k=A. نحن نختار أن نخسر جزءًا من المعلومة مقابل تمثيل أبسط.

A1=∑i=11σiuiviTA_{1} = \sum_{i=1}^{1} \sigma_i u_i v_i^T
المصفوفة الأصلية A
5410
4510
1132
0023
التقريب Aₖ
4.384.381.530.48
4.384.381.530.48
1.531.530.540.17
0.480.480.170.05
الباقي A − Aₖ
0.62-0.38-0.53-0.48
-0.380.62-0.53-0.48
-0.53-0.532.461.83
-0.48-0.481.832.95
مقياس الألوان المشترك
−50+5
∣A−Ak∣F\\|A-A_k\\|_F4.96

الشكل 7: إعادة البناء منخفضة الرتبة. تُعرض المصفوفة A وتقريبها من الرتبة k والباقي A − Aₖ بمقياس لوني موحّد. يحسّن رفع k التقريب ويقلل خطأ فروبينيوس.

truncated SVD

python

القيمتان تتفقان حتى حدود الدقة العددية.

ما الذي خسرناه؟ الفرق هو A−AkA-A_k.

ولقياس حجمه نستعمل Frobenius norm:

∥M∥F=∑i,jmij2.\boxed{ \|M\|_F= \sqrt{\sum_{i,j}m_{ij}^2}. }

وبسبب تعامد طبقات SVD نحصل على

∥A−Ak∥F2=∑i>kσi2.\boxed{ \|A-A_k\|_F^2 = \sum_{i>k}\sigma_i^2. }

أي أن خطأ الحذف ليس لغزًا؛ إنه مجموع طاقات الطبقات التي قررنا تركها خلفنا.


لماذا القطع الأولى هي الأفضل؟

هنا تأتي واحدة من أجمل نتائج القصة. truncated SVD ليس مجرد طريقة معقولة لاختيار rank-kk approximation. إنه الأفضل في Frobenius norm.

إذا كان BB أي مصفوفة تحقق rank⁡(B)≤k\operatorname{rank}(B)\le k، فإن

∥A−Ak∥F≤∥A−B∥F.\boxed{ \|A-A_k\|_F \le \|A-B\|_F. }

أي أنه إذا أعطيتك ميزانية لا تسمح إلا بـkk اتجاهات مستقلة، فلن تجد rank-kk matrix أقرب إلى AA من truncated SVD.

الفكرة وراء البرهان هي أن row space لأي BB رتبتها لا تتجاوز kk لا يمكن أن تلتقط أكثر من kk اتجاهات مستقلة. إذا أسقطنا AA على أي فضاء بعده kk، فإن أكبر طاقة يمكن الاحتفاظ بها تأتي من الاتجاهات المرتبطة بأكبر singular values. لذلك اختيار v1,…,vkv_1,\ldots,v_k ليس ذوقًا؛ هو الاختيار الذي يحتفظ بأكبر مقدار ممكن من ∑σi2\sum\sigma_i^2.

وبالتالي يكون الجزء المفقود أصغر ما يمكن:

∑i>kσi2.\sum_{i>k}\sigma_i^2.

هذه هي روح Eckart–Young: إذا كان عليك أن تنسى، فانْسَ أضعف الاتجاهات أولًا.


أين نتوقف؟

النظر إلى singular-value spectrum يشبه النظر إلى طبقات الجبل من جانبه. إذا هبطت القيم بسرعة ثم ظهر ذيل طويل صغير، فهذا يخبرنا أن كثيرًا من البنية يمكن وصفه بعدد قليل من الاتجاهات.

محتفظ بهامستبعدة
05.2410.479.3514.782130.874k = 2رقم المركبة iالقيمة المفردة σᵢ
الطاقة المحتفظ بها98.4%
خطأ فروبينيوس1.33
∥A−Ak∥F=∑i>kσi2\|A-A_k\|_F = \sqrt{\sum_{i>k}\sigma_i^2}

الشكل 8: طيف القيم المفردة واختيار الرتبة. تُظهر القيم المفردة المرتبة مكونات مهيمنة يعقبها انخفاض حاد. وتتغير الطاقة المحتفظ بها وخطأ إعادة البناء وفق الرتبة k المختارة.

singular values وخطأ التقريب

python

خطأ Frobenius الأمثل عند rank-kk:

python

مقياس شائع هو الطاقة المحتفظ بها:

Ek=∑i=1kσi2∑iσi2.E_k= \frac{\sum_{i=1}^{k}\sigma_i^2} {\sum_i\sigma_i^2}.

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


وهنا تدخل PCA

لنفترض أن XX data matrix مركز حول المتوسط، وفيه nn observations على الصفوف وpp features على الأعمدة.

نفككه:

X=UΣVT.X=U\Sigma V^T.

مصفوفة هي

S=1n−1XTX.S=\frac{1}{n-1}X^TX.

باستخدام SVD:

XTX=VΣTUTUΣVT=VΣTΣVT.X^TX =V\Sigma^TU^TU\Sigma V^T =V\Sigma^T\Sigma V^T.

إذن

S=VΣTΣn−1VT.\boxed{ S= V\frac{\Sigma^T\Sigma}{n-1}V^T. }

وهنا نرى الجسر بوضوح: أعمدة VV هي principal directions، وeigenvalues للـcovariance تساوي

λi=σi2n−1.\boxed{ \lambda_i=\frac{\sigma_i^2}{n-1}. }

إذن SVD لا يصبح PCA تلقائيًا لمجرد أننا نفكك أي مصفوفة. نحتاج أولًا إلى تفسير data matrix، وعادةً إلى mean centering، ثم نستخدم SVD كآلة حسابية ونظرية لاستخراج اتجاهات أكبر variance.

البيانات الأصليةبعد الإسقاط
PC₁PC₂
التباين على PC₁99.2%
المشاهدة المحددة: 1قيمة PC₁ -2.77 · الباقي على PC₂ 0.06

الشكل 9: إسقاط PCA على المركبة الرئيسية الأولى. تُسقط المشاهدات عموديًا على PC₁، التي تفسر 99.2% من التباين في هذا المثال؛ وتمثل الإزاحة العمودية الباقي.

PCA مباشرة من SVD

python

ولخفض البيانات إلى kk components:

python

دع PCA يتحرك

للبيانات ثنائية الأبعاد:

python

إذا أردنا reduction إلى kk أبعاد، نحتفظ بأول kk أعمدة من VV. و ratio للمكوّن ii يصبح

σi2∑jσj2.\boxed{ \frac{\sigma_i^2}{\sum_j\sigma_j^2}. }

لاحظ المربع. PCA تحاسب variance، ولذلك تدخل σi2\sigma_i^2، لا σi\sigma_i وحدها.

يمكن تلخيص العلاقة في جملة واحدة:

SVD هي آلة المصفوفات؛ PCA أحد أجمل الاستخدامات الإحصائية لهذه الآلة.

SVD في الصور: حين ترى الـ بعينيك

حتى الآن تحدثنا عن approximation وكأننا نحرك رموزًا على الورق. الصورة تجعلنا نرى الخسارة بأعيننا.

الصورة الأصلية
إعادة بناء بالرتبة k · 1
طاقة الصورة المحتفظ بها88.3%
القيم المخزنة37 / 32488.6% قيمة أقل
طبقات القيم المفردة
σ1
σ2
σ3
σ4

الشكل 10: إعادة بناء صورة منخفضة الرتبة باستخدام SVD. تستعيد إعادة البناء بالرتبة k البنية العامة للصورة قبل التفاصيل الدقيقة. تكفي أربع قيم مفردة غير صفرية لإعادة بناء هذا المثال ذي الأبعاد 18 × 18 بدقة، بينما تتطلب الرتب الأقل قيمًا مخزنة أقل.

الصورة الرمادية ذات mm صفوف وnn أعمدة يمكن تمثيلها كمصفوفة

A∈Rm×n,A\in\mathbb R^{m\times n},

حيث تمثل كل قيمة شدة pixel. وبمجرد أن أصبحت الصورة مصفوفة، أصبحت كل قصة SVD صالحة لها:

A=∑i=1rσiuiviT.A= \sum_{i=1}^{r}\sigma_i u_i v_i^T.

كل σiuiviT\sigma_i u_iv_i^T صورة-sized pattern من rank-1. لا يجب أن تتوقع أن تكون الطبقة الأولى “العين” والثانية “الشجرة”. هذه ليست segmentation دلالية؛ إنها أنماط separable رياضية تتراكب لتعيد الصورة.

إذا احتفظنا بأول kk طبقات فقط نحصل على

Ak=UkΣkVkT.A_k=U_k\Sigma_kV_k^T.

عندما يكون kk صغيرًا تظهر البنية العامة أولًا، ثم تعود التفاصيل مع زيادة kk. ونسبة الطاقة المحتفظ بها هي

Ek=∑i=1kσi2∑i=1rσi2.\boxed{ E_k= \frac{\sum_{i=1}^{k}\sigma_i^2} {\sum_{i=1}^{r}\sigma_i^2}. }

من ناحية التخزين، الصورة الأصلية تحتوي mnmn رقمًا، بينما تمثيل rank-kk يحتاج تقريبًا

k(m+n+1)k(m+n+1)

رقمًا إذا خزنا UkU_k وΣk\Sigma_k وVkTV_k^T. هذا يشرح المبدأ الرياضي للضغط، لكنه لا يعني أن JPEG أو WebP يعملان حرفيًا بحفظ هذه العوامل؛ codecs الحقيقية تدخل فيها quantization وentropy coding وتفاصيل هندسية أخرى.

أما صورة RGB فيمكن في أبسط تجربة تعليمية أن نفكك قنوات RR وGG وBB كل واحدة على حدة، ثم نعيد جمعها بعد .

الفائدة من هذا المثال ليست فقط “ضغط صورة”. إنه يمنح Eckart–Young وجهًا نراه: نحذف اتجاهات رياضية، ثم ننظر مباشرة إلى ما اختفى من الصورة.

ضغط الصور بـSVD

python

جرّب عدة قيم لـkk، ثم قارن جودة الصورة بصريًا مع Frobenius error.

SVD داخل الشبكات العصبية

ضغط الشبكات العصبية موضوع أوسع بكثير، لكن هناك جسرًا واحدًا يستحق أن نفتحه لأن الرياضيات هي نفسها تمامًا.

طبقة كثيفةطبقة من عاملينW ∈ ℝᵐˣⁿW ≈ UₖΣₖVₖᵀالمدخلات · n = 96المخرجات · m = 64المدخلات · n = 96k = 12المخرجات · m = 64VₖᵀUₖΣₖ···
أوزان الطبقة الكثيفة6,144
أوزان العاملين1,920
التغير في عدد المعاملات68.8% معاملات أقل

الشكل 11: تفكيك طبقة في شبكة عصبية إلى عوامل منخفضة الرتبة. تُقرب مصفوفة الأوزان الكثيفة W بالتعبير UₖΣₖVₖᵀ، فتُستبدل عملية تحويل خطية كبيرة بعمليتي تحويل أضيق.

طبقة fully connected تبدأ ب:

y=Wx+b.y=Wx+b.

تجاهل activation لحظة وانظر إلى WW. إنها مصفوفة. إذن

W=UΣVT.W=U\Sigma V^T.

إذا هبطت singular values بسرعة، يمكننا تقريبها بـ

W≈UkΣkVkT.W\approx U_k\Sigma_kV_k^T.

ضع ذلك داخل الطبقة:

y≈UkΣkVkTx+b.y\approx U_k\Sigma_kV_k^Tx+b.

الآن بدل linear layer كبيرة واحدة يمكن أن نفكر في تحويلين خطيين أصغر:

x→VkTz∈Rk→UkΣky∈Rm.x \xrightarrow{V_k^T} z\in\mathbb R^k \xrightarrow{U_k\Sigma_k} y\in\mathbb R^m.

إذا كانت W∈Rm×nW\in\mathbb R^{m\times n}، فالطبقة الأصلية تحمل mnmn weight parameters، بينما العاملان يحتاجان تقريبًا

k(m+n).k(m+n).

إذا كان k≪m,nk\ll m,n، فالفرق قد يكون كبيرًا.

لكن هناك تفصيلة لا يجوز القفز فوقها: إذا كان العاملان يستبدلان linear map واحدة، فلا نضع nonlinearity بينهما، وإلا لم نعد نمثل نفس rank-kk matrix product.

وهنا يظهر اتصال جميل مع PCA. PCA تسأل: هل activations تحتاج فعلًا كل هذه الاتجاهات؟ أما SVD على weights فتسأل: هل weight matrix نفسها تحتاج كل هذه الاتجاهات؟


استكشاف عددي

الصيغتان σi=λi(ATA)\sigma_i=\sqrt{\lambda_i(A^TA)} and ui=Aviσiu_i=\frac{Av_i}{\sigma_i} ممتازتان للفهم.

لكن في البرمجيات العددية قد يؤدي تكوين ATAA^TA صراحةً إلى سوء أكبر في conditioning لأن condition number يُربّع عمليًا. لذلك تستخدم مكتبات SVD الموثوقة خوارزميات أكثر استقرارًا بدل تنفيذ الفكرة النظرية حرفيًا.

إذن افصل بين سؤالين. إذا كان السؤال: من أين جاءت SVD؟ فـATAA^TA باب جميل للفهم. أما إذا كان السؤال: كيف أحسبها في عمل عددي حقيقي؟ فاستخدم routine موثوقة مثل numpy.linalg.svd أو scipy.linalg.svd أو MATLAB svd. الفهم والتنفيذ مرتبطان، لكنهما ليسا الشيء نفسه.


إشارات صغيرة لا تغيّر القصة

حتى بعد أن نجد SVD، لا يعني ذلك أن كل حرف فيها فريد بالطريقة التي قد نتوقعها. فإذا غيّرنا إشارة uiu_i وviv_i معًا، فإن σi(−ui)(−vi)T=σiuiviT\sigma_i(-u_i)(-v_i)^T=\sigma_i u_iv_i^T.

إذن الإشارة يمكن أن تنقلب في الزوج معًا دون أن تتغير المصفوفة.

وإذا تكررت singular value، مثل σ1=σ2\sigma_1=\sigma_2، فقد يكون subspace نفسه محددًا بينما لا يكون اختيار basis داخله فريدًا. المهم هنا أن SVD ترتب البنية، لكن بعض التفاصيل التمثيلية يمكن أن تتغير من خوارزمية إلى أخرى دون أن تتغير الحقيقة الرياضية.


أربعة فضاءات في لقطة واحدة

إذا كانت رتبة AA تساوي rr، فإن أول rr right singular vectors تمتد عليها row space:

R(AT)=span⁡(v1,…,vr).\mathcal R(A^T)=\operatorname{span}(v_1,\ldots,v_r).

أما البقية فتملأ null space:

N(A)=span⁡(vr+1,…,vn).\mathcal N(A)=\operatorname{span}(v_{r+1},\ldots,v_n).

وعلى جهة الخرج، أول rr left singular vectors تمتد عليها column space:

R(A)=span⁡(u1,…,ur),\mathcal R(A)=\operatorname{span}(u_1,\ldots,u_r),

والبقية تعطي left null space:

N(AT)=span⁡(ur+1,…,um).\mathcal N(A^T)=\operatorname{span}(u_{r+1},\ldots,u_m).

هنا نفهم لماذا يبدو SVD كأنه يجمع فصولًا كثيرة من الجبر الخطي في مشهد واحد: rank وrow space وcolumn space وnull spaces وorthogonality وeigenvectors وapproximation كلها تلتقي في نفس البناء.


ماذا تحمل كل طبقة؟

القطعة σiuiviT\sigma_i u_i v_i^T يمكن قراءتها بثلاث لهجات مختلفة من نفس اللغة. كـtransformation تقول vi→Aσiuiv_i\xrightarrow{A}\sigma_i u_i.

كـrank-1 layer هي لبنة واحدة داخل المصفوفة. وكـdata component، فإن viv_i اتجاه على جهة features، بينما uiσiu_i\sigma_i يحمل scores على جهة observations، وσi2\sigma_i^2 يتحول — بعد scaling الخاص بالـcovariance — إلى مقدار variance الذي تشرحه هذه الجهة في PCA.

ليست هذه ثلاث نظريات. إنها ثلاث زوايا لنفس الجبر.


الخريطة كاملة

التجميعالتفكيكالرتبةSVDقطع rank-1truncated SVDEckart–YoungPCAالصورالشبكات العصبية
truncated SVD

نحتفظ بأقوى الطبقات ونترك الضعيفة.

الشكل 12: خريطة مفاهيم SVD وتطبيقاته. تربط الخريطة بين تركيب المصفوفات وتفكيكها والرتبة وSVD المبتور وPCA وإعادة بناء الصور والطبقات منخفضة الرتبة في الشبكات العصبية.

يمكن ضغط الرحلة كلها في سلسلة واحدة:

Composition→Decomposition→Structured factors\boxed{ \text{Composition} \rightarrow \text{Decomposition} \rightarrow \text{Structured factors} }

ثم

Rank→Rank-1 pieces→A=∑iσiuiviT\boxed{ \text{Rank} \rightarrow \text{Rank-1 pieces} \rightarrow A=\sum_i\sigma_i u_iv_i^T }

ثم

A=UΣVT→Avi=σiui\boxed{ A=U\Sigma V^T \rightarrow Av_i=\sigma_i u_i }

ثم نحتفظ بالأقوى:

Ak=UkΣkVkT\boxed{ A_k=U_k\Sigma_kV_k^T }

فتعطينا Eckart–Young أفضل rank-kk approximation، ثم تظهر نفس right singular directions في PCA عندما يكون لدينا centered data.

إذا اختفت كل التفاصيل غدًا، احتفظ بهذه الفكرة:

SVD تبحث عن اتجاهات دخل متعامدة معيارية تتعامل معها المصفوفة بصورة مستقلة، وتخبرنا بقوة كل اتجاه، ثم ترتبها بحيث تصنع أقوى الاتجاهات أفضل وصف منخفض الرتبة للمصفوفة.

الجيران الذين مررنا بهم

LU يكتب A=LUA=LU ويحوّل Gaussian elimination إلى عامل سفلي وآخر علوي. QR يكتب A=QRA=QR ويفصل basis orthonormal عن معاملات مثلثية، ولذلك يظهر طبيعيًا في least squares. Cholesky يكتب A=LLTA=LL^T عندما تكون المصفوفة symmetric positive definite، مستغلًا التماثل بدل حساب عاملين مستقلين.

Spectral decomposition يجعل المصفوفة symmetric في صورة A=QΛQTA=Q\Lambda Q^T، حيث الأعمدة في QQ eigenvectors orthonormal وΛ\Lambda diagonal. Jordan يذهب أبعد نظريًا ليصل إلى صورة قطرية أو شبه قطرية عندما تسمح البنية، لكنه أكثر حساسية عدديًا. Schur يرضى ب TT لكنه يكسب تحويلًا unitary مستقرًا، ولهذا هو أكثر راحة للحساب العددي.

Polar decomposition يكتب A=QHA=QH، فيفصل rotation/reflection عن pure stretching. وإذا كانت لدينا SVD

A=UΣVT,A=U\Sigma V^T,

فيمكن رؤية

Q=UVT,H=VΣVT.Q=UV^T, \qquad H=V\Sigma V^T.

أما Interpolative decomposition فيكتب تقريبًا A≈CXA\approx CX مع اختيار أعمدة فعلية من AA، فيكسب interpretability على حساب أن اتجاهاته ليست بالضرورة الاتجاهات المثلى التي تنتجها SVD.

الفكرة التي تجمع الجميع لا تزال كما هي:

هل توجد طريقة ننظر بها إلى المصفوفة فتغدو أبسط؟

من القمة

النظر من القمة نحو الأفق شيء جميل. من هناك يبدو SVD كأن كل شيء اجتمع في لقطة واحدة: اتجاهات نظيفة، وتمدد، وطبقات rank-1، وتقريب منخفض الرتبة، ثم PCA والصور وحتى لمحة من الشبكات العصبية.

لكن القمة تخفي الطريق الذي صنعها. بدأنا بقطع نعرفها فجمعناها، ثم قلبنا السؤال وبدأنا التفكيك. ومع كل طبقة انكشف جزء آخر من الجبل.

النظر من القمة نحو الأفق شيء جميل، لكن ما كنا نحتاجه فقط قفزة إيمان لنرى ممَّا تكوَّن هذا الجبل.

المراجع

Andrews, H. C., & Patterson, C. L. (1976). Singular value decomposition (SVD) image coding. IEEE Transactions on Communications, 24(4), 425–432. https://doi.org/10.1109/TCOM.1976.1093309

Brain Station Advanced. (n.d.). No one taught SVD (singular value decomposition) like this [Video]. YouTube. https://youtu.be/llisH02KLrE

Denton, E. L., Zaremba, W., Bruna, J., LeCun, Y., & Fergus, R. (2014). Exploiting linear structure within convolutional networks for efficient evaluation. In Advances in neural information processing systems (Vol. 27, pp. 1269–1277). https://proceedings.neurips.cc/paper/2014/hash/1adaeb993eba95859121a43ea61bd858-Abstract.html

Existence of the singular value decomposition (SVD): A very detailed step-by-step explanation. (n.d.). [Unpublished study notes].

Jaderberg, M., Vedaldi, A., & Zisserman, A. (2014). Speeding up convolutional neural networks with low rank expansions. In Proceedings of the British Machine Vision Conference 2014. https://doi.org/10.5244/C.28.88

Matrix decompositions: Cohesive summary. (n.d.). [Unpublished study notes].

MIT OpenCourseWare. (n.d.-a). Singular value decomposition [Video]. YouTube. https://youtu.be/TX_vooSnhm8

MIT OpenCourseWare. (n.d.-b). Singular value decomposition (the SVD) [Video]. YouTube. https://youtu.be/mBcLRGuAFUk

Sainath, T. N., Kingsbury, B., Sindhwani, V., Arisoy, E., & Ramabhadran, B. (2013). Low-rank matrix factorization for deep neural network training with high-dimensional output targets. In 2013 IEEE International Conference on Acoustics, Speech and Signal Processing (pp. 6655–6659). https://doi.org/10.1109/ICASSP.2013.6638949

SVD, matrix rank, low-rank approximation, PCA, and the existence proof: A detailed, intuitive, step-by-step study guide. (n.d.). [Unpublished study notes].

Visual . (n.d.). SVD visualized, singular value decomposition explained | SEE Matrix, chapter 3 [Video]. YouTube. https://youtu.be/vSczTbgc8Rc

اقرأ المزيد