在由Karpathy编写的以下代码中,为什么我们需要这行代码(为什么我们在策略函数已经完成这个任务的情况下,还需要与均匀分布进行比较来选择动作)
# 前向传播策略网络并从返回的概率中抽样一个动作 aprob, h = policy_forward(x) action = 2 if np.random.uniform() < aprob else 3 # 掷骰子!
而不是直接使用
# 前向传播策略网络并从返回的概率中抽样一个动作 aprob, h = policy_forward(x) action = 2 if 0.5 < aprob else 3 # 掷骰子!
….Karpathy的完整代码来自 : https://gist.github.com/karpathy/a4166c7fe253700972fcbc77e4ea32c5
""" 使用(随机)策略梯度在Pong上训练一个智能体。使用OpenAI Gym。 """import numpy as npimport cPickle as pickleimport gym# 超参数H = 200 # 隐藏层神经元的数量batch_size = 10 # 每隔多少个回合进行一次参数更新?learning_rate = 1e-4gamma = 0.99 # 奖励的折扣因子decay_rate = 0.99 # RMSProp中梯度平方和的衰减因子resume = False # 从之前的检查点恢复?render = False# 模型初始化D = 80 * 80 # 输入维度:80x80网格if resume: model = pickle.load(open('save.p', 'rb'))else: model = {} model['W1'] = np.random.randn(H,D) / np.sqrt(D) # "Xavier"初始化 model['W2'] = np.random.randn(H) / np.sqrt(H) grad_buffer = { k : np.zeros_like(v) for k,v in model.iteritems() } # 更新缓冲区,用于在批次中累加梯度rmsprop_cache = { k : np.zeros_like(v) for k,v in model.iteritems() } # rmsprop内存def sigmoid(x): return 1.0 / (1.0 + np.exp(-x)) # sigmoid "压缩"函数到区间[0,1]def prepro(I): """ 将210x160x3 uint8的帧预处理成6400(80x80)的1D浮点向量 """ I = I[35:195] # 裁剪 I = I[::2,::2,0] # 按2的因子降采样 I[I == 144] = 0 # 擦除背景(背景类型1) I[I == 109] = 0 # 擦除背景(背景类型2) I[I != 0] = 1 # 其他一切(球拍,球)都设置为1 return I.astype(np.float).ravel()def discount_rewards(r): """ 接受一个奖励的1D浮点数组并计算折扣后的奖励 """ discounted_r = np.zeros_like(r) running_add = 0 for t in reversed(xrange(0, r.size)): if r[t] != 0: running_add = 0 # 重置总和,因为这是一个游戏边界(Pong特定!) running_add = running_add * gamma + r[t] discounted_r[t] = running_add return discounted_rdef policy_forward(x): h = np.dot(model['W1'], x) h[h<0] = 0 # ReLU非线性 logp = np.dot(model['W2'], h) p = sigmoid(logp) return p, h # 返回采取动作2的概率和隐藏状态def policy_backward(eph, epdlogp): """ 反向传播。(eph是中间隐藏状态的数组) """ dW2 = np.dot(eph.T, epdlogp).ravel() dh = np.outer(epdlogp, model['W2']) dh[eph <= 0] = 0 # 反向传播ReLU dW1 = np.dot(dh.T, epx) return {'W1':dW1, 'W2':dW2}env = gym.make("Pong-v0")observation = env.reset()prev_x = None # 用于计算差异帧xs,hs,dlogps,drs = [],[],[],[]running_reward = Nonereward_sum = 0episode_number = 0while True: if render: env.render() # 预处理观察,将网络的输入设置为差异图像 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 # 掷骰子! # 记录各种中间结果(稍后用于反向传播) xs.append(x) # 观察 hs.append(h) # 隐藏状态 y = 1 if action == 2 else 0 # 一个“假标签” dlogps.append(y - aprob) # 鼓励采取已采取动作的梯度(如果感到困惑,请参阅http://cs231n.github.io/neural-networks-2/#losses) # 步进环境并获取新测量值 observation, reward, done, info = env.step(action) reward_sum += reward drs.append(reward) # 记录奖励(必须在调用step()后进行,以获取前一个动作的奖励) if done: # 一个回合结束 episode_number += 1 # 将本回合的所有输入、隐藏状态、动作梯度和奖励堆叠在一起 epx = np.vstack(xs) eph = np.vstack(hs) epdlogp = np.vstack(dlogps) epr = np.vstack(drs) xs,hs,dlogps,drs = [],[],[],[] # 重置数组内存 # 通过时间向后计算折扣后的奖励 discounted_epr = discount_rewards(epr) # 将奖励标准化为单位正态分布(有助于控制梯度估计器的方差) discounted_epr -= np.mean(discounted_epr) discounted_epr /= np.std(discounted_epr) epdlogp *= discounted_epr # 用优势调制梯度(策略梯度的魔法在这里发生) grad = policy_backward(eph, epdlogp) for k in model: grad_buffer[k] += grad[k] # 在批次中累积梯度 # 每batch_size个回合执行一次rmsprop参数更新 if episode_number % batch_size == 0: for k,v in model.iteritems(): g = grad_buffer[k] # 梯度 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) # 重置批次梯度缓冲区 # 无聊的记录工作 running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01 print '重置环境。本回合总奖励为%f。运行平均值:%f' % (reward_sum, running_reward) 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在游戏结束时有+1或-1的奖励。 print ('回合%d:游戏结束,奖励:%f' % (episode_number, reward)) + ('' if reward == -1 else ' !!!!!!!!')
回答:
如果没有与均匀分布的比较,策略将是确定性的。对于任何给定的状态,policy_forward
函数将返回相同的输出,因此每次都会采取相同的动作。所以,如果使用您提出的方法,就不会有任何探索。均匀分布为动作选择引入了一些随机性,这鼓励了探索。没有探索,基本上不可能发现最优策略。