当前位置: 首页 > news >正文

图解强化学习 |强化学习在自动加药系统上的尝试(在线更新,和模型微调)

🌞欢迎来到图解强化学习的世界
🌈博客主页:卿云阁

💌欢迎关注🎉点赞👍收藏⭐️留言📝

📆首发时间:🌹2026年4月12日🌹

✉️希望可以和大家一起完成进阶之路!

🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!


目录

初始化函数

加载历史缓冲区

保存在缓冲区

增加一条新的样本

微调模型

模拟运行

初始化函数

def __init__(self, trainer, processor, buffer_file, model_file, max_days, update_every):
self.trainer = trainer self.processor = processor

将之前训练好的(trainer)和(processor)移交给在线更新器。

self.buffer_file = buffer_file self.model_file = model_file

指定(缓冲区文件)和(模型文件)在硬盘上的位置。

self.update_every = update_every # 默认为 30 self.buffer = deque(maxlen=max_days) # 默认为 365

设定了每积攒30 天的数据才进行一次微调。deque 是双端队列,设置了 maxlen 后,当存入第

366 天的数据时,它会自动把第 1 天的数据给“吐”出来。

self._load()

在对象创建的一瞬间,立刻去硬盘里把之前保存的online_buffer.jsonl全部读进内存。


加载历史缓冲区

def _load(self): """加载历史缓冲区""" if os.path.exists(self.buffer_file): with open(self.buffer_file, 'r', encoding='utf-8') as f: for line in f: try: self.buffer.append(json.loads(line)) except: pass print(f"✓ 加载 {len(self.buffer)} 条历史样本")

假设你的buffer_file(即online_buffer.jsonl)在硬盘里长这个样子(只有 3 行):

{"date": "2025-03-01", "reward": 0.5, "action": 2} {"date": "2025-03-02", "reward": 0.8, "action": 1} {"date": "2025-03-03", "reward": -0.2, "action": 4}

self.buffer = deque(maxlen=2) (假设我们为了演示,记忆长度只设为 2)

读取第 1 行:

line = {"date": "2025-03-01", "reward": 0.5, "action": 2} 执行 append。

当前内存 buffer:[{"date": "3-01", ...}] (长度 1)

读取第 2 行:

line = {"date": "2025-03-02", "reward": 0.8, "action": 1} 执行 append。

当前内存 buffer:[{"date": "3-01", ...}, {"date": "3-02", ...}] (长度 2,已满)

读取第 3 行(关键点):

line = {"date": "2025-03-03", "reward": -0.2, "action": 4}\n

执行 append。

内存变化:因为 maxlen=2,队列会自动弹出最老的一行(3-01)。

最终内存 buffer:[{"date": "3-02", ...}, {"date": "3-03", ...}] (长度 2)

最后输出: ✓ 加载 2 条历史样本

self.buffer最后的样子如下:

deque([ {"date": "2025-01-01", "state": [...], "action": 2, ...}, {"date": "2025-01-02", "state": [...], "action": 1, ...}, ... ], maxlen=365)

保存在缓冲区

def _save(self): """保存缓冲区""" with open(self.buffer_file, 'w', encoding='utf-8') as f: for item in self.buffer: f.write(json.dumps(item, ensure_ascii=False) + '\n')

执行前,内存中的 self.buffer 状态:

条目 1:{"date": "2025-03-15", "reward": 0.5}

条目 2:{"date": "2025-03-16", "reward": 0.9}

硬盘上原本旧的文件内容:

{"date": "2024-03-14", "reward": 0.2} {"date": "2025-03-15", "reward": 0.5}

执行后,硬盘上的新文件内容:

{"date": "2025-03-15", "reward": 0.5} {"date": "2025-03-16", "reward": 0.9}

增加一条新的样本

