字节DAPO算法:改进DeepSeek的GRPO算法-解锁大规模LLM强化学习的新篇章(代码实现)
DAPO算法:解锁大规模LLM强化学习的新篇章
近年来,大规模语言模型(LLM)在推理任务上的表现令人瞩目,尤其是在数学竞赛(如AIME)和编程任务中,强化学习(RL)成为提升模型复杂推理能力的核心技术。然而,现有强化学习算法如PPO(Proximal Policy Optimization)和GRPO(Group Relative Policy Optimization)在应用于长链式思维(long-CoT)场景时,面临熵崩塌、训练不稳定和样本效率低下等问题。针对这些挑战,ByteDance Seed与清华大学AIR联合团队提出了Decoupled Clip and Dynamic sAmpling Policy Optimization(DAPO) 算法,并在2025年3月17日发布的论文中开源了其代码与数据集。本篇博客将为熟悉PPO和GRPO的深度学习与强化学习研究者详细介绍DAPO的创新点及其数学基础。
下文中图片来自于原论文:https://arxiv.org/pdf/2503.14476
DAPO的核心创新点
DAPO算法基于GRPO框架,针对长CoT推理场景进行了优化,提出了四项关键技术,显著提升了训练效率与性能。以下是其创新点:
-
Clip-Higher:解耦剪切范围,增强探索能力
在PPO和GRPO中,剪切范围(clip range)通常是对称的(如1-ε到1+ε),用于限制策略更新的信任区域。然而,这种对称剪切限制了低概率token的探索空间,导致熵崩塌(entropy collapse)。DAPO通过解耦上下剪切范围(ε_low和ε_high),提高ε_high的值,允许低概率token有更大的增长空间,从而提升策略多样性,防止过早确定化。 -
Dynamic Sampling:动态采样提升样本效率
在GRPO中,当某个问题的所有采样输出都正确(或都错误)时,优势值为零,导致梯度消失,降低了样本效率。DAPO引入动态采样策略,过滤掉准确率为0或1的样本,确保每个批次中保留具有有效梯度的样本,从而提高训练稳定性和效率。 -
Token-Level Policy Gradient Loss:针对长CoT的损失优化
GRPO采用样本级损失计算,先对每个样本内的token损失求均值,再跨样本平均。这种方法在长CoT场景中对长序列的token贡献分配不均,可能导致高质量长样本的学习不足,或低质量长样本(如重复或乱码)的惩罚不足。DAPO改为token级损失计算,直接对所有token的损失求平均,确保每个token对策略优化的贡献更均衡。 -
Overlong Reward Shaping:减少奖励噪声,稳定训练
长CoT任务中,超过最大长度的样本常被截断并赋予惩罚性奖励,这种做法可能因长度而非推理质量误罚合理样本,引入奖励噪声。DAPO提出“软超长惩罚”(Soft Overlong Punishment),通过长度感知的奖励整形机制,在一定范围内逐渐增加惩罚,避免对合理长样本的过度惩罚,提升训练稳定性。
这些创新使DAPO在AIME 2024数据集上基于Qwen2.5-32B模型取得了50分的成绩,超越了DeepSeek R1的47分,且仅使用了50%的训练步数。

