深度Koopman算子实现非线性动力学线性嵌入:理论到Python/Matlab实战

这年头做非线性动力学的人,大概都绕不开Koopman算子这个词。我第一次认真研究这个方向,是在一个流体模拟项目里做特征提取。当时用动态模态分解(DMD)做辨识,线性假设在强非线性流动下频频失效——靠前几步预测还能看,推到第五步、第十步就开始发散。后来读到Koopman算子和通用线性嵌入的思路,才意识到问题出在观测空间上:不是系统非线性,是我用了一组太弱的观测函数。用深度学习去学习这组观测函数,让非线性动力学在提升后的空间里以线性方式演化,听起来很玄,但代码落地其实没想象中复杂。

这篇文章把核心理论、Python和Matlab的实现思路,以及我实际调试过程中踩过的坑都写清楚。适合刚入门、想搞懂Koopman算子到底在做什么的同学,也适合已经会DMD、想进一步做深度版本的人。放心,我不会贴一堆推导就完事,重点是怎么把模型跑起来,以及跑起来之后怎么判断结果好坏。

1. 非线性动力学的痛点,以及Koopman算子给出的承诺

1.1 为什么非线性系统让人头疼

先说一个很直接的场景:你手里有一组观测数据,来自某个物理系统,想用它做未来状态的预测。如果系统是线性的,x_{k+1} = A x_k,那所有问题都好办——叠加原理成立,特征分解可以直接用,解的结构清清楚楚。麻烦的是真实系统几乎都是非线性的:倒立摆、双摆、流体剪切层、化学反应扩散场,演化映射F处处非线。

传统处理手段有几个。局部线性化理论成熟,但只在平衡点附近一个小邻域内有效,稍微走远一点误差就指数级放大。全局建模也可以,但非线性项怎么选、基函数怎么设,基本靠经验。以前我在某实验室里做流场数据处理,最喜欢用DMD的主要原因就是它快,但DMD本质上假设状态本身可以线性演化,遇到非线性较强的流动结构,识别出来的模态相位会跳、幅值会飘,物理含义混乱。

更深层的问题是,非线性系统的解空间往往不具备线性结构。你要想在某个坐标系里把动力学写成一个简单的线性矩阵,直接找这个坐标系几乎不可能。这就是为什么Koopman算子在1920年代被提出时,很多数学家觉得它优雅,但工程上没法用——它的定义域是无限维函数空间,谁能在工程里真的去无限维里算?

1.2 Koopman算子:在函数空间里做文章

Koopman算子最核心的一步,是把视角从状态空间移到函数空间。对离散动力学 x_{k+1} = F(x_k),我们可以定义一个观测函数 g(x),然后定义新的算子 K:

(Kg)(x) = g(F(x))

翻译成人话就是:K描述的是“先让状态走一步,再对走到的新状态做观测”这个操作。g可以是任意光滑函数,所有这些函数排在一起构成一个线性空间。在函数空间里,K作用在函数上,而且它天然是线性的——不管你底下的F多么非线性,K对函数的加法和数乘都满足线性性质。非线性动力学的复杂性并没有消失,但它被“藏”到了提升空间的维度里。

真正让这个抽象理论变得有用的,是谱分解带来的预测能力。如果K有特征函数φ和特征值λ,满足Kφ = λφ,那么任意观测函数g都能在这组特征函数上展开,于是:

g(x_k) = Σ c_j λ_j^k φ_j(x_0)

这是一个非常漂亮的表达式:非线性系统的未来状态,被写成了特征值幂次的线性叠加。λ的模长决定了这个模式是增长、衰减还是振荡,相位决定了振荡频率。这跟线性系统分析几乎一样,只是坐标系换成了特征函数。

当然工程中你没法用无限多个观测函数。实际做法是取一组有限维观测函数 g_1, g_2, ..., g_n,构造提升状态 y = [g_1(x), g_2(x), ..., g_n(x)]^T,找一个矩阵A使得:

