【深度强化学习】(8) iPPO 模型解析,附Pytorch完整代码

这篇具有很好参考价值的文章主要介绍了【深度强化学习】(8) iPPO 模型解析,附Pytorch完整代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好,今天和各位分享一下多智能体深度强化学习算法 ippo,并基于 gym 环境完成一个小案例。完整代码可以从我的 GitHub 中获得:https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Model


1. 算法原理

多智能体的情形相比于单智能体更加复杂,因为每个智能体在和环境交互的同时也在和其他智能体进行直接或者间接的交互。因此,多智能体强化学习要比单智能体更困难,其难点主要体现在以下几点:

(1)由于多个智能体在环境中进行实时动态交互,并且每个智能体在不断学习并更新自身策略,因此在每个智能体的视角下,环境是非稳态的,即对于一个智能体而言,即使在相同的状态下采取相同的动作,得到的状态转移和奖励信号的分布可能在不断改变;

(2)多个智能体的训练可能是多目标的,不同智能体需要最大化自己的利益;

(3)训练评估的复杂度会增加,可能需要大规模分布式训练来提高效率。

iPPO 算法的模型部分和 PPO 类似,可以看我下面这篇博文:

https://blog.csdn.net/dgvv4/article/details/129496576?spm=1001.2014.3001.5501


IPPO(Independent PPO)是一种完全去中心化的算法,此类算法被称为独立学习。由于对于每个智能体使用单智能体算法 PPO 进行训练,所因此这个算法叫作独立 PPO 算法。

这里使用的 PPO 算法版本为 PPO-截断,其算法流程如下:

ippo算法,深度强化学习,人工智能,pytorch,python,强化学习,深度强化学习


2. 代码实现

代码和 ppo 离散模型基本相同

# 和PPO离散模型基本一致
import torch
from torch import nn
from torch.nn import functional as F
import numpy as np

# ----------------------------------------- #
# 策略网络--actor
# ----------------------------------------- #

class PolicyNet(nn.Module):  # 输入当前状态,输出动作的概率分布
    def __init__(self, n_states, n_hiddens, n_actions):
        super(PolicyNet, self).__init__()
        self.fc1 = nn.Linear(n_states, n_hiddens)
        self.fc2 = nn.Linear(n_hiddens, n_hiddens)
        self.fc3 = nn.Linear(n_hiddens, n_actions)
    def forward(self, x):  # [b,n_states]
        x = self.fc1(x)  # [b,n_states]-->[b,n_hiddens]
        x = F.relu(x)
        x = self.fc2(x)  # [b,n_hiddens]-->[b,n_hiddens]
        x = F.relu(x)
        x = self.fc3(x)  # [b,n_hiddens]-->[b,n_actions]
        x = F.softmax(x, dim=1)  # 每种动作选择的概率
        return x

# ----------------------------------------- #
# 价值网络--critic
# ----------------------------------------- #

class ValueNet(nn.Module):  # 评价当前状态的价值
    def __init__(self, n_states, n_hiddens):
        super(ValueNet, self).__init__()
        self.fc1 = nn.Linear(n_states, n_hiddens)
        self.fc2 = nn.Linear(n_hiddens, n_hiddens)
        self.fc3 = nn.Linear(n_hiddens, 1)
    def forward(self, x):  # [b,n_states]
        x = self.fc1(x)  # [b,n_states]-->[b,n_hiddens]
        x = F.relu(x)
        x = self.fc2(x)  # [b,n_hiddens]-->[b,n_hiddens]
        x = F.relu(x)
        x = self.fc3(x)  # [b,n_hiddens]-->[b,1]
        return x

# ----------------------------------------- #
# 模型构建
# ----------------------------------------- #

class PPO:
    def __init__(self, n_states, n_hiddens, n_actions,
                 actor_lr, critic_lr, 
                 lmbda, eps, gamma, device):
        # 属性分配
        self.n_hiddens = n_hiddens
        self.actor_lr = actor_lr  # 策略网络的学习率
        self.critic_lr = critic_lr  # 价值网络的学习率
        self.lmbda = lmbda  # 优势函数的缩放因子
        self.eps = eps  # ppo截断范围缩放因子
        self.gamma = gamma  # 折扣因子
        self.device = device
        # 网络实例化
        self.actor = PolicyNet(n_states, n_hiddens, n_actions).to(device)  # 策略网络
        self.critic = ValueNet(n_states, n_hiddens).to(device)  # 价值网络
        # 优化器
        self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=actor_lr)
        self.critic_optimizer = torch.optim.Adam(self.critic.parameters(), lr=critic_lr)
    
    # 动作选择
    def take_action(self, state):  # [n_states]
        state = torch.tensor([state], dtype=torch.float).to(self.device)  # [1,n_states]
        probs = self.actor(state)  # 当前状态的动作概率 [b,n_actions]
        action_dist = torch.distributions.Categorical(probs)  # 构造概率分布
        action = action_dist.sample().item()  # 从概率分布中随机取样 int
        return action
    
    # 训练
    def update(self, transition_dict):
        # 取出数据集
        states = torch.tensor(transition_dict['states'], dtype=torch.float).to(self.device)  # [b,n_states]
        actions = torch.tensor(transition_dict['actions']).view(-1,1).to(self.device)  # [b,1]
        next_states = torch.tensor(transition_dict['next_states'], dtype=torch.float).to(self.device)  # [b,n_states]
        dones = torch.tensor(transition_dict['dones'], dtype=torch.float).view(-1,1).to(self.device)  # [b,1]
        rewards = torch.tensor(transition_dict['rewards'], dtype=torch.float).view(-1,1).to(self.device)  # [b,1]

        # 价值网络
        next_state_value = self.critic(next_states)  # 下一时刻的state_value  [b,1]
        td_target = rewards + self.gamma * next_state_value * (1-dones)  # 目标--当前时刻的state_value  [b,1]
        td_value = self.critic(states)  # 预测--当前时刻的state_value  [b,1]
        td_delta = td_value - td_target  # 时序差分  # [b,1]

        # 计算GAE优势函数,当前状态下某动作相对于平均的优势
        advantage = 0  # 累计一个序列上的优势函数
        advantage_list = []  # 存放每个时序的优势函数值
        td_delta = td_delta.cpu().detach().numpy()  # gpu-->numpy
        for delta in td_delta[::-1]:  # 逆序取出时序差分值
            advantage = self.gamma * self.lmbda * advantage + delta
            advantage_list.append(advantage)  # 保存每个时刻的优势函数
        advantage_list.reverse()  # 正序
        advantage = torch.tensor(advantage_list, dtype=torch.float).to(self.device)

        # 计算当前策略下状态s的行为概率 / 在之前策略下状态s的行为概率
        old_log_probs = torch.log(self.actor(states).gather(1,actions))  # [b,1]
        log_probs = torch.log(self.actor(states).gather(1,actions))
        ratio = log_probs / old_log_probs

        # clip截断
        surr1 = ratio * advantage
        surr2 = torch.clamp(ratio, 1-self.eps, 1+self.eps) * advantage
        
        # 损失计算
        actor_loss = torch.mean(-torch.min(surr1, surr2))  # clip截断
        critic_loss = torch.mean(F.mse_loss(td_value, td_target))  # 
        # 梯度更新
        self.actor_optimizer.zero_grad()
        self.critic_optimizer.zero_grad()
        actor_loss.backward()
        critic_loss.backward()
        self.actor_optimizer.step()
        self.critic_optimizer.step()

3. 案例演示

ma-gym 库中的 Combat 环境。Combat 是一个在二维的格子世界上进行的两个队伍的对战模拟游戏,每个智能体的动作集合为:向四周移动格,攻击周围格范围内其他敌对智能体,或者不采取任何行动。起初每个智能体有 3 点生命值,如果智能体在敌人的攻击范围内被攻击到了,则会扣 1 生命值,生命值掉为 0 则死亡,最后存活的队伍获胜。每个智能体的攻击有一轮的冷却时间。

IPPO 代码实践的最主要部分。值得注意的是,在训练时使用了参数共享(parameter sharing)的技巧,即对于所有智能体使用同一套策略参数,这样做的好处是能够使得模型训练数据更多,同时训练更稳定。能够这样做的前提是,两个智能体是同质的(homogeneous),即它们的状态空间和动作空间是完全一致的,并且它们的优化目标也完全一致。感兴趣的读者也可以自行实现非参数共享版本的 IPPO,此时每个智能体就是一个独立的 PPO 的实例。

