دالة بمقابض وطريقة لتدويرها
الشبكة العصبية مجرد دالة بأرقام كثيرة قابلة للضبط هي الأوزان. تضرب الطبقة المدخلات بمصفوفة أوزان وتضيف انحيازًا؛ ثم تُطبَّق لاخطية مثل ReLU (max(x, 0))؛ ويغذي الناتج الطبقة التالية. وبتكديسها هكذا تستطيع هذه الدوال تقريب علاقات معقدة جدًا. والتدريب يعني اختيار الأوزان لتطابق التنبؤات أهدافًا معروفة: قِس عدم المطابقة بـخسارة (للتنبؤ برقم هي متوسط مربع الخطأ) واحسب كيف تتغير الخسارة مع كل وزن وادفع كل وزن قليلًا في الاتجاه الذي يخفضها. وهذه الدفعة المكررة آلاف المرات هي الانحدار التدريجي.
# A one-hidden-layer network: relu(x @ w1 + b1) @ w2 + b2
import numpy as np
def relu(x):
return np.maximum(x, 0.0)
def mlp_forward(x, w1, b1, w2, b2):
return relu(x @ w1 + b1) @ w2 + b2
x = np.array([[1.0, 2.0], [0.5, -1.0]]) # two samples, two features
w1 = np.array([[1.0, -1.0], [0.5, 1.0]]) # two hidden units
b1 = np.array([0.0, 0.5])
w2 = np.array([1.0, 2.0])
print(relu(np.array([-1.5, 0.0, 2.0]))) # [0. 0. 2.]
print(mlp_forward(x, w1, b1, w2, 0.1)) # [5.1 0.1] a prediction for each sample; the second sample's hidden values are switched off by the reluالانحدار التدريجي على أبسط نموذج
يستعمل تدريب الشبكة الانتشار العكسي للحصول على المشتقات لكن الفكرة مكتملة أصلًا لنموذج خطي y ~ x @ w + b. فلمتوسط مربع الخطأ مشتقة 2/n * x.T @ err بالنسبة إلى w و2 * mean(err) بالنسبة إلى b حيث err = التنبؤ - الهدف. ابدأ من الأصفار واطرح معدل التعلم مضروبًا في المشتقة وكرّر. ومعدل التعلم الكبير جدًا يتجاوز الهدف ويتباعد والصغير جدًا يزحف. وقِّس المتغيرات أولًا (متوسط صفر وتباين واحد) ليلائم معدل واحد كلها. وتحسب مكتبات مثل PyTorch المشتقات تلقائيًا لكنها تؤدي هذه الحلقة بالضبط.
# Gradient descent on a line: start at zero and walk downhill on the mean squared error
import numpy as np
def mse_loss(pred, target):
return float(np.mean((pred - target) ** 2))
def train_linear(x, y, lr, epochs):
n, d = x.shape
w, b = np.zeros(d), 0.0
for _ in range(epochs):
err = x @ w + b - y
w = w - lr * 2 / n * x.T @ err
b = b - lr * 2 * float(np.mean(err))
return w, float(b)
x = np.array([[0.0], [1.0], [2.0], [3.0]])
y = np.array([1.0, 3.0, 5.0, 7.0]) # exactly y = 2x + 1
for epochs in (0, 10, 2000):
w, b = train_linear(x, y, 0.05, epochs)
print(epochs, np.round(w, 3), round(b, 3), round(mse_loss(x @ w + b, y), 6))
# 0 [0.] 0.0 21.0 the zero start
# 10 [2.009] 0.958 0.00092 already close
# 2000 [2.] 1.0 0.0 the line y = 2x + 1 is foundلماذا يصعب على الشبكة التنبؤ بالعوائد
تستطيع الشبكة مطابقة أي شيء تقريبًا وهذا هو الخطر مع البيانات المالية: العوائد ضجيج في معظمها، فيحفظ النموذج المرن ضجيج فترة التدريب ويفشل في التالية. وفرط التعلم يظهر خطأ تدريب أدنى بكثير من الخطأ على بيانات لم تُرَ. والدفاعات هي ما رأيناه في المواضيع السابقة: قارن بخط أساس بسيط (نموذج خطي أو التنبؤ بصفر) وقيّم على بيانات لاحقة فقط بـالتحقق المتقدم (walk-forward) دون خلط الزمن، واستعمل متغيرات قليلة وشبكة صغيرة، وأضف تنظيمًا (اضمحلال الأوزان، dropout) وإيقافًا مبكرًا، وخذ متوسط عدة شبكات بدأت ببذور مختلفة. فإن لم تتفوق الشبكة بوضوح على الخط الخطي خارج العينة فاستعمل النموذج الخطي.
# Overfitting in miniature: a flexible fit to pure noise looks great in-sample and useless afterwards
import numpy as np
rng = np.random.default_rng(5)
x_train, x_test = rng.normal(size=(30, 12)), rng.normal(size=(1000, 12)) # 12 features that mean nothing
y_train, y_test = rng.normal(0, 0.01, size=30), rng.normal(0, 0.01, size=1000) # next-day returns: pure noise
w = np.linalg.lstsq(x_train, y_train, rcond=None)[0] # a model with 12 free weights fitted to 30 points
train_mse = np.mean((x_train @ w - y_train) ** 2)
test_mse = np.mean((x_test @ w - y_test) ** 2)
baseline_mse = np.mean(y_test ** 2) # predict zero
print(train_mse < baseline_mse, test_mse > baseline_mse) # True True better in-sample, worse than zero out of sample# The learning rate matters: a small one settles, one that is too large overshoots and the error blows up
import numpy as np
x = np.array([[1.0], [2.0], [3.0]])
y = np.array([2.0, 4.0, 6.0])
def final_errors(lr, epochs):
w, b, errors = np.zeros(1), 0.0, []
for _ in range(epochs):
err = x @ w + b - y
errors.append(float(np.mean(err ** 2)))
w = w - lr * 2 / len(y) * x.T @ err
b = b - lr * 2 * float(np.mean(err))
return errors
small, large = final_errors(0.05, 30), final_errors(0.5, 30)
print(small[-1] < small[0]) # True the error shrinks
print(large[-1] > 1000 * large[0]) # True the error explodes: the steps are too big- الطبقة هي
relu(x @ w + b)؛ والشبكة تكدّس طبقات، وتقيس الخسارة (متوسط مربع الخطأ في التنبؤ) بُعد التنبؤات عن الأهداف. - التدريب انحدار تدريجي: للنموذج الخطي
w -= lr * 2/n * x.T @ errوb -= lr * 2 * mean(err)؛ وقِس المتغيرات واضبط معدل التعلم. - العوائد ضجيج في معظمها: قارن بخط أساس خطي وتحقق بـ walk-forward واستعمل شبكات صغيرة منظَّمة وتوقف حين يختفي المكسب خارج العينة.
التالي: التعلم المعزَّز للتداول، تعلّم سياسة من المكافآت بدل الإجابات الموسومة.
المختبر: ما الذي يُقيَّم
- أطفئ السالب باستخدام
relu25 نقطة - شغّل الشبكة أمامًا باستخدام
mlp_forward25 نقطة - قِس الخطأ باستخدام
mse_loss25 نقطة - تعلّم بالنزول باستخدام
train_linear25 نقطة