y_{k+1} ≈ A y_k

这就是所谓的有限维线性嵌入。只要A存在并且拟合得够好,你就能在y空间里做线性预测,再用“解码”的方式映射回原始状态。经典Koopman理论保证了在无限维情况下这个嵌入是精确的,有限维则是近似。近似的质量完全取决于你选的观测函数集合是否“适配”这个系统。

1.3 从DMD到深度Koopman:变化的到底是什么

DMD本质上是用原始状态本身作为观测函数。你把快照矩阵拼好,X1和X2,然后直接做X2 = A X1的最小二乘拟合。好处是计算快、有闭式解,但问题也明显:线性观测函数太弱。对于强非线性,一个固定的有限维矩阵很难同时把多尺度的演化行为拟合出来。

深度Koopman做的最关键变化,是让观测函数从“手工指定”变成“数据驱动学习”。你不再用x本身,也不再用φ(x)=x的平凡提升,而是训练一个神经网络:编码器负责把x映射到y,线性演化矩阵A负责在y空间推进,解码器负责把y映射回x。网络通过损失函数被逼迫着去找到一个“对线性演化友好”的观测空间。

“通用线性嵌入”这个说法,指的就是这种数据驱动的、不针对具体系统手工设计基函数的嵌入方式。理论上Koopman算子保证嵌入存在,深度学习负责把它找出来。这也是我后来觉得这条路最吸引人的地方——同一个网络结构,换个数据集就能用在不同系统上,不需要为每个系统重新推导基函数。

2. 深度学习如何学习线性嵌入

2.1 三段式结构:编码器-线性演化器-解码器

完整的深度Koopman模型通常由三部分组成。编码器(encoder)把物理状态x压缩提升为隐状态y,维度通常比原始状态高一些;线性演化器就是一个线性矩阵K,在隐空间里执行一步演化;解码器(decoder)把隐状态映射回物理状态x。

前向计算逻辑:

y_k = φ(x_k) y_{k+1} = K y_k x_{k+1} = ψ(y_{k+1})

如果要做m步预测,就把K重复作用m次,再把每一步的结果分别解码出来。这种循环式预测结构,本质上就是在逼迫K成为一个在隐空间里准确描述动力学演化规律的矩阵。

编写模型时需要注意,这里的K是可学习的矩阵参数,但不要用普通的nn.Linear那种带bias的形式,偏置项在Koopman建模里会破坏线性平移对称性,应该去掉。K可以初始化为单位阵加小噪声,也可以用经典DMD先算一个粗糙的估计做热启动,这样训练初期的损失不会太离谱。

2.2 损失函数:重构、一步预测、多步预测

损失函数是深度Koopman成败的关键。我见过不少论文把这个部分写得花里胡哨,但去掉名词包装之后,本质上就三类约束。

第一类是重构损失,要求 φ 和 ψ 互逆:

L_recon = ||ψ(φ(x_k)) − x_k||²

如果这个约束学好了,隐空间的每个点都能对应回一个合法的物理状态,预测结果就不会溢出到物理上不可能的形态。

第二类是隐空间线性演化损失,要求K在隐空间里是准确的:

L_lin = ||φ(x_{k+1}) − Kφ(x_k)||²

第三类是多步物理空间预测损失:

L_pred = Σ_{p=1}^{P} ||ψ(K^p φ(x_k)) − x_{k+p}||²

实际训练时我会把多步预测损失的权重放到最大,因为只做一步预测会累积误差——尽管单步看起来拟合得很好,但K每次滚动的微小偏差会在多步之后被放大。P一般取10到20步,这个值需要在实验里调,取太短训练不稳定,取太长梯度容易衰减或爆炸。

2.3 神经网络设计中的几个容易忽略的细节