import numpy as np
import matplotlib.pyplot as plt
import torch
from ma_gym.envs.combat.combat import Combat
from RL_brain import PPO
import time

# ----------------------------------------- #
# 参数设置
# ----------------------------------------- #

n_hiddens = 64  # 隐含层数量
actor_lr = 3e-4
critic_lr = 1e-3
gamma = 0.9
lmbda = 0.97
eps = 0.2
device = torch.device('cuda') if torch.cuda.is_available() \
                            else torch.device('cpu')
num_episodes = 10  # 回合数
team_size = 2  # 智能体数量
grid_size = (15, 15)

# ----------------------------------------- #
# 环境设置--onpolicy
# ----------------------------------------- #

# 创建Combat环境,格子世界的大小为15x15,己方智能体和敌方智能体数量都为2
env = Combat(grid_shape=grid_size, n_agents=team_size, n_opponents=team_size)
n_states = env.observation_space[0].shape[0]  # 状态数
n_actions = env.action_space[0].n  # 动作数

# 两个智能体共享同一个策略
agent = PPO(n_states = n_states,
            n_hiddens = n_hiddens,
            n_actions = n_actions,
            actor_lr = actor_lr,
            critic_lr = critic_lr,
            lmbda = lmbda,
            eps = eps,
            gamma = gamma,
            device = device,
            )

# ----------------------------------------- #
# 模型训练
# ----------------------------------------- #

for i in range(num_episodes):
    # 每回合开始前初始化两支队伍的数据集
    transition_dict_1 = {
        'states': [],
        'actions': [],
        'next_states': [],
        'rewards': [],
        'dones': [],
    }
    transition_dict_2 = {
        'states': [],
        'actions': [],
        'next_states': [],
        'rewards': [],
        'dones': [],
    }

    s = env.reset()  # 状态初始化
    terminal = False  # 结束标记

    while not terminal:

        env.render()

        # 动作选择
        a_1 = agent.take_action(s[0])
        a_2 = agent.take_action(s[1])

        # 环境更新
        next_s, r, done, info = env.step([a_1, a_2])

        # 构造数据集
        transition_dict_1['states'].append(s[0])
        transition_dict_1['actions'].append(a_1)
        transition_dict_1['next_states'].append(next_s[0])
        transition_dict_1['dones'].append(False)
        transition_dict_1['rewards'].append(r[0])

        transition_dict_2['states'].append(s[1])
        transition_dict_2['actions'].append(a_2)
        transition_dict_2['next_states'].append(next_s[1])
        transition_dict_2['dones'].append(False)
        transition_dict_2['rewards'].append(r[1])

        s = next_s  # 状态更新
        terminal = all(done)  # 判断当前回合是否都为True,是返回True,不是返回False

        time.sleep(0.1)
    
    print('epoch:', i)

    # 回合训练
    agent.update(transition_dict_1)
    agent.update(transition_dict_2)

ippo算法,深度强化学习,人工智能,pytorch,python,强化学习,深度强化学习文章来源地址https://www.toymoban.com/news/detail-780564.html

