التعلم بالتجربة
في التعلم الخاضع للإشراف يأتي كل مثال بجوابه الصحيح. أما التداول فليس كذلك: لا أحد يخبرك بأفضل مركز، بل تتصرف فيجيبك السوق بربح أو خسارة. والتعلم المعزَّز ينمذج هذا بـوكيل يرصد حالة ويتخذ إجراءً ويتلقى مكافأة وينتقل إلى حالة جديدة بهدف تعظيم المكافأة الإجمالية عبر الزمن. وفي التداول قد تكون الحالة العوائد الأخيرة أو المركز الحالي والإجراءات الشراء أو الإبقاء أو البيع والمكافأة ربح الخطوة مطروحًا منه التكاليف. والصعوبة أن للإجراءات عواقب لاحقة وعلى الوكيل أن يكتشف ما يدرّ بالتجربة.
# Reward of one step: profit from the position held, minus the cost of changing position
def step_reward(position, price_change, previous_position, cost):
return position * price_change - cost * abs(position - previous_position)
print(round(step_reward(1, 0.5, 0, 0.1), 4)) # 0.4 went long, the price rose 0.5, paid 0.1 to trade
print(round(step_reward(-1, 0.5, 1, 0.1), 4)) # -0.7 flipped from long to short just before a rise: lost 0.5 and paid 0.2
print(step_reward(1, 0.5, 1, 0.1)) # 0.5 holding the same position costs nothingQ-learning: قيمة الإجراء في حالة
يحتفظ Q-learning بجدول Q[حالة, إجراء]: المكافأة الإجمالية المتوقعة إن اتخذت الإجراء في الحالة ثم أحسنت التصرف بعدها. وبعد كل خطوة يدفع الخانة نحو تقدير أفضل هو الهدف: المكافأة التي نلتها للتو مضافًا إليها القيمة المخصومة لأفضل إجراء في الحالة التالية reward + gamma * max(Q[الحالة التالية]). والتحديث Q[s, a] += alpha * (الهدف - Q[s, a]) بمعدل تعلم alpha. ومعامل الخصم gamma (من 0 إلى 1) يبين مدى أهمية المكافآت المستقبلية: gamma = 0 وكيل قصير النظر وقريب من 1 وكيل صبور، والعائد لمتتالية هو r0 + gamma r1 + gamma^2 r2 + .... وفي الخطوة النهائية لا توجد حالة تالية والهدف هو المكافأة فقط.
# One Q-learning update on a table of 2 states x 3 actions (short, flat, long)
import numpy as np
def q_update(q, state, action, reward, next_state, alpha, gamma):
updated = q.copy()
target = reward if next_state is None else reward + gamma * updated[next_state].max()
updated[state, action] += alpha * (target - updated[state, action])
return updated
q = np.zeros((2, 3))
q = q_update(q, 0, 2, 1.0, 1, 0.5, 0.9) # in state 0 we went long and earned 1.0
print(q[0]) # [0. 0. 0.5] moved halfway (alpha 0.5) toward the target of 1.0
q = q_update(q, 0, 2, 1.0, 1, 0.5, 0.9)
print(q[0]) # [0. 0. 0.75] a second visit moves it furtherالاستكشاف وحلقة تدريب كاملة
الوكيل الذي يتخذ دائمًا أفضل إجراء يعرفه لا يكتشف أبدًا إن كان غيره أفضل. وابسيلون الشره (epsilon-greedy) يعالج ذلك: باحتمال epsilon يستكشف إجراءً عشوائيًا وإلا يستغل الإجراء ذا أكبر Q ويذهب التعادل إلى الأول. وعادةً يبدأ epsilon مرتفعًا ثم يتناقص. والحلقة حينئذ: رصد الحالة واختيار إجراء وتلقي المكافأة والحالة التالية وتحديث Q والتكرار. وفي سوق لعبة يتبع فيه يوم صاعد يومٌ صاعد غالبًا يتعلم الوكيل الذي يرى «أمس كان صاعدًا» أن البقاء طويلًا يدرّ، ويكفي جدول من حالتين وثلاثة إجراءات لإظهار ذلك.
# A toy market where an up day tends to be followed by another up day; the agent learns to follow the trend
import random
import numpy as np
rng = random.Random(1)
positions = [-1, 0, 1] # action 0 = short, 1 = flat, 2 = long
q = np.zeros((2, 3)) # state 0 = yesterday down, state 1 = yesterday up
alpha, gamma, cost = 0.1, 0.9, 0.0005
state, previous = 1, 0
for step in range(20000):
epsilon = max(0.05, 1 - step / 10000)
u, explore = rng.random(), rng.randrange(3)
action = explore if u < epsilon else int(np.argmax(q[state]))
up = rng.random() < (0.65 if state == 1 else 0.35) # the trend continues 65% of the time
change = 0.01 if up else -0.01
reward = positions[action] * change - cost * abs(positions[action] - previous)
next_state = 1 if up else 0
target = reward + gamma * q[next_state].max()
q[state, action] += alpha * (target - q[state, action])
state, previous = next_state, positions[action]
print(int(np.argmax(q[0])), int(np.argmax(q[1]))) # 0 2 after a down day go short, after an up day go long# The discounted return: with gamma below 1 a reward now is worth more than the same reward later
def discounted_return(rewards, gamma):
total = 0.0
for reward in reversed(rewards):
total = reward + gamma * total
return total
rewards = [1.0, 1.0, 1.0]
print(discounted_return(rewards, 0.5)) # 1.75 1 + 0.5 + 0.25
print(discounted_return(rewards, 1.0)) # 3.0 a patient agent: a plain sum
print(discounted_return(rewards, 0.0)) # 1.0 a short-sighted agent: only the first reward counts- يرصد الوكيل حالة ويتصرف ويتلقى مكافأة (ربح ناقص تكاليف) ويتعلم أي الإجراءات تدرّ؛ والعائد هو المجموع المخصوم
r0 + gamma r1 + gamma^2 r2 + .... - يحدّث Q-learning القيمة
Q[s, a] += alpha * (reward + gamma * max Q[s'] - Q[s, a])(rewardفقط في الخطوة النهائية) ولا يعدّل الجدول القديم في مكانه هنا. - يستكشف epsilon-greedy باحتمال epsilon وإلا يستغل أكبر Q؛ درّب واختبر على فترات منفصلة واحتسب تكاليف واقعية وقارن بخطوط أساس بسيطة.
التالي: المشروع الختامي، مكتبة تسعير أو استراتيجية متكاملة تجمع كل شيء.
المختبر: ما الذي يُقيَّم
- استكشف أو استغل باستخدام
choose_action25 نقطة - تعلّم من خطوة واحدة باستخدام
q_update25 نقطة - اجعل التداول مكلفًا في
step_reward25 نقطة - اجمع المستقبل باستخدام
discounted_return25 نقطة