PPO-KL散度近端策略优化玩cartpole游戏

其实KL散度在这个游戏里的作用不大,游戏的action比较简单,不像LM里的action是一个很大的向量,可以直接用surr1,最大化surr1,实验测试确实是这样,而且KL的系数不能给太大,否则惩罚力度太大,action model 和ref model产生的action其实分布的差距并不太大

import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import pygame
import sys
from collections import deque

# 定义策略网络
class PolicyNetwork(nn.Module):
    def __init__(self):
        super(PolicyNetwork, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(4, 2),
            nn.Tanh(),
            nn.Linear(2, 2),  # CartPole的动作空间为2
            nn.Softmax(dim=-1)
        )

    def forward(self, x):
        return self.fc(x)

# 定义值网络
class ValueNetwork(nn.Module):
    def __init__(self):
        super(ValueNetwork, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(4, 2),
            nn.Tanh(),
            nn.Linear(2, 1)
        )

    def forward(self, x):
        return self.fc(x)

# 经验回放缓冲区
class RolloutBuffer:
    def __init__(self):
        self.states = []
        self.actions = []
        self.rewards = []
        self.dones = []
        self.log_probs = []
    
    def store(self, state, action, reward, done, log_prob):
        self.states.append(state)
        self.actions.append(action)
        self.rewards.append(reward)
        self.dones.append(done)
        self.log_probs.append(log_prob)
    
    def clear(self):
        self.states = []
        self.actions = []
        self.rewards = []
        self.dones = []
        self.log_probs = []

    def get_batch(self):
        return (
            torch.tensor(self.states, dtype=torch.float),
            torch.tensor(self.actions, dtype=torch.long),
            torch.tensor(self.rewards, dtype=torch.float),
            torch.tensor(self.dones, dtype=torch.bool),
            torch.tensor(self.log_probs, dtype=torch.float)
        )

# PPO更新函数
def ppo_update(policy_net, value_net, optimizer_policy, optimizer_value, buffer, epochs=100, gamma=0.99, clip_param=0.2):
    states, actions, rewards, dones, old_log_probs = buffer.get_batch()
    returns = []
    advantages = []
    G = 0
    adv = 0
    dones = dones.to(torch.int)
    # print(dones)
    for reward, done, value in zip(reversed(rewards), reversed(dones), reversed(value_net(states))):
        if done:
            G = 0
            adv = 0
        G = reward + gamma * G  #蒙特卡洛回溯G值
        delta = reward + gamma * value.item() * (1 - done) - value.item()  #TD差分
        # adv = delta + gamma * 0.95 * adv * (1 - done)  #
        adv = delta + adv*(1-done)
        returns.insert(0, G)
        advantages.insert(0, adv)

    returns = torch.tensor(returns, dtype=torch.float)  #价值
    advantages = torch.tensor(advantages, dtype=torch.float)
    advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8)  #add baseline

    for _ in range(epochs):
        action_probs = policy_net(states)
        dist = torch.distributions.Categorical(action_probs)
        new_log_probs = dist.log_prob(actions)
        ratio = (new_log_probs - old_log_probs).exp()

        KL = new_log_probs.exp()*(new_log_probs - old_log_probs).mean()   #KL散度 p*log(p/p')
        #下面三行是核心
        surr1 = ratio * advantages

        PPO1,PPO2 = True,False
        # print(surr1,KL*500)
        if PPO1 == True:
            actor_loss = -(surr1 - KL).mean()

        if PPO2 == True:
            surr2 = torch.clamp(ratio, 1.0 - clip_param, 1.0 + clip_param) * advantages
            actor_loss = -torch.min(surr1, surr2).mean()

        optimizer_policy.zero_grad()
        actor_loss.backward()
        optimizer_policy.step()

        value_loss = (returns - value_net(states)).pow(2).mean()

        optimizer_value.zero_grad()
        value_loss.backward()
        optimizer_value.step()

# 初始化环境和模型
env = gym.make('CartPole-v1')
policy_net = PolicyNetwork()
value_net = ValueNetwork()
optimizer_policy = optim.Adam(policy_net.parameters(), lr=3e-4)
optimizer_value = optim.Adam(value_net.parameters(), lr=1e-3)
buffer = RolloutBuffer()

# Pygame初始化
pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()