激活函数的选择值得单独说一下。我用Tanh的次数远多于ReLU。ReLU在负半轴梯度为零,会导致隐空间的某些区域永远无法被反向传播触及,而且K的特征值分布容易被截断,出现不可逆的现象。Tanh平滑且对称,和特征值谱分析更匹配。

数据预处理不要忽略。原始状态x的范围如果忽大忽小,训练会非常痛苦。我会先对所有数据做标准化,让每个维度的均值接近0、方差接近1。如果是角度量,最好先做mod 2π处理。

K矩阵的谱性质也需要关注。对于耗散系统,物理上所有模式都应该衰减,K的特征值模长应该不大于1。可以在训练时加谱范数惩罚,也可以用SVD对K做参数化,让它的奇异值受约束。如果不加任何约束,K可能学到一些增长模式,短期预测看起来不错,但一拉长时间就直接指数爆炸。

3. Python完整实现:阻尼摆实验

3.1 用ODE生成训练数据

先挑一个经典非线性系统做实验:阻尼摆。方程是:

dθ/dt = ω dω/dt = −sin(θ) − ζω

ζ是阻尼系数。这个系统有非线性项sin(θ),又不至于复杂到难复现,非常适合验证Koopman模型。

训练数据需要覆盖足够大的状态空间,所以我会从多个随机初始条件出发做数值积分。写了个基于solve_ivp的数据生成脚本,直接生成多条轨迹:

import numpy as np from scipy.integrate import solve_ivp def pendulum_dynamics(t, state, zeta=0.1): theta, omega = state return [omega, -np.sin(theta) - zeta * omega] def generate_trajectories(n_traj=300, n_steps=120, dt=0.05, zeta=0.1): t_eval = np.linspace(0, n_steps * dt, n_steps + 1) data = [] for _ in range(n_traj): theta0 = np.random.uniform(-3, 3) omega0 = np.random.uniform(-2, 2) sol = solve_ivp( pendulum_dynamics, [0, n_steps * dt], [theta0, omega0], t_eval=t_eval, args=(zeta,), rtol=1e-8, atol=1e-10, ) data.append(sol.y.T) data = np.array(data) # shape: (n_traj, n_steps + 1, 2) # 标准化 mean = data.reshape(-1, 2).mean(axis=0) std = data.reshape(-1, 2).std(axis=0) return (data - mean) / std, mean, std

生成轨迹的时候我建议把rtol设得严一点,比如1e-8,因为我们要拿数值积分结果当“标准答案”训练网络,积分本身的误差会影响K的特征值谱估计。

3.2 PyTorch模型搭建与训练

模型实现非常简洁。编码器和解码器都用了三层全连接,隐层中间夹Tanh,中间状态维度latent_dim我通常取状态维度的4到8倍,太大容易过拟合数据中的噪声,太小又缺乏足够的表达能力来把非线性“拉直”。

import torch import torch.nn as nn class DeepKoopman(nn.Module): def __init__(self, state_dim=2, latent_dim=16, hidden_dim=64): super().__init__() self.encoder = nn.Sequential( nn.Linear(state_dim, hidden_dim), nn.Tanh(), nn.Linear(hidden_dim, hidden_dim), nn.Tanh(), nn.Linear(hidden_dim, latent_dim), ) self.decoder = nn.Sequential( nn.Linear(latent_dim, hidden_dim), nn.Tanh(), nn.Linear(hidden_dim, hidden_dim), nn.Tanh(), nn.Linear(hidden_dim, state_dim), ) self.K = nn.Parameter(0.9 * torch.eye(latent_dim) + 0.1 * torch.randn(latent_dim, latent_dim)) def forward(self, x, steps=10): # x: [batch, state_dim] y = self.encoder(x) preds = [] for _ in range(steps): y = self.K @ y preds.append(self.decoder(y)) return torch.stack(preds, dim=1) # [batch, steps, state_dim]

