为什么现在的强化学习算法不使用纯蒙特卡洛的方法? —— 使用蒙特卡洛法求解强化学习算法中的q值/q函数值
自己用AI大模型生成了一个使用蒙特卡洛法求解强化学习算法中的q值/q函数值的代码,发现这个蒙特卡洛法求解函数拟合的q值的强化学习算法性能简直是太low了。
通过本文中的代码可以知道,虽然都是使用函数拟合的方法来表示q值(使用pytorch中的神经网络模型mlp),但是q-learning算法所得到的算法模型性能更优,训练速度更快(本文没有给出q-learning算法的代码实现,该代码实现比较常见,这里就不再给出),而使用函数拟合表示q值并使用蒙特卡洛方法进行模型训练的方式训练,所得到的算法模型性能十分的有限,并且训练时间也更长,训练稳定性也更差,收敛性也更差。
而且更为需要注意的是,使用函数拟合q值并使用蒙特卡洛法进行训练的方式中,如果训练的时候使用多个episodes的数据时甚至可能使算法的性能更差,不过这样也有可能使训练的稳定性更强,但是算法的性能就更可能变差。该种方法下,算法模型的最终性能可能远远低于q-learning方法。
函数拟合q值并使用蒙特卡洛法进行训练的方式,同时训练的episodes(回合数量)越多则训练过程更稳定,但是其算法模型的性能(天花板)可能越差。
下面代码中使用的仿真环境为cartpole小车。
代码:(AI大模型生成)
import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from collections import deque
import random
# ---------------------------
# Q 网络(PyTorch)
# ---------------------------
class QNet(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=128):
super().__init__()
self.fc = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, action_dim)
)
def forward(self, x):
return self.fc(x)
# ---------------------------
# 蒙特卡洛 Q-Learning
# ---------------------------
class MonteCarloQLearning:
def __init__(self, state_dim, action_dim, gamma=0.99, lr=1e-3):
self.gamma = gamma
self.action_dim = action_dim
self.q_net = QNet(state_dim, action_dim)
self.optimizer = optim.Adam(self.q_net.parameters(), lr=lr)
self.loss_fn = nn.MSELoss()
def act(self, state, eps=0.1):
# epsilon-greedy
if random.random() < eps:
return random.randint(0, self.action_dim - 1)
with torch.no_grad():
s = torch.FloatTensor(state)
q = self.q_net(s)
return q.argmax().item()
def update(self, trajectory_s):
L = 0
self.optimizer.zero_grad()
for trajectory in trajectory_s:
# trajectory: [(s, a, r), ...]
states, actions, rewards = zip(*trajectory)
states = torch.FloatTensor(states)
actions = torch.LongTensor(actions).unsqueeze(1)
# 计算折扣回报 G(蒙特卡洛核心)
G = 0
returns = []
for r in reversed(rewards):
G = r + self.gamma * G
returns.append(G)
returns = torch.FloatTensor(list(reversed(returns))).unsqueeze(1)
# 拟合 Q(s,a) = G
q = self.q_net(states).gather(1, actions)
loss = self.loss_fn(q, returns)
L += loss.item()
loss.backward()
self.optimizer.step()
return L
# ---------------------------
# 主训练
# ---------------------------
batch_episodes = 1000
def train_mc_cartpole():
all_time = 0
ex_episode = 0
env = gym.make("CartPole-v1")
s_dim = env.observation_space.shape[0]
a_dim = env.action_space.n
agent = MonteCarloQLearning(s_dim, a_dim)
max_episodes = 1000000
eps = 1.0
eps_min = 0.01
eps_decay = 0.995
traj_s = []
for epi in range(max_episodes):
s = env.reset()
if isinstance(s, tuple):
s = s[0]
traj = []
total_reward = 0
done = False
while not done:
a = agent.act(s, eps)
ns, r, terminated, truncated, _ = env.step(a)
done = terminated or truncated
traj.append((s, a, r))
s = ns
total_reward += r
traj_s.append(traj)
if len(traj_s)>=batch_episodes:
# 回合结束才更新(蒙特卡洛特点)
loss = agent.update(traj_s)
traj_s.clear()
# 衰减探索率
if eps > eps_min:
eps *= eps_decay
print(f"Episode {epi:3d} | Reward: {total_reward:4.0f} | Loss: {loss/batch_episodes:.3f} | eps: {eps:.3f}")
# else:
# print(f"Episode {epi:3d} | Reward: {total_reward:4.0f}")
# 认为连续高分即解决
if total_reward >= 490:
if epi == ex_episode+1:
all_time += 1
else:
all_time = 1
ex_episode = epi
if all_time == 10:
print("CartPole 已通过蒙特卡洛强化学习解决!")
break
env.close()
if __name__ == "__main__":
train_mc_cartpole()





本博客是博主个人学习时的一些记录,不保证是为原创,个别文章加入了转载的源地址,还有个别文章是汇总网上多份资料所成,在这之中也必有疏漏未加标注处,如有侵权请与博主联系。
如果未特殊标注则为原创,遵循 CC 4.0 BY-SA 版权协议。
posted on 2026-08-03 22:11 Angry_Panda 阅读(2) 评论(0) 收藏 举报
浙公网安备 33010602011771号