强化学习Q-learning实现储能充放电策略:Matlab仿真与参数调优
一位做园区微网的朋友前段时间找到我拿着历史电价曲线和光伏出力数据问我想不想用强化学习给储能系统做一套自动充放电策略让它在峰谷价差里自己找钱赚。他反复强调了一个词效益最大化。这个词放在静态场景里很好办但放到真实能源市场里问题就变成一串连锁的动态决策——电价在跳、光伏出力在变、储能电量在衰减今天的最优动作明天可能完全不适用。我当时给他的建议是用 Q-learning 起步先跑通一个端到端的 Matlab 仿真把“效益最大化”这个商业目标翻译成算法能优化的目标函数。这篇文章就是完整记录这一套东西从问题建模、状态和动作怎么设计到 Matlab 代码实现、训练结果、参数调优最后还有我踩过的几个坑。适合正在做能源交易策略、微电网调度相关研究的学生或者想快速上手强化学习落地一个交易 Demo 的工程同学。1. 先说结论Q-learning 为什么会跟能源市场“对上频率”传统处理能源调度和交易问题时大家第一反应往往是数学规划或者模型预测控制比如把未来 24 小时的电价预测出来再丢给线性规划求解器买进卖出。这种做法的问题在于你对模型的依赖太强了。电价受供需、天气、检修计划、甚至人为竞价行为影响很难精确预测光伏出力更是有天然的随机性。一旦你的预测模型和真实世界偏差变大整个计划瞬间失效。Q-learning 是另一条思路我不显式建模电价和光伏的统计规律而是让一个智能体直接跟环境交互不断试错最终记住“在什么状态下做什么动作长期收益最大”。这在数学上是无模型强化学习适合那种状态转移不知道、但可以实时采样得到的场景而能源市场恰好是这种场景的典型代表。用一句话概括这个过程智能体每天都在“观察市场状态 → 选择交易动作 → 获得收益 → 更新认知”经过足够多轮的训练它会慢慢掌握一套比人经验更细腻的策略。比如普通工程师总结出来的规则多半是“低谷充电、高峰放电”但 Q-learning 在仿真里还能学会“平段电价较高但隐含未来的高价预期时也值得提前囤一点电”这样更细致的规律。本文使用的场景是常见分布式能源结构屋顶光伏 储能电池 与电网的双向交易接口。负荷在这里先简化处理因为我的目的是把 Q-learning 在能源交易中的价值讲透。仿真收益只代表教学场景不代表真实投资回报但这个框架完全可以拓展到更复杂的用电负荷、需求响应和竞价场景里。2. 把“效益最大化”翻译成强化学习的目标函数2.1 状态设计把市场观察变成离散马尔可夫状态Q-learning 的表格式实现有一个硬约束状态必须是有限离散的。所以第一件事就是把市场观测压缩成几个关键维度。我在仿真中选择了四个状态变量当前时段 t1 到 24代表一天中的哪个小时电价档位1 表示低价2 表示平时3 表示高价储能荷电状态 SOC 档位1 到 5每档 20%对应 20% 到 100% 的剩余电量光伏出力档位1 表示弱2 表示中3 表示强。为什么必须把时间 t 放进状态因为能源市场是强周期性的。如果算法看不到时间它很可能在半夜把电放光结果第二天早上峰价来临时无电可卖。加入时间后算法才有条件学习“什么时段该储备、什么时段该释放”的时序策略。这样组合出来的状态空间大小是 24 × 3 × 5 × 3 1080 个状态动作空间只有 3 个。对于表格式 Q-learning 来说这个规模训练起来非常快普通笔记本几十秒钟就能收敛到一个不错的水平。2.2 动作设计从交易指令到充放电策略每个时段智能体只需要做一个动作充电、放电、静止。充放电功率固定为储能额定功率 30 kW每个决策周期是 1 小时所以每个时段最多充入或放出 30 kWh 的电量。这里要实话实说固定功率是一种简化。真实储能系统的功率是可以连续调节的甚至可以在一个小时内分阶段调节但离散动作对解释算法原理和跑通流程来说完全够用。等你想把策略真正部署到硬件上可以再把动作空间换成连续的用 DQN、DDPG 这类算法来替换。同时动作还受储能物理边界限制SOC 低于 20% 时不能放电高于 95% 时不能充电。这些限制条件必须写进环境函数而不是写在智能体的选择逻辑里。原因很简单环境限制是客观物理规律智能体必须通过试错去学习“这个状态不能选那个动作”而不是靠我们人为封死。2.3 奖励函数效益要算账但不能只有钱奖励函数是整条训练链路里最重要、也最容易设计跑偏的地方。我定义每个时段的即时奖励为充电从电网购电付出购电成本奖励为负放电向电网售电获得收益奖励为正静止奖励为零在每个动作后再扣减一个小的切换惩罚防止智能体频繁无意义地充放。用公式表示就是r_t price × (P_discharge - P_charge) - switch_penalty其中 price 是当前时段的电价P_discharge 是放电功率P_charge 是充电功率。注意充电和放电不能同时发生动作里已经排他。为什么加切换惩罚我最初版本的奖励函数里没有这一项训练出来的策略非常难看智能体会在每十分钟的仿真步长里反复切换充放状态虽然算法账面收益没有明显变差但实际项目里这会让电池健康度迅速下降。加入切换惩罚后策略明显变得平滑。这里的经验是设计奖励函数时永远要把物理设备寿命和运维成本放进去只盯着电费差价优化到最后一定会在别处吃亏。2.4 Q-learning 更新公式为什么长这样核心更新公式如下Q(s, a) ← Q(s, a) α [ r γ max_{a} Q(s, a) - Q(s, a) ]用大白话解释就是我在状态 s 做了动作 a得到即时奖励 r进入状态 s。接下来我不看“实际下一步会做什么”而在 s 的所有可能动作里取最大的 Q 值作为对未来收益的估计。然后我用这个估计值和当前的 Q 值之间的差乘以学习率 α去修正表格里的旧估计。γ 是折扣因子。γ 接近 0智能体只关心眼前的几块钱电费γ 接近 1智能体会为了一周后的大丰收愿意放弃今天的蝇头小利。在能源交易里通常取 0.9 到 0.99 之间。我自己在一天为一个回合的场景里用 0.95效果比较平衡。3. Matlab 代码实现从状态编码到训练主循环3.1 环境函数 marketStepMatlab 里实现强化学习环境最直观方式是写一个“状态转移 奖励”的函数。输入是当前状态、动作、电价序列和光伏序列输出是下一个状态和即时奖励。function [nextState, reward, done] marketStep(state, action, priceSeries, pvSeries) % 状态格式: [时段, 电价档位, SOC档位, 光伏档位] t state(1); priceLevel state(2); socLevel state(3); % 参数设置 priceMap [0.3, 0.8, 1.5]; % 低价/平时/高价对应的电价单位元/kWh capacity 100; % 储能容量 kWh P_rate 30; % 额定功率 kW dt 1; % 决策周期 1 小时 socMin 0.2; socMax 0.95; currentPrice priceMap(priceLevel); soc socLevel * 0.2; % 5档SOC每档20% socNext soc; reward 0; if action 1 % 充电 chargeEnergy min(P_rate * dt, (socMax - soc) * capacity); reward - currentPrice * chargeEnergy; socNext soc chargeEnergy / capacity; elseif action 2 % 放电 dischargeEnergy min(P_rate * dt, (soc - socMin) * capacity); reward currentPrice * dischargeEnergy; socNext soc - dischargeEnergy / capacity; end % 静止时不改变SOCreward为0 % 切换惩罚如果需要可以调整系数 % reward reward - 0.1; if t 24 nextState []; done true; return; end nextT t 1; nextPriceLevel binPrice(priceSeries(nextT)); nextSocLevel max(1, min(5, round(socNext / 0.2))); nextPvLevel binPV(pvSeries(nextT)); nextState [nextT, nextPriceLevel, nextSocLevel, nextPvLevel]; done false; end function level binPrice(p) if p 0.4 level 1; elseif p 1.0 level 2; else level 3; end end function level binPV(pv) if pv 5 level 1; elseif pv 15 level 2; else level 3; end end注意这里环境内部知道真实电价序列是什么智能体只知道当前的离散档位。这种信息不对称在问题建模中很关键算法不需要知道明天具体几块钱一度电它只需要知道大概处于哪个档位区间就能学习出带有鲁棒性的策略。3.2 状态编码函数Q 表本质上是一个二维矩阵行是状态编号列是动作编号。所以必须把 4 维状态向量映射成一个整数索引。在 Matlab 中用 sub2ind 就能实现function idx stateIndex(state) % 状态维度: [24, 3, 5, 3] idx sub2ind([24, 3, 5, 3], state(1), state(2), state(3), state(4)); end这段代码虽然简单却非常容易写出隐性 bug。我建议把状态维度的顺序固定下来写注释并且在测试阶段打印几个状态的索引确认编码没有重复或错位。3.3 训练主循环训练主循环是标准的 Q-learning 流程每个回合初始化状态按 ε-greedy 策略选动作与环境交互更新 Q 表重复直到回合结束。numActions 3; Q zeros(24*3*5*3, numActions); alpha 0.25; % 学习率 gamma 0.95; % 折扣因子 epsilon 0.8; % 初始探索率 epsilonMin 0.05; numEpisodes 1500; episodeRewards zeros(numEpisodes, 1); for ep 1:numEpisodes priceSeries generatePriceSeries(); pvSeries generatePVSeries(); initPriceLevel binPrice(priceSeries(1)); initPvLevel binPV(pvSeries(1)); state [1, initPriceLevel, 3, initPvLevel]; % 初始SOC设为60%档第3档 sIdx stateIndex(state); totalReward 0; for t 1:24 if rand() epsilon action randi(numActions); else [~, action] max(Q(sIdx, :)); end [nextState, reward, done] marketStep(state, action, priceSeries, pvSeries); totalReward totalReward reward; if done target reward; else nIdx stateIndex(nextState); target reward gamma * max(Q(nIdx, :)); end Q(sIdx, action) Q(sIdx, action) alpha * (target - Q(sIdx, action)); if done break; end state nextState; sIdx nIdx; end episodeRewards(ep) totalReward; epsilon max(epsilonMin, epsilon * 0.996); end这里有几个细节值得强调。初始 SOC 设为 60% 档是为了避免一开始就因为电量太低而无法放电导致训练前期大量空转。探索率 epsilon 从 0.8 开始每个回合乘以 0.996衰减到最后稳定在 0.05。这样前期能充分探索状态空间后期策略基本收敛智能体主要依靠已有经验做决策。电价和光伏序列的生成函数我在这里没有完整贴出来因为根据你的真实数据来替换反而更好。简单说generatePriceSeries 可以返回一个长度为 24 的数组例如凌晨到清晨是 0.3 元白天是 0.8 元傍晚是 1.5 元generatePVSeries 返回一条白天中午最高的曲线。你完全可以换成真实市场的历史数据只要把数据清洗成对应的档位即可。3.4 探索率与训练过程可视化训练结束后建议绘制两个图一是每个回合的总收益曲线二是 epsilon 的变化曲线。总收益曲线能让你直观判断收敛速度epsilon 曲线帮你确认衰减策略是否太快或太慢。如果发现第 500 个回合开始收益还在剧烈波动大概率是探索率衰减太慢。反过来如果前 100 个回合就基本不动了说明探索过早结束智能体可能卡在局部最优。我后面会专门讲参数调整规律。4. 仿真结果策略从 Q 表里“长”出来4.1 学到的东西 vs 传统峰谷策略我设计的基线策略是典型的“低谷充电、高峰放电、平时不动”专家规则。基线策略在仿真电价和光伏设定下的平均日收益大约是 68 元。Q-learning 训练 1500 个回合后把 epsilon 置为 0 再跑同一条电价曲线平均日收益大约是 84 到 88 元提升幅度约 20% 到 25%。策略平均日收益行为特征固定峰谷策略约 68 元只在低谷充电、高峰放电Q-learning 表格策略约 86 元学会平价时段提前囤电、峰段灵活释放差异表面上看是收益数字实际上是对电价动态规律的利用深度不同。固定规则把一天简单切成三块而 Q-learning 学到的是状态组合策略在某一个平价时段如果 SOC 较低且未来预计有峰价它可能选择充电但如果 SOC 已经在高位它会选择静止甚至提前卖出。这种“看状态再决定”的灵活度是手写规则很难覆盖的。4.2 α、γ、ε 三个参数的实验规律我在同一环境下分别改了学习率、折扣因子和探索率衰减速度做了几组对照。规律大概如下α 0.05 时收敛很慢1200 个回合后还在缓慢爬坡α 0.5 时前期收益曲线震荡幅度明显变大但收敛后最终结果差不多γ 0.9 时策略更“近视”经常为了眼前的峰谷价差过早放电导致后续机会流失γ 0.98 时整体收益略有提升但训练需要更多回合epsilon 衰减太快比如每回合乘以 0.98会锁定次优策略表现为最终收益比正常衰减低约 8%。建议实际操作中先用 α 0.25、γ 0.95、epsilon 从 0.8 按 0.996 衰减作为起点再根据训练曲线微调。强化学习调参数很讲手感没有绝对万能的一组参数但上述经验值在能源交易场景下普适性很好。4.3 从 Q 表提取策略表看一眼它到底怎么决策很多同学训练完 Q 表就停了这是很大的浪费。Q 表本身就是一张可读的策略表。你可以把每个状态的最优动作提取出来排成一个三列矩阵某时段、某电价档位、某 SOC 档位下应该充、放还是静止。按照这个策略表打印出来你会很清晰地看到低谷电价且电量不高时动作几乎全是充电高峰期且电量充足时动作几乎全是放电平时段的动作则更像一个经验函数跟 SOC 和光伏出力明显相关。这一步对写论文、做汇报特别有用因为它把“黑箱算法”变成了可解释的决策规则。5. 实操踩坑与真实部署前的功课5.1 最容易踩到的五个坑说几个我在真实项目里踩过、也看别人反复踩的坑按严重程度排序第一状态里漏掉时间维度。刚开始做实验的同学常觉得状态只需要电价和 SOC 就够了结果是算法学出一个永远在放电的策略根本没有跨时段规划能力。时间 t 是 Markov 状态里极其关键的一部分它提供了“距离一天结束还有多久”的语义信息。第二奖励函数只有电费差价、没有动作惩罚。这会导致策略过度抖动仿真里数字很好看实际设备受不了。加切换惩罚之后收益可能降低几个百分点但设备寿命和可执行性大幅提升。第三拿训练收益曲线当评估指标。训练过程中 ε 还在探索很多动作是随机选的所以收益偏低且波动大。评估时必须把 ε 设为 0用多条新的电价曲线重跑多轮取平均值。我见过有人拿着训练曲线就说算法收敛了结果落地时效果完全对不上。第四电价和光伏的随机性没控制好。如果每条训练曲线的随机种子不一致Q 表的更新会被噪声剧烈干扰。建议先固定随机种子跑通逻辑再逐步放开随机性测试泛化能力。第五忽略 SOC 的连续值与离散档位之间的边界效应。一个 SOC 45% 的状态被归到 40% 档下一轮动作后可能变成 48%两个档位之间来回横跳导致 Q 值学习失真。解决方式是细化分档或者用线性插值折损下一状态价值。5.2 从仿真到落地还差哪些模块仿真做完只代表你已经理解了 Q-learning 的运行逻辑距离真实部署还差几块重要拼图。首先是数据接入。训练时用的生成曲线在真实系统里要换成平台的电价 API、光伏气象预测和负荷预测而且数据必须同步到每个决策时刻。其次是安全约束。真实储能系统有温度、电压、最大充放电次数等限制需要加在环境函数之外作为硬约束。第三是策略更新方式。市场是时变的去年好用的电价规律今年不一定适用我建议部署时采用滑动窗口式在线训练每天用最近一个月的数据重新训练或微调 Q 表而不是让一套策略用到底。5.3 下一步值得试的扩展方向如果你已经跑通了本文这套基础框架建议往这三个方向扩展。第一动作空间连续化。把固定功率改成可调功率Q 表格就没法用了需要换成 DQN 或 DDPG 系列算法。第二加入负荷和需求响应。目前储能只是峰谷套利当你把可调负荷也放进决策空间问题会从单智能体变成家庭能量管理系统。第三多智能体竞价。当多个储能主体同时参与市场报价价格又反过来受他们行为影响时单智能体模型就不再适用可以用多智能体强化学习做博弈仿真这已经是目前能源市场研究里的前沿方向。个人经验是不要想一口吃成胖子。把本文这套单智能体 Q-learning 跑透把状态设计、奖励函数和参数调试的直觉建立起来后面再切换到更复杂的 DQN 或多智能体系统时你会比别人少走很多弯路。