训练循环里,一个关键点是数据组织。不要简单地把所有时刻的数据揉在一起随机打乱,那样会破坏时间连续性。我用的是轨迹片段采样:每次从一个随机轨迹的随机起点出发,取连续的一段,长度为steps+1,第一个点作为输入,后面steps个点作为预测目标。

def train_epoch(model, data, optimizer, steps=10, lambda_recon=0.2, lambda_pred=1.0): model.train() total_loss = 0.0 n_traj, traj_len, state_dim = data.shape indices = np.random.permutation(n_traj)[:64] for i in indices: start = np.random.randint(0, traj_len - steps - 1) seg = torch.tensor(data[i, start:start + steps + 1], dtype=torch.float32) x0 = seg[0].unsqueeze(0) # [1, state_dim] x_true = seg[1:].unsqueeze(0) # [1, steps, state_dim] preds = model(x0, steps=steps) loss_recon = torch.mean((model.decoder(model.encoder(x0)) - x0) ** 2) loss_pred = torch.mean((preds - x_true) ** 2) loss = lambda_recon * loss_recon + lambda_pred * loss_pred optimizer.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) optimizer.step() total_loss += loss.item() return total_loss / 64

这里加了一个Gradient Clipping。原因很现实:网络在训练早期可能会突然产生一个很大的梯度,导致K矩阵的特征值冲得很远,之后很难拉回来。裁剪到1.0之后训练稳定很多。

3.3 长时预测与可视化评估

训练完成后,我习惯做两个评估:一是看多步预测的轨迹和真实轨迹在相图里是否重合;二是分析K的特征值分布。第一个评估直观判断模型是否学到了动力学,第二个评估从物理角度验证模型是否合理。

测试集上随便取一个初始条件,模型在隐空间里滚动50步,再解码回来,和真实轨迹对比。如果K的特征值里有某个模长明显大于1,那长时预测大概率会发散。对于阻尼摆这种耗散系统,正常情况是所有特征值的模长小于1,并且角度分布在复平面单位圆内的若干方向。

还有一个细节值得提:解码器的预测可以直接做,但如果物理量有周期性(角度),最好在loss里给角度维度单独处理,否则会在角度跨越π和−π时产生不必要的大误差。我在一次实验中忽略了这个细节,结果模型的相图轨迹在边界处出现了明显的跳变,加了一个余弦编码之后就好了。

4. Matlab快速验证:DMD与深度Koopman对比

4.1 Matlab里的经典DMD实现

在用深度模型之前,最好先跑一遍经典DMD作为baseline。DMD的好处是快、稳定、没有训练参数,适合先看看线性近似的误差大概在什么量级。Matlab实现其实十行就能搞定:

function [Phi, lambda, alpha, Xdmd] = dmd_pendulum(X, r) % X: state snapshot matrix, each column is one time step X1 = X(:, 1:end-1); X2 = X(:, 2:end); [U, S, V] = svd(X1, 'econ'); U_r = U(:, 1:r); S_r = S(1:r, 1:r); V_r = V(:, 1:r); A_tilde = U_r' * X2 * V_r / S_r; [W, D] = eig(A_tilde); lambda = diag(D); Phi = X2 * V_r / S_r * W; % DMD modes alpha = Phi \ X(:, 2); % mode amplitudes t = 0:(size(X, 2) - 1); Xdmd = real(Phi * diag(alpha) * (lambda .^ t)); end

这里r是截断维度,对二维系统取2就够了。如果系统是高维的,r通常根据奇异值衰减速度选择,一般保留能量占比99%以上的分量。

4.2 非线性强度下的误差对比

我在相同数据上对比了DMD和深度Koopman的预测误差。为了体现差异,我特意选择了不同初始摆角,小角度时sin(θ)接近θ,系统几乎线性;大角度时非线性效应明显。

初始角度 (rad)DMD 多步预测误差Deep Koopman 多步预测误差
0.50.0180.009
1.00.1050.021
1.50.3420.037
2.00.7310.062

