# -*- coding: utf-8 -*- """pg_pong_v2_2.ipynb Automatically generated by Colab. Original file is located at https://colab.research.google.com/drive/1sQXWjJUnVxBxajgAV-ruSLpGP5JoWDBz # Load packages """ !pip install gymnasium[atari,accept-rom-license] """# Define hyper parameters""" import numpy as np import pickle import gymnasium as gym from functools import partial print= partial(print, flush=True)#to always flush the output # hyperparameters H = 200 # number of hidden layer neurons batch_size = 10 # every how many episodes to do a param update? learning_rate = 1e-4 gamma = 0.99 # discount factor for reward decay_rate = 0.99 # decay factor for RMSProp leaky sum of grad^2 resume = False # resume from previous checkpoint? render = True game_name='pong' # model initialization D = 80 * 80 # input dimensionality: 80x80 grid if resume: model = pickle.load(open('save_lattest_'+game_name, 'rb')) else: model = {} model['W1'] = np.random.randn(H,D) / np.sqrt(D) # "Xavier" initialization model['W2'] = np.random.randn(H) / np.sqrt(H) """# Initialize buffers (accumulated gradients)""" grad_buffer = { k : np.zeros_like(v) for k,v in model.items() } # update buffers that add up gradients over a batch rmsprop_cache = { k : np.zeros_like(v) for k,v in model.items() } # rmsprop memory """# Functions""" def sigmoid(x): return 1.0 / (1.0 + np.exp(-x)) # sigmoid "squashing" function to interval [0,1] def prepro(I): """ prepro 210x160x3 uint8 frame into 6400 (80x80) 1D float vector """ I = I[35:195] # crop I = I[::2,::2,0] # downsample by factor of 2 I[I == 144] = 0 # erase background (background type 1) I[I == 109] = 0 # erase background (background type 2) I[I != 0] = 1 # everything else (paddles, ball) just set to 1 return I.astype(float).ravel() def discount_rewards(r): """ take 1D float array of rewards and compute discounted reward """ discounted_r = np.zeros_like(r) running_add = 0 for t in reversed(range(0, r.size)): if r[t] != 0: running_add = 0 # reset the sum, since this was a game boundary (pong specific!) running_add = running_add * gamma + r[t] discounted_r[t] = running_add return discounted_r def policy_forward(x): h = np.dot(model['W1'], x) h[h<0] = 0 # ReLU nonlinearity logp = np.dot(model['W2'], h) p = sigmoid(logp) return p, h # return probability of taking action 2, and hidden state def policy_backward(eph, epdlogp): """ backward pass. (eph is array of intermediate hidden states) """ dW2 = np.dot(eph.T, epdlogp).ravel() dh = np.outer(epdlogp, model['W2']) dh[eph <= 0] = 0 # backpro prelu dW1 = np.dot(dh.T, epx) return {'W1':dW1, 'W2':dW2} env = gym.make("Pong-v4") observation,_ = env.reset() prev_x = None # used in computing the difference frame xs,hs,dlogps,drs = [],[],[],[] running_reward = None reward_sum = 0 episode_number = 0 """# Main training loop Adapted for gymnasium instead of gym """ while True: # preprocess the observations cur_x = prepro(observation) x = cur_x - prev_x if prev_x is not None else np.zeros(D) prev_x = cur_x aprob, h = policy_forward(x) action = 2 if np.random.uniform() < aprob else 3 # roll the dice! xs.append(x) hs.append(h) y = 1 if action == 2 else 0 dlogps.append(y - aprob) # implements action observation, reward, done, info,_ = env.step(action) reward_sum += reward drs.append(reward) # rewards if done: # an episode finished episode_number += 1 #store all epx = np.vstack(xs) eph = np.vstack(hs) epdlogp = np.vstack(dlogps) epr = np.vstack(drs) xs,hs,dlogps,drs = [],[],[],[] # reset array memory # update rewards discounted_epr = discount_rewards(epr) # standardize discounted_epr -= np.mean(discounted_epr) discounted_epr /= (1.e-6+np.std(discounted_epr)) epdlogp *= discounted_epr # modulate the gradient with advantage (PG magic happens right here.) grad = policy_backward(eph, epdlogp) for k in model: grad_buffer[k] += grad[k] # accumulate grad over batch # rmsprop if episode_number % batch_size == 0: for k,v in model.items(): g = grad_buffer[k] # gradient rmsprop_cache[k] = decay_rate * rmsprop_cache[k] + (1 - decay_rate) * g**2 model[k] += learning_rate * g / (np.sqrt(rmsprop_cache[k]) + 1e-5) grad_buffer[k] = np.zeros_like(v) # reset batch gradient buffer # rewards, initialise states setc running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01 print('resetting env. episode %f reward total was %f. running mean: %f' % (episode_number, reward_sum, running_reward)) if episode_number % 500 == 0: pickle.dump(model, open('save_'+game_name+'_ep'+str(episode_number)+"_avg_rev"+ str(np.round(running_reward,2)), 'wb') ) pickle.dump(model, open('save_lattest_'+game_name,'wb')) # if episode_number % 100 == 0: pickle.dump(model, open('save.p', 'wb')) reward_sum = 0 observation,_ = env.reset() prev_x = None #if reward != 0: # Pong has either +1 or -1 reward exactly when game ends. # print('ep {}: game finished, reward: {}'.format(episode_number, reward) + ('' if reward == -1 else ' !!!!!!!!'))