ناوبری ابتدا
بسم الله الرحمن الرحیم

ماتریس‌ها و مشتق: یک آغاز

توسط بهروز در بیست و نهم دی ماه ۱۳۹۷ (ریاضیات)

از همه چیز من مشخص است که چه‌قدر به ریاضیات علاقه دارم. با این وجود، سال دوم کارشناسی ارشد بود که مجبور شدم بصورت جدی، دنبال مشتق‌گرفتن از توابع با ورودی ماتریس بروم. آخرش هم یک کتابچه‌ی کوچک ۱۴ صفحه‌ای از یک استاد اقتصاد کشاورزی بود که کار من را راه انداخت.

الآن بعد گذشت بیش از ۱۲ سال، دیگر مشتق‌گرفتن از این‌طور توابع دغدغه‌ی جدی‌ای محسوب نمیشود. حالاها دیگر جعبه‌ابزارهایی مثل پای‌تورچ و تنسورفلو خودشان برایت از تابعی که ساخته‌ای مشتق میگیرند و هزار کار دیگر هم می‌کنند. با این وجود، داشتن دانش مشتق‌گیری از توابع با متغیرهای ماتریسی، هنوز هم می‌تواند برای کسانی که با جزئیات بهینه‌سازی مدل‌هایشان دست و پنجه نرم می‌کنند مفید باشد (حداقل این گزاره بهانه‌ی خوبی برای من است که در این ارتباط بنویسم!)

توابع با ورودی ماتریس

مثال‌های توابع با ورودی ماتریس فراوانند. یکی از معروف‌ترین‌هاشان همین تابع توزیع گوسی خودمان است. تابع توزیع گوسی چند متغیره: $$p(x\mid \Sigma, \mu)=(2\pi\text{det}\Sigma)^{-\frac{1}{2}}\text{exp}\left(\frac{1}{2}(x-\mu)^T\Sigma^{-1}(x-\mu)\right)$$ اگر یک سری نمونه از این توزیع داشته باشیم و بخواهیم ماتریس $\Sigma$ را تخمین بزنیم، با توابعی سر و کار خواهیم داشت که ورودی‌شان ماتریس است.

از دیگر نمونه‌های این توابع، انواع مدل‌های شبکه‌ی عصبی هستند. در اکثر انواع شبکه‌های عصبی، یک سری ماتریس وزن وجود دارد که برای بهینه‌سازی و یافتن پارامترهای مدل سر و کارمان با توابعی از همین ماتریس‌های وزن خواهد افتاد.

برای آنکه یک نمونه را تا انتها دیده باشیم، بیایید دوباره به تحمین ماتریس $\Sigma$ برگردیم. $n$ نمونه از $x$ داریم که با $x_1$ و $x_2$ تا $x_n$ نمایش می‌دهیم. می‌خواهیم $\Sigma$یی پیدا کنیم که احتمال رخداد این نمونه‌ها را بیشینه کند. فرض هم میکنیم که $x_i$ها همگی IID باشند؛ یعنی توزیع همگی‌شان مشابه باشد و از همدیگر مستقل هم باشند. با این توضیحات: $$\begin{aligned} J(\Sigma)=p(x_1,x_2,\ldots x_n\mid \Sigma,\mu )&=\prod (2\pi\text{det}\Sigma)^{-\frac{1}{2}}\text{exp}\left(\frac{1}{2}(x_i-\mu)^T\Sigma^{-1}(x_i-\mu)\right)\\ &=(2\pi\text{det}\Sigma)^{-\frac{n}{2}}\text{exp}\left(\frac{1}{2}\sum (x_i-\mu)^T\Sigma^{-1}(x_i-\mu)\right) \end{aligned}$$ تابعی است که باید نسبت به ورودی خود یعنی $\Sigma$ بیشینه شود. تابعی با ورودی ماتریس که باید از آن نسبت به ورودی مشتق بگیریم و برابر صفر قرار دهیم و مقدار بهینه را بیابیم.

مشتق توابع ماتریسی بدون درد و خونریزی