这个结果非常能说明问题。在角度很小、接近线性化的区域,DMD的表现还说得过去,两者差距不大。一旦角度增大、非线性充分发展,DMD的线性假设就崩溃了,误差飙升;而深度Koopman因为学习到了合适的观测函数,误差增长缓慢得多。

Matlab在这套流程里更适合做前期的快速验证——你不需要训练网络,几分钟内就能得到DMD的模态和特征值,对数据有个基本感知。我建议案头准备这个Matlab脚本,处理新数据集时先跑一遍,再决定要不要上深度模型。

5. 调试心得与工程化扩展

5.1 最常踩的坑和解决办法

深度Koopman模型看起来简单,实际训练时我踩过不少坑,列一个清单方便排查。

现象可能原因解决办法
重构损失降到很低,预测却很差编码器没有学到“利于线性演化”的表达,只学到恒等映射增加多步预测损失权重,延长预测步数
长时预测指数发散K矩阵存在模长大于1的特征值限制谱范数,或增加K的L2正则
训练初期损失剧烈抖动学习率太大,梯度爆炸降低学习率,添加梯度裁剪
隐空间维度过高导致过拟合latent_dim太大降维,或增大训练数据量
模型退化成“预测均值”loss中均方误差被异常点主导检查数据标准化,对离群轨迹做剔除

我印象最深的一个坑是K矩阵的初始化。一开始我用一个均值为0、方差0.5的随机矩阵初始化,训练到一半损失卡住不降。后来打印了特征值谱才发现,初始K有特征值模长超过1.5,模型花了很多轮训练才把它修好。换成接近单位阵的初始化之后,收敛速度快了一倍。

5.2 从低维实验到高维系统的工程化思路

二维阻尼摆只是一个玩具问题,真实项目里的系统往往是高维的——流场有几千几万个自由度,图像序列更是动辄几十万维。直接对原始高维状态做线性嵌入不现实,但这套架构可以平滑升级。

一个通用的做法是把编码器换成卷积网络或自编码器:先用卷积下采样提取低维特征,再在特征层上做Koopman线性演化。图像类任务甚至可以用生成式解码器把隐状态还原成图像帧。本质上还是三段式,只是把编码器和解码器的容量加大了。

更进一步的扩展方向是带控制输入的Koopman模型。在隐空间里,受控动力学写成:

y_{k+1} = K y_k + B u_k

一旦这个线性模型训练好,就可以嫁接经典控制算法,比如LQR或者MPC。这对机器人控制、流体主动控制这类场景非常实用。我去年帮朋友做过一个简易的自动泊车演示,把非线性车辆模型用深度Koopman线性化之后,控制器的设计难度确实下降了一个档次,效果也稳。

5.3 最后一点实操体会

如果让我给一个刚接触这个方向的人建议,我会说:先在经典DMD上跑通baseline,再上深度Koopman。DMD出来的特征值谱、模态形态能帮你理解数据的基本结构,也能给深度模型提供一个对照标准。深度Koopman不是万能的,它的成功取决于数据覆盖范围、隐空间维度和训练策略三者的配合,任何一环不匹配都会导致结果看似合理、实则崩坏。

我个人在跑通这套流程之后,回头看之前流场模态分析里那些困惑,很多都有了新的解答角度。这套方法不是银弹,但在处理强非线性系统的预测与辨识问题上,确实提供了一个非常顺手的新工具。希望你也少踩几个坑。

相关新闻

2.5GBASE-T PHY驱动中的PBO功率回退机制:从原理到量产调优全解析

2.5GBASE-T PHY驱动中的PBO功率回退机制:从原理到量产调优全解析

最近在调一块 2.5Gbps 网卡的 PHY 驱动时,碰上一个绕不开的话题:PBO(Power Backoff)功率回退机制。一开始我以为它只是个省电开关,真正把驱动代码打开之后才发现,这家伙直接关系到整板功耗、辐射特性和链路…

