【学习笔记】RL算法 Q learning+SARSA+DQN

【学习笔记】RL算法 Q learning +SARSA + DQN


个人学习笔记,自用。代码仓库:https://github.com/lansinuote/More_Simple_Reinforcement_Learning

1 Q learning、SARSA、改进的SARSA、蒙特卡洛

前置基础:时序差分
思路:定义环境、初始化Q表格、进行一场游戏并记录数据、数据池、开始训练
Q learning

#Q矩阵当前估计的state下action的价值
value = Q[state, action]
#实际玩了之后得到的reward+下一个状态的价值*0.9
target = reward + Q[next_state].max() * 0.9

SARSA:

#Q矩阵当前估计的state下action的价值
value = Q[state, action]
#求下一个动作,和Q学习唯一的区别点
next_action = Q[next_state].argmax()  # argmax()-返回当前状态即所在的行的最大值的列索引
#实际玩了之后得到的reward+下一个状态的价值*0.9
target = reward + Q[next_state, next_action] * 0.9 

同策略的SARSA(理论上不能用池化理论上不能用池化,所以每次训练现玩游戏):
每次训练都要现玩一局游戏

#玩一局游戏并得到数据
for (state, action, reward, next_state, over) in play()[0]:

多步的TD算法(蒙特卡洛 ):

#玩一局游戏,得到数据
state, action, reward, next_state, over, _ = play()
for i in range(len(state)):
#计算value
value = Q[state[i], action[i]]
#计算target
#累加未来N步的reward,越远的折扣越大
#这里是在使用蒙特卡洛方法估计target
reward_s = 0
for j in range(i, min(len(state), i + 5)):
reward_s += reward[j] * 0.9**(j - i)
#计算最后一步的value,这是target的一部分,按距离给折扣
target = Q[next_state[j]].max() * 0.9**(j - i + 1)
#如果最后一步已经结束,则不需要考虑状态价值
#最后累加reward就是target
target = target + reward_s

2 DQN及改进DQN

QLearning使用表格估计Q函数,不便于扩展.
所以使用神经网络估计Q函数.
DQN

# 1. 定义模型,评估状态下每个动作的价值
model = torch.nn.Sequential(
    torch.nn.Linear(4, 64),
    torch.nn.ReLU(),
    torch.nn.Linear(64, 64),
    torch.nn.ReLU(),
    torch.nn.Linear(64, 2),
)

# 2. 玩一局游戏并记录数据
        action = model(torch.FloatTensor(state).reshape(1, 4)).argmax().item()

# 3. 获取一批数据样本
    def sample(self):
        data = random.sample(self.pool, 64)

        state = torch.FloatTensor([i[0] for i in data]).reshape(-1, 4)
        action = torch.LongTensor([i[1] for i in data]).reshape(-1, 1)
        reward = torch.FloatTensor([i[2] for i in data]).reshape(-1, 1)
        next_state = torch.FloatTensor([i[3] for i in data]).reshape(-1, 4)
        over = torch.LongTensor([i[4] for i in data]).reshape(-1, 1)

        return state, action, reward, next_state, over

# 4. 训练
def train():
    model.train()
    optimizer = torch.optim.Adam(model.parameters(), lr=2e-4)
    loss_fn = torch.nn.MSELoss()

    #共更新N轮数据
    for epoch in range(1000):
        pool.update()

        #每次更新数据后,训练N次
        for i in range(200):

            #采样N条数据
            state, action, reward, next_state, over = pool.sample()

            #计算value
            value = model(state).gather(dim=1, index=action)

            #计算target
            with torch.no_grad():
                target = model(next_state)
            target = target.max(dim=1)[0].reshape(-1, 1)
            target = target * 0.99 * (1 - over) + reward

            loss = loss_fn(value, target)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()

双模型DQN
双模型使用两个不同的模型计算value和target,缓解了自举造成的过高估计.

#定义模型,评估状态下每个动作的价值
model = torch.nn.Sequential(
    torch.nn.Linear(4, 64),
    torch.nn.ReLU(),
    torch.nn.Linear(64, 64),
    torch.nn.ReLU(),
    torch.nn.Linear(64, 2),
)
#延迟更新的模型,用于计算target
创建model_delay,等同model

#计算value
 value = model(state).gather(dim=1, index=action)
#计算target
with torch.no_grad():
	target = model_delay(next_state)
	
#复制参数
if (epoch + 1) % 5 == 0:              
	model_delay.load_state_dict(model.state_dict())

加权数据池
给高loss的数据加权,提高这些数据被采样中的概率.
为了缓解过拟合,降低这些数据的lr,这里以削减loss的方式实现.

数据池中添加 
# 维护概率表
self.prob.extend([1.0] * len(data))

idx = torch.FloatTensor(self.prob).clamp(0.1, 1.0).multinomial(num_samples=64, replacement=False)

Dueling DQN
Q(state,action) = state下最优action分数 + 误差
为了限制误差的范围,可以对它去均值,相当于去基线
Q(state,action) = state下最优action分数 + 误差 - mean(误差)
理解起来有点困难,所以可以这么理解
Q(state,action) = state分数 + action分数 - mean(action分数)

Noise DQN
给模型参数增加随机性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值