weixin_49706937 2025-01-14 22:56 采纳率: 0%
浏览 7

强化学习代码bug排查


import torch
import numpy as np
import gym
import torch.nn as nn
import matplotlib.pyplot as plt
from torch.nn import functional as F

class policynet(nn.Module):
    def __init__(self,state_dim,action_dim,hidden_dim=64):
        super (policynet ,self ).__init__()
        self.layer1=nn.Linear(state_dim ,hidden_dim )
        self.layer2 = nn.Linear (hidden_dim ,hidden_dim )
        self.layer3 = nn.Linear (hidden_dim ,action_dim )

    def forward(self,input):
        x=F.leaky_relu(self.layer1 (input))
        x=F.leaky_relu(self.layer2 (x))
        x=self.layer3 (x)
        mu=2.1*F.tanh(x)
        return mu

class valuenet(nn.Module):
    def __init__(self,state_dim,value_dim=1,hidden_dim=64):
        super(valuenet, self).__init__()
        self.layer1=nn.Linear (state_dim ,hidden_dim )
        self.layer2=nn.Linear (hidden_dim ,hidden_dim )
        self.layer3=nn.Linear (hidden_dim,value_dim )
    def forward(self,input):
        x=F.relu(self.layer1 (input))
        x=F.relu(self.layer2 (x))
        out=self.layer3 (x)
        return out
class PPOagent:
    def __init__(self,gama,policy_lr,critic_lr,lamda,state_dim,action_dim,epoch,device,eps=0.2):
        self.gama=gama
        self.policy_lr=policy_lr
        self.critic_lr = critic_lr
        self.lamda=lamda
        self.epoch=epoch
        self.eps=eps
        self.device=device
        self.critic=valuenet (state_dim).to(self.device)
        self.actor=policynet (state_dim,action_dim).to(self.device)
        self.policy_std=nn.Parameter(torch.ones(action_dim, device=self.device)*0.1)
        self.actor_optim=torch.optim.Adam (list(self.actor.parameters())+[self.policy_std],lr=self.policy_lr )
        self.critic_optim=torch.optim.Adam (self.critic.parameters(),lr=self.critic_lr)
    def getaction(self,state):
        state=torch.tensor(state,dtype=torch.float).unsqueeze(0).to(self.device) #将输入增加一个维度
        with torch.no_grad():
            mu = self.actor(state)
            std = self.policy_std.expand_as(mu)
            actor_list = torch.distributions.Normal(mu, std)
            action = actor_list.sample()
            action_tanh = torch.tanh(action)
            scaled_action = action_tanh * 2.0   #假设动作范围是[-2, 2]
            log_prob = actor_list.log_prob(action) - torch.log(1 - action_tanh.pow(2) + 1e-7)
            log_prob = log_prob.sum(dim=1, keepdim=True)
        return scaled_action.cpu().numpy()[0],log_prob.cpu().numpy()
    def learn(self,transition):
        state=np.array(transition.get('state'))
        state=torch.tensor(state,dtype=torch.float ).to(self.device )
        action=np.array(transition.get('action'))
        action = torch.tensor(action, dtype=torch.float).to(self.device )
        reward=np.array(transition.get('reward'))
        reward = torch.tensor(reward, dtype=torch.float).view(-1,1).to(self.device )
        next_state=np.array(transition.get('next_state'))
        next_state = torch.tensor(next_state , dtype=torch.float).to(self.device )
        done=transition.get('done')
        done = torch.tensor(done, dtype=torch.int32).view(-1,1).to(self.device )
        old_probs =transition.get('old_probs')
        old_probs = torch.tensor(old_probs, dtype=torch.float).to(self.device )
        #reward =(reward -reward.mean())/(reward.std()+1e-8)
        td_target=reward+self.gama*self.critic(next_state)*(1-done)
        td_value=self.critic(state)
        td_delta=(td_target-td_value).detach().cpu().numpy()
        advantage=0
        advantage_list=[]
        for delta in reversed(td_delta):
            advantage=delta+self.gama*self.lamda*advantage
            advantage_list.append(advantage)
        advantage_list=np.array(advantage_list)
        advantage =torch.tensor(advantage_list ,dtype=torch.float).to(self.device)
        advantage =torch.flip(advantage, dims=[0])
        #advantage = (advantage - advantage.mean()) / (advantage.std() + 1e-8)  # 归一化
        for i in range(self.epoch):
            mu=self.actor(state)
            std = self.policy_std.expand_as(mu)
            std = torch.clamp(std, 1e-6, 10)
            dist=torch.distributions.Normal(mu,std)
            entropy=dist.entropy()
            probs = dist.log_prob(action)
            ratio=torch.exp(probs-old_probs)
            sur1=torch.clamp(ratio,1-self.eps,1+self.eps)*advantage
            sur2=ratio*advantage
            actorloss=-torch.min(sur1,sur2).mean()-0.01*entropy.mean()
            criticloss=F.mse_loss(self.critic(state),td_target.detach())
            self.actor_optim.zero_grad()
            self.critic_optim.zero_grad()
            actorloss.backward()
            criticloss.backward()
            self.critic_optim.step()
            self.actor_optim.step()

env=gym.make('Pendulum-v1')
gama=0.99
critic_lr=5e-3
policy_lr=1e-3
lamda=0.95
state_dim=env.observation_space.shape[0]
action_dim=env.action_space.shape[0]
epoch=10
num_episode=100
max_step=200
return_list=[]
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
agent=PPOagent (gama,policy_lr,critic_lr,lamda,state_dim ,action_dim ,epoch ,device )
for i in range(num_episode ):
    state=env.reset()[0]
    done=False
    esp_return=0
    step_count=0
    transition={
      'state':[],'action':[],
      'reward':[],'next_state':[],
       'done':[],'old_probs':[]
    }
    while not done:
        action,old_probs=agent.getaction(state)
        next_state,reward,done,_,_=env.step(action)
        transition['state'].append(state)
        transition['action'].append(action)
        transition['reward'].append(reward)
        transition['next_state'].append(next_state)
        transition['done'].append(done)
        transition['old_probs'].append(old_probs)
        state=next_state
        esp_return=esp_return+reward
        step_count+=1
        if step_count>=max_step:
            done=True
    return_list.append(esp_return )
    agent.learn(transition)
    if i % 1 == 0:
        print(f'Episode {i}/{num_episode}, Reurn: {esp_return}')
env.close()
plt.figure()
plt.plot(return_list )
plt.xlabel('Episode')
plt.ylabel('Return')
plt.title('PPO on Pendulum-v1')
plt.show()

新学python的强化学习,这是我写的代码,但是多次尝试,训练效果一直很差,我想知道为什么,我各种排查,没发现问题在哪里,恳求各位

img


训练多次都是这种效果,不知道问题在哪里。

  • 写回答

2条回答 默认 最新

  • 关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    从您提供的代码和图表来看,您的强化学习模型的训练效果不佳可能是由于多种原因导致的。我会分析并提供一些建议来尝试解决这个问题。

    1. 学习率过高或过低: 在强化学习中,学习率的设置非常重要。如果学习率过高,可能会导致模型难以收敛;如果学习率过低,模型可能需要更长的训练时间,甚至可能无法学习到有效的策略。尝试调整 policy_lrcritic_lr 的值,并观察训练效果的变化。
    2. 神经网络架构问题: 确保您的神经网络架构适合您的任务。虽然您的 policynetvaluenet 看起来相对简单,但它们可能对于 Pendulum-v1 任务来说已经足够好了。但是,您可以尝试增加隐藏层或使用不同的激活函数来改进性能。
    3. 超参数调整: gama(折扣因子)、lamda(优势函数的lambda值)、epoch(更新次数)等超参数的选择对于强化学习的性能有很大的影响。尝试调整这些超参数并观察效果。特别是,优势函数的使用对PPO算法很重要,确保其正确实现和参数调整。
    4. 训练时间: 您的模型可能还没有充分训练。增加训练的轮数(episodes)或每个轮次的步骤数(steps)可能会提高性能。考虑增加 num_episodemax_step 的值。
    5. 状态处理: 确保您对状态进行了适当的预处理和标准化,使其在神经网络输入的范围之内。
    6. 代码实现细节: 检查您的代码实现是否有任何错误或遗漏。例如,确保在 getaction 函数中正确地计算了动作和概率。此外,检查 learn 函数中的损失计算是否正确实现。
    7. 环境反馈: 检查环境反馈是否正确地传递给了模型。确保 env.step(action) 正确返回奖励、新的状态和是否结束等信息。

    为了更有效地调试,您可以尝试以下步骤:

    • 在训练过程中打印更多的信息,例如每轮的损失值、策略的优势等,以了解模型的学习过程。
    • 尝试在不同的任务上测试模型,以确定问题是否特定于某个任务还是普遍存在的问题。
    • 使用可视化工具(如TensorBoard)来监视模型的训练过程和损失变化。

    希望这些建议能帮助您找到问题并提高模型的性能。如果问题仍然存在,您可以提供更详细的信息或代码片段以供进一步分析。

    评论

报告相同问题?

问题事件

  • 创建了问题 1月14日