اگر بخواهیم بصورت اصولی از توابع با ورودی ماتریس مشتق بگیریم، سر و کارمان با تنسورها و عملگرهای تنسوری خواهد افتاد. اما راه ساده‌تری هم هست. این راه ساده، بر مبنای یک دیدگاه نغز است؛ «هنگام محاسبه‌ی مشتق، چیدمان عناصر ماتریس موضوعی در درجه‌ی دوم اهمیت است.»

وقتی با این نگاه به سراغ مشتق نسبت به ماتریس‌ها برویم، دیگر چیدمان عناصر ماتریس را وقعی نمی‌نهیم! هر ماتریس یک بردار بزرگ است به همراه دو عدد که نمایشگر نحوه‌ی چیدمان عناصر هستند. مثلاً: $$\left[\begin{array}{cc} 5 &4\\ 3 &2\\ 1 &0 \end{array}\right]\sim \left(\left[\begin{array}{c} 5\\ 3\\ 1\\ 4\\ 2\\ 0 \end{array}\right],(3,2)\right)$$ اگر دقت کنید، در این نمایش جدید واقعاً هیچ چیزی گم نشده. همان ماتریس اول را دوباره می‌توانیم بسازیم. یک بردار داریم که به هم چسبیده‌ی ستون‌های ماتریس اولیه است و یک زوج مرتب داریم که ابعاد ماتریس را نمایش می‌دهد.

ممکن است بپرسید که این به چه دردی می‌خورد؟ اما من الآن به این سؤال پاسخ نمی‌دهم! اولش باید بگویم که چسباندن ستون‌های یک ماتریس به هم عملگری ریاضی است که اسم هم دارد. به آن در مشتق‌گیری ماتریسی عملگر $\text{vec}$ می‌گوییم.

به سؤال بالا برگردیم: وقتی ماتریس‌ها را بصورت بردار نمایش دهیم، مشتق‌گیری نسبت به ماتریس‌ها می‌شود مشتق‌گیری نسبت به بردارها که اصولاً شناخته شده است و از ریاضیات ۲ در سال اول دانشگاه با این کار آشنا هستیم. ماتریس ژاکوبی را که یادتان هست.

در ریاضیات ۲ سال اول دانشگاه دیدیم که برای مشتق گرفتن توابع نسبت به بردارها طبق تعریف به این صورت عمل می‌کنیم: $$\begin{aligned} &f(x)=(f_1(x), f_2(x),\ldots f_n(x))\\ &\frac{\partial f}{\partial x}=J=\left[\begin{array}{cccc} \frac{\partial f_1}{\partial x_1} &\frac{\partial f_1}{\partial x_2} &\cdots &\frac{\partial f_1}{\partial x_m}\\ \frac{\partial f_2}{\partial x_1} &\frac{\partial f_2}{\partial x_2} &\cdots &\frac{\partial f_2}{\partial x_m}\\ \vdots &\ddots &\vdots\\ \frac{\partial f_n}{\partial x_1} &\frac{\partial f_n}{\partial x_2} &\cdots &\frac{\partial f_n}{\partial x_m} \end{array}\right] \end{aligned}$$ خب از همین شیوه برای گرفتن مشتق نسبت به ماتریس‌ها هم استفاده می‌کنیم. مشتق نسبت به ماتریس را مشتق نسبت به $\text{vec}$شده‌ی آن ماتریس در نظر می‌گیریم: $$\frac{\partial f}{\partial X}=\frac{\partial f}{\partial \text{vec}(X)}$$ به عبارت دقیق‌تر: $$\frac{\partial F}{\partial X}=\frac{\partial \text{vec}(F)}{\partial \text{vec}(X)}$$ کار تمام شد رفت. دیگر نه نیاز به جبر تنسوری داریم و نه آن کووکتور و کنتراوکتورها! تنها چیزی که از جبر تنسوری به سطح ماتریس‌ها نزول پیدا می‌کند و لازمش داریم، ضرب کرونکر است. فی‌الحال ضرب کرونکر را فراموش کنید. اولش یک مقدار با همین ساده‌سازی حال کنیم، برای نگاه عمیق‌تر فرصت هست.