到了这里,关于【深度强化学习】(8) iPPO 模型解析,附Pytorch完整代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Pytorch深度强化学习(3):详解K摇臂赌博机模型和ϵ-贪心算法

    本专栏重点介绍强化学习技术的数学原理,并且 采用Pytorch框架对常见的强化学习算法、案例进行实现 ,帮助读者理解并快速上手开发。同时,辅以各种机器学习、数据处理技术,扩充人工智能的底层知识。 🚀详情:

    2024年02月11日
    浏览(7)
  • Pytorch深度强化学习1-2:详解K摇臂赌博机模型和ϵ-贪心算法

    本专栏重点介绍强化学习技术的数学原理,并且 采用Pytorch框架对常见的强化学习算法、案例进行实现 ,帮助读者理解并快速上手开发。同时,辅以各种机器学习、数据处理技术,扩充人工智能的底层知识。 🚀详情:

    2024年02月11日
    浏览(15)
  • 【深度强化学习】Python:OpenAI Gym-CarRacing 自动驾驶 | 提供项目完整代码 | 车道检测功能 | 路径训练功能 | 车辆控制功能

    【深度强化学习】Python:OpenAI Gym-CarRacing 自动驾驶 | 提供项目完整代码 | 车道检测功能 | 路径训练功能 | 车辆控制功能

          💭 写在前面: 本篇是关于 OpenAI Gym-CarRacing 自动驾驶项目的博客,面向掌握 Python 并有一定的深度强化学习基础的读者。 GYM-Box2D CarRacing 是一种在 OpenAI Gym 平台上开发和比较强化学习算法的模拟环境。它是流行的 Box2D 物理引擎的一个版本,经过修改以支持模拟汽车在

    2024年02月16日
    浏览(15)
  • PyTorch各种损失函数解析:深度学习模型优化的关键(2)

    目录 详解pytorch中各种Loss functions mse_loss 用途 用法 使用技巧 注意事项 参数 数学理论公式 代码演示  margin_ranking_loss 用途 用法 使用技巧 注意事项 参数 数学理论公式  代码演示 multilabel_margin_loss 用途 用法 使用技巧 注意事项 参数 数学理论公式 代码演示 multilabel_soft_margin_

    2024年01月19日
    浏览(26)
  • 医学图像的深度学习的完整代码示例:使用Pytorch对MRI脑扫描的图像进行分割

    医学图像的深度学习的完整代码示例:使用Pytorch对MRI脑扫描的图像进行分割

    图像分割是医学图像分析中最重要的任务之一,在许多临床应用中往往是第一步也是最关键的一步。在脑MRI分析中,图像分割通常用于测量和可视化解剖结构,分析大脑变化,描绘病理区域以及手术计划和图像引导干预,分割是大多数形态学分析的先决条件。 本文我们将介绍

    2024年02月05日
    浏览(13)
  • 【图像分割】【深度学习】SAM官方Pytorch代码-各模块的功能解析

    【图像分割】【深度学习】SAM官方Pytorch代码-各模块的功能解析

    Segment Anything:建立了迄今为止最大的分割数据集,在1100万张图像上有超过1亿个掩码,模型的设计和训练是灵活的,其重要的特点是Zero-shot(零样本迁移性)转移到新的图像分布和任务,一个图像分割新的任务、模型和数据集。SAM由三个部分组成:一个强大的图像编码器(Image

    2024年02月11日
    浏览(9)
  • Pytorch训练深度强化学习时CPU内存占用一直在快速增加

    最近在用MATD3算法解决多机器人任务,但是在训练过程中,CPU内存一直在增加(注意,不是GPU显存)。我很头疼,以为是算法代码出了问题,导致了内存泄漏,折腾了1天也没解决。后来用memory_profiler对代码分析,才发现是这个函数占用的内存一直在增加:  def store_transition(

    2024年02月07日
    浏览(11)
  • 一文读懂强化学习:RL全面解析与Pytorch实战

    一文读懂强化学习:RL全面解析与Pytorch实战

    在本篇文章中,我们全面而深入地探讨了强化学习(Reinforcement Learning)的基础概念、主流算法和实战步骤。从马尔可夫决策过程(MDP)到高级算法如PPO,文章旨在为读者提供一套全面的理论框架和实用工具。同时,我们还专门探讨了强化学习在多个领域,如游戏、金融、医疗

    2024年02月06日
    浏览(79)
  • [PyTorch][chapter 58][强化学习-2-有模型学习2]

    [PyTorch][chapter 58][强化学习-2-有模型学习2]

    前言:    前面我们讲了一下策略评估的原理,以及例子.    强化学习核心是找到最优的策略,这里    重点讲解两个知识点:     策略改进    策略迭代与值迭代    最后以下面环境E 为例,给出Python 代码 。 目录:      1:  策略改进       2:  策略迭代与值迭代    

    2024年02月06日
    浏览(10)
  • Pytorch深度强化学习:Gym安装与环境搭建教程(附基本指令表)

    Pytorch深度强化学习:Gym安装与环境搭建教程(附基本指令表)

    本专栏重点介绍强化学习技术的数学原理,并且 采用Pytorch框架对常见的强化学习算法、案例进行实现 ,帮助读者理解并快速上手开发。同时,辅以各种机器学习、数据处理技术,扩充人工智能的底层知识。 🚀详情:《Pytorch深度强化学习》 强化学习是在潜在的不确定复杂环

    2024年02月05日
    浏览(8)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包