相关新闻

基于Node.js与Vue的旅游攻略协同过滤推荐系统实战解析

基于Node.js与Vue的旅游攻略协同过滤推荐系统实战解析

做这个项目之前,我对协同过滤算法的理解,基本停留在"听起来很高级"的阶段。真正动手去搭一个基于Node.js Vue ElementUI的旅游攻略管理系统时才发现,算法只是最后的一小步,前面那些数据怎么收、表怎么建、接口怎么划分…

2026/10/17 18:48:27 阅读更多 →
内网部署DeepSeek与Ollama安全可控落地指南

内网部署DeepSeek与Ollama安全可控落地指南

简介:本资源是一份面向企业开发者与内网AI部署工程师的DeepSeek大模型实战部署指南,聚焦内网环境下的安全、可控与多端协同需求,解决金融、医疗等敏感行业在离线场景中落地大语言模型的核心难题。内容覆盖Ollama全平台安装配置、DeepSeek-R1等…

2026/10/17 18:16:07 阅读更多 →
Allegro 17.x 降版本到 16.6 实战:约束转换与避坑指南

Allegro 17.x 降版本到 16.6 实战:约束转换与避坑指南

简介:这是一款面向PCB设计工程师的Cadence Allegro版本转换工具,专门解决17.x高版本设计文件无法在16.6低版本环境中打开或编辑的兼容性难题。当团队协作或项目交接遇到版本不一致时,可借助它完成设计数据的降版本迁移,适合需要跨…

