چیت‌شیت

ریاضی برای یادگیری ماشین

Math for Machine Learning

گرادیان‌ها، احتمال، اطلاعات، بهینه‌سازها، تجزیه‌ها و ایمنی ممیز شناور. NumPy، SciPy و PyTorch.

  • ۱۲ بخش
  • ۱۴ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. گراف محاسباتی، پیش‌رو و پس‌رو
  2. فرمول‌های کلیدی
  3. قواعد به‌روزرسانی
  4. وظایف در NumPy
  5. وظایف در PyTorch و SciPy
  6. مشتق‌گیری خودکار در چند خط
  7. سافت‌مکس و آنتروپی متقاطع پایدار
  8. تحلیل مؤلفه‌های اصلی (PCA) با SVD
  9. مقادیر پیش‌فرض و اعداد
  10. عیب‌یابی
  11. پرسش‌ها
  12. نکات کاربردی

گراف محاسباتی، پیش‌رو و پس‌رو

معماری
acگام رو به عقبx1 = 2dy/dx1 = 3x2 = 3dy/dx2 = 2ضربa = 6b = 1dy/db = 1جمعc = 7reluy = 7مقدار اولیه (Seed)dy/dy = 1

فرمول‌های کلیدی

مفهوم‌ها
قاعده‌ی زنجیره‌ای
$\frac{dy}{dx} = f'(g(x)) \cdot g'(x)$
بیز
$P(A \mid B) = \frac{P(B \mid A) \cdot P(A)}{P(B)}$
آنتروپی
$H(P) = -\sum_{x} p(x) \log(p(x))$
آنتروپی متقاطع
$H(P, Q) = -\sum_{x} p(x) \log(q(x))$
واگرایی کولبک-لایبلر
$D_{KL}(P \,\|\, Q) = H(P, Q) - H(P)$. متقارن نیست.
Log-sum-exp
$\log \sum_i e^{x_i} = \max(x) + \log \sum_i e^{x_i - \max(x)}$
شباهت کسینوسی
$\frac{a \cdot b}{\lVert a \rVert_2 \, \lVert b \rVert_2}$، بین -1 تا +1
تجزیه مقادیر منفرد (SVD)
$A = U \Sigma V^T$. رتبه $k$: $A_k = U_k \Sigma_k V_k^T$

قواعد به‌روزرسانی

مفهوم‌ها
گرادیان کاهشی
$w = w - \text{lr} \cdot \text{gradient}$
تکانه
$v = \beta v + \text{gradient}$، سپس $w = w - \text{lr} \cdot v$
گشتاورهای Adam
$m = \beta_1 m + (1 - \beta_1) g$، $v = \beta_2 v + (1 - \beta_2) g^2$
تصحیح سوگیری
$\hat{m} = m / (1 - \beta_1^t)$، $\hat{v} = v / (1 - \beta_2^t)$
گام Adam
$w = w - \text{lr} \cdot \hat{m} / (\sqrt{\hat{v}} + \epsilon)$
برنامه‌ی زمان‌بندی کسینوسی
$\text{lr}_{\min} + 0.5 (\text{lr}_{\max} - \text{lr}_{\min})(1 + \cos(\pi t / T))$
گام نیوتن
$w_{\text{new}} = w_{\text{old}} - H^{-1} \cdot \text{gradient}$
دما
$p_i = e^{z_i / T} / \sum_j e^{z_j / T}$

وظایف در NumPy

کار و کد
وظیفهکد
لایه‌ی متراکمnp.maximum(0, weights @ inputs + bias)
حل دستگاه مربعیnp.linalg.solve(A, b)
حداقل مربعاتnp.linalg.lstsq(X, y, rcond=None)[0]
Thin SVDU, S, Vt = np.linalg.svd(A, full_matrices=False)
تقریب با رتبه kU[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]
حل با شبه‌وارونnp.linalg.pinv(A) @ b
نُرم‌های سطریnp.linalg.norm(X, axis=1, keepdims=True)
ضرب ماتریسی دسته‌ایnp.einsum("bij,bjk->bik", batch_A, batch_B)

