למידת Reforcement עם גימנסיום: מדריך מעשי

למידת חיזוק (RL) היא אחת משלושת פרדיגמות למידת מכונה העיקריות, השתיים האחרות הן למידה בהדרכה ולא בהדרכה. ב-RL, סוכן לומד להתקשר עם הסביבה שלו כדי למקסם את הפרסומים הצבוריים. הוא לומד את הפעולה האופטימלית בתנאים סביבתיים שונים דרך ניסיון וטעייה. למידת חיזוק עם משוב אנושי (RLHF) מאפשרת לסוכן לשנות את ההתנהגות על סמך קלטים אנושיים בכל שלב.

RL פותרת בעיות כמו רכבים המתנהלים באופן עצמאי, מסחר אוטומטי, שחקנים ממוחשבים במשחקי וידאו, הכשרת רובוטים ועוד. כאשר רשתות עצבים עמוקות משמשות ליישום של אלגוריתמי RL, נקרא למידת חיזוק עמוקה.

במדריך זה, אני אראה לך כיצד להתחיל עם גימנזיום, ספריית פייתון קוד פתוחה לפיתוח והשוואת אלגוריתמי למידת חיזוק. אני אדגים כיצד להגדיר אותה, לחקור סביבות RL שונות, ולהשתמש בפייתון כדי לבנות סוכן פשוט ליישום אלגוריתם RL.

מהו גימנזיום?

גימנסיום הוא ספריית פייתון מקור פתוח המיועדת לתמוך בפיתוח של אלגוריתמי למידת חיזוי והחלטה. כדי לקדם מחקר ופיתוח בלמידת חיזוי והחלטה, גימנסיום מספקת:

  • מגוון רחב של סביבות, ממשחקים פשוטים עד בעיות הדומות לסצנאות בחיים אמיתיים.
  • ממשקי תכנות קלים ועטופים להתממשקות עם הסביבות.
  • היכולת ליצור סביבות מותאמות אישית ולהשתמש במסגרת ה- API.

מפתחים יכולים לבנות אלגוריתמים למידה חיזוית ולהשתמש בקריאות API למשימות כמו:

  • העברת הפעולה שנבחרה של הסוכן לסביבה.
  • להכיר את מצב הסביבה ואת הפרס לאחר כל פעולה.
  • אימון המודל.
  • בדיקת ביצועי המודל.

חדר הכושר של OpenAI מול חדר הכושר של Farama

OpenAI לא התחייבה למקורות משמעותיים לפיתוח חדר הכושר כי זה לא היה עדיפות עסקית עבור החברה. ה קרן פארמה הוקמה כדי לסטנדרטיזציה ותחזוק ספריות RL לאורך זמן. חדר הכושר הוא הפיצול של קרן פארמה מחדר הכושר של OpenAI. חדר הכושר 0.26.2 הוא תחליף ישיר לחדר הכושר 0.26.2. עם הפיצול, פארמה שואפת להוסיף שיטות פונקציונליות (בנוסף לשיטות מבוססות מחלקה) לכל קריאות ה-API, לתמוך בסביבות וקטור ולשפר את העטיפות. המטרה הכוללת היא להפוך את המסגרת לנקייה ויעילה יותר.

הגדרת חדר הכושר

הגימנסיה זקוקה לגרסאות ספציפיות (לא הגרסאות האחרונות) של תוכניות תלות שונות כמו NumPy ו-PyTorch. לכן, אנו ממליצים ליצור סביבה חדשה של Conda או venv או מחברת חדשה כדי להתקין, להשתמש בגימנסיה ולהריץ תוכניות RL. 

אתה יכול להשתמש ב-מחברת DataLab זו כדי להתקדם לפי המדריך.

התקנת גימנסיה

כדי להתקין את הגימנסיה על שרת או מחשב מקומי, הרץ:

$ pip install gymnasium

כדי להתקין באמצעות מחשב נייד דוגמת Colab של Google או DataLab של DataCamp, השתמש:

!pip install gymnasium

הפקודה שמעל מתקינה את Gymnasium ואת גרסאות התלות הנכונות.

חקירת סביבות Gymnasium

כפי שלנובמבר 2024, ב-Gymnasium יש מעל 60 סביבות מובנות. כדי לעיין בסביבות מובנות זמינות, השתמש בפונקציה gym.envs.registry.all(), כפי שמודגם בדוגמה שלהלן: 

import gymnasium as gym for i in gym.envs.registry.keys(): print(i)

אתה יכול גם לבקר בדף הבית של הגימנסיום. בעמוד הראשי יש קישורים לכל הסביבות. בעמוד הרשות של כל סביבה כולל פרטים עליה, כמו פעולות, מצבים, וכו'.

