دوال التنشيط — التعلم العميق
دوال التنشيط (Activation Functions)
لماذا نحتاجها؟
بدون دالة تنشيط، كل طبقة مجرد تحويل خطي، وتركيب تحويلات خطية = تحويل خطي واحد. شبكة من 100 طبقة بلا تنشيط تساوي انحداراً خطياً بسيطاً! اللاخطية هي ما يسمح للشبكة بتعلم الحدود المنحنية والأنماط المعقدة.
import numpy as np
rng = np.random.default_rng(0)
W1, W2 = rng.normal(size=(3, 4)), rng.normal(size=(4, 2))
x = rng.normal(size=(1, 3))
print(np.allclose((x @ W1) @ W2, x @ (W1 @ W2))) # True: طبقتان خطيتان = طبقة واحدةالدوال الشائعة
| الدالة | المدى | الاستخدام |
|---|---|---|
| ReLU: max(0, z) | [0, ∞) | الافتراضي للطبقات المخفية: بسيطة وسريعة ولا تتشبع للقيم الموجبة |
| Leaky ReLU / GELU | | بدائل لـ ReLU؛ GELU شائعة في Transformers |
| Sigmoid: 1/(1+e⁻ᶻ) | (0, 1) | مخرج التصنيف الثنائي (احتمال) |
| Tanh | (−1, 1) | داخل RNN؛ متمركزة حول الصفر |
| Softmax | احتمالات مجموعها 1 | مخرج التصنيف متعدد الفئات |
| بلا تنشيط (linear) | (−∞, ∞) | مخرج الانحدار |
import numpy as np
def relu(z): return np.maximum(0, z)
def sigmoid(z): return 1 / (1 + np.exp(-z))
def softmax(z):
e = np.exp(z - z.max()) # طرح الأكبر لتجنب الفيض العددي
return e / e.sum()
z = np.array([-2.0, 0.0, 3.0])
print("ReLU ", relu(z))
print("Sigmoid", sigmoid(z).round(3))
print("Softmax", softmax(z).round(3), "المجموع =", softmax(z).sum())لاحظ z - z.max() في softmax: np.exp(1000) يفيض إلى inf، والطرح لا يغيّر النتيجة رياضياً ويمنع الفيض.
مشكلة تلاشي التدرج (Vanishing Gradient)
مشتقة sigmoid أقصاها 0.25، وتقترب من الصفر للقيم الكبيرة والصغيرة. في شبكة عميقة تُضرب المشتقات ببعضها عبر الطبقات (الدرس القادم: Backpropagation)، فتصبح ضئيلة جداً في الطبقات الأولى ولا تتعلم شيئاً:
import numpy as np
d_sigmoid_max = 0.25
for layers in [2, 5, 10, 20]:
print(layers, "طبقة ←", d_sigmoid_max ** layers)مشتقة ReLU = 1 للقيم الموجبة، فلا تتلاشى بنفس الطريقة — لهذا كانت ReLU من أسباب نجاح الشبكات العميقة.
مشكلة ReLU: العصبونات الميتة
إذا صار مدخل العصبون سالباً دائماً، فمخرجه ومشتقته صفر ولن يتعلم بعدها. معدل تعلم مرتفع جداً يسببها غالباً؛ Leaky ReLU (ميل صغير للقيم السالبة) أحد الحلول.
القاعدة العملية
- الطبقات المخفية: ReLU (أو GELU في Transformers).
- المخرج: sigmoid للثنائي، softmax للمتعدد، بلا تنشيط للانحدار.
تمرين
ارسم (أو اطبع جدولاً لـ) مشتقات ReLU و sigmoid و tanh للقيم من −5 إلى 5. أيها يتلاشى أسرع؟
import numpy as np
import matplotlib.pyplot as plt
# ===== تعريف الدوال =====
def relu(x):
return np.maximum(0, x)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def tanh(x):
return np.tanh(x)
# ===== رسم الدوال =====
x = np.linspace(-5, 5, 100)
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.plot(x, relu(x))
plt.title('ReLU')
plt.grid(True)
plt.subplot(1, 3, 2)
plt.plot(x, sigmoid(x))
plt.title('Sigmoid')
plt.grid(True)
plt.subplot(1, 3, 3)
plt.plot(x, tanh(x))
plt.title('Tanh')
plt.grid(True)
plt.show()
# ===== في Keras =====
from tensorflow import keras
model = keras.Sequential([
keras.layers.Dense(128, activation='relu'), # Hidden
keras.layers.Dense(64, activation='relu'), # Hidden
keras.layers.Dense(10, activation='softmax') # Output (10 فئات)
])
# للتصنيف الثنائي
binary_model = keras.Sequential([
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(1, activation='sigmoid') # Output (0 أو 1)
])اختبر فهمك