حساب التفاضل والتكامل والتحسين
“من المشتقات إلى الانحدار التدريجي — المحرك الذي يدرّب كل شبكة عصبية”
المشتقات والمشتقات الجزئية وقاعدة السلسلة (الانتشار العكسي) والانحدار التدرجي — ثم Adam والزخم وجدولة معدل التعلم. القصة الكاملة لكيفية تعلم الشبكات العصبية.
المتطلبات الأساسية
المفاهيم المغطاة
∑الصيغ الرئيسية
التدرج
متجه المشتقات الجزئية — يشير إلى اتجاه أشد صعود
قاعدة السلسلة
العمود الفقري للانتشار الخلفي — تركيب المشتقات عبر الطبقات
الانحدار التدرجي
التحرك بشكل متكرر عكس التدرج لتقليل الخسارة L
تحديث آدم
انحدار تدرجي مع معدلات تعلم تكيفية لكل معامل (العزمات الأولى والثانية المصحَّحة)
▶محاكاة تفاعلية
التحسين هو ما يجعل النماذج تتعلم
تدريب نموذج التعلم الآلي هو مشكلة تحسين: إيجاد المعاملات θ التي تقلل دالة الخسارة L(θ). الانحدار التدرجي هو الخوارزمية الأساسية التي تحل هذا لمشاكل بملايين المعاملات حيث لا توجد حلول بصيغة مغلقة. قاعدة السلسلة تجعل حساب التدرجات عبر تركيبات عميقة من الدوال ممكناً — هذا هو الانتشار الخلفي.
نموذج GPT يحتوي على ~175 مليار معامل. الانحدار التدرجي يُحدّث جميعها في آنٍ واحد في تمرير خلفي واحد بفضل قاعدة السلسلة.
التدرج كاتجاه في فضاء المعاملات
تخيل دالة الخسارة كمنظر تلالي وموقعك هو معاملاتك. التدرج ∇L(θ) سهم يشير إلى الأعلى. التحرك في الاتجاه المعاكس (−η∇L) ينزل — نحو خسارة أقل. معدل التعلم η يتحكم في حجم الخطوة: كبير جداً فترتد (التشتت)، صغير جداً فيستغرق التدريب أبداً. يحل Adam هذا بالحفاظ على معدل تعلم منفصل لكل معامل بناءً على تاريخ تدرجاته.
الحدس لقاعدة السلسلة: إذا كان تغيير درجة الحرارة يؤثر على الضغط، والضغط يؤثر على الحجم، فكيف تؤثر درجة الحرارة على الحجم؟ اضرب الحساسيات الفردية.
محسِّن آدم — خطوة بخطوة
التهيئة: θ، m₀=0 (العزم الأول)، v₀=0 (العزم الثاني)، t=0، β₁=0.9، β₂=0.999، ε=1e-8
حساب التدرج: g_t = ∇_θ L(θ_{t-1})
تحديث العزم الأول المتحيز (الزخم): m_t = β₁·m_{t-1} + (1-β₁)·g_t
تحديث العزم الثاني المتحيز (المقياس التكيفي): v_t = β₂·v_{t-1} + (1-β₂)·g_t²
تصحيح التحيز: m̂_t = m_t/(1-β₁ᵗ)، v̂_t = v_t/(1-β₂ᵗ)
تحديث المعاملات: θ_t = θ_{t-1} - η·m̂_t / (√v̂_t + ε)
الحدس: m̂_t متوسط متحرك للتدرجات (زخم). √v̂_t يُطبّع حسب الحجم — المتغيرات ذات التدرجات الكبيرة تحصل على معدلات تعلم أصغر.
الانحدار التدرجي من الصفر
import numpy as np import matplotlib.pyplot as plt class="tok-comment"># ── Numerical derivatives (educational) ────────────────────────────────────── def numerical_grad(f, x, h=class="tok-num">1e-5): class="tok-str">"""Central difference approximation: (f(x+h) - f(x-h)) / 2h""" grad = np.zeros_like(x, dtype=float) for i in range(len(x)): x_plus = x.copy(); x_plus[i] += h x_minus = x.copy(); x_minus[i] -= h grad[i] = (f(x_plus) - f(x_minus)) / (class="tok-num">2 * h) return grad class="tok-comment"># ── class="tok-num">1. Gradient Descent on simple quadratic ─────────────────────────────────── def loss(theta): return (theta[class="tok-num">0] - class="tok-num">3)**class="tok-num">2 + (theta[class="tok-num">1] + class="tok-num">1)**class="tok-num">2 class="tok-comment"># minimum at (class="tok-num">3,-class="tok-num">1) def grad_loss(theta): return np.array([class="tok-num">2*(theta[class="tok-num">0]-class="tok-num">3), class="tok-num">2*(theta[class="tok-num">1]+class="tok-num">1)]) theta = np.array([class="tok-num">0., class="tok-num">0.]) lr = class="tok-num">0.1 history = [theta.copy()] for step in range(class="tok-num">50): g = grad_loss(theta) theta -= lr * g history.append(theta.copy()) if np.linalg.norm(g) < class="tok-num">1e-6: print(fclass="tok-str">"Converged at step {step}") break print(fclass="tok-str">"Final θ: {theta.round(class="tok-num">4)}") class="tok-comment"># ≈ [class="tok-num">3, -class="tok-num">1] class="tok-comment"># ── class="tok-num">2. Adam optimizer ──────────────────────────────────────────────────────── def adam(grad_fn, theta_init, lr=class="tok-num">0.01, n_steps=class="tok-num">100, b1=class="tok-num">0.9, b2=class="tok-num">0.999, eps=class="tok-num">1e-8): theta = theta_init.copy().astype(float) m, v = np.zeros_like(theta), np.zeros_like(theta) history = [theta.copy()] for t in range(class="tok-num">1, n_steps+class="tok-num">1): g = grad_fn(theta) m = b1*m + (class="tok-num">1-b1)*g v = b2*v + (class="tok-num">1-b2)*g**class="tok-num">2 m_hat = m / (class="tok-num">1 - b1**t) v_hat = v / (class="tok-num">1 - b2**t) theta -= lr * m_hat / (np.sqrt(v_hat) + eps) history.append(theta.copy()) return theta, history theta_adam, hist_adam = adam(grad_loss, np.array([class="tok-num">0., class="tok-num">0.]), lr=class="tok-num">0.1) print(fclass="tok-str">"Adam θ: {theta_adam.round(class="tok-num">4)}") class="tok-comment"># ── class="tok-num">3. Chain rule in action (manual backprop) ───────────────────────────────── class="tok-comment"># f(x) = (2x + class="tok-num">1)^class="tok-num">2. df/dx = class="tok-num">2 * (2x+class="tok-num">1) * class="tok-num">2 = class="tok-num">4*(2x+class="tok-num">1) x = class="tok-num">3.0 class="tok-comment"># Forward pass u = class="tok-num">2*x + class="tok-num">1 class="tok-comment"># u = class="tok-num">7 f = u**class="tok-num">2 class="tok-comment"># f = class="tok-num">49 class="tok-comment"># Backward pass (chain rule) df_du = class="tok-num">2*u class="tok-comment"># = class="tok-num">14 du_dx = class="tok-num">2 class="tok-comment"># constant df_dx = df_du * du_dx class="tok-comment"># = class="tok-num">28 print(fclass="tok-str">"df/dx at x=class="tok-num">3: {df_dx}") class="tok-comment"># analytical: class="tok-num">4*(class="tok-num">2*class="tok-num">3+class="tok-num">1) = class="tok-num">28 ✓ class="tok-comment"># ── class="tok-num">4. Learning rate sensitivity ───────────────────────────────────────────── fig, axes = plt.subplots(class="tok-num">1, class="tok-num">3, figsize=(class="tok-num">12,class="tok-num">3)) for ax, lr_val in zip(axes, [class="tok-num">0.01, class="tok-num">0.1, class="tok-num">0.9]): theta = np.array([class="tok-num">0.]) losses = [] for _ in range(class="tok-num">100): g = class="tok-num">2*(theta[class="tok-num">0] - class="tok-num">5) theta[class="tok-num">0] -= lr_val * g losses.append((theta[class="tok-num">0]-class="tok-num">5)**class="tok-num">2) ax.semilogy(losses) ax.set_title(fclass="tok-str">"lr = {lr_val}") ax.set_xlabel(class="tok-str">"Steps") ax.set_ylabel(class="tok-str">"Loss") plt.tight_layout() plt.show() class="tok-comment"># lr=class="tok-num">0.01: slow, lr=class="tok-num">0.1: perfect, lr=class="tok-num">0.9: oscillates
الحد الأدنى المحلي مقابل نقاط السرج — ما يبطئ التدريب فعلاً
في أسطح الخسارة عالية الأبعاد، الحدود الدنيا المحلية الحقيقية نادرة — معظم النقاط 'العالقة' هي نقاط سرج. الانحدار التدرجي مع الضوضاء (SGD) يهرب من نقاط السرج بشكل طبيعي. المشاكل العملية الأكبر هي: (1) انفجار التدرجات في الشبكات العميقة — استخدم قص التدرج. (2) اختفاء التدرجات في الشبكات التكررية — استخدم LSTM/GRU. (3) سوء التكييف — استخدم تطبيع الدُفعات أو تهيئة الأوزان.
للمشاكل المحدبة (الانحدار الخطي، اللوجستي، SVM)، الانحدار التدرجي مضمون للعثور على الحد الأدنى العالمي. للشبكات العصبية، يجد حوضاً 'جيداً بما يكفي'.
?اختبار المعرفة
يتم حفظ التقدم في متصفحك — لا حاجة لحساب.