הסביבות מאורגנות לקטגוריות כמו בקרת קלאסית, Box2D, ועוד. להלן רשימה של חלק מהסביבות הנפוצות בקבוצה כלא:

  • בקרת קלאסית: אלה הן סביבות קנוניות המשמשות בפיתוח של למידת עמוק בהזדמנויות; הן מהוות את הבסיס של המון דוגמאות בספרי למידת עמוק. הן מספקות את השילוב הנכון של מורכבות ופשטות כדי לבחון ולהשוות אלגוריתמים חדשים של למידת עמוק. סביבות בקרת קלאסית בגימנסיום כוללות: 
    • Acrobot
    • Cart Pole
    • Mountain Car Discrete
    • Mountain Car Continuous
    • Pendulum
  • Box2D: Box2D הוא מנוע פיזיקה דו-ממדי למשחקים. סביבות המבוססות על מנוע זה כוללות משחקים פשוטים כמו:
    • נחיתת ירח
    • מרוץ מכוניות
  • טקסט צעצוע: אלו הן סביבות קטנות ופשוטות שהשימוש בהן נפוץ באיתור באגים באלגוריתמים של RL. רבות מהסביבות הללו מבוססות על מודל של עולם רשת קטן ומשחקי קלפים פשוטים. דוגמאות כוללות: 
    • בלק ג'ק
    • מונית
    • אגם קפוא
  • MuJoCo: דינמיקה מרובת מפרקים עם מגע (MuJoCo) הוא מנוע פיזיקה קוד פתוח המדמה סביבות ליישומים כמו רובוטיקה, ביומכניקה, ML וכו'. סביבות MuJoCo ב-Gymnasium כוללות:
    • נמלה
    • קופץ
    • הומנואיד
    • שחיין
    • ועוד

בנוסף לסביבות המובנות, ניתן להשתמש ב-Gymnasium עם רבות סביבות חיצוניות תוך שימוש באותו API.

נשתמש באחד מסביבות השליטה הקלאסיות הקנוניות בשיעור זה. כדי לייבא סביבה מסוימת, יש להשתמש בפקודת .make() ולהעביר את שם הסביבה כארגומנט. לדוגמה, כדי ליצור סביבה חדשה המבוססת על CartPole (גרסה 1), יש להשתמש בפקודה הבאה:

import gymnasium as gym env = gym.make("CartPole-v1")

הבנת מושגי למידת החיזוק בגימנזיום

בקצרה, למידת החיזוק כוללת סובל (כמו רובוט) שמתגבר עם הסביבה שלו. מדיניות היא שמה שמחליט פעולות של הסובל. תלוי בפעולות של הסובל, הסביבה נותנת פרס (או ענישה) בכל צעד זמן. הסובל משתמש בלמידת החיזוק כדי לגלות את המדיניות האופטימלית שמקסימלית את סכום הפרסים הכולל שהסובל מרוויח.

רכיבי סביבת למידת החיזוק

המרכיבים המרכזיים של סביבה RL הם:

  • סביבה: המערכת החיצונית, העולם או ההקשר. הסוכן מתקשר עם הסביבה בסדרה של צעדים בזמן. בכל צעד, בהתבסס על הפעולה של הסוכן, הסביבה:
    • נותנת תגמול (או עונש)
    • קובעת את המצב הבא
  • מצב: ייצוג מתמטי של הקונפיגורציה הנוכחית של הסביבה.
    • לדוגמה, מצב של סביבת מטופס יכול לכלול את מיקום המטופס ומהירות הזוויתית שלו בכל שלב זמן.
    • מצב סופי: מצב שאינו מוביל למצבים חדשים או אחרים.
  • סוכן: האלגוריתם שמתבונן בסביבה ומבצע פעולות שונות בהתאם לתצפית זו. מטרת הסוכן היא למקסם את הפרסים שלו.
    • לדוגמה, הסוכן מחליט כמה קשה ובאיזו כיוון לדחוף את המטופס.
  • תצפית: ייצוג מתמטי של התפיסה של הסוכן לגבי הסביבה, שהושג, למשל, באמצעות חיישנים.
  • פעולה: ההחלטה שהתקבלה על ידי הסוכן לפני המעבר לשלב הבא. הפעולה משפיעה על המצב הבא של הסביבה ומזכה את הסוכן בפרס.
  • פרס: המשוב מהסביבה לסוכן. הוא יכול להיות חיובי או שלילי, בהתאם לפעולה ולמצב של הסביבה.
  • החזרה:ההחזר הצפוי הצפוי מעבר לשלבי זמן עתידיים. פרסים משלבי זמן עתידיים ניתן להנחית באמצעות מקדם הנחית.
  • מדיניות:אסטרטגיית הסוכן לגבי איזה פעולה לבצע במצבים שונים. נהוג לייצג אותה כמטריצה של סיכויים, P, שממפה מצבים לפעולות.
    • נתונה קבוצה סופית m של מצבים ו n פעולות אפשריות, האיבר Pmn במטריצה מציין את סיכוי הביצוע של פעולה an במצב sm.  
  • פרק: סדרת הצעדים מהמצב ההתחלתי (המוקצה באקראי) עד שהסוכן מגיע למצב סופי.

מרחב התצפיות ומרחב הפעולות

התצפית היא המידע שהסוכן אוסף על הסביבה. סוכן, כמו לדוגמה רובוט, יכול לאסוף מידע סביבתי באמצעות חיישנים. באופן אידיאלי, הסוכן צריך להיות מסוגל לצפות במצב המלא, שמתאר את כל ההיבטים של הסביבה. למעשה, הסוכן משתמש בתצפיות שלו כתחליף למצב. כך, התצפיות קובעות את הפעולות של הסוכן. 

מרחב מרחב דומה לקבוצת מתמטית. מרחב הפריטים X כולל את כל המקרים האפשריים של X. מרחב של X גם מגדיר את המבנה (תחביר ושלב) של כל הפריטים מסוג X. כל סביבה של גימנסיה מכילה שני מרחבים, מרחב הפעולה, action_space, ומרחב התצפית, observation_space. גם מרחבי הפעולה והתצפית נגזרים מההורה gymnasium.spaces.Space עליון. 

מרחב התצפית

מרחב התצפית הוא המרחב שמכיל את כל התצפיות האפשריות. הוא גם מגדיר את הפורמט שבו התצפיות מאוחסנות. מרחב התצפית מיוצג בדרך כלל כאובייקט מסוג Box. זהו ndarray שמתאר את הפרמטרים של התצפיות. הקופסה מגדירה את הגבולות של כל מימד. אתה יכול לצפות במרחב התצפית עבור סביבה באמצעות השיטה observation_space:

print("observation space: ", env.observation_space)

במקרה של הסביבה CartPole-v1 הפלט נראה כמו בדוגמה למטה: 

observation space: Box([-4.8 -inf -0.41887903 -inf], [4.8 inf 0.41887903 inf], (4,), float32)

בדוגמה זו, CartPole-v1 מרחב התצפיות מכיל 4 ממדים. 4 המרכיבים של מערך התצפיות הם:

  • מיקום העגלה – משתנה בין -4.8 ל +4.8
  • מהירות הרכב – נעה בין ל +
  • זווית הקוטר – משתנה בין -0.4189 ל +0.4189
  • מהירות זווית עמוד – מתנהלת בין ל +

כדי לראות דוגמה של מערך תצפית יחיד, השתמשו בפקודת .reset()

observation, info = env.reset() print("observation: ", observation)

במקרה של הסביבה CartPole-v1 הפלט נראה כמו בדוגמה למטה: 

[ 0.03481963 -0.0277232 0.01703267 -0.04870504]

הארבעה אלמנטים של מערך זה מתאימים לארבע הכמויות שנצפו (מיקום העגלה, מהירות העגלה, זווית המוט, מהירות זווית המוט), כפי שהוסבר קודם לכן. 

מרחב הפעולה

מרחב הפעולה כולל את כל הפעולות האפשריות שהסוכן יכול לבצע. מרחב הפעולה גם מגדיר את הפורמט שבו פעולות מיוצגות. ניתן לצפות במרחב הפעולה עבור סביבה באמצעות המתודה action_space :

print("action space: ", env.action_space)

במקרה של הסביבה CartPole-v1, הפלט נראה כמו בדוגמה למטה:

action space: Discrete(2)

במקרה של הסביבה CartPole-v1, מרחב הפעולות הוא דיסקרטי. ישנן בסך הכול שתי פעולות שהסוכן יכול לבצע:

  • 0: לדחוף את הקרון לשמאל
  • 1: לדחוף את הקרון לימין

בניית הסוכן הראשון שלך עם גימנסיום

בקטעים הקודמים, חקרנו את המושגים הבסיסיים של RL ו-Gymnasium. בקטע זה אנו מראים לך כיצד להשתמש ב-Gymnasium כדי לבנות סוכן RL.

יצירת ואיפוס הסביבה

השלב הראשון הוא ליצור מופע של הסביבה. כדי ליצור סביבות חדשות, יש להשתמש בשיטת .make().

env = gym.make('CartPole-v1')

האינטראקציות של הסוכן משנות את מצב הסביבה. השיטה .reset() מאפסת את הסביבה למצב התחלתי. כברירת מחדל, הסביבה מאותחלת למצב אקראי. ניתן להשתמש בפרמטר SEED עם השיטה .reset() כדי לאתחל את הסביבה לאותו מצב בכל פעם שהתוכנית מופעלת. הקוד להלן מראה כיצד לעשות זאת:

SEED = 1111 env.reset(seed=SEED)

דגימת פעולות כרוכה גם באקראיות. כדי לשלוט באקראיות זו ולקבל מסלול אימון שניתן לשחזור במלואו, אנו יכולים לזרוע את הגנרטורים האקראיים של NumPy ו-PyTorch:

np.random.seed(SEED) torch.manual_seed(SEED)

אקראי מול פעולות אינטליגנטיות

בכל שלב בתהליך מרקוב, הסוכן יכול לבחור פעולה באקראי ולחקור את הסביבה עד שהוא מגיע למצב סופי. על ידי בחירת פעולות באקראי:

  • זה יכול לקחת הרבה זמן להגיע למצב הסופי.
  • הפרסים המצטברים נמוכים בהרבה ממה שהם היו יכולים להיות.

לאמן את הסוכן למקסם את בחירת הפעולות בהתבסס על חוויות קודמות (של אינטראקציה עם הסביבה) הוא יותר יעיל כדי למקסם את הפרסים לטווח הארוך.

הסוכן שאינו מאומן מתחיל עם פעולות אקראיות שמבוצעות על פי מדיניות שהתחילויות אקראיות. מדיניות זו מיוצגת כלפת עצבים. במהלך האימון, הסוכן לומד את המדיניות האופטימלית שמקסימליזות את הפרסים. בלמידת ריבונות, תהליך האימון נקרא גם אופטימיזציה של מדיניות.

קיימים שיטות שונות של אופטימיזציה של מדיניות. משוויונות בלמן מתארות איך לחשב את ערך המדיניות של למידת החילופין ולקבוע את המדיניות האופטימלית. במדריך זה, נשתמש בטכניקה פשוטה בשם גרדיאני פוליטיקה. שיטות אחרות קיימות, כמו אופטימיזצית מדיניות קרובה (PPO).

יישום סוכן גרדיינטי פשוט

כדי לבנות סוכן RL שמשתמש בגרדיינטי מדיניות, אנו יוצרים רשת עצבית כדי ליישם את המדיניות, כותבים פונקציות לחישוב ההחזרים וההפסד מהפרסים שלב אחר שלב וההסתברויות של הפעולות, ומעדכנים את המדיניות באופן איטרטיבי באמצעות טכניקות סטנדרטיות של backpropagation.

הגדרת רשת המדיניות

אנו משתמשים ברשת עצבית כדי ליישם את המדיניות. מאחר ש-CartPole-v1 היא סביבה פשוטה, אנו משתמשים ברשת עצבית עם:

  • מימדי קלט שזהים לממדי מרחב התפיסה של הסביבה.
  • שכבה נסתרת אחת עם 64 נוירונים.
  • ממדי הפלט שווים לממדי מרחב הפעולות של הסביבה.

לכן, תפקיד רשת המדיניות הוא למפות מצבים שנראים לפעולות. בנתונים קלטיים, היא עושה זאת על מנת לחזות את הפעולה הנכונה. הקוד למטה מיישם את רשת המדיניות:

class PolicyNetwork(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim, dropout): super().__init__() self.layer1 = nn.Linear(input_dim, hidden_dim) self.layer2 = nn.Linear(hidden_dim, output_dim) self.dropout = nn.Dropout(dropout) def forward(self, x): x = self.layer1(x) x = self.dropout(x) x = F.relu(x) x = self.layer2(x) return x

איסוף הפרסים והמעבר הקדימה

כפי שצוין, בכל שלב של התהליך של מרקוב, הסביבה נותנת פרס בהתבסס על פעולת הסוכן והמצב. המטרה בלמידת חיזוי הפעולה היא למקסם את ההחזר הכולל.

  • החזר בכל שלב הוא סכום הפרסים המצטבר מההתחלה עד לשלב זה.
  • החזר הכולל בכל פרק מושג על ידי צבירת כל הפרסים הצעדיים מאותו פרק. כך, ההחזר הכולל הוא ההחזר בזמן הצעד האחרון (כאשר הסוכן מגיע למצב סופי).

במעשה, כאשר צוברים פרסים, זה נפוץ: 

  • לכוון את הפרסים העתידיים באמצעות גורם הנחה. 
  • לנרמל את מערך ההחזרים הצעדיים כדי להבטיח אימון חלק ויציב. 

הקוד למטה מראה כיצד לעשות זאת: 

def calculate_stepwise_returns(rewards, discount_factor): returns = [] R = 0 for r in reversed(rewards): R = r + R * discount_factor returns.insert(0, R) returns = torch.tensor(returns) normalized_returns = (returns - returns.mean()) / returns.std() return normalized_returns

