下肢假肢的控制系统设计一直是个老大难问题。传统控制理论需要建立肢体和环境的精确数学模型,但现实世界可以不一样,比如说地面摩擦力时刻在变,坡度各不相同,患者随时可能绊一下。这就需要控制器具备自适应能力,能从失误中恢复,还得在没有显式编程的情况下习得自然的步态模式。
强化学习给出了一条思路:让假肢自己通过试错"学会"走路。但是标准RL算法有个毛病,它太贪心了,找到一种能用的移动方式就死守着不放,一旦外界条件变化,整个控制策略就非常容易崩盘。
这篇文章用Soft Actor-Critic(SAC)算法解决BipedalWalker-v3环境。但这不只是跑个游戏demo那么简单,更重要的是从生物工程视角解读整个问题:把神经网络对应到神经系统,把奖励函数对应到代谢效率。
SAC的核心思想:为什么要"soft"?
常规强化学习只盯着一个目标——最大化期望累积奖励。这种贪心策略在国际象棋这类确定性博弈里表现不错,但放到物理控制任务上问题就非常的多了,这是因为系统动力学稍有变化,贪心策略往往直接翻车。
要理解SAC里的"软"字,先得搞清楚Actor-Critic架构。这个框架其实模拟了人类学习运动技能的过程。打个比方:患者(Actor)在学习使用假肢,旁边有个理疗师(Critic)在观察和指导。
Actor(策略网络π) 负责控制肢体,观察当前状态(关节角度、身体平衡),然后决定该怎么动。训练初期它啥也不懂只能瞎动弹。Critic(Q函数网络) 负责评估Actor动作的质量,不直接控制肢体,只预测某个动作长期来看能拿到多少奖励。
传统算法里,Actor拼命想找到那个"最优解"来讨好Critic。但SAC不一样,Critic鼓励Actor尝试多种不同的成功路径,不仅看结果,还看方法的多样性。
SAC采用最大熵框架,智能体的目标变成了同时最大化期望奖励和策略熵(随机性):
这里的𝓗就是熵。
这对假肢控制有什么意义?
一方面是探索机制。比如说婴儿会用随机运动(所谓motor babbling)来摸索肢体的运动规律。高熵保证了充分探索,避免智能体掉进"安全小碎步"的局部最优陷阱,就是那种几乎不动、只求不摔的保守策略。另一方面是泛化性,熵最大化训练出来的智能体掌握了一整套策略组合。某条肌肉激活路径被干扰了?没关系,还有备选方案。这让步态对打滑、绊绊脚之类的意外具备容错能力。
从仿真到临床的映射关系
BipedalWalker-v3
是个24维数字向量。但从生物工程角度看它相当于膝上假肢控制问题的简化版。
观察空间对应传感器融合
Gym里的24维观察向量可以直接对应到Otto Bock Genium这类智能假肢的传感器配置:
躯干角度和速度对应前庭系统——"躯干"代表质心位置,硬件上用IMU(惯性测量单元)采集平衡数据。关节编码器对应本体感觉,仿真里提供的关节角度和速度,在真实假肢上由霍尔传感器和旋转编码器获取。激光雷达对应视觉前馈,现代研究型假肢已经开始集成深度相机来预判地形。
动作空间对应执行器
智能体用[-1, 1]范围的连续值控制髋关节和膝关节。这对应到硬件上就是直流电机的电流控制,或者气动人工肌肉(PAMs)的压力调节。
为什么连续控制这么重要呢?DQN这类离散算法输出的是生硬的开关命令,SAC输出的是连续平滑的扭矩曲线。对患者来说这可不是小事,生硬的驱动会在残肢上产生剪切力长期下去会损伤组织。
代码实现
以下实现改编自CleanRL并使用PyTorch搭建网络,通过Gymnasium提供仿真环境运行。
Actor网络:物理约束的强制执行
连续控制的一个核心挑战是把动作限制在物理边界内。这里用高斯策略配合
tanh
函数压缩输出,确保电机指令不会超出[−1, 1]的安全范围。
# LOGIC: The Actor Network (from sac_bipedalwalker_enhanced.py)
def get_action(self, x):
mean, log_std = self(x)
std = log_std.exp()
# The Reparameterization Trick:
# Allows gradients to flow back through the sampling process
normal = torch.distributions.Normal(mean, std)
x_t = normal.rsample()
# Squash output to [-1, 1] for the environment limits
y_t = torch.tanh(x_t)
action = y_t * self.action_scale + self.action_bias
# Correction for the log_prob due to tanh squashing (Math detail)
log_prob = normal.log_prob(x_t)
log_prob -= torch.log(self.action_scale * (1 - y_t.pow(2)) + 1e-6)
log_prob = log_prob.sum(1, keepdim=True)
return action, log_prob, mean
注意
x_t = normal.rsample()
这行。看起来普普通通,实际上是整个算法的数学根基。
标准随机策略里,采样动作是个随机事件,会打断反向传播需要的导数链,随机数生成器没法求导。重参数化技巧绕开了这个问题:不直接从分布采样,而是先采一个标准正态噪声ε,再用网络输出的均值μ和标准差σ做变换:xt = μ + σ · ε。因为ε跟网络参数无关,μ和σ的梯度就能正常计算了,Actor网络也就能从Critic的反馈里学到东西。没这个技巧,连续策略根本没法训。
自动熵调节
早期SAC版本里,温度参数α是固定的。α太大,智能体走路像喝醉了;α太小,又永远学不会探索。现在的做法是把α当成可学习参数,让智能体自己决定什么时候该收敛:
# LOGIC: Automatic Entropy Tuning (inside training loop)
if args.autotune:
with torch.no_grad():
_, log_pi, _ = actor.get_action(data.observations)
# Minimize difference between current entropy and target entropy
# target_entropy is usually -dim(Action Space)
alpha_loss = (-log_alpha.exp() * (log_pi + target_entropy)).mean()
a_optimizer.zero_grad()
alpha_loss.backward()
a_optimizer.step()
alpha = log_alpha.exp().item()
实验结果分析
训练跑了350k步。这里我们要看的不是最终分数多高,而是学出来的步态在生物力学上是否合理。
学习曲线的解读
智能体一开始回报是负的,站都站不稳,跟患者刚装上新假肢时的状态很像。
看下面的学习曲线,蓝色阴影是各episode的标准差。0-100k步阶段方差很低,但这不好,因为智能体一直在失败,每次都是秒摔。
到了150k-250k步,方差突然爆炸。这是个关键转折期,智能体开始尝试高风险策略,有时走得漂亮,有时摔得很惨。只有进入300k步之后的稳定区,均值高、方差收窄,这样才能考虑"冻结"策略用于实际部署。方差收窄意味着策略从"碰运气"进化到了"真会走"。
而150k步左右发生了"相变",智能体突然开窍了,奖励曲线急剧上升。250k步后稳定在200分以上,算是解决了这个环境。
相位图分析
光看分数不够,还得检查运动学特征。下图是髋关节的相位图,横轴关节角度,纵轴角速度。
紫色和蓝色的散点代表早期阶段,角度和速度之间毫无关联,智能体就是在瞎蹬腿,漫无目的地探索状态空间。
随着训练推进(颜色向黄绿过渡),散点开始收敛成一个封闭的轨道形状。这在控制论和生物力学里叫极限环(Limit Cycle)。
极限环说明系统找到了稳定的周期轨道。即使遇到小扰动,系统也倾向于回到这个环上,这正是动态稳定步态的定义。这个环是从SAC目标函数里自发涌现出来的,不是显式编程的结果。环的形状比较光滑并且没有锯齿,说明Actor网络里的
tanh
压缩确实产生了平滑的扭矩曲线,避免了离散RL常见的"抖振"问题。这对假肢安全性至关重要。
能效特征
最后看Critic损失(智能体的"困惑程度")和动作幅度(扭矩大小)的关系。
学习阶段(50k-200k步),Critic损失达到峰值,智能体还在跟物理规律较劲。极限环建立后(200k步以后),动作幅度稳定下来,Critic损失也降到较低水平。
更细致地看,可以把训练过程分成三个力学阶段:
"僵住"阶段(0-70k步):动作幅度(绿线)起始值很低。智能体把关节锁死以避免摔倒惩罚,这在运动学习里叫"共同收缩"策略。不怎么动,自然也不会摔得太惨。
"疯狂试探"阶段(70k-200k步):Critic损失剧烈震荡,这正是智能体开始尝试往前走的时候。反复失败带来高"惊讶度"。同时动作幅度急剧攀升说明智能体意识到想走路就得狠狠发力,哪怕暂时会摔。
"熟练掌握"阶段(200k步以后):极限环形成,Critic损失骤降,智能体对物理世界不再感到意外。有意思的是动作幅度:在200k附近达到峰值后反而略有下降然后趋于平稳。这是熟练运动的典型特征,智能体学会了借力,不再每一步都用蛮力,而是顺着动力学"流"起来,能量消耗得到了优化。
一个可能的改进方向是在奖励函数里加入代谢运输成本(COT)惩罚项,鼓励智能体发现更"被动-动态"的步态模式,靠惯性而不是持续肌肉输出来行走,这对延长真实假肢的电池续航很有价值。
总结
SAC算法在BipedalWalker环境中跑了350k步后,智能体从"秒摔"进化到稳定行走(200+分)。相位图显示髋关节运动收敛成极限环,动态稳定步态的标志。能效曲线也印证了这点:智能体最终学会借力而非蛮干。
从假肢控制角度看,SAC的最大熵框架带来的策略多样性是关键优势,让系统对打滑、绊脚这类意外有容错空间。不过真要落地到Otto Bock C-Leg这类设备上,还得解决传感器噪声、执行延迟和安全约束的问题,域随机化和PID安全笼是两个可行方向。
https://avoid.overfit.cn/post/ab5860e7071441e9aab80e9876b2f45d
作者:Cristlianreal