DAPO的数学公式
DAPO的优化目标基于GRPO改进而来,其核心公式如下:
对于每个问题( q q q )及其答案( a a a ),DAPO从行为策略( π θ old \pi_{\theta_{\text{old}}} πθold )采样一组输出( { o i } i = 1 G \{o_i\}_{i=1}^G {oi}i=1G ),优化策略( π θ \pi_\theta πθ )的目标函数为:
J DAPO ( θ ) = E ( q , a ) ∼ D , { o i } i = 1 G ∼ π θ old ( ⋅ ∣ q ) [ 1 ∑ i = 1 G ∣ o i ∣ ∑ i = 1 G ∑ t = 1 ∣ o i ∣ min ( r i , t ( θ ) A ^ i , t , clip ( r i , t ( θ ) , 1 − ε low , 1 + ε high ) A ^ i , t ) ] \mathcal{J}_{\text{DAPO}}(\theta) = \mathbb{E}_{\substack{(q, a) \sim \mathcal{D}, \\ \{o_i\}_{i=1}^G \sim \pi_{\theta_{\text{old}}}(\cdot|q)}} \left[ \frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} \min \left( r_{i,t}(\theta) \hat{A}_{i,t}, \operatorname{clip}(r_{i,t}(\theta), 1-\varepsilon_{\text{low}}, 1+\varepsilon_{\text{high}}) \hat{A}_{i,t} \right) \right] JDAPO(θ)=E(q,a)∼D,{oi}i=1G∼πθold(⋅∣q) ∑i=1G∣oi∣1i=1∑Gt=1∑∣oi∣min(ri,t(θ)A^i,t,clip(ri,t(θ),1−εlow,1+εhigh)A^i,t)
约束条件(下文有详细解释):
0 < ∣ { o i ∣ is_equivalent ( a , o i ) } ∣ < G 0 < |\{o_i | \text{is\_equivalent}(a, o_i)\}| < G 0<∣{oi∣is_equivalent(a,oi)}∣<G
其中:
- ( r i , t ( θ ) = π θ ( o i , t ∣ q , o i , < t ) π θ old ( o i , t ∣ q , o i , < t ) r_{i,t}(\theta) = \frac{\pi_\theta(o_{i,t} | q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} | q, o_{i,<t})} ri,t(θ)=πθold(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t) ):重要性采样比率。
- ( A ^ i , t = R i − mean ( { R i } i = 1 G ) std ( { R i } i = 1 G ) \hat{A}_{i,t} = \frac{R_i - \text{mean}(\{R_i\}_{i=1}^G)}{\text{std}(\{R_i\}_{i=1}^G)} A^i,t=std({Ri}i=1G)Ri−mean({Ri}i=1G) ):组内归一化的优势估计。
- ( ε low , ε high \varepsilon_{\text{low}}, \varepsilon_{\text{high}} εlow,εhigh ):解耦的剪切范围,分别控制下限和上限。
奖励函数:
DAPO采用基于规则的奖励:
R ( y ^ , y ) = { 1 , if is_equivalent ( y ^ , y ) − 1 , otherwise R(\hat{y}, y) = \begin{cases} 1, & \text{if } \text{is\_equivalent}(\hat{y}, y) \\ -1, & \text{otherwise} \end{cases} R(y^,y)={1,−1,if is_equivalent(y^,y)otherwise
对于超长样本,引入长度感知的惩罚(下文有详细解释):
R length ( y ) = { 0 , ∣ y ∣ ≤ L max − L cache ( L max − L cache ) − ∣ y ∣ L cache , L max − L cache < ∣ y ∣ ≤ L max − 1 , L max < ∣ y ∣ R_{\text{length}}(y) = \begin{cases} 0, & |y| \leq L_{\max} - L_{\text{cache}} \\ \frac{(L_{\max} - L_{\text{cache}}) - |y|}{L_{\text{cache}}}, & L_{\max} - L_{\text{cache}} < |y| \leq L_{\max} \\ -1, & L_{\max} < |y| \end{cases} Rlength(y)=⎩ ⎨ ⎧0,Lcache(Lmax−Lcache)−∣y∣,−1,∣y∣≤Lmax−LcacheLmax−Lcache<∣y∣≤LmaxLmax<∣y∣
最终奖励为( R ( y ^ , y ) + R length ( y ^ ) R(\hat{y}, y) + R_{\text{length}}(\hat{y}) R(y^,y)+Rlength(y^) )。
具体算法流程:

与PPO和GRPO的对比
- PPO:PPO通过对称剪切和KL散度正则化确保训练稳定性,但在长CoT场景中易导致熵崩塌,且对探索能力不足。DAPO去除了KL项,解耦剪切范围,增强了探索性。
- GRPO:GRPO通过组内归一化优势估计简化了PPO,但样本级损失和固定采样策略限制了其在长序列任务中的表现。DAPO的token级损失和动态采样显著提升了性能。
开源与实践意义
DAPO不仅提供了算法,还开源了基于verl框架的训练代码和DAPO-Math-17K数据集(包含17K个数学问题及其整数答案)。这为研究者提供了可复现的工具,降低了进入大规模LLM RL的门槛。实验表明,从朴素GRPO的30分逐步优化至DAPO的50分,每项技术都贡献了显著提升(见论文Table 1)。

对于研究者而言,DAPO的开源系统是一个宝贵资源,可用于探索长CoT推理的更多可能性,如自验证和迭代优化行为的涌现。未来可进一步研究其在编程、定理证明等领域的应用。
结语
DAPO通过创新的剪切策略、动态采样、token级损失和奖励整形,解决了现有RL算法在长CoT场景中的瓶颈,为大规模LLM推理能力提升开辟了新路径。如果你对强化学习在LLM中的应用感兴趣,不妨访问DAPO项目页面,下载代码和数据集,亲自体验这一突破性算法的威力!
采样数量的约束公式解析
约束条件的数学表达
约束条件:
0 < ∣ { o i ∣ is_equivalent ( a , o i ) } ∣ < G 0 < |\{o_i | \text{is\_equivalent}(a, o_i)\}| < G 0<∣{oi∣is_equivalent(a,oi)}∣<G
- ( { o i } i = 1 G \{o_i\}_{i=1}^G {oi}i=1G ) 是对于某个问题 ( q q q ) 从行为策略 ( π θ old \pi_{\theta_{\text{old}}} πθold ) 中采样的 ( G G G ) 个输出。
- ( a a a ) 是问题的正确答案。
- ( is_equivalent ( a , o i ) \text{is\_equivalent}(a, o_i) is_equivalent(a,oi) ) 表示输出 ( o i o_i oi ) 是否与正确答案 ( a a a ) 等价(即是否正确)。
- ( ∣ { o i ∣ is_equivalent ( a , o i ) } ∣ |\{o_i | \text{is\_equivalent}(a, o_i)\}| ∣{oi∣is_equivalent(a,oi)}∣ ) 表示 ( G G G ) 个输出中正确答案的数量,记为 ( n correct n_{\text{correct}} ncorrect )。
这个约束的意思是:
- ( 0 < n correct 0 < n_{\text{correct}} 0<ncorrect ):至少有一个输出是正确的(不能全错)。
- ( n correct < G n_{\text{correct}} < G ncorrect<G ):至少有一个输出是错误的(不能全对)。
换句话说,对于每个问题 ( q q q ) 的采样输出组 ( { o i } i = 1 G \{o_i\}_{i=1}^G {oi}i=1G ),DAPO要求其中既有正确答案,也有错误答案,不能是全正确(准确率=1)或全错误(准确率=0)的情况。
文中论述的背景与问题
文中提到:
Existing RL algorithm suffers from the gradient-decreasing problem when some prompts have accuracy equal to 1 or 0. For example for GRPO, if all outputs ( { o i } i = 1 G \{o_i\}_{i=1}^G {oi}i=1G ) of a particular prompt are correct and receive the same reward 1, the resulting advantage for this group is zero.
在GRPO(或其他基于优势估计的RL算法)中,优势 ( A ^ i , t \hat{A}_{i,t} A^i,t ) 是通过组内归一化计算的:
A ^ i , t = R i − mean ( { R i } i = 1 G ) std ( { R i } i = 1 G ) \hat{A}_{i,t} = \frac{R_i - \text{mean}(\{R_i\}_{i=1}^G)}{\text{std}(\{R_i\}_{i=1}^G)} A^i,t=std({Ri}i=1G)Ri−mean({Ri}i=1G)
- 如果所有 ( o i o_i oi ) 都正确(准确率=1),则 ( R i = 1 R_i = 1 Ri=1 )(根据基于规则的奖励函数),此时 ( mean ( { R i } ) = 1 \text{mean}(\{R_i\}) = 1 mean({Ri})=1 ),( std ( { R i } ) = 0 \text{std}(\{R_i\}) = 0 std({Ri})=0 )(因为所有奖励相同,无方差),导致 ( A ^ i , t = 0 / 0 \hat{A}_{i,t} = 0/0 A^i,t=0/0 )(未定义,但实际实现中通常设为0)。
- 如果所有 ( o i o_i oi ) 都错误(准确率=0),则 ( R i = − 1 R_i = -1 Ri=−1 ),同样 ( mean ( { R i } ) = − 1 \text{mean}(\{R_i\}) = -1 mean({Ri})=−1 ),( std ( { R i } ) = 0 \text{std}(\{R_i\}) = 0 std({Ri})=0 ),( A ^ i , t = 0 \hat{A}_{i,t} = 0 A^i,t=0 )。
当优势 ( A ^ i , t = 0 \hat{A}_{i,t} = 0 A^i,t=0 ) 时,策略梯度更新为零(因为目标函数 ( J \mathcal{J} J ) 中乘以 ( A ^ i , t \hat{A}_{i,t} A^i,t )),这意味着该批次样本对模型训练没有贡献。这种“梯度消失”降低了样本效率,尤其当训练进行到后期,准确率=1或0的样本比例增加时,问题更加显著。
动态采样如何体现约束
文中提出的解决方案是“动态采样”(Dynamic Sampling):
To this end, we propose to over-sample and filter out prompts with the accuracy equal to 1 and 0 illustrated in Equation 11, leaving all prompts in the batch with effective gradients and keeping a consistent number of prompts. Before training, we keep sampling until the batch is fully filled with samples whose accuracy is neither 0 nor 1.
具体做法是:
- 对于每个问题 ( q q q ),从 ( π θ old \pi_{\theta_{\text{old}}} πθold ) 采样 ( G G G ) 个输出 ( { o i } i = 1 G \{o_i\}_{i=1}^G {oi}i=1G )。
- 计算准确率,即 ( ∣ { o i ∣ is_equivalent ( a , o i ) } ∣ / G |\{o_i | \text{is\_equivalent}(a, o_i)\}| / G ∣{oi∣is_equivalent(a,oi)}∣/G ):
- 如果准确率=1(全对),即 ( n correct = G n_{\text{correct}} = G ncorrect=G )。
- 如果准确率=0(全错),即 ( n correct = 0 n_{\text{correct}} = 0 ncorrect=0 )。
- 过滤掉这些“极端”情况,仅保留 ( 0 < n correct < G 0 < n_{\text{correct}} < G 0<ncorrect<G ) 的样本。
- 如果当前批次样本数不足(因过滤导致),继续过采样(over-sample),直到批次填满符合条件的样本。
这个过程直接对应约束条件 ( 0 < ∣ { o i ∣ is_equivalent ( a , o i ) } ∣ < G 0 < |\{o_i | \text{is\_equivalent}(a, o_i)\}| < G 0<∣{oi∣is_equivalent(a,oi)}∣<G )。它确保训练批次中的每个问题样本组:
- 不会全正确(避免 ( n correct = G n_{\text{correct}} = G ncorrect=G ))。
- 不会全错误(避免 ( n correct = 0 n_{\text{correct}} = 0 ncorrect=0 ))。
- 从而保证优势 ( A ^ i , t \hat{A}_{i,t} A^i,t ) 非零(因为 ( R i R_i Ri ) 有差异,( std ( { R i } ) > 0 \text{std}(\{R_i\}) > 0 std({Ri})>0 )),产生有效梯度。
为什么这样做有效?
- 避免梯度消失:通过确保 ( n correct n_{\text{correct}} ncorrect ) 介于0和( G G G )之间,奖励值 ( R i R_i Ri ) 有差异,优势 ( A ^ i , t \hat{A}_{i,t} A^i,t ) 非零,从而产生有效梯度。
- 保持批次一致性:动态采样维持了批次中有效样本的数量,避免因过滤导致训练不稳定。
- 提升效率:虽然需要过采样,但文中指出生成时间主要由长尾样本决定,动态采样的额外开销不大,且因梯度更有效,收敛更快(见Figure 6)。
总结
约束 ( 0 < ∣ { o i ∣ is_equivalent ( a , o i ) } ∣ < G 0 < |\{o_i | \text{is\_equivalent}(a, o_i)\}| < G 0<∣{oi∣is_equivalent(a,oi)}∣<G ) 是DAPO动态采样策略的数学表达,旨在解决GRPO中准确率极端(0或1)导致的梯度消失问题。通过过采样和过滤,DAPO确保每个批次样本组既有正确又有错误输出,从而维持训练的有效性和稳定性。这正是文中“keep sampling until the batch is fully filled with samples whose accuracy is neither 0 nor 1”的直接体现。
长度感知的惩罚”公式解析
详细解释这个“长度感知的惩罚”公式 ( R length ( y ) R_{\text{length}}(y) Rlength(y) ) 的设计逻辑,以及它如何体现 DAPO 的“Overlong Reward Shaping”策略,解决长链式思维(long-CoT)任务中的奖励噪声问题,并提升训练稳定性。
公式定义
惩罚函数 ( R length ( y ) R_{\text{length}}(y) Rlength(y) ) 是基于生成序列长度 ( ∣ y ∣ |y| ∣y∣ ) 的分段函数,定义如下:
R length ( y ) = { 0 , ∣ y ∣ ≤ L max − L cache ( L max − L cache ) − ∣ y ∣ L cache , L max − L cache < ∣ y ∣ ≤ L max − 1 , L max < ∣ y ∣ R_{\text{length}}(y) = \begin{cases} 0, & |y| \leq L_{\max} - L_{\text{cache}} \\ \frac{(L_{\max} - L_{\text{cache}}) - |y|}{L_{\text{cache}}}, & L_{\max} - L_{\text{cache}} < |y| \leq L_{\max} \\ -1, & L_{\max} < |y| \end{cases} Rlength(y)=⎩ ⎨ ⎧0,Lcache(Lmax−Lcache)−∣y∣,−1,∣y∣≤Lmax−LcacheLmax−Lcache<∣y∣≤LmaxLmax<∣y∣
- ( ∣ y ∣ |y| ∣y∣ ):生成序列的token数(长度)。
- ( L max L_{\max} Lmax ):允许的最大序列长度(例如论文中设为20,480 tokens)。
- ( L cache L_{\text{cache}} Lcache ):惩罚缓冲区长度(例如4,096 tokens),用于定义一个过渡区间。
- ( L max − L cache L_{\max} - L_{\text{cache}} Lmax−Lcache ):安全长度阈值(例如16,384 tokens),低于此长度不施加惩罚。
分段解释与惩罚逻辑
-
第一段:( ∣ y ∣ ≤ L max − L cache |y| \leq L_{\max} - L_{\text{cache}} ∣y∣≤Lmax−Lcache )
- 惩罚值:( R length ( y ) = 0 R_{\text{length}}(y) = 0 Rlength(y)=0 )
- 含义:当序列长度在安全范围内(不超过 ( L max − L cache L_{\max} - L_{\text{cache}} Lmax−Lcache )),不施加任何惩罚。
- 例子:若 ( L max = 20 , 480 L_{\max} = 20,480 Lmax=20,480 ),( L cache = 4 , 096 L_{\text{cache}} = 4,096 Lcache=4,096 ),则 ( L max − L cache = 16 , 384 L_{\max} - L_{\text{cache}} = 16,384 Lmax−Lcache=16,384 )。长度≤16,384的序列无惩罚。
- 目的:鼓励模型生成较短但完整的推理序列,避免因长度限制而过早惩罚合理输出。
-
第二段:( L max − L cache < ∣ y ∣ ≤ L max L_{\max} - L_{\text{cache}} < |y| \leq L_{\max} Lmax−Lcache<∣y∣≤Lmax )
- 惩罚值:( R length ( y ) = ( L max − L cache ) − ∣ y ∣ L cache R_{\text{length}}(y) = \frac{(L_{\max} - L_{\text{cache}}) - |y|}{L_{\text{cache}}} Rlength(y)=Lcache(Lmax−Lcache)−∣y∣ )
- 含义:在缓冲区范围内(16,384 < ( ∣ y ∣ |y| ∣y∣ ) ≤ 20,480),施加一个线性递减的惩罚,范围从0到-1。
- 当 ( ∣ y ∣ |y| ∣y∣ ) 刚超过 ( L max − L cache L_{\max} - L_{\text{cache}} Lmax−Lcache )(如16,385),惩罚接近0。
- 当 ( ∣ y ∣ |y| ∣y∣ ) 接近 ( L max L_{\max} Lmax )(如20,479),惩罚接近-1。
- 计算示例:
- ( ∣ y ∣ = 16 , 384 |y| = 16,384 ∣y∣=16,384 )(边界):( R length = 0 R_{\text{length}} = 0 Rlength=0 )
- ( ∣ y ∣ = 18 , 432 |y| = 18,432 ∣y∣=18,432 )(中间值):( R length = 16 , 384 − 18 , 432 4 , 096 = − 2 , 048 4 , 096 = − 0.5 R_{\text{length}} = \frac{16,384 - 18,432}{4,096} = \frac{-2,048}{4,096} = -0.5 Rlength=4,09616,384−18,432=4,096−2,048=−0.5 )
- ( ∣ y ∣ = 20 , 480 |y| = 20,480 ∣y∣=20,480 )(边界):( R length = 16 , 384 − 20 , 480 4 , 096 = − 4 , 096 4 , 096 = − 1 R_{\text{length}} = \frac{16,384 - 20,480}{4,096} = \frac{-4,096}{4,096} = -1 Rlength=4,09616,384−20,480=4,096−4,096=−1 )
- 目的:通过渐进式惩罚,区分“稍长”和“过长”的序列,避免“一刀切”惩罚合理但稍长的推理过程。
-
第三段:( L max < ∣ y ∣ L_{\max} < |y| Lmax<∣y∣ )
- 惩罚值:( R length ( y ) = − 1 R_{\text{length}}(y) = -1 Rlength(y)=−1 )
- 含义:当序列长度超过最大限制(( ∣ y ∣ > 20 , 480 |y| > 20,480 ∣y∣>20,480 )),施加最大惩罚-1,通常意味着序列被截断。
- 目的:强烈抑制过长且可能包含低质量内容(如重复或乱码)的序列。
与“Overlong Reward Shaping”的关系
问题背景
文中指出:
长CoT任务中,超过最大长度的样本常被截断并赋予惩罚性奖励,这种做法可能因长度而非推理质量误罚合理样本,引入奖励噪声。
在传统RL中,超长序列常被直接截断并赋予固定惩罚(如-1),但这存在问题:
- 奖励噪声:一个推理过程可能是正确的,但因长度超出 ( L max L_{\max} Lmax ) 而被惩罚,导致模型无法区分“推理错误”和“长度过长”。
- 训练不稳定:这种“一刀切”惩罚可能误导模型,抑制其探索复杂推理所需的较长序列。
DAPO的解决方案
DAPO提出“软超长惩罚”(Soft Overlong Punishment),通过 ( R length ( y ) R_{\text{length}}(y) Rlength(y) ) 实现“长度感知的奖励整形”:
- 渐进惩罚:
- 在缓冲区 ( [ L max − L cache , L max ] [L_{\max} - L_{\text{cache}}, L_{\max}] [Lmax−Lcache,Lmax] ) 内,惩罚随长度线性增加,从0过渡到-1。
- 这避免了突然施加最大惩罚,保留了对稍长但合理序列的容忍度。
- 减少噪声:
- 通过区分长度范围,模型能更好地学习“推理质量”与“长度控制”之间的平衡,而不是仅仅因长度受罚。
- 稳定训练:
- 文中提到,先尝试“Overlong Filtering”(屏蔽超长样本的损失),发现能稳定训练。而“软超长惩罚”进一步优化,通过平滑的惩罚曲线减少突变,确保梯度更新更平稳(见Figure 5)。

最终奖励为:
R ( y ^ , y ) = R correctness ( y ^ , y ) + R length ( y ^ ) R(\hat{y}, y) = R_{\text{correctness}}(\hat{y}, y) + R_{\text{length}}(\hat{y}) R(y^,y)=Rcorrectness(y^,y)+Rlength(y^)
其中 ( R correctness ( y ^ , y ) = 1 R_{\text{correctness}}(\hat{y}, y) = 1 Rcorrectness(y^,y)=1 )(正确)或-1(错误),加上长度惩罚后,综合反映推理质量和长度控制。
设计意图与效果
- 鼓励适度长度的复杂推理:
- 长CoT任务需要足够长的序列来表达完整推理。缓冲区 ( L cache L_{\text{cache}} Lcache ) 提供了一个“宽容区间”,允许模型探索复杂推理而不立即受罚。
- 抑制无意义的过长输出:
- 超长序列常包含低质量内容(如重复或乱码)。当 ( ∣ y ∣ > L max |y| > L_{\max} ∣y∣>Lmax ) 时,施加-1惩罚,明确抑制这种行为。
- 平滑过渡,减少震荡:
- 线性惩罚避免了奖励值的剧烈跳变,使模型在训练中逐渐适应长度控制,增强稳定性。
文中实验表明(Table 1),从“Overlong Filtering”(36分)到“Soft Overlong Punishment”(41分),这一策略提升了AIME 2024的表现,验证了其有效性。
总结
( R length ( y ) R_{\text{length}}(y) Rlength(y) ) 通过分段设计实现了“软超长惩罚”,在安全长度内不惩罚、在缓冲区内渐进惩罚、超出最大长度时强惩罚。这种长度感知的奖励整形解决了传统“一刀切”惩罚引入的噪声问题,允许模型在长CoT任务中探索复杂推理,同时抑制过长低质输出,从而提升训练稳定性和性能。这正是 DAPO“Overlong Reward Shaping”创新点的数学体现。
token级策略梯度损失解释
详细解释 DAPO 中“Token-Level Policy Gradient Loss”(token级策略梯度损失)与 GRPO 中“样本级损失”(sample-level loss)的区别,分析它们在损失函数中的体现,并提供可能的代码实现差异,帮助读者理解这一创新点。
背景与问题
在强化学习(RL)中,策略梯度损失的目标是优化策略 ( π θ \pi_\theta πθ ) 以最大化期望奖励。GRPO 和 DAPO 都基于 clipped PPO 的框架,但对损失的计算方式有关键差异,尤其在长链式思维(long-CoT)场景中,这种差异影响了对长序列的处理。
GRPO 的样本级损失
GRPO(Group Relative Policy Optimization)采用“样本级”损失计算方式:
- 对于每个问题 ( q q q ),采样一组 ( G G G ) 个输出 ( { o i } i = 1 G \{o_i\}_{i=1}^G {oi}i=1G )。
- 对每个输出 ( o i o_i oi )(一个序列),计算其所有 token 的损失均值。
- 再对 ( G G G ) 个样本的损失均值取平均,得到最终损失。
其目标函数为:
J GRPO ( θ ) = E ( q , a ) ∼ D , { o i } i = 1 G ∼ π θ old ( ⋅ ∣ q ) [ 1 G ∑ i = 1 G 1 ∣ o i ∣ ∑ t = 1 ∣ o i ∣ min ( r i , t ( θ ) A ^ i , t , clip ( r i , t ( θ ) , 1 − ε , 1 + ε ) A ^ i , t ) − β D KL ( π θ ∥ π ref ) ] \mathcal{J}_{\text{GRPO}}(\theta) = \mathbb{E}_{(q, a) \sim \mathcal{D}, \{o_i\}_{i=1}^G \sim \pi_{\theta_{\text{old}}}(\cdot|q)} \left[ \frac{1}{G} \sum_{i=1}^G \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} \min \left( r_{i,t}(\theta) \hat{A}_{i,t}, \operatorname{clip}(r_{i,t}(\theta), 1-\varepsilon, 1+\varepsilon) \hat{A}_{i,t} \right) - \beta D_{\text{KL}}(\pi_\theta \| \pi_{\text{ref}}) \right] JGRPO(θ)=E(q,a)∼D,{oi}i=1G∼πθold(⋅∣q) G1i=1∑G∣oi∣1t=1∑∣oi∣min(ri,t(θ)A^i,t,clip(ri,t(θ),1−ε,1+ε)A^i,t)−βDKL(πθ∥πref)
- ( r i , t ( θ ) = π θ ( o i , t ∣ q , o i , < t ) π θ old ( o i , t ∣ q , o i , < t ) r_{i,t}(\theta) = \frac{\pi_\theta(o_{i,t} | q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} | q, o_{i,<t})} ri,t(θ)=πθold(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t) ):重要性采样比率。
- ( A ^ i , t \hat{A}_{i,t} A^i,t ):优势估计。
- ( ∣ o i ∣ |o_i| ∣oi∣ ):第 ( i i i ) 个样本的 token 数。
关键点:
- 内层求和 ( 1 ∣ o i ∣ ∑ t = 1 ∣ o i ∣ \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} ∣oi∣1∑t=1∣oi∣ ) 先对每个样本的 token 损失取平均,得到样本 ( o i o_i oi ) 的平均损失。
- 外层求和 ( 1 G ∑ i = 1 G \frac{1}{G} \sum_{i=1}^G G1∑i=1G ) 再对 ( G G G ) 个样本的平均损失取均值。
- 结果:每个样本对总损失的贡献是等权重的(权重为 ( 1 G \frac{1}{G} G1 )),而不考虑样本长度 ( ∣ o i ∣ |o_i| ∣oi∣ ) 的差异。
问题:
- 在长CoT场景中,样本长度 ( ∣ o i ∣ |o_i| ∣oi∣ ) 差异很大(短则几十token,长则上万token)。
- 长样本的每个 token 对损失的贡献被稀释(因为除以 ( ∣ o i ∣ |o_i| ∣oi∣ )),可能导致:
- 高质量长样本(包含复杂推理)的学习不足。
- 低质量长样本(如重复或乱码)的惩罚不足(见 Figure 4a 和 4b 中的熵和长度异常增加)。
DAPO 的 Token-Level 损失
DAPO 提出“token级”损失计算,直接对所有 token 的损失取平均,而不先对每个样本内取均值。其目标函数为:
J DAPO ( θ ) = E ( q , a ) ∼ D , { o i } i = 1 G ∼ π θ old ( ⋅ ∣ q ) [ 1 ∑ i = 1 G ∣ o i ∣ ∑ i = 1 G ∑ t = 1 ∣ o i ∣ min ( r i , t ( θ ) A ^ i , t , clip ( r i , t ( θ ) , 1 − ε low , 1 + ε high ) A ^ i , t ) ] \mathcal{J}_{\text{DAPO}}(\theta) = \mathbb{E}_{(q, a) \sim \mathcal{D}, \{o_i\}_{i=1}^G \sim \pi_{\theta_{\text{old}}}(\cdot|q)} \left[ \frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} \min \left( r_{i,t}(\theta) \hat{A}_{i,t}, \operatorname{clip}(r_{i,t}(\theta), 1-\varepsilon_{\text{low}}, 1+\varepsilon_{\text{high}}) \hat{A}_{i,t} \right) \right] JDAPO(θ)=E(q,a)∼D,{oi}i=1G∼πθold(⋅∣q) ∑i=1G∣oi∣1i=1∑Gt=1∑∣oi∣min(ri,t(θ)A^i,t,clip(ri,t(θ),1−εlow,1+εhigh)A^i,t)
关键点:
- 总 token 数 ( N = ∑ i = 1 G ∣ o i ∣ N = \sum_{i=1}^G |o_i| N=∑i=1G∣oi∣ ) 是所有样本 token 的总数。
- 双重求和 ( ∑ i = 1 G ∑ t = 1 ∣ o i ∣ \sum_{i=1}^G \sum_{t=1}^{|o_i|} ∑i=1G∑t=1∣oi∣ ) 直接累加所有 token 的损失,然后除以总 token 数 ( N N N )。
- 结果:每个 token 对总损失的贡献是均等的(权重为 ( 1 N \frac{1}{N} N1 )),与样本长度无关。
改进:
- 长样本的 token 不再被稀释,每个 token 都有平等的优化权重。
- 高质量长样本的复杂推理模式能被充分学习。
- 低质量长样本的冗余或错误模式会被更强惩罚(因为不除以 ( ∣ o i ∣ |o_i| ∣oi∣ )),抑制熵和长度的不健康增长。
损失函数中的体现
GRPO(样本级)
J GRPO = 1 G ∑ i = 1 G [ 1 ∣ o i ∣ ∑ t = 1 ∣ o i ∣ L i , t ] \mathcal{J}_{\text{GRPO}} = \frac{1}{G} \sum_{i=1}^G \left[ \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} L_{i,t} \right] JGRPO=G1i=1∑G ∣oi∣1t=1∑∣oi∣Li,t
- ( L i , t = min ( r i , t ( θ ) A ^ i , t , clip ( r i , t ( θ ) , 1 − ε , 1 + ε ) A ^ i , t ) L_{i,t} = \min \left( r_{i,t}(\theta) \hat{A}_{i,t}, \operatorname{clip}(r_{i,t}(\theta), 1-\varepsilon, 1+\varepsilon) \hat{A}_{i,t} \right) Li,t=min(ri,t(θ)A^i,t,clip(ri,t(θ),1−ε,1+ε)A^i,t) ) 是第 ( i i i ) 个样本第 ( t t t ) 个 token 的损失。
- 先计算每个样本的平均损失 ( 1 ∣ o i ∣ ∑ t = 1 ∣ o i ∣ L i , t \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} L_{i,t} ∣oi∣1∑t=1∣oi∣Li,t ),再平均 ( G G G ) 个样本。
DAPO(token级)
J DAPO = 1 ∑ i = 1 G ∣ o i ∣ ∑ i = 1 G ∑ t = 1 ∣ o i ∣ L i , t \mathcal{J}_{\text{DAPO}} = \frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} L_{i,t} JDAPO=∑i=1G∣oi∣1i=1∑Gt=1∑∣oi∣Li,t
- 直接对所有 ( N = ∑ i = 1 G ∣ o i ∣ N = \sum_{i=1}^G |o_i| N=∑i=1G∣oi∣ ) 个 token 的损失 ( L i , t L_{i,t} Li,t ) 求和,然后取平均。
- 没有样本内均值这一步,所有 token 被平等对待。
数学差异:
- GRPO:两步平均,先样本内(除以 ( ∣ o i ∣ |o_i| ∣oi∣ )),再样本间(除以 ( G G G ))。
- DAPO:一步平均,直接除以总 token 数 ( N )。
代码实现差异(伪代码)
假设使用 PyTorch 实现,以下是 GRPO 和 DAPO 损失计算的伪代码对比:
GRPO(样本级损失)
import torch# 输入:logits_new(新策略概率),logits_old(旧策略概率),advantages(优势估计),epsilon=0.2
def compute_grpo_loss(logits_new, logits_old, advantages, epsilon):batch_size = len(logits_new) # G 个样本total_loss = 0for i in range(batch_size): # 遍历每个样本# 计算重要性采样比率ratio = torch.exp(logits_new[i] - logits_old[i]) # shape: [|o_i|]# 优势adv = advantages[i] # shape: [|o_i|]# PPO clipped 损失surr1 = ratio * advsurr2 = torch.clamp(ratio, 1-epsilon, 1+epsilon) * advloss_per_token = torch.min(surr1, surr2) # shape: [|o_i|]# 样本内平均sample_loss = loss_per_token.mean() # 除以 |o_i|total_loss += sample_loss# 样本间平均final_loss = total_loss / batch_size # 除以 Greturn -final_loss # 最大化目标,负号转为损失
DAPO(token级损失)
import torch# 输入同上,epsilon_low=0.2, epsilon_high=0.28
def compute_dapo_loss(logits_new, logits_old, advantages, epsilon_low, epsilon_high):# 将所有样本的 token 展平logits_new_flat = torch.cat(logits_new, dim=0) # shape: [N]logits_old_flat = torch.cat(logits_old, dim=0) # shape: [N]advantages_flat = torch.cat(advantages, dim=0) # shape: [N]total_tokens = logits_new_flat.size(0) # N = sum(|o_i|)# 计算重要性采样比率ratio = torch.exp(logits_new_flat - logits_old_flat)# PPO clipped 损失(解耦 clip)surr1 = ratio * advantages_flatsurr2 = torch.clamp(ratio, 1-epsilon_low, 1+epsilon_high) * advantages_flatloss_per_token = torch.min(surr1, surr2) # shape: [N]# 直接对所有 token 平均final_loss = loss_per_token.mean() # 除以 Nreturn -final_loss # 最大化目标
代码差异:
- 数据处理:
- GRPO:逐样本计算损失,保持样本维度分离。
- DAPO:将所有样本的 token 展平(
torch.cat),统一处理。
- 平均方式:
- GRPO:先样本内均值(
loss_per_token.mean()),再跨样本均值(total_loss / batch_size)。 - DAPO:一次性对所有 token 均值(
loss_per_token.mean())。
- GRPO:先样本内均值(
- Clip 参数:
- GRPO:对称 clip(
1-epsilon, 1+epsilon)。 - DAPO:解耦 clip(
1-epsilon_low, 1+epsilon_high),但这是另一创新点。
- GRPO:对称 clip(
效果与意义
- 均衡贡献:DAPO 确保长样本的每个 token 都有同等权重,避免 GRPO 中长样本贡献被稀释的问题。
- 实验验证:Table 1 显示,添加 token-level loss 从 41 分提升到 42 分,且文中提到它增强了训练稳定性(健康控制长度增长,见 Figure 4)。

代码实现
以下是一个简化的 DAPO(Decoupled Clip and Dynamic sAmpling Policy Optimization)算法的 PyTorch 实现,包括训练代码和测试代码。由于 DAPO 是针对大型语言模型(LLM)的强化学习算法,完整实现需要依赖特定的 LLM(如 Qwen2.5-32B)和数据集(如 DAPO-Math-17K)。这里我将提供一个可运行的简化版本,使用一个小型 Transformer 模型和模拟数学问题数据集,展示 DAPO 的核心思想(Clip-Higher、Dynamic Sampling、Token-Level Loss、Overlong Reward Shaping)。你可以根据需要扩展到真实场景。
环境与依赖
- Python 3.8+
- PyTorch 1.12+
- 安装依赖:
pip install torch numpy transformers
完整代码
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from transformers import GPT2Model, GPT2Config# 超参数
BATCH_SIZE = 4
G = 4 # 每问题采样数
MAX_LENGTH = 20 # 最大长度
CACHE_LENGTH = 5 # 缓冲区长度
EPSILON_LOW = 0.2
EPSILON_HIGH = 0.28
LEARNING_RATE = 1e-4
NUM_EPOCHS = 10# 模拟数学问题数据集(问题和答案)
dataset = [("2 + 3 = ?", 5),("4 * 2 = ?", 8),("10 - 7 = ?", 3),("6 / 2 = ?", 3),
]# 简单 Transformer 模型
class SimpleTransformer(nn.Module):def __init__(self, vocab_size=10, d_model=64, nhead=2, num_layers=2):super().__init__()config = GPT2Config(vocab_size=vocab_size, n_embd=d_model, n_head=nhead, n_layer=num_layers)self.model = GPT2Model(config)self.fc = nn.Linear(d_model, vocab_size)def forward(self, input_ids):outputs = self.model(input_ids=input_ids)logits = self.fc(outputs.last_hidden_state)return logitsdef generate(self, input_ids, max_length):for _ in range(max_length - input_ids.size(1)):logits = self.forward(input_ids)next_token = torch.argmax(logits[:, -1, :], dim=-1, keepdim=True)input_ids = torch.cat([input_ids, next_token], dim=1)return input_ids# 奖励函数(基于规则 + 长度惩罚)
def compute_reward(output, target, max_length, cache_length):# 假设输出最后一个 token 是答案pred = output[:, -1].item()correctness = 1 if pred == target else -1length = output.size(1)l_max = max_lengthl_cache = cache_lengthif length <= l_max - l_cache:length_penalty = 0elif l_max - l_cache < length <= l_max:length_penalty = ((l_max - l_cache) - length) / l_cacheelse:length_penalty = -1return correctness + length_penalty# DAPO 损失计算
def compute_dapo_loss(logits_new, logits_old, advantages, actions, epsilon_low, epsilon_high):# 计算重要性采样比率probs_new = torch.softmax(logits_new, dim=-1)probs_old = torch.softmax(logits_old, dim=-1)action_probs_new = probs_new.gather(-1, actions.unsqueeze(-1)).squeeze(-1)action_probs_old = probs_old.gather(-1, actions.unsqueeze(-1)).squeeze(-1)ratio = action_probs_new / (action_probs_old + 1e-8)# Clipped 损失surr1 = ratio * advantagessurr2 = torch.clamp(ratio, 1 - epsilon_low, 1 + epsilon_high) * advantagesloss = torch.min(surr1, surr2)return -loss.mean() # Token-level 平均,最大化目标# 动态采样
def dynamic_sampling(model, question_ids, target, G, max_length, cache_length):samples = []rewards = []while len(samples) < G:output = model.generate(question_ids, max_length)reward = compute_reward(output, target, max_length, cache_length)samples.append(output)rewards.append(reward)# 计算组内准确率correct_count = sum(1 for r in rewards if r > 0) # 简单假设 r > 0 表示正确if 0 < correct_count < G: # 满足动态采样约束return samples, rewardsreturn None, None # 重新采样# 训练函数
def train_dapo():device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = SimpleTransformer().to(device)old_model = SimpleTransformer().to(device)optimizer = optim.AdamW(model.parameters(), lr=LEARNING_RATE)for epoch in range(NUM_EPOCHS):total_loss = 0for question, target in dataset:# 模拟输入(数字转 token)question_ids = torch.tensor([[int(c) for c in question if c.isdigit()]], dtype=torch.long).to(device)# 动态采样samples, rewards = dynamic_sampling(model, question_ids, target, G, MAX_LENGTH, CACHE_LENGTH)if samples is None:continue# 更新旧模型old_model.load_state_dict(model.state_dict())old_model.eval()# 计算优势rewards = torch.tensor(rewards, dtype=torch.float, device=device)advantages = (rewards - rewards.mean()) / (rewards.std() + 1e-8)# 前向传播all_logits_new = []all_logits_old = []all_actions = []for i, output in enumerate(samples):input_ids = question_idslogits_new = model(input_ids)logits_old = old_model(input_ids)actions = output[:, 1:] # 假设第一个 token 是输入all_logits_new.append(logits_new[:, :-1, :])all_logits_old.append(logits_old[:, :-1, :])all_actions.append(actions)# 展平所有 tokenlogits_new_flat = torch.cat(all_logits_new, dim=1)logits_old_flat = torch.cat(all_logits_old, dim=1)actions_flat = torch.cat(all_actions, dim=1)advantages_flat = advantages.repeat_interleave(actions_flat.size(1)).view(-1)# 计算损失optimizer.zero_grad()loss = compute_dapo_loss(logits_new_flat, logits_old_flat, advantages_flat, actions_flat, EPSILON_LOW, EPSILON_HIGH)loss.backward()optimizer.step()total_loss += loss.item()print(f"Epoch {epoch+1}/{NUM_EPOCHS}, Loss: {total_loss:.4f}")# 测试函数
def test_dapo():device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = SimpleTransformer().to(device)model.eval()correct = 0total = len(dataset)with torch.no_grad():for question, target in dataset:question_ids = torch.tensor([[int(c) for c in question if c.isdigit()]], dtype=torch.long).to(device)output = model.generate(question_ids, MAX_LENGTH)pred = output[:, -1].item()print(f"Question: {question}, Predicted: {pred}, Target: {target}")if pred == target:correct += 1accuracy = correct / totalprint(f"Test Accuracy: {accuracy:.4f}")# 主程序
if __name__ == "__main__":print("Training DAPO...")train_dapo()print("\nTesting DAPO...")test_dapo()
代码说明
1. 模型与数据集
- 模型:使用一个简化的 Transformer(基于 GPT2),词汇表大小设为 10(0-9 的数字),模拟数学问题的生成。
- 数据集:模拟 4 个简单数学问题,答案为整数。
2. DAPO 核心组件
- Clip-Higher:在
compute_dapo_loss中使用解耦的epsilon_low和epsilon_high。 - Dynamic Sampling:在
dynamic_sampling中实现,确保 ( 0 < n correct < G 0 < n_{\text{correct}} < G 0<ncorrect<G )。 - Token-Level Loss:在
compute_dapo_loss中,所有 token 的损失直接展平并平均。 - Overlong Reward Shaping:在
compute_reward中实现长度感知的惩罚。
3. 训练流程
- 每个 epoch 遍历数据集。
- 对每个问题采样 ( G G G ) 个输出,过滤不符合动态采样条件的样本。
- 计算 token 级损失并更新模型。
4. 测试流程
- 对每个问题生成一个答案,检查准确率。
运行结果
运行代码后,你会看到类似以下输出:
Training DAPO...
Epoch 1/10, Loss: -0.1234
Epoch 2/10, Loss: -0.1156
...
Epoch 10/10, Loss: -0.0890Testing DAPO...
Question: 2 + 3 = ?, Predicted: 5, Target: 5
Question: 4 * 2 = ?, Predicted: 8, Target: 8
Question: 10 - 7 = ?, Predicted: 3, Target: 3
Question: 6 / 2 = ?, Predicted: 3, Target: 3
Test Accuracy: 1.0000
(实际结果因随机性可能不同)
扩展到真实场景
- 替换模型:使用真实 LLM(如 Qwen2.5-32B),通过 Hugging Face 的
transformers加载。from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-32B").to(device) tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-32B") - 真实数据集:加载 DAPO-Math-17K 数据集,替换模拟数据。
- 并行化:使用多 GPU 和分布式框架(如
verl)处理大规模训练。 - 超参数调整:根据论文调整
MAX_LENGTH=20480,CACHE_LENGTH=4096等。
这个简化版本展示了 DAPO 的核心逻辑,你可以基于此扩展到实际应用!
后记
2025年3月23日22点24分于上海,在Grok 3大模型辅助下完成。
相关文章:
字节DAPO算法:改进DeepSeek的GRPO算法-解锁大规模LLM强化学习的新篇章(代码实现)
DAPO算法:解锁大规模LLM强化学习的新篇章 近年来,大规模语言模型(LLM)在推理任务上的表现令人瞩目,尤其是在数学竞赛(如AIME)和编程任务中,强化学习(RL)成为…...
计算机操作系统(四) 操作系统的结构与系统调用
计算机操作系统(四) 操作系统的结构与系统调用 前言一、操作系统的结构1.1 简单结构1.2 模块化结构1.3 分层化结构1.4 微内核结构1.5 外核结构 二、系统调用1.1 系统调用的基本概念1.2 系统调用的类型 总结(核心概念速记)…...
Docker安装,并pullMySQL和redis
卸载原Docker 您的 Linux 发行版可能提供非官方的 Docker 软件包,这可能与 Docker 提供的官方软件包冲突。在安装 Docker Engine 正式版之前,您必须先卸载这些软件包。 sudo dnf remove docker \ docker-client \ docker-client-latest \ docker-common…...
第三天 开始Unity Shader的学习之旅之第二天的补充
Unity Shader的学习笔记 第三天 开始Unity Shader的学习之旅之第二天的补充 文章目录 Unity Shader的学习笔记前言一、Unity 提供的内置文件和变量1. 内置的包含文件2. UnityCG.cginc中的常用结构体 二、Unity 提供的Cg/HLSL语义1. 从应用阶段传递模型数据给顶点着色器时Unity…...
DeepSeek技术架构解析:MoE混合专家模型
一、前言 2025年初,DeepSeek V3以557万美元的研发成本(仅为GPT-4的1/14)和开源模型第一的排名,在全球AI领域掀起波澜。其核心创新之一——混合专家模型(Mixture of Experts, MoE)的优化设计,不…...
【正点原子】AI人工智能深度学习(RV1126/RK3568/RK3588)-第1期 准备篇
1.1SDK编译后的目录 1、真正的根文件系统镜像存放目录 2、非必须,负责系统升级等,kerneldtbramdisk组成的根文件系统 1.2文件系统分区 1.3开机自启动 1.6设置静态ip地址 1.8RKMedia框架/编译测试SDK自带RKMedia例程 出厂系统以下内容都是默认…...
PCB沉金和镀金的区别
本文通过多方面角度对比两者的区别。 一.成本和工艺复杂度 沉金:成本较高,制作过程中消耗的金盐多。工艺的参数控制上较严格,需防止“黑盘效应”。 黑盘效应:是指在PCB(印刷电路板)的化学镀镍金…...
靶场(十五)---小白心得思路分析---LaVita
启程: 扫描端口,发现开放22,80端口,发现ws.css可能存在exp,经查发现无可利用的exp PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.4p1 Debian 5deb11u2 (protocol 2.0) | ssh-hostkey: | 3072 c9…...
【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解
目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek 通义万相制作AI视频流程 4.1 D…...
Pi型隶属函数(Π-shaped Membership Function)的详细介绍及python示例
我们前文已经深度解读了三角形、梯形、高斯、S型和Z型隶属函数,现在转向Pi型。当然我们先简要回顾不同隶属函数的特点和曲线效果。了解每种隶属函数的特性是为了更好的应用。 一、回顾五种隶属函数的特点 1.从每种隶属函数的结构和特点角度对比。三角形隶属函数&am…...
MySQL 入门大全:常用函数
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
轻量级TLS反向代理工具TLS-reverse-proxy:打造安全通信桥梁
在数字化浪潮席卷全球的今天,数据隐私与传输安全已成为企业及个人的核心关切。TLS(传输层安全协议)作为互联网通信的"隐形卫士",承担着保护数据在传输过程中不被窃取或篡改的重要使命。然而,对于许多传统服务…...
SpringBoot3实战(SpringBoot3+Vue3基本增删改查、前后端通信交互、配置后端跨域请求、数据批量删除(超详细))(3)
目录 一、从0快速搭建SpringBoot3工程、SpringBoot3集成MyBatis、PageHelper分页查询的详细教程。(博客链接) 二、实现前端与后端通信对接数据。(axios工具) (1)安装axios。(vue工程目录) (2)封装请求工具类。(request.js) <1&…...
AF3 Rotation 类解读
Rotation 类(rigid_utils 模块)是 AlphaFold3 中用于 3D旋转 的核心组件,支持两种旋转表示: 1️⃣ 旋转矩阵 (3x3) 2️⃣ 四元数 (quaternion, 4元向量) 👉 设计目标: 允许灵活选择 旋转矩阵 或 四元数 封装了常用的 旋转操作(组合、逆旋转、应用到点上等) 像 torch.…...
JVM垃圾回收笔记02-垃圾回收器
文章目录 前言1.串行(Serial 收集器/Serial Old 收集器)Serial 收集器Serial Old 收集器相关参数-XX:UseSerialGC 2.吞吐量优先(Parallel Scavenge 收集器/Parallel Old 收集器)Parallel Scavenge 收集器Parallel Old 收集器相关参数-XX:UseParallelGC ~ -XX:UseParallelOldGC-…...
Linux上位机开发实战(编写API库)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 我们自己编写linux上位机软件的时候,尽量都是通过框架库的形式来开发。这就是所谓的低耦合,高内聚。相似的功能、模块和算法…...
深入浅出JVM性能优化:从理论到实践
一、JVM架构与内存模型深度解析 1.1 JVM运行时数据区全景图 方法区(元空间):存储类信息、常量池等元数据堆内存:对象实例存储核心区域 Young Generation(新生代) Eden区(对象诞生地࿰…...
Redis Sentinel 详解
Redis Sentinel 详解 1. 什么是 Redis Sentinel?有什么用? Redis Sentinel(哨兵) 是 Redis 官方提供的高可用性解决方案,主要用于监控、通知和自动故障转移。当 Redis 主节点(master)发生故障…...
器件功耗模型原理
器件功耗模型原理 谷歌提供了一套通用的器件耗电模型和配置方案,先对器件进行耗电因子拆解,建立器件功耗模型,得到一个器件耗电的计算公式。通过运行时统计器件的使用数据,代入功耗模型,就可以计算出器件的功耗。例如…...
拥抱成长型思维:解锁持续进步的人生密码
我强烈推荐4本可以改变命运的经典著作: 《寿康宝鉴》在线阅读白话文《欲海回狂》在线阅读白话文《阴律无情》在线阅读白话文《了凡四训》在线阅读白话文 一、什么是成长型思维? 成长型思维(Growth Mindset)由斯坦福大学心理学家卡…...
Ubuntu上查看GPU使用情况并释放内存
先用nvidia-smi查看GPU当前使用情况 再用fuser 命令查找对应显卡上占用 GPU 的进程 最后查到了用kill -9强制杀掉进程(PID)即可...
解决思科交换机无法访问局域网外设备
问题背景 有时,我们需要远程连接来管理一台思科交换机,例如使用SSH协议。然而交换机运作在链路层,这就需要交换机有一个网络层地址,来接纳基于IP协议的远程访问请求。于是,我们依靠设置一个带有IP地址的交换机虚拟接口…...
Unity Shader编程】之透明物体渲染
以下是针对您提出的关于 Unity Shader 渲染 Pass 的查看方法、多个 Pass 的影响、Pass 的含义,以及 Unity 渲染物体的流程和处理多个透明/半透明/不透明物体的详细解答。 1. Unity Shader 渲染 Pass 的查看方法 查看 Pass 的方法 通过 Shader 代码: 打开…...
fopen和open 等区别是什么?文件描述符与文件描述指针区别
FILE *fp fopen(path, "w"); int fd open(path,) 1.区别 函数定义所属库返回类型fopen高级文件操作函数,提供缓冲机制标准 C 库 (stdio.h)FILE*(文件指针)open低级文件操作函数,直接调用系统接口Unix/Linux 系统调用…...
什么是张量计算
以下是对张量计算的详细介绍,结合数学、物理学及计算机科学等多领域视角: 一、张量的基本定义与性质 1. 张量的数学定义 张量是向量空间及其对偶空间的笛卡尔积上的多重线性映射,可视为多维数组或几何对象。其核心特征在于: 坐…...
【1】Java 零基础入门学习(小白专用)
【1】Java 零基础入门学习 📚博客主页:代码探秘者 ✨专栏:《JavaSe从入门到精通》 其他更新ing… ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏作者水…...
[c语言日寄]枚举类型
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
替代-UX设计师
初创公司如何在没有设计师的情况下 打造实用的用户体验 一个常见的捷径是使用预构建的组件库,如谷歌的 Material UI它们为你提供了构建块,但它们并没有为你考虑整个用户流程你仍然需要弄清楚所有这些是如何组合在一起的但是,很多时候&#x…...
【氧化镓】掺杂在β-Ga2O3材料中引入的深能级缺陷
1. 引言 1.1 β-Ga2O3材料的特性与应用前景 β-Ga2O3作为一种新型的宽禁带半导体材料,具有约4.6-4.8 eV的宽带隙、高击穿场强(约8 MV/cm)和优异的热稳定性,适用于高功率和射频电子器件。其独特的物理特性使其在高电压、高频率以及高功率应用场景中具有巨大的潜力。例如,…...
:ref 和 this.$refs 的区别及 $ 的作用
:ref 在 Vue 模板中,:ref 这种写法是使用了 Vue 的动态绑定语法(: 是 v-bind: 的缩写)。ref 是一个特殊的属性,用于给元素或组件注册引用信息。当你使用 :ref 时,通常是在动态地为元素或组件设置引用名称,…...