השלב הקדמי כולל הפעלת הסוכן על פי המדיניות הנוכחית עד שהוא מגיע למצב סיימת ואיסוף הפרסויות שלב אחר שלב והסתברויות הפעולה. השלבים להלן מסבירים כיצד ליישם את השלב הקדמי:

  • אפס את הסביבה למצב ראשוני.
  • אתחל גיליונות לאחסון הסתברויות הפעולה, הפרסויות וההחזר הצבירתי
  • השתמש בפונקצית .step() כדי להריץ באופן דיאלקטי את הסוכן בסביבה עד שהיא תסיים:
    • קבל את התצפית של מצב הסביבה.
    • קבל את הפעולה שחזתה המדיניות על סמך התצפית.
    • השתמש בפונקציית Softmax כדי להעריך את הסבירות לבצע את הפעולה שחזתה.
    • סימולציה של הפצת סבירות קטגורית על סמך סבירות אלו שהוערכו.
    • דגום הפצה זו כדי לקבל את הפעולה של הסוכן.
    • הערך את הסבירות הלוגריתמית של הפעולה המדוגמת מההפצה המוסמכת. 
  • הוסף את הסבירות הלוגריתמית של הפעולות והפרסים מכל שלב לבופרים המתאימים להן. 
  • הערך את הערכים הנורמליים והמוזלים של ההחזרים בכל שלב על סמך הפרסים. 
def forward_pass(env, policy, discount_factor): log_prob_actions = [] rewards = [] done = False episode_return = 0 policy.train() observation, info = env.reset() while not done: observation = torch.FloatTensor(observation).unsqueeze(0) action_pred = policy(observation) action_prob = F.softmax(action_pred, dim = -1) dist = distributions.Categorical(action_prob) action = dist.sample() log_prob_action = dist.log_prob(action) observation, reward, terminated, truncated, info = env.step(action.item()) done = terminated or truncated log_prob_actions.append(log_prob_action) rewards.append(reward) episode_return += reward log_prob_actions = torch.cat(log_prob_actions) stepwise_returns = calculate_stepwise_returns(rewards, discount_factor) return episode_return, stepwise_returns, log_prob_actions

עדכון המדיניות על סמך הפרסים

ההפסד מייצג את הכמות שעליה אנו מיישמים ירידת גרדיאנט. המטרה ב-RL היא למקסם את ההחזרים. לכן, אנו משתמשים בערך ההחזר הצפוי כחלופה להפסד. ערך ההחזר הצפוי מחושב כמכפלה של ההחזרים הצפויים בכל שלב והסבירות הלוגריתמית של הפעולות בכל שלב. הקוד למטה מחשב את ההפסד:

def calculate_loss(stepwise_returns, log_prob_actions): loss = -(stepwise_returns * log_prob_actions).sum() return loss

כדי לעדכן את המדיניות, אתה מפעיל הפצת אחורה ביחס לפונקציית ההפסד. המתודה update_policy() קוראת למתודה calculate_loss() ולאחר מכן מפעילה הפצת אחורה על ההפסד הזה כדי לעדכן את פרמטרי המדיניות, כלומר, משקלי המודל של רשת המדיניות.

def update_policy(stepwise_returns, log_prob_actions, optimizer): stepwise_returns = stepwise_returns.detach() loss = calculate_loss(stepwise_returns, log_prob_actions) optimizer.zero_grad() loss.backward() optimizer.step() return loss.item()

עדכון המדיניות על בסיס הגרדיאנט של התשואות נקרא שיטת גרדיאנט המדיניות

אימון המדיניות

עכשיו יש לנו את כל הרכיבים הדרושים כדי לאמן ולהעריך את המדיניות. אנו מיישמים את לולאת האימון כפי שהוסבר בשלבים הבאים:  

לפני התחלת הריצה, אנו מצהירים על היפרפרמטרים, מפעילים מדיניות, ויוצרים אופטימיזציה:

  • מצהירים על היפרפרמטרים כקבועי Python:
    • MAX_EPOCHS היא המספר המרבי של איטרציות שאנו מוכנים להריץ כדי לאמן את המדיניות.
    • DISCOUNT_FACTOR קובע את החשיבות היחסית של פרסומים מצעדי זמן עתידיים. גורם הנחיתה של 1 אומר שכל הפרסומים חשובים באותה מידה, כשערך של 0 אומר שרק הפרסום מהצעד הנוכחי חשוב.
    • N_TRIALS הוא מספר הפרקים שבהם אנו ממוצעים את התשואות כדי להעריך את הביצועים של הסוכן. אנו קובעים שהאימון הצליח אם התשואה הממוצעת על פני N_TRIALS פרקים היא מעל הסף. 
    • REWARD_THRESHOLD: אם המדיניות יכולה להשיג תשואה גבוהה מהסף, היא נחשבת להצלחה. 
    • DROPOUT קובע את השבר של המשקלים שצריכים להיות מאופסים באקראי. פונקציית ה-dropout קובעת באקראי חלק מהמשקלים של המודל לאפס. זה מפחית את התלות בנוירונים ספציפיים ומונע התאמה יתרה, מה שהופך את הרשת ליותר עמידה.
    • מהירות_למידההיא כמה הפרמטרים של המדיניות יכולים להשתנות בכל שלב. העדכון לפרמטרים בכל איטרציה הוא תוצאת הגרדיאנט כפול מהירות הלמידה.
  • הגדר את המדיניות כמופע של מחלקת PolicyNetwork (שכבר נממשה במוקדם יותר).
  • צור אופטימיזציה באמצעות אלגוריתם Adam ומהירות הלמידה.

כדי לאמן את המדיניות, אנו מריצים את שלבי האימון בצורה משובצת עד שההחזר הממוצע (מעל N_TRIALS) גדול מסף הפרס:

  • לכל פרק, בצע את המעבר הקדימה פעם אחת. אסוף את ההסתברות היומנית של פעולות, את ההחזרים שלב אחר שלב ואת ההחזר הכולל מאותו פרק. צבור את ההחזרים הפרקטיים במערך.
  • חשבו את ההפסד באמצעות ההסתברויות הלוגרית וההחזרים שלשות. הפעילו את ה backpropagation על ההפסד. השתמשו במגבר כדי לעדכן את פרמטרי הפוליסה.
  • בדקו האם ההחזר הממוצע מעל N_TRIALS עולה על את סף הפרס.

הקוד למטה מיישם את השלבים הללו:

def main(): MAX_EPOCHS = 500 DISCOUNT_FACTOR = 0.99 N_TRIALS = 25 REWARD_THRESHOLD = 475 PRINT_INTERVAL = 10 INPUT_DIM = env.observation_space.shape[0] HIDDEN_DIM = 128 OUTPUT_DIM = env.action_space.n DROPOUT = 0.5 episode_returns = [] policy = PolicyNetwork(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT) LEARNING_RATE = 0.01 optimizer = optim.Adam(policy.parameters(), lr = LEARNING_RATE) for episode in range(1, MAX_EPOCHS+1): episode_return, stepwise_returns, log_prob_actions = forward_pass(env, policy, DISCOUNT_FACTOR) _ = update_policy(stepwise_returns, log_prob_actions, optimizer) episode_returns.append(episode_return) mean_episode_return = np.mean(episode_returns[-N_TRIALS:]) if episode % PRINT_INTERVAL == 0: print(f'| Episode: {episode:3} | Mean Rewards: {mean_episode_return:5.1f} |') if mean_episode_return >= REWARD_THRESHOLD: print(f'Reached reward threshold in {episode} episodes') break

לבסוף, קראו לפונקציית main() כדי לאמן את הפוליסה:

main()

השתמש בחוברת העבודה של DataLab כדי להריץ את האלגוריתם מעלה ישירות ולפתור את סביבת ה- CartPole באמצעות RL.

טכניקות מתקדמות בגימנסיום

לאחר שהדגמנו כיצד ליישם אלגוריתם של RL, נדון כעת בכמה טכניקות מתקדמות המשמשות בדרך כלל בתרגול.

שימוש במבני מבנה מובנים

יישום אלגוריתמי RL מהתחלה הוא תהליך ארוך ומורכב, במיוחד עבור סביבות מורכבות ומדיניות מתקדמת ביותר.

חלופה מעשית יותר היא להשתמש בתוכנה כמו Stable Baselines3 . היא מגיעה עם מימושים שנבדקו של אלגוריתמים של RL. היא כוללת סוכנים מאומנים מראש, תסריטי אימון, כלי הערכה ומודולים כדי לשרטט גרפים ולתעד סרטונים.

Ray RLib הוא כלי פופולרי נוסף ל-RL. RLib מתוכנן כפתרון נרחב, מה שמקל על יישום אלגוריתמים של RL במערכות מרובות GPU. הוא גם תומך ב-RL מרובה סוכנים, מה שפותח אפשרויות חדשות כמו:

  • למידת סוכנים מרובים עצמאית: כל סוכן מתייחס לסוכנים אחרים כחלק מהסביבה.
  • הכשרת סוחרים רב-סוחרית בשיתוף פעולה: קבוצת סוחרים משתפים מדיניות ופונקציות ערך זהות ומלמדים מניסיון האחר במקביל.
  • הכשרת ידידותית: סוחרים (או קבוצות של סוחרים) מתחרים זה בזה בסביבות משחק תחרותיות דומות למשחק.

עם RLib ו-Stable Baselines3, ניתן לייבא ולהשתמש בסביבות מ OpenAI Gymnasium.

סביבות מותאמות

