我的第一个pytorch例程-梯度计算

本文详细解释了如何使用Python的PyTorch库计算张量a、b、c关于表达式y=a²*x+b*x+c的梯度,展示了autograd模块的基本用法和梯度求导原理。
摘要由CSDN通过智能技术生成

这段 Python 代码使用 PyTorch 库来演示了一个简单的自动梯度计算过程。让我们逐步解析代码:

1. **导入 PyTorch 相关模块**:
   ```python
   import torch
   from torch import autograd
   ```
   这里导入了 PyTorch 库以及其自动梯度模块。

2. **定义张量(Tensor)**:
   ```python
   x = torch.tensor(1.)
   a = torch.tensor(1., requires_grad=True)
   b = torch.tensor(2., requires_grad=True)
   c = torch.tensor(3., requires_grad=True)
   ```
   定义了四个张量:`x`、`a`、`b`、`c`。其中,`a`、`b`、`c` 设置 `requires_grad=True`,表示 PyTorch 需要计算它们的梯度。

3. **定义表达式**:
   ```python
   y = a**2 * x + b * x + c
   ```
   这里定义了一个多项式表达式 `y`。因为 `a`、`b`、`c` 要计算梯度,所以 `y` 将是它们的函数。

4. **梯度计算前的打印语句**:
   ```python
   print('before:', a.grad, b.grad, c.grad)
   ```
   在计算梯度之前,打印 `a`、`b`、`c` 的梯度。由于此时还未进行梯度计算,所以它们的梯度都是 `None`。

5. **计算梯度**:
   ```python
   grads = autograd.grad(y, [a, b, c])
   ```
   使用 `autograd.grad` 函数计算 `y` 相对于 `[a, b, c]` 的梯度。

6. **梯度计算后的打印语句**:
   ```python
   print('after :', grads[0], grads[1], grads[2])
   ```
   打印出计算后的梯度值。

在运行这段代码后,你将看到 `a`、`b`、`c` 关于 `y` 的梯度值。这个计算基于定义的表达式 `y = a**2 * x + b * x + c`。

在提供的代码中,PyTorch 的自动微分系统(autograd)被用来计算表达式 `y = a**2 * x + b * x + c` 关于张量 `a`、`b`、`c` 的梯度。下面是具体的计算过程:

1. **表达式定义**:
   - 表达式 `y = a**2 * x + b * x + c` 定义了 `y` 作为 `a`、`b`、`c` 的函数。其中,`x` 是一个常数张量(值为1),`a`、`b`、`c` 是需要计算梯度的变量。

2. **计算梯度**:
   - 使用 `autograd.grad` 函数,代码计算了 `y` 相对于 `a`、`b`、`c` 的梯度。梯度是表达式的局部导数,描述了 `y` 如何随这些变量变化而变化。

3. **梯度的数学计算**:
   - 对于 `a`:梯度是 `dy/da`。根据表达式,`y = a**2 * x + b * x + c`,求导后得到 `2 * a * x`。由于 `x = 1`,所以梯度为 `2 * a`。
   - 对于 `b`:梯度是 `dy/db`。同样根据表达式求导,得到 `x`。由于 `x = 1`,所以梯度为 `1`。
   - 对于 `c`:梯度是 `dy/dc`。因为 `y` 对 `c` 的导数是常数 `1`。

4. **输出结果**:
   - 执行 `grads = autograd.grad(y, [a, b, c])` 后,`grads` 包含了三个梯度值,分别对应于 `a`、`b`、`c`。根据提供的初始值(`a = 1`、`b = 2`、`c = 3`),梯度计算结果将分别是 `2 * 1 = 2`,`1`,和 `1`。

因此,执行代码后,你会在“after”后看到 `a`、`b`、`c` 的梯度值,分别是 `2`、`1` 和 `1`。

在提供的代码中,`x` 被设置为 `1` 主要是为了简化表达式 `y = a**2 * x + b * x + c` 的求导过程。当 `x = 1` 时,它对表达式的梯度计算没有实际影响,因为任何数乘以 1 都等于其本身。这样设置可以让我们更直观地看到 `a`、`b`、`c` 对于表达式 `y` 的影响,而不是 `x` 的影响。

在实际应用中,`x` 可以是任何值,但在这个特定的例子里,选择 `x = 1` 是为了便于展示和理解梯度计算的过程。如果 `x` 是除了 1 以外的其他值,那么它就会相应地影响梯度的计算结果。

