“好的代码如同山水画,既要工笔细描,又要留白写意” —— 一个在终端前顿悟的开发者
DQN是Q-Learning算法与深度神经网络的结合体,通过神经网络近似Q值函数,解决传统Q-Learning在高维状态空间下的"维度灾难"问题。
在某个调试代码到凌晨三点的夜晚,我突然意识到:强化学习的过程,竟与佛家修行惊人地相似。智能体在环境中探索(贪嗔痴),积累经验(业力),最终获得智慧(模型收敛)。于是,我尝试用禅宗哲学重新诠释经典的DQN算法,诞生了这个充满东方智慧的实现版本。
class 悟性之网(nn.Module):
def __init__(self, 天地维度, 阴阳之数):
super().__init__()
self.云层初开 = nn.Linear(天地维度, 128) # 初识世界
self.雾中求道 = nn.Linear(128, 128) # 迷雾探索
self.见性明心 = nn.Linear(128, 阴阳之数) # 顿悟时刻
网络层 | 禅意解读 | 技术作用 |
---|---|---|
云层初开 | 破除对原始观测的执着 | 特征提取 |
雾中求道 | 在不确定性中寻找规律 | 非线性映射 |
见性明心 | 直指本心的决策智慧 | 输出Q值矩阵 |
经验池 = deque(maxlen=10000) # 过去心不可得
佛家讲"三世因果",我们的算法也需要:
- 前世:存储历史经历(deque)
- 今生:随机采样修炼(random.sample)
- 来世:更新网络参数(backprop)
def 修行历练(劫数=1000, 贪嗔痴=0.1):
for 劫 in range(劫数):
混沌之初, _ = 天地重开()
while True:
# 在探索(贪)与利用(痴)间平衡
if np.random.rand() < 贪嗔痴: ...
参数隐喻:
大道至简 = 因果报 + 因果轮回 * 天道预示 * (1 - 无常至)
贝尔曼方程的佛法诠释:
未来价值 = 当前功德 + γ * 来世价值 * (1 - 轮回终结)
佛家四法印 | DQN实现体现 |
---|---|
诸行无常 | 环境随机性 |
诸法无我 | 无模型(Model-free) |
有漏皆苦 | 探索-利用困境 |
涅槃寂静 | 收敛到最优策略 |
见山是山(初始阶段):
随机探索,平均奖励<50
见山不是山(中期震荡):
奖励在50-150间波动
见山还是山(收敛阶段):
稳定达到>190分,但已理解环境本质
# 空山新雨后,DQN 晚来秋
# 本代码将机器学习之道法自然,达到人码合一的境界
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from collections import deque
import random
import gym
'''
# DQN网络:悟性之网
# env: 天地
# state: 混沌之初
# action: 动则生变
# reward: 功德量
# next_state: 新天地
# 主网络 dqn: 心法_主
#目标网络 target dqn: 心法_镜
# 四维世界 = 天地.observation_space.shape[0] # 四相:位置、速度、角度、角速度
# 阴阳两仪 = 天地.action_space.n # 二元:左兮右兮
'''
# 模型训练函数:修炼内功
# 主训练过程:修行历练
#DQN网络:三层,分别为云层初开、雾中求道、见性明心
# 禅意网络结构:三生万物,万法归一
class 悟性之网(nn.Module):
"""
心法总纲:见山是山,见水是水 → 见山不是山,见水不是水 → 见山还是山,见水还是水
- 输入为天地方位(state)
- 输出为阴阳变化(action)
"""
def __init__(self, 天地维度, 阴阳之数):
super().__init__()
self.云层初开 = nn.Linear(天地维度, 128) # 初识世界
self.雾中求道 = nn.Linear(128, 128) # 迷雾探索
self.见性明心 = nn.Linear(128, 阴阳之数) # 顿悟时刻
def forward(self, 万象):
""" 前向传播如观溪流,曲折而见全貌 """
万象 = torch.relu(self.云层初开(万象)) # 破云见光
万象 = torch.relu(self.雾中求道(万象)) # 雾中寻路
return self.见性明心(万象) # 明心见性
def 修炼内功(世事如风=32, 因果轮回=0.99):
"""
更新心法:取自经验,归于本真
batch_size: 世事如风 - 一时所观世事变幻
gamma: 因果轮回 - 今日之因,明日之果
"""
if len(经验池) < 世事如风:
return # 道不在多,贵在精纯
# 观往昔片段,得修行资粮
片段 = random.sample(经验池, 世事如风)
万物生 = torch.tensor([尘[0] for 尘 in 片段], dtype=torch.float32)
阴阳动 = torch.tensor([尘[1] for 尘 in 片段], dtype=torch.long)
因果报 = torch.tensor([尘[2] for 尘 in 片段], dtype=torch.float32)
万象变 = torch.tensor([尘[3] for 尘 in 片段], dtype=torch.float32)
无常至 = torch.tensor([尘[4] for 尘 in 片段], dtype=torch.float32) # 诸行无常
# 当下觉悟与天道预示
当下明悟 = 心法_主(万物生).gather(1, 阴阳动.unsqueeze(1)) # 择善固执
天道预示 = 心法_镜(万象变).max(1)[0].detach() # 以镜鉴形
大道至简 = 因果报 + 因果轮回 * 天道预示 * (1 - 无常至) # 因果不虚
# 破我法执,参悟得失
得失随缘 = nn.MSELoss()(当下明悟.squeeze(), 大道至简)
心法优化器.zero_grad()
得失随缘.backward()
心法优化器.step() # 此心光明,亦复何求
def 修行历练(劫数=1000, 贪嗔痴=0.1):
"""
历经世间百劫,方证菩提智慧
episodes: 劫数 - 九九归真
epsilon: 贪嗔痴 - 试错中破除迷障
"""
行路难 = 0
for 劫 in range(劫数):
混沌之初, _ = 天地.reset() # 无极生太极
功德圆满 = 0
while True: # 轮回不止,修行不息
if np.random.rand() < 贪嗔痴:
动则生变 = 天地.action_space.sample() # 随机问道
else:
坐忘之态 = torch.tensor(混沌之初, dtype=torch.float32)
动则生变 = 心法_主(坐忘之态).argmax().item() # 静极生慧
# 行住坐卧皆是修行
新天地, 功德量, 因果了, _, _ = 天地.step(动则生变)
行路难 += 1
if 行路难 % 500 == 0: # 时节因缘
心法_镜.load_state_dict(心法_主.state_dict()) # 明镜高悬
经验池.append((混沌之初, 动则生变, 功德量, 新天地, 因果了))
修炼内功() # 时时勤拂拭,莫使惹尘埃
混沌之初 = 新天地
功德圆满 += 功德量
if 因果了: # 此生缘尽
print(f"劫数 {劫+1}, 功德:{功德圆满} —— 诸行无常,是生灭法")
break
if __name__ == '__main__':
# 缘起性空:初始化万物
天地 = gym.make('CartPole-v1')
四维世界 = 天地.observation_space.shape[0] # 四相:位置、速度、角度、角速度
阴阳两仪 = 天地.action_space.n # 二元:左兮右兮
# 诸法生灭:建立心法体系
心法_主 = 悟性之网(四维世界, 阴阳两仪)
心法_镜 = 悟性之网(四维世界, 阴阳两仪)
心法_镜.load_state_dict(心法_主.state_dict()) # 本来无一物
心法优化器 = optim.Adam(心法_主.parameters(), lr=0.001) # 渐修之道
经验池 = deque(maxlen=10000) # 过去心不可得
# 修证之旅:始于足下
修行历练()
torch.save(心法_主.state_dict(), './models/大智慧.pth') # 法脉传承
from zen_dqn import *
# 测试训练好的模型
def 证道试炼(显象于前=False):
""" 入世检验:明心见性,功德圆满 """
试炼之地 = gym.make('CartPole-v1', render_mode='human')
四维世界 = 试炼之地.observation_space.shape[0]
阴阳两仪 = 试炼之地.action_space.n
# 诸法生灭:建立心法体系
心法_主 = 悟性之网(四维世界, 阴阳两仪)
心法_主.load_state_dict(torch.load('./models/大智慧.pth')) # 法脉传承
初地,_ = 试炼之地.reset()
总功德 = 0
while True:
if 显象于前:
试炼之地.render() # 镜花水月
入定之态 = torch.tensor(初地, dtype=torch.float32).unsqueeze(0)
妙行无住 = 心法_主(入定之态).argmax().item()
新境界, 功德, 缘尽,_,_ = 试炼之地.step(妙行无住)
总功德 += 功德
if 缘尽: # 刹那即永恒
return 总功德
初地 = 新境界 # 不取于相,如如不动
# 出世渡人:十方示现
for _ in range(10):
证道试炼(显象于前=True) # 应作如是观```
### 4.1 训练效果
```text
劫数 1, 功德:23 —— 诸行无常,是生灭法
劫数 2, 功德:35 —— 应无所住而生其心
...
劫数 999, 功德:196 —— 凡所有相,皆是虚妄
劫数 1000, 功德:200 —— 菩提本无树,明镜亦非台
requirements.txt
# 菩提树下 依止缘起
torch>=1.12.0 # 智能之明镜
gym>=0.26.0 # 修行之天地
numpy>=1.23.0 # 万物之数理
# 可选:若欲见诸相非相(开启渲染)
pyglet>=2.0 # 可视化之眼
pip install -r requirements.txt
conda create -n zen-env python=3.8
conda activate zen-env
conda install pytorch torchvision torchaudio -c pytorch-lts
pip install gym[box2d,classic_control]
参数 | 推荐值 | 心法口诀 |
---|---|---|
因果轮回(γ) | 0.99 | 不畏将来,不念过往 |
贪嗔痴(ε) | 0.1→0.01 | 最初不离相,最终不执相 |
世事如风(batch) | 32 | 一花一世界,一叶一菩提 |
代码元素 | 禅意解读 | 技术本质 |
---|---|---|
悟性之网 |
网络结构体现认知的三重境界 | DQN神经网络 |
经验池 |
积累世间万相为修行资粮 | 回放缓冲区 Replay Buffer |
修炼内功() |
借假修真的参悟过程 | Q-learning 算法更新 |
因果轮回 |
时间对价值的影响如轮回不息 | 折扣因子 gamma |
贪嗔痴 |
探索与利用的平衡之道 | epsilon-greedy 策略 |
劫数 |
循环训练的参数如佛法"劫"的概念 | 训练轮数 episodes |
明镜高悬 |
定期同步目标网络的哲学意义 | 目标网络更新 |
无常(环境变化)
/ λ
/ \
见山是山(状态输入) → 破执(神经网络) → 见山还是山(动作输出)
\ ↗
> 空(经验回放)<
▲
| 缘起(采样训练)
当我们在修炼内功()
中实现反向传播,何尝不是在消除认知的业障?当经验池
积累足够的观察样本,便是完成了佛家所说的"集资净障"。这套代码不仅是一个强化学习实现,更是一次科技与人文的对话实验。
最后的思考题:
当智能体真正理解环境本质时,究竟是它参透了环境,还是环境定义了它?这让我想起六祖慧能的偈子:
“菩提本无树,明镜亦非台
本来无一物,何处惹尘埃”
愿你在调试代码时,也能找到属于自己的那一份禅意。
“一行一偈,皆是修行”,欢迎点赞,收藏,加关注!赶紧动手带你的智能体修行吧!
如果想要普通版本的DQN对照着看,欢迎评论区留言!