סביבות המגיעות עם גימנסיום הן הבחירה הנכונה לבדיקת אסטרטגיות RL חדשות והכשרת מדיניות. עם זאת, עבור רוב היישומים המעשיים, עליכם ליצור ולהשתמש בסביבה שמשקפת במדויק את הבעיה שאתם רוצים לפתור. אתם יכולים להשתמש בגימנסיום כדי ליצור סביבה מותאמת אישית. היתרון של שימוש בסביבות מותאמות אישית בגימנסיום הוא שכבר ישנם כלים חיצוניים רבים כמו RLib ו-Stable Baselines3 שמוכנים לפעול עם מבנה ה-API של גימנסיום.

כדי ליצור סביבה מותאמת אישית בגימנסיום, עליכם להגדיר:

  • את מרחב התצפיות.
  • את תנאי הסיום.
  • את קבוצת הפעולות שהסוכן יכול לבחור מהן.
  • איך לאתחל את הסביבה (כאשר נקראת הפונקציה reset()). 
  • איך הסביבה מחליטה על המצב הבא בהתאם לפעולות של הסוכן (כאשר נקראת הפונקציה step()). 

כדי ללמוד יותר, עקבו אחרי המדריך של Gymnasium על יצירת סביבות מותאמות אישית

פרקטיקות מומלצות לשימוש ב-Gymnasium

ניסוי עם סביבות שונות

הקוד במדריך זה הראה כיצד ליישם את אלגוריתם מדריך המדיניות בסביבת CartPole. זו סביבה פשוטה עם מרחב פעולות דיסקרטי. כדי להבין את RL טוב יותר, אנו ממליצים לך ליישם את אותו אלגוריתם מדריך המדיניות (ואלגוריתמים אחרים, כמו PPO) בסביבות אחרות.

למשל, בסביבת הפנדולום יש מרחב פעולה רציף. הוא מורכב מקלט בודד המיוצג כמשתנה רציף – הטורק (הגודל והכיוון של) המיושם על הפנדולום בכל מצב נתון. טורק זה יכול לקבל כל ערך בין -2 ל-+2

ניסוי עם אלגוריתמים שונים בסביבות שונות עוזר לך להבין טוב יותר סוגים שונים של פתרונות RL ואת האתגרים שלהם. 

ניטור התקדמות האימון

סביבות RL כוללות לעיתים קרובות רובוטים, פנדולים, מכוניות הרים, משחקי מחשב וכו'. הדמיה של פעולות הסוכן בתוך הסביבה מספקת הבנה אינטואיטיבית טובה יותר של ביצועי המדיניות.

ב-Gymnasium, env.render() השיטה מדמיינת את האינטראקציות של הסוכן עם הסביבה. היא מציגה גרפית את המצב הנוכחי של הסביבה—מסכי משחק, מיקום הפנדול או מוט העגלה, וכו'. משוב ויזואלי על פעולות הסוכן ותגובות הסביבה עוזר במעקב אחר ביצועי הסוכן וההתקדמות שלו בתהליך האימון.

יש ארבעה מצבי הדמיה: "אדם", "rgb_array", "ansi", ו-"rgb_array_list". כדי לדמיין את ביצועי הסוכן, השתמש במצב ההדמיה "אדם". מצב ההדמיה מצוין כאשר הסביבה מאותחלת. לדוגמה:

env = gym.make(‘CartPole-v1’, render_mode=’human’)

כדי לבצע את ההנפשה, יש לכלול את השיטה .render() לאחר כל פעולה שביצע הסוכן (באמצעות קריאה לשיטה .step() ). הקוד המדומה למטה מדגים כיצד לעשות זאת:

while not done: … step, reward, terminated, truncated, info = env.step(action.item()) env.render()

פתרון בעיות שגיאות נפוצות

Gymnasium מקלה על החיבור עם סביבות RL מורכבות. עם זאת, זהו תוכנה המתעדכנת באופן מתמשך עם הרבה תלותים. לכן, חשוב להיות מודעים לסוגים מסוימים של שגיאות נפוצות.