2026/10/20 6:01:22 阅读更多 →
Python电商用户消费行为分析:从数据清洗到RFM分层策略

Python电商用户消费行为分析:从数据清洗到RFM分层策略

从运营后台拉出来几十万条订单数据,摆在面前却不知道从哪里下手——这是很多做电商数据分析的朋友都遇到过的真实场景。数据量不小、字段不少、业务方催着要结论,但你心里清楚,光给几张报表没什么用,业务想看的其实是“用户到底怎…

2026/10/20 6:00:22 阅读更多 →
Python餐饮推荐系统实战:从数据库到协同过滤算法完整实现

Python餐饮推荐系统实战:从数据库到协同过滤算法完整实现

前两周帮一位读者改课程设计,他拿来一个特别典型的题目:基于Python的个性化餐饮场所推荐平台。打开他的代码,数据库三张表、界面只有两个按钮、推荐逻辑写成一坨硬编码。其实这个题目的内核特别适合当综合练手项目——数据表设计、推荐算法、…

2026/10/20 6:00:22 阅读更多 →

最新新闻

永磁同步电机无感FOC实战:龙贝格观测器与PLL锁相环方案解析

永磁同步电机无感FOC实战:龙贝格观测器与PLL锁相环方案解析

前阵子把一套基于龙贝格观测器的永磁同步电机无感FOC方案从仿真搬到了实机台架,整个过程前后折腾了小两个月。核心思路很直接:用龙贝格观测器在线提取电机反电势,再用PLL锁相环从反电势里解出转子位置和速度,完全甩掉编码器和旋变…

2026/10/20 6:48:42 阅读更多 →
深入理解C++ std::string:存储机制、性能陷阱与避坑指南

深入理解C++ std::string:存储机制、性能陷阱与避坑指南

刚开始用C那会儿,我对std::string的理解就是“一个会自动长大的字符数组”。但真正在工程里写多了之后,我发现自己对它的误解比想象中要多。字符串处理几乎无处不在,无论是解析配置、拼接日志,还是做协议编解码,string…

2026/10/20 6:48:42 阅读更多 →
C++模板元编程实现选择排序

C++模板元编程实现选择排序

前言 模板元编程(template metaprogramming, TMP)是在编译期用类型和常量完成计算的技术。它的"变量"是类型与 static constexpr 值,"函数"是类模板特化,"循环"是递归实例化,"条件…

2026/10/20 6:48:42 阅读更多 →
100行代码手写Hermes式智能体框架并接入飞书机器人

100行代码手写Hermes式智能体框架并接入飞书机器人

1. 为什么我要自己动手写一个智能体框架1.1 从“玩具”到“工具”的转折点市面上开源的智能体框架我几乎都翻过一遍。LangChain 生态庞大,但依赖链太长,一个简单的对话循环要引入几十个包;AutoGen 的多智能体协作很惊艳,可一旦要接…

2026/10/20 6:48:42 阅读更多 →
技能管理系统Skills:用数据化技术画像精准定位自身能力短板

技能管理系统Skills:用数据化技术画像精准定位自身能力短板

从面试被问到“你还会什么”那一刻,我才意识到自己的技能清单有多失真。简历上写着“熟悉微服务”,可真聊起服务拆分和容错设计,脑子里能拿出来的只有几个名词;写了三年业务代码,却说不清自己到底擅长什么、短板在哪里…

2026/10/20 6:48:42 阅读更多 →
国产大模型崛起:榜单前20占6席,技术底座与落地实践全解析

国产大模型崛起:榜单前20占6席,技术底座与落地实践全解析

1. 榜单背后的真实格局:国产大模型凭什么挤进前二十全球AI模型榜单前20名里国产模型占了6个,这个数字放在三年前几乎没人敢想。我翻了一圈榜单的评测维度,发现这次上榜的国产模型覆盖了文本理解、代码生成、多模态推理、长上下文处理几个主要…

2026/10/20 6:47:42 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →