{"id":20522209,"url":"https://github.com/piperliu/approachable-reinforcement-learning","last_synced_at":"2025-04-14T02:53:04.612Z","repository":{"id":118614775,"uuid":"255797007","full_name":"PiperLiu/Approachable-Reinforcement-Learning","owner":"PiperLiu","description":"这个仓库用于存储一些强化学习练手小项目与算法实验。具体来讲，就是不至于单独成一个 repo 的项目，但是又值得拿出来讨论的代码。","archived":false,"fork":false,"pushed_at":"2021-05-27T00:14:41.000Z","size":18582,"stargazers_count":19,"open_issues_count":0,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-27T16:55:59.482Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PiperLiu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-15T03:42:19.000Z","updated_at":"2025-01-14T14:43:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"60c19569-e0d6-4229-baeb-f56a167e736c","html_url":"https://github.com/PiperLiu/Approachable-Reinforcement-Learning","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PiperLiu%2FApproachable-Reinforcement-Learning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PiperLiu%2FApproachable-Reinforcement-Learning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PiperLiu%2FApproachable-Reinforcement-Learning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PiperLiu%2FApproachable-Reinforcement-Learning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PiperLiu","download_url":"https://codeload.github.com/PiperLiu/Approachable-Reinforcement-Learning/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248813829,"owners_count":21165631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T22:34:32.139Z","updated_at":"2025-04-14T02:53:04.605Z","avatar_url":"https://github.com/PiperLiu.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 强化学习练手场地\n这个仓库本来用于复现某本国内强化学习教材的案例，奈何这本书写得实在太差了，因此弃坑此书。我的书评在这里：[豆瓣书评](https://book.douban.com/review/12673161/)。\n\n现在，这个仓库用于存储一些强化学习练手小项目与算法实验。具体来讲，就是不至于单独成一个 repo 的项目，但是又值得拿出来讨论的代码。\n\n### 我的笔记分布\n- 🥊 入门学习 / 读书笔记 [GitHub链接：PiperLiu/Reinforcement-Learning-practice-zh](https://github.com/PiperLiu/Reinforcement-Learning-practice-zh)\n- 💻 阅读论文 / 视频课程的笔记 [GitHub链接：PiperLiu/introRL](https://github.com/PiperLiu/introRL)\n- ✨ 大小算法 / 练手操场 [GitHub链接：PiperLiu/Approachable-Reinforcement-Learning](https://github.com/PiperLiu/Approachable-Reinforcement-Learning)\n\n### 仓库目录\n- 强化学习基础复现案例 [转到摘要与索引](#强化学习基础复现案例)\n\n\n****\n\n## 强化学习基础复现案例\n\n参考《深入浅出强化学习：编程实战》内容。奈何实在写得不行，因此照着复现了第0、1章与AlphaZero后，弃坑。\n\n- [附录 A PyTorch 入门](#A)\n- 第 0 篇 先导篇\n- - [1 一个及其简单的强化学习实例](#sec_1)\n- - [2 马尔可夫决策过程](#sec_2)\n- 第 1 篇 基于值函数的方法\n- - [3 基于动态规划的方法](#sec_3)\n- - [4 基于蒙特卡洛的方法](#sec_4)\n- - [5 基于时间差分的方法](#sec_5)\n- - [6 基于函数逼近的方法](#sec_6)\n- AlphaZero 实战：五子棋\n- - [链接](#sec_11)\n\n### 附录 A PyTorch 入门\n\u003ca id='A'\u003e\u003c/a\u003e\n\n[./pyTorch_learn/](./pyTorch_learn/)\n\n介绍了 PyTorch 的基本使用，主要实例为：构建了一个极其单薄简单的卷积神经网络，数据集为 `CIFAR10` 。学习完附录 A ，我主要收获：\n- 输入 PyTorch 的 `nn.Module` 应该是 `mini-batch` ，即比正常数据多一个维度；\n- 输入 `nn.Module` 应该是 `Variable` 包裹的；\n- 在网络类中， `__init__()` 并没有真正定义网络结构的关系，网络结构的输入输出关系在 `forward()` 中定义。\n\n此外，让我们梳理一下神经网络的“学习”过程：\n```python\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.autograd import Variabl\nimport torch.optim as optim\n\n# 神经网络对象\nnet = Net()\n# 损失函数：交叉熵\ncriterion = nn.CrossEntropyLoss()\n# 优化方式\noptimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)\n# 遍历所有数据 5 次\nfor epoch in range(5):\n    # data 是一个 mini-batch ， batch-size 由 trainloader 决定\n    for i, data in enumerate(trainloader, 0):\n        # 特征值与标签：注意用 Variable 进行包裹\n        inputs, labels = data\n        inputs, labels = Variable(inputs), Variable(labels)\n        # pytorch 中 backward() 函数执行时，梯度是累积计算，\n        # 而不是被替换；\n        # 但在处理每一个 batch 时并不需要与其他 batch 的梯度\n        # 混合起来累积计算，\n        # 因此需要对每个 batch 调用一遍 zero_grad()\n        # 将参数梯度置0。\n        optimizer.zero_grad()\n        # 现在的输出值\n        outputs = net(inputs)\n        # 求误差\n        loss = criterion(outputs, labels)\n        # 在初始化 optimizer 时,我们明确告诉它应该更新模型的\n        # 哪些参数；一旦调用了 loss.backward() ，梯度就会被\n        # torch对象“存储”（它们具有grad和requires_grad属性）；\n        # 在计算模型中所有张量的梯度后，调用 optimizer.step()\n        # 会使优化器迭代它应该更新的所有参数（张量），\n        # 并使用它们内部存储的 grad 来更新它们的值。\n        loss.backward()\n        optimizer.step()\n\n# 模型的保存与加载\ntorch.save(net.state_dict(), './pyTorch_learn/data/' + 'model.pt')\nnet.load_state_dict(torch.load('./pyTorch_learn/data/' + 'model.pt'))\n```\n\n### 第 0 篇 先导篇\n\n#### 1 一个及其简单的强化学习实例\n\u003ca id='sec_1'\u003e\u003c/a\u003e\n\n[./ch_0/sec_1/](./ch_0/sec_1/)\n\n很简答的一个实例，探讨“探索”与“利用”间的博弈平衡。\n\n我对原书的代码进行了一些改进与 typo 。\n\n#### 2 马尔可夫决策过程\n\u003ca id='sec_2'\u003e\u003c/a\u003e\n\n[./ch_0/sec_2/](./ch_0/sec_2/)\n\n优势函数（Advantage Function）：$A(s, a) = q_\\pi (s, a) - v_\\pi (s)$\n\n造了一个交互环境，以后测试可以用到。典型的“网格世界”。\n\n### 第 1 篇 基于值函数的方法\n\n#### 3 基于动态规划的方法\n\u003ca id='sec_3'\u003e\u003c/a\u003e\n\n[./ch_1/sec_3/](./ch_1/sec_3/)\n\n- 修改了“鸳鸯环境”：[yuan_yang_env.py](./ch_1/sec_3/yuan_yang_env.py)\n- 策略迭代：[dp_policy_iter.py](./ch_1/sec_3/dp_policy_iter.py)\n- 价值迭代：[dp_value_iter.py](./ch_1/sec_3/dp_value_iter.py)\n\n#### 4 基于蒙特卡洛的方法\n\u003ca id='sec_4'\u003e\u003c/a\u003e\n\n[./ch_1/sec_4/](./ch_1/sec_4/)\n\n基于蒙特卡洛方法，分别实现了：\n- 纯贪心策略；\n- 同轨策略下的 Epsilon-贪心策略。\n\n#### 5 基于时间差分的方法\n\u003ca id='sec_5'\u003e\u003c/a\u003e\n\n[./ch_1/sec_5/](./ch_1/sec_5/)\n\n本书让我对“离轨策略”的概念更加清晰：\n- 离轨策略可以使用重复的数据、不同策略下产生的数据；\n- 因为，离轨策略更新时，只用到了(s, a, r, s')，并不需要使用 a' 这个数据；\n- 换句话说，并不需要数据由本策略产生。\n\n**发现了一个神奇的现象：关于奖励机制的设置。**\n\n书上说，本节使用的 env 可以与蒙特卡洛同，这是不对的。\n先说上节蒙特卡洛的奖励机制：\n- 小鸟撞到墙：-10；\n- 小鸟到达目的地：+10；\n- 小鸟走一步，什么都没有发生：-2。\n\n如果你运行试验，你会发现，TD(0) 方法下，小鸟会 **畏惧前行** ：\n- 在蒙特卡洛方法下，如此的奖励机制有效的，因为训练是在整整一幕结束之后；\n- 在 TD(0) 方法下，小鸟状态墙得到的奖励是 -10 ，而它行走五步的奖励也是 -10 （不考虑折扣）；\n- 但在这个环境中，小鸟要抵达目的地，至少要走 20 步；\n- 因此，与其“披荆斩棘走到目的地”，还不如“在一开始就一头撞在墙上撞死”来的奖励多呢。\n\n可以用如下几个例子印证，对于 [./ch_1/sec_5/yuan_yang_env_td.py](./ch_1/sec_5/yuan_yang_env_td.py) 的第 151-159 行：\n```python\nflag_collide = self.collide(next_position)\n        if flag_collide == 1:\n            return self.position_to_state(current_position), -10, True\n        \n        flag_find = self.find(next_position)\n        if flag_find == 1:\n            return self.position_to_state(next_position), 10, True\n        \n        return self.position_to_state(next_position), -2, False\n```\n\n现在 (撞墙奖励, 到达重点奖励, 走路奖励) 分别为 (-10, 10, -2) 。现在的实验结果是：小鸟宁可撞死，也不出门。\n\n我们把出门走路的痛感与抵达目的地的快乐进行更改，：\n- (-10, 10, -1)，出门走路没有那么疼了，小鸟倾向于抵达目的地；\n- (-10, 10, -1.2)，出门走路的痛感上升，小鸟倾向于宁可开局就撞死自己；\n- (-10, 100, -1.2)，出门走路虽然疼，但是到达目的地的快乐是很大很大的，小鸟多次尝试，掐指一算，还是出门合适，毕竟它是一只深谋远虑的鸟。\n\n运行试验，我们发现，上述试验并不稳定，这是因为每次训练小鸟做出的随机决策不同，且“走路痛感”与“抵达快乐”很不悬殊，小鸟左右为难。\n\n因此，一个好的解决方案是：**别管那么多！我们不是希望小鸟抵达目的地吗？那就不要让它走路感到疼痛！**\n- 设置奖励为(-10, 10, 0)，我保证小鸟会“愿意出门”，并抵达目的地！\n\n这也提醒了我：**作为一个强化学习算法实践者，不应该过多干涉智能体决策！告诉智能体几个简单的规则，剩下的交给其自己学习。过于复杂的奖励机制，会出现意想不到的状况！**\n\n对于此问题，其实还可以另一个思路：调高撞墙的痛感。\n- 设置奖励为(-1000, 10, -2)，如次，小鸟便不敢撞墙：因为撞墙太疼了！！！\n- 并且，小鸟也不会“多走路”，因为多走路也有痛感。你会发现，如此得到的结果，小鸟总是能找到最优方案（最短的路径）。\n\n#### 6 基于函数逼近的方法\n\u003ca id='sec_6'\u003e\u003c/a\u003e\n\n[./ch_1/sec_6/](./ch_1/sec_6/)a\n\n本节前半部分最后一次使用“鸳鸯系统”，我发现：\n- 无论是正常向量状态表示，还是固定稀疏状态表示，书中都将 `epsilon = epsilon * 0.99` 在迭代中去掉；\n- 事实证明，不应该将其去掉，尤其是第一组情况。第一组情况其实就是上节的表格型 q-learning ；\n- 固定稀疏表示中，可以不加探索欲望的收敛（在这个环境中）。\n\n此外，还发现：\n- 固定稀疏中，鸟倾向于走直线；\n- 我认为这是因为固定稀疏矩阵中，抽取了特征，同一个 x 或同一个 y 对应的状态，其价值更趋同。\n\n本节后半部分：非线性函数逼近。\n\n书中没有给代码地址，我 Google 到作者应该是借鉴了这个：[https://github.com/yenchenlin/DeepLearningFlappyBird](https://github.com/yenchenlin/DeepLearningFlappyBird)\n- 我将这个项目写在了：[./ch_1/sec_6/flappy_bird/](./ch_1/sec_6/flappy_bird/)\n- - 我添加了手动操作体验游戏的部分，按 H 键可以煽动翅膀：[./ch_1/sec_6/flappy_bird/game/keyboard_agent.py](./ch_1/sec_6/flappy_bird/game/keyboard_agent.py)\n- - 书上是 tf 1 的代码，我使用 tf 2 重写，这个过程中参考了：[https://github.com/tomjur/TF2.0DQN](https://github.com/tomjur/TF2.0DQN)\n- `python -u \"d:\\GitHub\\rl\\Approachable-Reinforcement-Learning\\ch_1\\sec_6\\flappy_bird\\dqn_agent.py\"`以训练\n\n### AlphaZero 实战：五子棋\n\u003ca id='sec_13'\u003e\u003c/a\u003e\n\n代码在 [./AlphaZero](./AlphaZero) 。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiperliu%2Fapproachable-reinforcement-learning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiperliu%2Fapproachable-reinforcement-learning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiperliu%2Fapproachable-reinforcement-learning/lists"}