אי-התאמות גרסה

  • התאמת גרסאות של חדר כושר: חבילת התוכנה של חדר הכושר של פארמה נלקחה מגרסה 0.26.2 של חדר הכושר של OpenAI. היו כמה שינויים משמעותיים בין גרסאות חדר הכושר הוותיקות לגרסאות החדשות של חדר הכושר. רבות מהיישומים הציבוריים המבוססים על גרסאות חדר הכושר הוותיקות עשויים שלא לעבוד ישירות עם הגרסה החדשה ביותר. במקרים כאלה, יש צורך לחזור לגרסה ישנה יותר או להתאים את הקוד כך שיעבוד עם הגרסה החדשה.
  • התאמת גרסאות סביבה: בסביבות הגימנסיום יש הבדלי גרסאות. לדוגמה, ישנם שתי סביבות של CartPole – CartPole-v1 ו- CartPole-v0. אף על פי שההתנהגות של הסביבה זהה בשתי הגרסאות, חלק מהפרמטרים, כמו אורך הפרק, סף תקן הפרסום וכו', עשויים להיות שונים. מדיניות שטוחה על פי גרסה אחת עשויה שלא לבצע כמו בגרסה אחרת של אותה סביבה. עליך לעדכן את פרמטרי האימון ולאמן מחדש את המדיניות עבור כל גרסת סביבה.
  • חוסר התאמה בגרסאות התלויות: Gymnasium תלויה בתלויות כמו NumPy ו-PyTorch. נכון לדצמבר 2024, הגרסאות האחרונות של תלויות אלו הן numpy 2.1.3 ו-torch 2.5.1. עם זאת, Gymnasium עובדת הכי טוב עם torch 1.13.0 ו-numpy 1.23.3. ייתכן שתיתקל בבעיות אם תתקין את Gymnasium בסביבה עם תלויות אלו מותקנות מראש. אנו ממליצים להתקין ולעבוד עם Gymnasium בסביבה חדשה של Conda. 

בעיות התכנסות

  • היפרפרמטרים: דומה לאלגוריתמי למידת מכונה אחרים, מדיניות הלמידה החיצונית רגישה להיפרפרמטרים כגון קצב למידה, גורם הנחיית, וכו'. אנו ממליצים לנסות ולכוון את ההיפרפרמטרים באופן ידני או להשתמש בטכניקות אוטומטיות כמו חיפוש רשת וחיפוש אקראי.
  • כחקר נגד פיתוח: עבור כמה מחלקות המדיניות (כמו PPO), הסוכן מאמץ אסטרטגיה דו-צידית: לחקור את הסביבה כדי לגלות נתיבים חדשים ולאמץ גישה שקפצנית כדי למקסם את הפרסים על פי הנתיבים הידועים עד כה. אם הוא חוקר יותר מדי, המדיניות לא תקבע. להיפך, היא לעולם לא תנסה את הנתיב האופטימלי אם היא לא חוקרת מספיק. לכן, מציאת האיזון הנכון בין החקירה והפיתוח חיונית. גם נפוץ להעדיף את החקירה בפרקים הראשונים ואת הפיתוח בפרקים מאוחרים במהלך האימון.

אי יציבות באימון

  • ערכים למידה גדולים: אם ערך הלמידה גבוה מדי, מערכי המדיניות עוברים עדכונים גדולים בכל שלב. זה עשוי להוביל לאיבוד של ערכים האופטימליים. פתרון נפוץ הוא להפחית בהדרגה את ערך הלמידה, מבטיח עדכונים קטנים יותר ויציבים יותר עם התקרבות האימון.
  • גילוי יתר: יתר רעשנות (אנטרופיה) בבחירת הפעולה מונע קונברגנציה ומוביל לשינויים גדולים בפונקציית ההפסד בין צעדים רצופים. כדי לקבל תהליך הדרכה יציב וקונברגנטי, עליך לאזן בין גילוי ובין עיבוד.
  • בחירה שגויה של אלגוריתם: אלגוריתמים פשוטים כמו גרדיאנט מדיניות עשויים להוביל לאימון לא יציב בסביבות מורכבות עם מרחבי פעולה ומצב גדולים. במקרים כאלה, אנו ממליצים להשתמש באלגוריתמים יותר עמידים כמו PPO ואופטימיזציית מדיניות באזור אמון (TRPO). אלגוריתמים אלה נמנעים מעדכוני מדיניות גדולים בכל צעד ויכולים להיות יותר יציבים.
  • אקראיות: אלגוריתמים של RL ידועים כרגישים מאוד למצבים ראשוניים ולאקראיות הקיימת בבחירת פעולה. כאשר ריצת אימון אינה יציבה, ניתן לעיתים לייצב אותה באמצעות זרם אקראי שונה או על ידי אתחול מחדש של המדיניות.

מסקנה

במדריך זה, חקרנו את העקרונות הבסיסיים של RL, דנינו ב-Gymnasium כחבילת תוכנה עם API נקי לקישור עם סביבות RL שונות, והראינו כיצד לכתוב תוכנית ב-Python כדי ליישם אלגוריתם פשוט של RL ולהחיל אותו בסביבת Gymnasium.

לאחר הבנת היסודות במדריך זה, אני ממליץ להשתמש בסביבות Gymnasium כדי ליישם את המושגים של RL ולפתור בעיות פרקטיות כמו אופטימיזצית מסלולי מוניות ו-דמיונים במסחר במניות.

Source:
https://www.datacamp.com/tutorial/reinforcement-learning-with-gymnasium