وظایف در PyTorch و SciPy

کار و کد
وظیفهکد
AdamW برای ترنسفورمرهاtorch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
برنامه‌ی زمان‌بندی کسینوسیtorch.optim.lr_scheduler.CosineAnnealingLR(adam, T_max=100)
برش بر اساس نُرمtorch.nn.utils.clip_grad_norm_()
بررسی گام رو به عقبtorch.autograd.gradcheck()
لگاریتم پایدار سافت‌مکسtorch.nn.functional.log_softmax()
معکوس CDF برای N(0, 1)stats.norm(loc=0, scale=1).ppf(0.975)
کاهش بعد PCA به 2DSklearnPCA(n_components=2).fit_transform(X)
کاهش بعد t-SNE به 2DTSNE(n_components=2, perplexity=30, random_state=42)

مشتق‌گیری خودکار در چند خط

کد
python
x = torch.tensor(2.0, requires_grad=True)   # ثبت عملیات روی x
y = x ** 2 + 3 * x + 1                      # گراف را می‌سازد
y.backward()                                # پیمایش حالت معکوس
print(x.grad)                              # 7.0 = 2*x + 3
def __mul__(self, other):
    out = Value(self.data * other.data, (self, other), '*')
    def _backward():
        self.grad += other.data * out.grad  # گرادیان محلی ضربدر بالادست
        other.grad += self.data * out.grad  # علامت =+ روی تمام موارد استفاده جمع می‌زند
    out._backward = _backward
    return out
self.grad = 1.0                             # مقداردهی اولیه dy/dy = 1
for v in reversed(topo):                    # از خروجی به ورودی‌ها
    v._backward()                           # قاعده‌ی زنجیره‌ای در هر گره

سافت‌مکس و آنتروپی متقاطع پایدار

کد
python
def softmax_stable(logits):
    max_logit = max(logits)                           # ابتدا بیشینه را کم کنید
    exps = [math.exp(z - max_logit) for z in logits]  # بزرگ‌ترین مقدار 1 می‌شود
    total = sum(exps)
    return [e / total for e in exps]
def cross_entropy_stable(true_class, logits):
    max_logit = max(logits)
    shifted = [z - max_logit for z in logits]
    log_sum_exp = math.log(sum(math.exp(s) for s in shifted))
    log_prob = shifted[true_class] - log_sum_exp      # ماندن در فضای لگاریتمی
    return -log_prob

تحلیل مؤلفه‌های اصلی (PCA) با SVD

گام‌به‌گام
  1. مرکزسازیمیانگین را از هر ویژگی کم کنید.
  2. کوواریانس$C = \frac{1}{n-1} X^T X$ برای داده‌های مرکزسازی‌شده.
  3. تجزیهتابع np.linalg.svd(A) را روی داده فراخوانی کنید. از eig روی $A^T A$ پرهیز کنید.
  4. مؤلفه‌هابردارهای منفرد راست V همان مؤلفه‌های اصلی هستند.
  5. واریانسمؤلفه‌ی i مقدار $\sigma_i^2 / (n-1)$ را توضیح می‌دهد.
  6. انتخاب kمؤلفه‌ها را تا رسیدن به واریانس تجمعی 90 تا 95٪ نگه دارید.
  7. تصویر کردنk جهت برتر را نگه دارید و بقیه را حذف کنید.

