Ես ուզում էի ստեղծել խելացի գործակալ, որը կարող է խաղալ տիկին Փաք-Մենի դասական խաղը: Ես որոշեցի օգտագործել Q-Learning ալգորիթմը գործակալին վերապատրաստելու համար, քանի որ այն հանրաճանաչ և հաստատված ամրապնդման ուսուցման տեխնիկա է:
Ես սկսեցի ստեղծելով ALE ինտերֆեյսը, որը թույլ կտա ինձ շփվել խաղի հետ: Ես միացրեցի ցուցադրման էկրանը և ձայնը, որպեսզի կարողանայի տեսնել և լսել խաղը, երբ խաղում էր գործակալը: Այնուհետև ես բեռնեցի Ms. Pac-Man ROM-ը և ստացա գործողությունների տարածքի չափը, որը կորոշեր իմ Q-աղյուսակի չափը:
Հաջորդը, ես փորձեցի բեռնել նախկինում պատրաստված Q-աղյուսակը, բայց քանի որ այն չկար, ես ստիպված էի սկսել նոր Q-աղյուսակից, որը լցված էր պատահական արժեքներով: Ես սահմանեցի ուսուցման տոկոսադրույքը (ալֆա), զեղչի գործակիցը (գամմա) և հետախուզման արագությունը (էպսիլոն) համապատասխանաբար 0,5, 0,9 և 9,0:
Ամեն ինչ տեղում, ես պատրաստ էի սկսել մարզել իմ գործակալին: Ես ցուցադրեցի տիկին Փաք-Մանի 10,000 դրվագ, որտեղ գործակալը գործողություններ էր կատարում և պարգևներ ստանում Q-աղյուսակի արժեքների հիման վրա: Յուրաքանչյուր գործողությունից հետո ես թարմացնում էի Q-աղյուսակը՝ հիմնվելով դիտարկված պարգևի և հաջորդ վիճակի արժեքների վրա: Ես նաև տպել էի յուրաքանչյուր դրվագի ընդհանուր պարգևը, որպեսզի կարողանամ հետևել գործակալի առաջընթացին:
Երբ գործակալը խաղում էր, նա սովորեց իր փորձից և աստիճանաբար բարելավեց իր կատարումը: Ամեն 500 դրվագը ես պահում էի Q-աղյուսակը, որպեսզի համոզվեմ, որ չեմ կորցնի գործակալի առաջընթացը, եթե ինչ-որ բան սխալ լինի:
Ի վերջո, 10,000 պարապմունքներից հետո իմ գործակալը բավականին հմուտ էր դարձել միսիս Փաք-Մենին խաղալու հարցում: Այն կարողացավ հեշտությամբ նավարկել լաբիրինթոսում, ուտել կետերը և հեշտությամբ խուսափել ուրվականներից: Ես հպարտ էի այն ամենով, ինչ արել էի և ոգևորված էի տեսնելով, թե ինչ այլ խաղեր կարող եմ պատրաստել իմ գործակալին հաջորդ խաղում:
ստորև ներկայացված է օգտագործված կոդը.
import pickle import numpy as np import gymnasium as gym from ale_py import ALEInterface # Create the ALE interface ale = ALEInterface() # Enable the display screen to show the game screen while the AI is playing. ale.setBool('display_screen', True) # Enable sound ale.setBool('sound', True) # Load the Ms. PacMan ROM #ale.loadROM("C:\\Users\\jimbu\\Atari\\Ms. PacMan.a26") #Windows ale.loadROM("/Users/beusse/Atari/Ms. PacMan.a26") #Mac # Get the size of the action space num_actions = len(ale.getMinimalActionSet()) valid_actions = set(ale.getMinimalActionSet()) # Define the Q-table with the size of the state space and action space screen_height, screen_width = ale.getScreenDims() q_table = np.random.rand(screen_height * screen_width, num_actions) # load the q_table try: with open('q_table_Ms.PacMan.pkl', 'rb') as f: q_table = pickle.load(f) print("Loading previously trained Q-table") except: q_table = np.random.rand(screen_height * screen_width, num_actions) print("Q-table not found, starting with new Q-table") # Define the learning rate, discount factor, and exploration rate (epsilon) alpha = 0.5 gamma = 0.9 epsilon = 0.5 #A good starting point for the learning rate (alpha) is typically between 0.1 and 0.5. #A low learning rate means that the agent will update its Q-values slowly, which can # make the learning process more stable but also slower. A high learning rate means that # the agent will update its Q-values quickly, which can make the learning process faster # but also more unstable. #A good starting point for the discount factor (gamma) is typically between 0.5 and 0.9. # A low discount factor means that the agent will prioritize short-term rewards over # long-term rewards, while a high discount factor means that the agent will prioritize # long-term rewards over short-term rewards. #A good starting point for the exploration rate (epsilon) is typically between 0.1 and 0.5. #A low exploration rate means that the agent will mostly follow the Q-table, while a high #exploration rate means that the agent will explore the state space more. # Define the number of episodes to train the AI num_episodes = 10000 # Train the AI for episode in range(num_episodes): # Reset the environment ale.reset_game() # Set the initial reward to zero total_reward = 0 # Run the episode while not ale.game_over(): # Get the current state state = ale.getScreenRGB() state = state.flatten() # Choose an action according to the Q-table and an exploration strategy if np.random.rand() < epsilon: action = np.random.randint(num_actions) else: action = np.argmax(q_table[state]) # Take the action and observe the next state and reward reward = ale.act(action) # Get the next state next_state = ale.getScreenRGB() next_state = next_state.flatten() # Update the Q-value for the current state and action q_table[state, action] = (1 - alpha) * q_table[state, action] + alpha * (reward + gamma * np.max(q_table[next_state])) # Update the total reward total_reward += reward # Update the current state state = next_state # Check if the episode is over if ale.game_over(): break # Save the Q-table every 500 episodes if episode % 500 == 0: with open('q_table_Ms.PacMan', 'wb') as f: pickle.dump(q_table, f) # Print the total reward for the episode print("Episode: {}, Total reward: {}".format(episode, total_reward))