بیایید از یک ماتریس نسبت به خودش مشتق بگیریم. برای اینکار باید آن را بصورت یک بردار در بیاوریم: $$\begin{aligned} &A=\left[\begin{array}{cccc} A_{11} &A_{12} &\cdots &A_{1m}\\ A_{21} &A_{22} &\cdots &A_{2m}\\ \vdots &\ddots &\vdots\\ A_{n1} &A_{n2} &\cdots &A_{nm} \end{array}\right]\\ &\text{vec}(A)=\left[\begin{array}{c} A_{11}\\ A_{21}\\ \vdots\\ A_{n1}\\ A_{12}\\ A_{22}\\ \vdots\\ A_{nm} \end{array}\right]\\ &\text{vec}(A)_k = A_{\lfloor \frac{k}{n}\rfloor,k-n\lfloor \frac{k}{n}\rfloor} \end{aligned}$$ بعدش کافیست ماتریس ژاکوبی را محاسبه کنیم: $$J_{ij}=\frac{\partial \text{vec}(A)_i}{\partial \text{vec}(A)_j}=\delta_{ij}$$ ژاکوبی در این مورد بصورت ساده‌ای می‌شود ماتریس همانی با ابعاد $nm\times nm$. خب همین هم انتظار می‌رفت. حالا یک مشتق که مقداری پیچیده‌تر باشد. فرض کنید که تابع تک متغیره‌ی $g$ را می‌شناسیم. آن را روی همه‌ی عناصر ماتریس $A$ اعمال می‌کنیم و اسم این کار را هم همان $g$ می‌گذاریم: $$g(A)=\left[\begin{array}{cccc} g(A_{11}) &g(A_{12}) &\cdots &g(A_{1m})\\ g(A_{21}) &g(A_{22}) &\cdots &g(A_{2m})\\ \vdots &\ddots &\vdots\\ g(A_{n1}) &g(A_{n2}) &\cdots &g(A_{nm}) \end{array}\right]$$ مشتق $\frac{\partial g(A)}{\partial A}$ چه می‌شود؟ با محاسباتی مشابه محاسبه‌ی $\frac{\partial A}{\partial A}$ داریم: $$J_{ij}=\frac{\partial \text{vec}\left(g(A)\right)_i}{\partial \text{vec}(A)_j}=\delta_{ij}g'(A_{\lfloor \frac{i}{n}\rfloor,i-n\lfloor \frac{i}{n}\rfloor})=\text{diag}(\text{vec}(g'(A)))$$ این یعنی ماتریسی که فقط عناصر قطر اصلی‌اش غیر صفرند و مقادیر آن‌ها هم مقادیر مشتقات $g$ به ازای عناصر $A$ هستند.

تنها چیزی که در این پست آغازین باید اضافه کنم این است که مشتق نسبت به ماتریس‌ها هم عملگری خطی است. این یعنی ضرب اسکالر و جمع نسبت به این عملگر خاصیت پخشی دارند: $$\frac{\partial (\alpha A+\beta B)}{\partial X}=\alpha\frac{\partial \text{vec}(A)}{\partial \text{vec}(X)}+\beta\frac{\partial \text{vec}(B)}{\partial \text{vec}(X)}$$

تا اینجا دیدیم که اگر فرم چینش متغیرها درون ماتریس را موقتاً نادیده بگیریم به یکسری تعریف خوش‌ساخت برای مشتق نسبت به ماتریس می‌رسیم. برای این کار هم از عملگر $vec$ استفاده می‌کنیم که ستون‌های ماتریس ورودی را به هم می‌چسباند و یک بردار طولانی درست می‌کند. برای راحتی کار از این به بعد هر جا $\frac{\partial A}{\partial B}$ نوشتم، منظورم همان $\frac{\partial \text{vec}(A)}{\partial \text{vec}(B)}$ است. در پست بعدی، به بخش‌های جالب‌تری از مشتق‌گیری نسبت به ماتریس خواهم پرداخت.