مقادیر پیش‌فرض و اعداد

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Adam lr0.001نقطه‌ی شروع اکثر مسائل
Adam beta20.999مقدار beta1 برابر 0.9 است
Adam epsilon1e-8جلوگیری از تقسیم بر صفر
SGD momentum lr0.01با تکانه 0.9
Gradient check h1e-5محدوده‌ی متداول 1e-5 تا 1e-7
Transformer max_norm1.00.5 برای RL و 5.0 برای شبکه‌های ساده‌تر
Dynamic loss scale start65536نصف کردن هنگام inf، دو برابر کردن پس از N گام بی‌خطا
Top-p0.9با دمای 0.7 برای کاربردهای عمومی

عیب‌یابی

عیب‌یابی
  • تابع زیان (loss) بعد از چند دوره NaN می‌شود

    علت
    سرریز سافت‌مکس یا نرخ یادگیری بسیار بالا
    راه‌حل
    سافت‌مکس پایدار، کاهش lr، برش گرادیان
  • توقف تابع زیان روی log(num_classes)

    علت
    خروجی‌های تقریباً یکنواخت
    راه‌حل
    بررسی برچسب‌ها، تابع زیان و نورون‌های مرده‌ی ReLU
  • دقت 1 تا 3٪ پایین‌تر با float16

    علت
    زیرریز گرادیان
    راه‌حل
    مقیاس‌بندی پویای تابع زیان یا bfloat16
  • نُرم گرادیان 0.0 در برخی لایه‌ها

    علت
    نورون مرده‌ی ReLU یا زیرریز float16
    راه‌حل
    استفاده از LeakyReLU یا GELU، مقیاس‌بندی گرادیان
  • تفاوت نتایج بین GPUها

    علت
    جمع ممیز شناور خاصیت شرکت‌پذیری ندارد
    راه‌حل
    torch.use_deterministic_algorithms(True)
  • مقدار 0.1 + 0.2 == 0.3 برابر با False است

    علت
    عدد 0.1 در دودویی نمایش دقیق ندارد
    راه‌حل
    math.isclose() یا استفاده از آستانه‌ی خطا (tolerance)
  • تغییر شدید جواب با تغییرات کوچک ورودی

    علت
    عدد حالت بزرگ
    راه‌حل
    افزودن $\lambda I$ یا حذف ویژگی‌های هم‌خط
  • یک کلمه‌ی دیده‌نشده خروجی بیز ساده را صفر می‌کند

    علت
    تخمین بیشینه‌ی درست‌نمایی (MLE) احتمال صفر می‌دهد
    راه‌حل
    هموارسازی لاپلاس، افزودن 1 به تعداد تکرارها

پرسش‌ها

پرسش و پاسخ
چرا حالت معکوس؟
ورودی‌های زیاد و یک تابع زیان. یک گام رو به عقب تمام گرادیان‌ها را محاسبه می‌کند.
چرا آنتروپی متقاطع؟
کمینه‌سازی آن درست‌نمایی داده‌ها را بیشینه می‌کند.
چرا bfloat16 برای آموزش؟
دامنه‌ی float32 را دارد، بنابراین مقادیر بالای 65,504 دچار سرریز نمی‌شوند.
چرا SVD و نه بردارهای ویژه‌ی A.T @ A؟
آن ضرب، عدد حالت را به توان دو می‌رساند.
چرا ترفند بازپارامتری‌سازی؟
فرمول $z = \mu + \sigma \epsilon$ اجازه می‌دهد گرادیان از $\mu$ و $\sigma$ عبور کند.

نکات کاربردی

نکته‌ها
  • ابعاد را چک کنید: (m x n) @ (n x p) = (m x p).
  • لگاریتم احتمالات را جمع کنید. ضرب احتمالات کوچک را تکرار نکنید.
  • هرگز اعداد ممیز شناور را با == مقایسه نکنید.
  • وقتی لایه یا تابع زیان جدیدی می‌نویسید گرادیان‌ها را بررسی کنید.
  • پرپلکسیتی برابر با نمای آنتروپی متقاطع در مبنای نپر (nats) است.
  • در بررسی گرادیان، خطای نسبی کمتر از 1e-5 قابل قبول است.