这是一个使用PyTorch实现DDPG算法的例程: ```python import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F import numpy as np # 定义Actor网络 class Actor(nn.Module): def __init__(self, state_dim, action_dim, max_action): super(Actor, self).__init__() self.layer1 = nn.Linear(state_dim, 400) self.layer2 = nn.Linear(400, 300) self.layer3 = nn.Linear(300, action_dim) self.max_action = max_action def forward(self, x): x = F.relu(self.layer1(x)) x = F.relu(self.layer2(x)) x = self.max_action * torch.tanh(self.layer3(x)) return x # 定义Critic网络 class Critic(nn.Module): def __init__(self, state_dim, action_dim): super(Critic, self).__init__() self.layer1 = nn.Linear(state_dim + action_dim, 400) self.layer2 = nn.Linear(400, 300) self.layer3 = nn.Linear(300, 1) def forward(self, x, u): xu = torch.cat([x, u], 1) x = F.relu(self.layer1(xu)) x = F.relu(self.layer2(x)) x = self.layer3(x) return x # 定义DDPG算法 class DDPG(object): def __init__(self, state_dim, action_dim, max_action): self.actor = Actor(state_dim, action_dim, max_action).to(device) self.actor_target = Actor(state_dim, action_dim, max_action).to(device) self.actor_target.load_state_dict(self.actor.state_dict()) self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=1e-4) self.critic = Critic(state_dim, action_dim).to(device) self.critic_target = Critic(state_dim, action_dim).to(device) self.critic_target.load_state_dict(self.critic.state_dict()) self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=1e-3) self.max_action = max_action def select_action(self, state): state = torch.FloatTensor(state.reshape(1, -1)).to(device) return self.actor(state).cpu().data.numpy().flatten() def train(self, replay_buffer, iterations, batch_size=100, discount=0.99, tau=0.005): for it in range(iterations): # 从replay buffer中随机采样一个batch的数据 batch_states, batch_next_states, batch_actions, batch_rewards, batch_dones = replay_buffer.sample(batch_size) state = torch.FloatTensor(batch_states).to(device) next_state = torch.FloatTensor(batch_next_states).to(device) action = torch.FloatTensor(batch_actions).to(device) reward = torch.FloatTensor(batch_rewards).to(device) done = torch.FloatTensor(batch_dones).to(device) # 训练Critic网络 target_Q = self.critic_target(next_state, self.actor_target(next_state)) target_Q = reward + ((1 - done) * discount * target_Q).detach() current_Q = self.critic(state, action) critic_loss = F.mse_loss(current_Q, target_Q) self.critic_optimizer.zero_grad() critic_loss.backward() self.critic_optimizer.step() # 训练Actor网络 actor_loss = -self.critic(state, self.actor(state)).mean() self.actor_optimizer.zero_grad() actor_loss.backward() self.actor_optimizer.step() # 更新target网络 for param, target_param in zip(self.critic.parameters(), self.critic_target.parameters()): target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data) for param, target_param in zip(self.actor.parameters(), self.actor_target.parameters()): target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data) def save(self, filename): torch.save(self.actor.state_dict(), filename + "_actor") torch.save(self.critic.state_dict(), filename + "_critic") def load(self, filename): self.actor.load_state_dict(torch.load(filename + "_actor")) self.critic.load_state_dict(torch.load(filename + "_critic")) # 定义Replay Buffer class ReplayBuffer(object): def __init__(self, max_size=1000000): self.storage = [] self.max_size = max_size self.ptr = 0 def add(self, state, next_state, action, reward, done): data = (state, next_state, action, reward, done) if len(self.storage) == self.max_size: self.storage[int(self.ptr)] = data self.ptr = (self.ptr + 1) % self.max_size else: self.storage.append(data) def sample(self, batch_size): ind = np.random.randint(0, len(self.storage), size=batch_size) batch_states = [] batch_next_states = [] batch_actions = [] batch_rewards = [] batch_dones = [] for i in ind: state, next_state, action, reward, done = self.storage[i] batch_states.append(np.array(state, copy=False)) batch_next_states.append(np.array(next_state, copy=False)) batch_actions.append(np.array(action, copy=False)) batch_rewards.append(np.array(reward, copy=False)) batch_dones.append(np.array(done, copy=False)) return np.array(batch_states), np.array(batch_next_states), np.array(batch_actions), np.array(batch_rewards).reshape(-1, 1), np.array(batch_dones).reshape(-1, 1) # 定义环境 class Environment(object): def __init__(self): self.state_dim = 3 self.action_dim = 1 self.max_action = 2.0 def step(self, action): next_state = np.zeros(3) next_state[0] = 0.5 next_state[1] = 0.5 * np.sin(3 * next_state[0]) + 0.5 * np.sin(2 * next_state[1]) next_state[2] = 0.5 * np.sin(2 * next_state[0]) + 0.5 * np.sin(3 * next_state[1]) reward = -np.linalg.norm(next_state - np.array([1, 0, 0])) # 奖励函数为到目标点的欧式距离的相反数 done = False return next_state, reward, done def reset(self): state = np.zeros(3) state[0] = np.random.uniform(low=-0.1, high=0.1) state[1] = np.random.uniform(low=-0.1, high=0.1) state[2] = np.random.uniform(low=-0.1, high=0.1) return state # 训练DDPG env = Environment() replay_buffer = ReplayBuffer() ddpg = DDPG(env.state_dim, env.action_dim, env.max_action) for i in range(100000): state = env.reset() done = False while not done: action = ddpg.select_action(state) next_state, reward, done = env.step(action) replay_buffer.add(state, next_state, action, reward, done) state = next_state if len(replay_buffer.storage) > 1000: ddpg.train(replay_buffer, 100) # 测试DDPG state = env.reset() done = False while not done: action = ddpg.select_action(state) next_state, reward, done = env.step(action) state = next_state print(state) # 保存DDPG模型 ddpg.save("ddpg") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值