draw_on = False
# 训练循环
state = env.reset()
for episode in range(10000):  # 训练轮次
    done = False
    state = state[0]
    step= 0
    while not done:
        step+=1
        state_tensor = torch.FloatTensor(state).unsqueeze(0)
        action_probs = policy_net(state_tensor)   #旧policy推理数据
        dist = torch.distributions.Categorical(action_probs)
        action = dist.sample()
        log_prob = dist.log_prob(action)
        
        next_state, reward, done, _ ,_ = env.step(action.item())
        buffer.store(state, action.item(), reward, done, log_prob)
        
        state = next_state

        # 实时显示
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        if draw_on:
            # 清屏并重新绘制
            screen.fill((0, 0, 0))
            cart_x = int(state[0] * 100 + 300)  # 位置转换为屏幕坐标
            pygame.draw.rect(screen, (0, 128, 255), (cart_x, 300, 50, 30))
            pygame.draw.line(screen, (255, 0, 0), (cart_x + 25, 300), (cart_x + 25 - int(50 * np.sin(state[2])), 300 - int(50 * np.cos(state[2]))), 5)
            pygame.display.flip()
            clock.tick(60)

    if step >2000:
        draw_on = True
    ppo_update(policy_net, value_net, optimizer_policy, optimizer_value, buffer)
    buffer.clear()
    state = env.reset()
    print(f'Episode {episode} completed , reward:  {step}.')

# 结束训练
env.close()
pygame.quit()

效果:

### 训练用于游戏的人工智能的方法和框架 #### 方法概述 训练用于电子游戏的人工智能主要依赖于强化学习(Reinforcement Learning, RL),这是一种通过试错来优化行为策略的学习范式。在RL中,代理(agent)通过与环境互动获得奖励(reward)或惩罚(penalty),从而调整自己的决策过程以最大化累积回报。 对于复杂的游戏场景,如《星际争霸II》,研究者们开发了专门的数据集和平台支持算法实验。例如,《星际争霸多智能体挑战赛》(StarCraft Multi-Agent Challenge, SMAC)[^2]提供了一个简化版的战斗地图集合供研究人员测试其提出的多智能体协调方案;而像AlphaGo这样的项目则展示了单个强大AI家可以达到怎样的成就水平,在围棋这种具有极高状态空间维的任务上取得了超越人类顶尖棋手的成绩[^5]。 #### 主要技术路径 1. **动态规划(Dynamic Programming)** 动态规划是一种解决马尔科夫决策过程(Markov Decision Process, MDP)的经典方法,它假设已知完整的MDP模型参数,并在此基础上计算最优价值函数或政策(policy)。然而由于大多数实际应用中的环境往往是未知且复杂的,因此这种方法的应用范围有限。 2. **试错学习(Trial-and-Error Learning)** 这种方式允许代理直接从环境中获取反馈并据此改进自身的行为模式。随着时间推移,代理能够逐渐积累经验教训,形成更加有效的应对机制。这类方法特别适用于那些难以构建精确模拟器的情况。 3. **深Q网络(Deep Q-Networks, DQN)** 结合神经网络的强大表征能力以及传统QLearning的思想,DQN能够在不完全可观测环境下有效地估计动作的价值函数(action-value function),进而指导探索(explore)-利用(exploit)之间的平衡关系处理。 4. **近端策略优化(Proximal Policy Optimization, PPO)** 作为一种先进的Actor-Critic架构变体,PPO旨在最小化更新过程中新旧策略间的差异KL(Kullback-Leibler divergence),以此防止性能崩溃的同时加快收敛速。此特性使得PPO非常适合应用于连续控制领域内的高维输入输出映射问题求解。 ```python import gymnasium as gym from stable_baselines3 import PPO env = gym.make('CartPole-v1') model = PPO('MlpPolicy', env, verbose=1) # Train the agent using Proximal Policy Optimization algorithm. model.learn(total_timesteps=int(1e5)) obs = env.reset() for i in range(1000): action, _states = model.predict(obs) obs, rewards, dones, info = env.step(action) env.render() ``` #### 面临的主要挑战 尽管上述提到的技术已经在许多基准测试任务上获得了成功,但在面对真实世界时仍然存在诸多困难: - 探索与利用两难困境(Exploration-exploitation dilemma): 如何合理分配时间去尝试未曾经历过的可能性还是坚持当前最佳选项; - 不确定性和部分可观察性(Uncertainty and partial observability): 当前状态下无法确切知道未来会发生什么变化; - 延迟奖励(Temporal delayed reward): 行动的效果可能不会立即显现出来而是经过一段时间才体现; - 安全约束下的不可行性(Infeasibility due to safety constraints): 特定操作可能导致危险后果因而被禁止执行; - 环境非平稳性(Non-stationary environment): 外部条件不断改变影响着内部逻辑判断的有效期限; - 泛化能力不足(Lack of generalizability): 学习到的知识很难迁移到相似但不同的情景之中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值