def add_sample(self, date, state, pac_dose, eff_tp_next): """ 添加一条新样本 参数: date : 日期字符串 '2025-03-16' state : 状态字典 {inf_tp, inf_ph, inf_temp, flow_rate_10kt_d, eff_tp} pac_dose : 今日执行的PAC量 (kg/h) eff_tp_next : 次日出水TP (mg/L) """ # 计算奖励 prior = lookup_prior(self.processor.lookup, state['inf_tp'], state['inf_temp']) reward = compute_reward_causal(eff_tp_next, pac_dose, state['inf_tp'], prior, self.processor.pac_mean) # 归一化状态 s = self.processor.transform_state(state).tolist() s_next = self.processor.transform_state({**state, 'eff_tp': eff_tp_next}).tolist() # 动作索引 action = int(np.argmin(np.abs(PAC_ACTIONS - pac_dose))) prior_action = int(np.argmin(np.abs(PAC_ACTIONS - prior))) # 保存样本 sample = { "date": date, "state": s, "action": action, "reward": float(reward), "next_state": s_next, "done": 0, "prior_action": prior_action, "raw": {"pac": pac_dose, "eff_tp": eff_tp_next} } self.buffer.append(sample) self._save() # 判断是否微调 if len(self.buffer) % self.update_every == 0 and len(self.buffer) >= self.update_every: print(f"\n[{date}] 累计 {len(self.buffer)} 条样本,触发微调...") self.finetune() return {"微调": True, "奖励": round(reward, 3)} return {"微调": False, "奖励": round(reward, 3)}

date = "2025-03-16"

state = {"inf_tp": 3.0, "inf_ph": 7.0, "inf_temp": 20, "flow_rate_10kt_d": 10, "eff_tp": 0.25}

pac_dose = 15.8

eff_tp_next = 0.22

prior = lookup_prior(self.processor.lookup, state['inf_tp'], state['inf_temp']) reward = compute_reward_causal(eff_tp_next, pac_dose, state['inf_tp'], prior, self.processor.pac_mean)

prior = 14.0

reward = 0.85

# 归一化状态 s = self.processor.transform_state(state).tolist() s_next = self.processor.transform_state({**state, 'eff_tp': eff_tp_next}).tolist()

s = [0.2, -0.5, 0.1, 0.8, -0.2]

s_next = [0.2, -0.5, 0.1, 0.8, -0.4]

action = int(np.argmin(np.abs(PAC_ACTIONS - pac_dose))) prior_action = int(np.argmin(np.abs(PAC_ACTIONS - prior)))

实际动作索引 action:action = 4

先验动作索引 prior_action: prior_action = 3

# 保存样本 sample = { "date": date, "state": s, "action": action, "reward": float(reward), "next_state": s_next, "done": 0, "prior_action": prior_action, "raw": {"pac": pac_dose, "eff_tp": eff_tp_next} } self.buffer.append(sample) self._save()

构造 sample 字典

{ "date": "2025-03-16", "state": [0.2, -0.5, 0.1, 0.8, -0.2], "action": 4, "reward": 0.85, "next_state": [0.2, -0.5, 0.1, 0.8, -0.4], "prior_action": 3, ... }

执行 self.buffer.append(sample):将这条数据塞进 365 天的记忆队列。

执行 self._save():立刻把这条热乎的数据写进硬盘的 .jsonl 文件中,防止停电丢失。

len(self.buffer) 刚好达到了30条: 调用 self.finetune()

返回结果:{"微调": True, "奖励": 0.85}


微调模型

# 构建数据集 buf = list(self.buffer) dataset = { "states": np.array([b["state"] for b in buf], dtype=np.float32), "actions": np.array([b["action"] for b in buf], dtype=np.int64), "rewards": np.array([b["reward"] for b in buf], dtype=np.float32), "next_states": np.array([b["next_state"] for b in buf], dtype=np.float32), "dones": np.array([b["done"] for b in buf], dtype=np.float32), "prior_actions": np.array([b["prior_action"] for b in buf], dtype=np.int64), }

假设 buffer 里只有 2 天的数据:

内存中的 buf:

{"state": [0.1, 0.2], "action": 2, "reward": 0.8, ...}

{"state": [0.3, 0.4], "action": 1, "reward": 0.5, ...}

执行这段代码后,dataset 变成了:

dataset["states"] = [[0.1, 0.2], [0.3, 0.4]] (矩阵)

dataset["actions"] = [2, 1] (向量)

dataset["rewards"] = [0.8, 0.5] (向量)


模拟运行

Row 0 (今天 i=0): date=04-01, inf_tp=3.0, eff_tp=0.25, inf_temp=20

Row 1 (明天 i=1): date=04-02, inf_tp=3.2, eff_tp=0.21

today = df_test.iloc[i] tomorrow = df_test.iloc[i+1] state = {c: today[c] for c in CFG["state_cols"]}

state = {"inf_tp": 3.0, "eff_tp": 0.25, ...}

s_norm = processor.transform_state(state) prior = lookup_prior(processor.lookup, today['inf_tp'], today['inf_temp']) rec = trainer.recommend(s_norm, today['eff_tp'], prior) pac = rec["推荐PAC量"]

对当天的状态标准化处理得到s_norm

查询当天状态的prior

pac=模型给出的推荐的加药量

eff_tp_next = tomorrow['eff_tp']
# 添加样本 info = updater.add_sample( date=str(today['date'])[:10], state=state, pac_dose=pac, eff_tp_next=eff_tp_next )

http://www.jsqmd.com/news/631644/

相关文章:

  • AP3216_WE库详解:ALS/PS传感器驱动开发与嵌入式集成
  • 万字拆解 LLM 运行机制:Token、上下文与采样参数址
  • 隐私党狂喜!用LM Studio+7B小模型打造完全离线的AI写作助手(含CPU优化配置)
  • [AI/向量数据库/GUI] Attu : Milvus 的图形化与一体化管理工具艘
  • 【内存心法】别在单片机里用 malloc!撕碎“动态分配”的慢性毒药,论堆碎片的谋杀与“静态内存池”的永生法则
  • SpringCloud进阶--Sentinel 流量防卫兵扯
  • MCGS触摸屏常见故障排查指南
  • 你的SSH密钥可能已经过期了牧
  • OpenClaw部署教程|nanobot镜像内置systemctl服务模板,支持开机自启与依赖管理
  • STM32F103C8T6 + LCD1602:手把手教你做一个带闹钟的桌面电子钟(附完整代码和PCB)
  • 不同代际Intel CPU运行效果差异大吗_性能对比技巧【技巧】
  • DeepFlow Agent 故障排查指南:注册失败、协议解析、资源识别与配置方式赋
  • AI开发-python-langchain框架(--提取pdf中的图片 )婪
  • 4.12周报
  • .Acwing基础课第题-简单-区间和诺
  • C语言到底能干啥?我列举了8种经典案例
  • Kindle电子书封面修复终极指南:三步解决“暂无图片“问题
  • tinyCore:轻量级多核任务分发框架
  • 解决RK芯片RGB显示驱动常见问题:DTS配置与调试技巧
  • AI 时代的程序员:从“建造者”到“定义者”宋
  • DeOldify图像上色服务应对复杂背景:人物肖像与风景照的处理差异
  • paddlex 摄像头实时目标检测低配优化版项目源码(基于 PP-YOLOE + ONNX + 多线程 + 简易跟踪 + 可打包)
  • 行式存储(Row-based Storage)和列式存储(Column-base Storage)简介舷
  • 让我失眠3个月的嵌入式项目,对C语言的认知全推翻了
  • IEEE 1888 FIAP协议嵌入式实现指南
  • PX4 EKF2协方差矩阵‘负定’了怎么办?保姆级排查与数值稳定性修复指南
  • Gin+Vue全栈速成:10秒API生成器赋能前后端分离开发实战
  • 2026年北京润府深度解析:一个TOD综合体的多维价值审视 - 品牌推荐
  • FreeRTOS在ARM Cortex-M上的移植原理与工程实践
  • Kettle入门指南:从零搭建可视化ETL环境到数据转换实战