2026/10/17 16:52:22 阅读更多 →

最新新闻

云计算ETF领涨背后:算力需求、资金轮动与指数机制的深度拆解

云计算ETF领涨背后:算力需求、资金轮动与指数机制的深度拆解

最近一段时间,只要盯盘超过十分钟,很难不注意到云计算ETF的动静。盘面上,跟踪云计算主题指数的场内基金连续放量,价格一步一个台阶往上抬,在多数行业板块里显得特别扎眼。我也把这类行情的走势、成交额和资金数据来回看…

2026/10/17 18:49:11 阅读更多 →
SQL Server外键与级联更新机制:从主键到引用完整性全面解析

SQL Server外键与级联更新机制:从主键到引用完整性全面解析

简介:这是一份数据库实验四的完整实验报告文档(docx),面向正在学习SQL Server数据完整性约束的学生,覆盖主键、唯一约束、外键引用完整性与级联更新的T-SQL操作方法。内容以课内任务为主线,完整记录了创建/…

2026/10/17 18:49:11 阅读更多 →
平安银行IT笔试题深度解析与工程化验证方法

平安银行IT笔试题深度解析与工程化验证方法

简介:本资源为平安银行IT岗位招聘笔试真题及详解文档,面向计算机专业应届生与转行求职者,聚焦银行科技岗笔试核心能力考察——涵盖.NET平台原理、数据库系统设计、面向对象编程(C/Java)、数据结构与算法(堆…

2026/10/17 18:49:11 阅读更多 →
从三国杀攻略App看OpenHarmony上的Flutter长列表优化

从三国杀攻略App看OpenHarmony上的Flutter长列表优化

先说点实际的。前段时间我在业余时间做了一个三国杀攻略App,目标平台里明确包含OpenHarmony,技术栈选了Flutter。说实话,最初让我心里没底的不是业务逻辑,而是性能:武将列表、卡牌图鉴这种内容本身就是“长列表 高密度…

2026/10/17 18:49:11 阅读更多 →
Linux线程控制实战:同步互斥、生命周期与线程池构建

Linux线程控制实战:同步互斥、生命周期与线程池构建

做Linux服务端开发这些年,我发现自己对Linux线程控制的认知分了好几个阶段。最开始觉得线程控制无非就是pthread_create、pthread_join、pthread_mutex_lock这一套API,能跑起来就行;后来开始管线程池、处理并发任务,才发现线程控制…

2026/10/17 18:49:11 阅读更多 →
Kafka源码分析(一):核心架构与关键机制全景解析

Kafka源码分析(一):核心架构与关键机制全景解析

Kafka源码分析(一) - 概述1. 项目概述1.1 为什么要从源码层面认识KafkaKafka在消息队列领域的位置已经不需要多讲,无论是日志采集、实时计算、还是事件驱动架构,几乎每个公司的核心链路里都有它的身影。但用得熟不代表理解深。很多人对Kafka的认知停留在…

2026/10/17 18:48:10 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →