وقتی در یادگیری ماشین با الگوریتمهایی مثل PCA، افزایش داده (Data Augmentation) یا تحلیل پایداری در شبکههای عصبی بازگشتی (RNN) روبهرو میشوید، با اصطلاحاتی مانند بردارهای ویژه، مقادیر ویژه و ماتریسهای دوران مواجه میشوید. اگر ماتریس را صرفاً جدولی از اعداد ببینید، فرمولها انتزاعی و خستهکننده میشوند؛ اما در دنیای واقعی، ماتریسها ابزارهایی هندسی برای جابهجایی، چرخش و تغییر شکل دادهها در فضا هستند.
درک هندسی ماتریسها به شما کمک میکند تا رفتار درونی لایههای شبکههای عصبی، تبدیلهای خطی و علت رخداد مشکلاتی مثل انفجار یا محو شدن گرادیان را بهدقت تحلیل کنید. در این درس یاد میگیرید که تبدیلهای دوران، مقیاسبندی و برش چطور تعریف میشوند و چگونه مقادیر و بردارهای ویژه را بهصورت پایهای با زبان پایتون محاسبه کنید.
تمام کدهای این درس کاملاً محاسباتی و سبک هستند و بدون نیاز به کارت گرافیک یا زیرساختهای ابری سنگین، روی سیستم شخصی یا پردازندهی معمولی سیستم شما با ابزار NumPy اجرا میشوند.
ماتریس ماشینی است که فضا را دگرگون میکند. ببینید با تکتک نقطهها چه میکند تا کل تبدیل را بفهمید.
اهداف یادگیری
- ساخت ماتریسهای دوران، مقیاسبندی، برش و بازتاب، و اِعمال آنها روی نقاط دوبعدی و سهبعدی
- ترکیب چند تبدیل با ضرب ماتریسی و بررسی اهمیت ترتیب تبدیلها
- محاسبهی مقادیر ویژه و بردارهای ویژهی ماتریسهای 2x2 با معادلهی مشخصه
- درک اینکه چرا مقادیر ویژه جهتهای PCA، پایداری RNN و رفتار خوشهبندی طیفی را تعیین میکنند
صورت مسئله
در مقالههای مربوط به تحلیل مؤلفههای اصلی (PCA) میخوانید: «بردارهای ویژهی ماتریس کوواریانس را پیدا کنید.» در مباحث پایداری مدل میخوانید: «بررسی کنید اندازهی تمام مقادیر ویژه کمتر از 1 باشد.» در بحث افزایش داده (Data augmentation) میخوانید: «یک دوران تصادفی اِعمال کنید.» تا وقتی ندانید ماتریسها از نظر هندسی چه بلایی سر فضا میآورند، هیچکدام از اینها معنا پیدا نمیکنند.
ماتریسها صرفاً جدولی از اعداد نیستند؛ ماشینهایی فضاییاند. ماتریس دوران نقطهها را میچرخاند؛ ماتریس مقیاسبندی آنها را میکشد یا فشرده میکند؛ ماتریس برش آنها را کج میکند. هر تبدیلی که یک شبکه عصبی روی دادهها پیاده میکند، یا یکی از همین عملیاتها است یا ترکیبی از آنها. در این درس این عملیات را کاملاً ملموس بررسی میکنیم.
مفاهیم پایه
تبدیلها در قالب ماتریس
هر تبدیل خطی در فضای دوبعدی را میتوان در قالب یک ماتریس 2x2 نوشت. این ماتریس دقیقاً نشان میدهد بردارهای پایهی [1, 0] و [0, 1] بعد از تبدیل به کجا میرسند. تکلیف بقیهی نقاط هم خودبهخود با همین دو بردار مشخص میشود.
دوران
دوران دوبعدی با زاویهی ، فاصلهها و زاویهها را دستنخورده نگه میدارد و هر نقطه را روی کمانی از یک دایره جابهجا میکند.
در فضای سهبعدی، دوران حول یک محور انجام میشود. هر محور ماتریس دوران مخصوص به خود را دارد:
مقیاسبندی
مقیاسبندی (Scaling) فضا را در راستای هر محور بهطور مستقل میکشد یا فشرده میکند.
برش
برش (Shearing) یک محور را کج میکند و محور دیگر را ثابت نگه میدارد؛ در نتیجه مستطیلها به متوازیالأضلاع تبدیل میشوند.
ماتریسهای برش:
- ماتریس
Shx = [[1, k], [0, 1]]مقدار را به اندازهی جابهجا میکند - ماتریس
Shy = [[1, 0], [k, 1]]مقدار را به اندازهی جابهجا میکند
بازتاب
بازتاب (Reflection) نقاط را نسبت به یک محور یا خط قرینه میکند.
ماتریسهای بازتاب:
- بازتاب نسبت به محور y: برابر با
[[-1, 0], [0, 1]] - بازتاب نسبت به محور x: برابر با
[[1, 0], [0, -1]]
ترکیب: زنجیرهسازی تبدیلها
اِعمال تبدیل A و سپس B دقیقاً معادل ضرب ماتریسهای آنها است: result = B @ A @ point. ترتیب در اینجا اهمیت دارد؛ نتیجهی دوران و سپس مقیاسبندی، با مقیاسبندی و سپس دوران متفاوت است.
ماتریس ترکیبشده: S @ R = [[0, -2], [0.5, 0]]
ماتریس ترکیبشده: R @ S = [[0, -0.5], [2, 0]]
نتایج متفاوتاند؛ ضرب ماتریسی خاصیت جابهجایی ندارد.
مقادیر ویژه و بردارهای ویژه
بیشتر بردارها وقتی با ماتریسی برخورد میکنند، جهتشان تغییر میکند. بردارهای ویژه (Eigenvectors) وضعیتی استثنایی دارند: ماتریس فقط مقیاس آنها را تغییر میدهد و هرگز جهتشان را نمیچرخاند. این ضریب مقیاس، همان مقدار ویژه (Eigenvalue) است.
A @ v = lambda * v
v is the eigenvector (direction that survives)
lambda is the eigenvalue (how much it stretches)
Example: A = | 2 1 |
| 1 2 |
Eigenvector [1, 1] with eigenvalue 3:
A @ [1,1] = [3, 3] = 3 * [1, 1] (same direction, scaled by 3)
Eigenvector [1, -1] with eigenvalue 1:
A @ [1,-1] = [1, -1] = 1 * [1, -1] (same direction, unchanged)
این ماتریس فضا را در راستای [1, 1] به میزان 3 برابر میکشد و راستای [1, -1] را بدون تغییر نگه میدارد. هر جهت دیگری در فضا، ترکیبی از همین دو بردار است.
تجزیهی مقادیر ویژه
اگر ماتریسی بردار ویژهی مستقل خطی داشته باشد، میتوان آن را تجزیه کرد (Eigendecomposition):
A = V @ D @ V^(-1)
V = matrix whose columns are eigenvectors
D = diagonal matrix of eigenvalues
V^(-1) = inverse of V
This says: rotate into eigenvector coordinates, scale along each axis, rotate back.
چرا مقادیر ویژه اهمیت دارند؟
تحلیل مؤلفههای اصلی (PCA): بردارهای ویژهی ماتریس کوواریانس، همان مؤلفههای اصلی هستند. مقادیر ویژه نشان میدهند هر مؤلفه چه میزان از واریانس را دربرمیگیرد. کافی است دادهها را بر اساس مقدار ویژه مرتب کنید، تای اول را نگه دارید و به همین سادگی کاهش بعد را انجام دهید.
پایداری: در شبکههای بازگشتی (RNN) و سیستمهای دینامیکی، مقادیر ویژهای با بزرگی (قدر مطلق) بیشتر از 1 خروجیها را منفجر میکنند. بزرگی کمتر از 1 هم باعث محو شدن و صفر شدن آنها میشود. این همان مسئلهی محو/انفجار گرادیان است که در یک جمله خلاصه شده.
روشهای طیفی: شبکههای عصبی گراف از مقادیر ویژهی ماتریس مجاورت استفاده میکنند. خوشهبندی طیفی سراغ مقادیر ویژهی ماتریس لاپلاسین میرود. بردارهای ویژه ساختار گراف را برملا میکنند.
دترمینان بهعنوان ضریب مقیاس حجم
دترمینان ماتریس تبدیل نشان میدهد که مساحت (در فضای دوبعدی) یا حجم (در فضای سهبعدی) با چه ضریبی مقیاسبندی میشود.
det = 1: area preserved (rotation)
det = 2: area doubled
det = 0: space crushed to lower dimension (singular)
det = -1: area preserved but orientation flipped (reflection)
| det(Rotation) | = 1 (always)
| det(Scale sx, sy) | = sx * sy
| det(Shear) | = 1 (area preserved)
| det(Reflection) | = -1 (orientation flipped)
پیادهسازی گامبهگام
گام 1: ماتریسهای تبدیل از صفر (Python)
import math
def rotation_2d(theta):
c, s = math.cos(theta), math.sin(theta)
return [[c, -s], [s, c]]
def scaling_2d(sx, sy):
return [[sx, 0], [0, sy]]
def shearing_2d(kx, ky):
return [[1, kx], [ky, 1]]
def reflection_x():
return [[1, 0], [0, -1]]
def reflection_y():
return [[-1, 0], [0, 1]]
def mat_vec_mul(matrix, vector):
return [
sum(matrix[i][j] * vector[j] for j in range(len(vector)))
for i in range(len(matrix))
]
def mat_mul(a, b):
rows_a, cols_b = len(a), len(b[0])
cols_a = len(a[0])
return [
[sum(a[i][k] * b[k][j] for k in range(cols_a)) for j in range(cols_b)]
for i in range(rows_a)
]
point = [1.0, 0.0]
angle = math.pi / 4
rotated = mat_vec_mul(rotation_2d(angle), point)
print(f"Rotate (1,0) by 45 deg: ({rotated[0]:.4f}, {rotated[1]:.4f})")
scaled = mat_vec_mul(scaling_2d(2, 3), [1.0, 1.0])
print(f"Scale (1,1) by (2,3): ({scaled[0]:.1f}, {scaled[1]:.1f})")
sheared = mat_vec_mul(shearing_2d(1, 0), [1.0, 1.0])
print(f"Shear (1,1) kx=1: ({sheared[0]:.1f}, {sheared[1]:.1f})")
reflected = mat_vec_mul(reflection_y(), [2.0, 1.0])
print(f"Reflect (2,1) across y: ({reflected[0]:.1f}, {reflected[1]:.1f})")
گام 2: ترکیب تبدیلها
R = rotation_2d(math.pi / 2)
S = scaling_2d(2, 0.5)
rotate_then_scale = mat_mul(S, R)
scale_then_rotate = mat_mul(R, S)
point = [1.0, 0.0]
result1 = mat_vec_mul(rotate_then_scale, point)
result2 = mat_vec_mul(scale_then_rotate, point)
print(f"Rotate 90 then scale: ({result1[0]:.2f}, {result1[1]:.2f})")
print(f"Scale then rotate 90: ({result2[0]:.2f}, {result2[1]:.2f})")
print(f"Same? {result1 == result2}")
گام 3: مقادیر ویژه از صفر (2x2)
برای ماتریس 2x2 به شکل [[a, b], [c, d]]، مقادیر ویژه پاسخهای معادلهی مشخصه هستند: .
def eigenvalues_2x2(matrix):
a, b = matrix[0]
c, d = matrix[1]
trace = a + d
det = a * d - b * c
discriminant = trace ** 2 - 4 * det
if discriminant < 0:
real = trace / 2
imag = (-discriminant) ** 0.5 / 2
return (complex(real, imag), complex(real, -imag))
sqrt_disc = discriminant ** 0.5
return ((trace + sqrt_disc) / 2, (trace - sqrt_disc) / 2)
def eigenvector_2x2(matrix, eigenvalue):
a, b = matrix[0]
c, d = matrix[1]
if abs(b) > 1e-10:
v = [b, eigenvalue - a]
elif abs(c) > 1e-10:
v = [eigenvalue - d, c]
else:
if abs(a - eigenvalue) < 1e-10:
v = [1, 0]
else:
v = [0, 1]
mag = (v[0] ** 2 + v[1] ** 2) ** 0.5
return [v[0] / mag, v[1] / mag]
A = [[2, 1], [1, 2]]
vals = eigenvalues_2x2(A)
print(f"Matrix: {A}")
print(f"Eigenvalues: {vals[0]:.4f}, {vals[1]:.4f}")
for val in vals:
vec = eigenvector_2x2(A, val)
result = mat_vec_mul(A, vec)
scaled = [val * vec[0], val * vec[1]]
print(f" lambda={val:.1f}, v={[round(x,4) for x in vec]}")
print(f" A@v = {[round(x,4) for x in result]}")
print(f" l*v = {[round(x,4) for x in scaled]}")
گام 4: دترمینان بهعنوان ضریب مقیاس حجم
def det_2x2(matrix):
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
print(f"det(rotation 45) = {det_2x2(rotation_2d(math.pi/4)):.4f}")
print(f"det(scale 2,3) = {det_2x2(scaling_2d(2, 3)):.1f}")
print(f"det(shear kx=1) = {det_2x2(shearing_2d(1, 0)):.1f}")
print(f"det(reflect y) = {det_2x2(reflection_y()):.1f}")
singular = [[1, 2], [2, 4]]
print(f"det(singular) = {det_2x2(singular):.1f}")
print("Singular: columns are proportional, space collapses to a line.")
استفاده از ابزارهای آماده
NumPy تمام این عملیات را با توابعی بهینهسازیشده انجام میدهد.
import numpy as np
theta = np.pi / 4
R = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
point = np.array([1.0, 0.0])
print(f"Rotate (1,0) by 45 deg: {R @ point}")
S = np.diag([2.0, 3.0])
composed = S @ R
print(f"Scale(2,3) after Rotate(45): {composed @ point}")
A = np.array([[2, 1], [1, 2]], dtype=float)
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"\nEigenvalues: {eigenvalues}")
print(f"Eigenvectors (columns):\n{eigenvectors}")
for i in range(len(eigenvalues)):
v = eigenvectors[:, i]
lam = eigenvalues[i]
print(f" A @ v{i} = {A @ v}, lambda * v{i} = {lam * v}")
print(f"\ndet(R) = {np.linalg.det(R):.4f}")
print(f"det(S) = {np.linalg.det(S):.1f}")
B = np.array([[3, 1], [0, 2]], dtype=float)
vals, vecs = np.linalg.eig(B)
D = np.diag(vals)
V = vecs
reconstructed = V @ D @ np.linalg.inv(V)
print(f"\nEigendecomposition A = V @ D @ V^-1:")
print(f"Original:\n{B}")
print(f"Reconstructed:\n{reconstructed}")
دورانهای سهبعدی با NumPy
def rotation_3d_z(theta):
c, s = np.cos(theta), np.sin(theta)
return np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
def rotation_3d_x(theta):
c, s = np.cos(theta), np.sin(theta)
return np.array([[1, 0, 0], [0, c, -s], [0, s, c]])
point_3d = np.array([1.0, 0.0, 0.0])
rotated_z = rotation_3d_z(np.pi / 2) @ point_3d
rotated_x = rotation_3d_x(np.pi / 2) @ point_3d
print(f"\n3D point: {point_3d}")
print(f"Rotate 90 around z: {np.round(rotated_z, 4)}")
print(f"Rotate 90 around x: {np.round(rotated_x, 4)}")
کاربرد در دنیای واقعی
این درس پایهی هندسی لازم را برای PCA (فاز 2) و تحلیل وزنهای شبکه عصبی میسازد. کدی که در اینجا برای محاسبهی مقادیر ویژه و بردارهای ویژه پیاده کردید، دقیقاً همان الگوریتمی است که سیستمهای کاهش بعد، خوشهبندی طیفی و تحلیل پایداری را در محیطهای عملیاتی یادگیری ماشین به راه میاندازد.
تمرینها
-
تبدیلهای دوران، مقیاسبندی و برش را روی یک مربع واحد (با گوشههای [0,0]، [1,0]، [1,1] و [0,1]) اِعمال کنید. مختصات جدید گوشهها را برای هر تبدیل چاپ کنید. بررسی کنید که دوران، فاصلهی بین گوشهها را حفظ میکند.
-
مقادیر ویژهی ماتریس [[4, 2], [1, 3]] را بهصورت دستی و با کمک معادلهی مشخصه پیدا کنید. سپس درستی آن را با تابعی که از صفر نوشتید و همچنین با NumPy بررسی کنید.
-
ترکیبی از سه تبدیل بسازید (دوران 30 درجه، مقیاسبندی با ضرایب [1.5, 0.8] و برش با kx=0.3) و آن را روی 8 نقطه که روی یک دایره چیده شدهاند اِعمال کنید. مختصات نقاط را قبل و بعد از تبدیل چاپ کنید. دترمینان ماتریس نهایی را محاسبه کنید و ببینید آیا با حاصلضرب دترمینانهای تکتک ماتریسها برابر است یا خیر.
راهنماییها
تمرین 1. توابع rotation_2d، scaling_2d و shearing_2d را با استفاده از mat_vec_mul روی هر گوشه اِعمال کنید. برای دوران، طول 4 ضلع و 2 قطر را قبل و بعد از تبدیل به دست آورید؛ این مقادیر باید دستنخورده باقی بمانند.
تمرین 2. معادلهی مشخصه را بنویسید و حل کنید. بررسی کنید که مجموع دو ریشه برابر با اثر ماتریس (7) و حاصلضرب آنها برابر با دترمینان (10) باشد؛ سپس نتیجه را با خروجی eigenvalues_2x2 و np.linalg.eigvals مقایسه کنید.
تمرین 3. این سه ماتریس را بسازید (برای ماتریس برش از shearing_2d(0.3, 0) استفاده کنید)، آنها را به ترتیبِ اِعمال با mat_mul در هم ضرب کنید و نتیجه را روی 8 نقطهی پیاده کنید. دترمینان ماتریس دوران 1 و ماتریس برش نیز 1 است؛ بنابراین خروجی تابع det_2x2 برای ماتریس نهایی باید دقیقاً برابر با شود.
اصطلاحات کلیدی
| اصطلاح | در گفتوگوهای روزمره | معنای دقیق فنی |
|---|---|---|
| ماتریس دوران (Rotation matrix) | «اشیا را میچرخاند» | ماتریسی متعامد (Orthogonal) که نقاط را روی کمانهای دایرهای جابهجا میکند و فاصلهها و زاویهها را ثابت نگه میدارد. دترمینان آن همیشه 1 است. |
| ماتریس مقیاسبندی (Scaling matrix) | «اشیا را بزرگ یا کوچک میکند» | ماتریسی قطری که فضا را در راستای هر محور بهطور مستقل میکشد یا فشرده میکند. دترمینان آن حاصلضرب ضرایب مقیاس است. |
| ماتریس برش (Shearing matrix) | «اشیا را کج میکند» | ماتریسی که یک مختصات را متناسب با مختصات دیگر جابهجا میکند و مستطیلها را به متوازیالأضلاع تبدیل میسازد. دترمینان آن برابر 1 است. |
| بازتاب (Reflection) | «تصویر آینهای میسازد» | ماتریسی که فضا را نسبت به یک محور یا صفحه برمیگرداند. دترمینان آن برابر 1- است. |
| ترکیب (Composition) | «انجام دو کار پشت سر هم» | ضرب ماتریسهای تبدیل برای زنجیرهسازی عملیات. ترتیب مهم است: B @ A یعنی اول A اِعمال شود، سپس B. |
| بردار ویژه (Eigenvector) | «جهت خاص» | جهتی که ماتریس فقط طول آن را تغییر میدهد و هرگز آن را نمیچرخاند؛ اثر انگشتِ تبدیل. |
| مقدار ویژه (Eigenvalue) | «میزان کشیدگی» | ضریب اسکالری که ماتریس، بردار ویژهی خود را با آن مقیاسبندی میکند. میتواند منفی (معکوس شدن جهت) یا مختلط (دوران) باشد. |
| تجزیهی مقادیر ویژه (Eigendecomposition) | «تجزیهی ماتریس به اجزای سازنده» | بازنویسی یک ماتریس به شکل ، که آن را به جهتها و اندازههای مقیاسبندی بنیادینش تفکیک میکند. |
| دترمینان (Determinant) | «یک عدد منفرد از ماتریس» | ضریبی که تبدیل مساحت (در 2D) یا حجم (در 3D) را با آن تغییر مقیاس میدهد. صفر بودن آن به معنای برگشتناپذیر بودن تبدیل است. |
| معادلهی مشخصه (Characteristic equation) | «معادلهای که مقادیر ویژه از آن میآیند» | معادلهی ؛ چندجملهای که ریشههای آن، مقادیر ویژهی ماتریس هستند. |
برای مطالعهی بیشتر
- 3Blue1Brown: Linear Transformations -- درک شهودی و بصری از نحوهی دگرگون شدن فضا توسط ماتریسها
- 3Blue1Brown: Eigenvectors and Eigenvalues -- بهترین توضیح بصری برای درک معنای هندسی بردارهای ویژه
- MIT 18.06 Lecture 21: Eigenvalues and Eigenvectors -- آموزش کلاسیک گیلبرت استرنگ (Gilbert Strang)
