在线字典学习MATLAB实现:稀疏编码与字典更新实战指南

简介:在线字典学习代码是一套基于MATLAB的机器学习实现资源,面向处理文本、音频等序列数据的开发者与研究者。代码演示了在线学习与字典学习的结合:通过逐样本或小批量方式更新模型参数,在节省内存的同时适应数据流场景,并以代价函数衡量预测效果,反复迭代以优化字典基。压缩包共5个文件,以4个m脚本/函数和1个mat数据文件构成,整体仅1.11MB,结构清晰,便于直接运行、修改参数和观察结果。已有693人学习该资源,适合具备一定MATLAB编程基础、希望动手实践机器学习算法的读者。借助该代码可深入理解在线学习的迭代逻辑、稀疏表示原理,并快速迁移到特征提取、信号压缩、文本编码等实际任务中。

1. 在线字典学习:用 MATLAB 跑通一个无需全量训练的自适应字典

在线字典学习(Online Dictionary Learning)和传统 K-SVD 的最大区别,是它不用把整批训练数据一次性载入内存,而是让字典随着样本逐个(或小批量)到达而持续更新。这份 MATLAB 代码把整个流程拆成了独立的稀疏编码、字典更新、重建误差统计三个模块,输入一个矩阵就能训练出过完备字典,直接用于图像去噪、缺失数据恢复、特征提取这些场景。对新手来说,它是一份能一步步跑通稀疏表示的入门实现;对老手来说,它的模块化结构方便替换求解器,比如把软阈值迭代换成 OMP 或 LARS,验证不同策略对收敛速度的影响。我拆完这份代码后最大的感受是:在线更新虽然只有短短几行,但踩坑点全在参数和矩阵维度上,这恰恰是文档说不清楚、跑一遍才能发现的地方。

2. 整体设计与目录结构:从 K-SVD 到在线更新的架构差异

2.1 在线字典学习与传统批处理的区别

传统字典学习(如 K-SVD)每一轮迭代都要用到全部训练样本,先固定字典用 OMP 对所有样本做稀疏编码,再固定稀疏系数逐列更新字典原子。这种方式在小规模数据上效果不错,但样本量一大,内存占用和计算时间就会急剧膨胀。在线字典学习换了个思路:每次只取一小批甚至一个样本,用当前字典做稀疏编码,然后立刻用一个简单的梯度步更新字典。这样字典的每一次更新都只依赖最近的数据,天然适合流式计算和增量学习场景。

这份 MATLAB 代码在架构上采用了最标准的交替迭代框架:稀疏编码阶段固定字典,求每个样本的稀疏系数;字典更新阶段固定系数,用梯度下降方向调整原子。和离线版本相比,它少了"逐列更新原子"的 SVD 步骤,取而代之的是统一矩阵运算,这对 MATLAB 的向量化更加友好。整个训练过程中,字典原子始终保持单位范数,防止目标函数被退化到零解附近。

2.2 目录结构与文件职责划分

代码解压后是一个平铺加小工具目录的结构,直接在主目录运行 demo 脚本即可。典型的目录形式如下:

online_dict_learning/ ├── odl.m % 在线字典学习主循环 ├── sparse_coding.m % 稀疏编码模块(Lasso 软阈值求解) ├── dict_update.m % 字典更新模块(梯度下降) ├── demo_denoise.m % 演示脚本:图像去噪 ├── demo_dict.m % 演示脚本:可视化学习到的字典 ├── utils/ │ ├── psnr.m % 峰值信噪比指标 │ ├── show_dict.m % 将字典原子以图像网格展示 │ └── img2patch.m % 将图像切成重叠小块

主函数odl.m是唯一需要用户直接调用的入口,它返回字典矩阵 D 和稀疏系数矩阵 A。sparse_coding.m和dict_update.m是核心算法模块,demo_denoise.m展示了如何把训练好的字典用于含噪图像重建。这样划分的好处是:如果只想看算法,读前两个文件就够了;如果想落地到具体任务,再去看 demo 脚本。

2.3 主循环的初始化与迭代框架

主函数中最容易忽略的是字典初始化。这份代码用随机高斯矩阵加上列归一化来做初始字典,每一列代表一个长度等于样本维度的原子。如果训练样本是 8×8 的灰度图像块,拉直后维度是 64,那么字典就是一个 64×256 的矩阵,256 是超参数,表示字典原子数量。原子数越少,字典越紧凑,重建精度会下降;原子数越接近样本维度,字典越接近完备基,稀疏性优势就体现不出来。

主循环里有个关键变量batchSize,它控制每一步用多少样本做稀疏编码和字典更新。设为 1 时是纯随机梯度下降,收敛路径震荡但计算最快;设为几十个样本时更接近小批量梯度下降,收敛更稳。代码中默认取 100,实际使用时可以根据训练集大小调整,一般经验是让 batchSize 占总样本数的 1%~10%。

3. 核心模块拆解:稀疏编码与字典更新的 MATLAB 实现

3.1 稀疏编码模块:软阈值迭代求解 Lasso

在线字典学习每一轮先固定字典,对当前批次中的每个样本求解如下优化问题:

min_a 0.5 * ||x - D*a||_2^2 + lambda * ||a||_1

这个问题的标准求解方式是近端梯度下降,也叫 ISTA。核心步骤是重复做梯度下降和软阈值收缩,直到精度满足要求。这段代码用两层循环实现:外层迭代 T 次,内层对批次中的每个样本分别求系数。

function A = sparse_coding(D, Xbatch, lambda, innerIter) % 稀疏编码:求解 lasso 问题 % D : 字典矩阵,大小为 m*k % Xbatch : 当前批次样本,大小为 m*b % lambda : L1 正则化系数,控制稀疏度 % innerIter: 内部迭代次数,默认 50 [m, k] = size(D); b = size(Xbatch, 2); A = zeros(k, b); for j = 1:b a = zeros(k, 1); for t = 1:innerIter grad = D' * (D * a - Xbatch(:, j)); a = a - 0.01 * grad; a = sign(a) .* max(abs(a) - lambda * 0.01, 0); end A(:, j) = a; end end

这段代码每一步先用梯度的负方向更新系数,然后用软阈值算子把绝对值小于阈值的元素直接置零。lambda * 0.01是阈值,其中 0.01 是梯度步长,这样写避免了单独计算步长。实际调参时如果发现系数收敛太慢,可以把 0.01 换成基于 Lipschitz 常数推导的步长,即 1 / max(eig(D'*D)),那样迭代次数可以降到 10 次以内。

软阈值算子sign(a) .* max(abs(a) - th, 0)是整段代码的核心,它等价于求解 L1 正则化问题的闭式解。注意这里每一步都要重新计算D * a,当字典和样本维度较大时会有计算浪费。更快的做法是提前缓存字典的 Gram 矩阵,但对在线学习来说,字典每轮都在变,缓存意义不大,反倒不如这种直接计算的方式容易维护。

3.2 字典更新模块:随机梯度上升

拿到当前批次的稀疏系数后,字典更新目标是减小重建误差。将目标函数对 D 求梯度,可以得到更新方向是残差矩阵乘以系数矩阵转置。因为我们在最小化误差,所以要用梯度下降的相反方向,也就是向负梯度方向调整。这段代码直接实现了该更新规则,乘上一个学习率eta。

function D = dict_update(D, A, Xbatch, eta) % 字典更新:随机梯度下降 % A : 当前批次的稀疏系数,大小为 k*b % Xbatch : 当前批次样本,大小为 m*b % eta : 学习率,默认 0.01 residual = Xbatch - D * A; D = D + eta * residual * A' / size(Xbatch, 2); colNorm = sqrt(sum(D.^2, 1)) + 1e-12; D = D ./ colNorm; end

整个更新只需要三行核心计算。residual是当前字典下对本批次样本的重建误差,residual * A'得到的是梯度的相反方向,除以批次大小是为了让学习率不随 batchSize 变化而波动。最后一步列归一化有两个作用:一是防止某些原子在迭代中范数趋近于零导致数值不稳定,二是让每个原子都处于同一尺度下,保证稀疏编码阶段的梯度计算有意义。

这里有个细节值得注意:学习率 eta 在在线学习中通常需要随时间衰减,否则后期系数会一直震荡。这份代码里直接用固定值,适合快速验证。实际使用时我会加上一个简单的衰减策略,比如eta = eta0 / sqrt(t),每轮用当前时间步 t 更新学习率,收敛效果会更稳定,特别是当训练数据分布不均时。

3.3 主循环组装:在线更新的完整流程

主函数odl.m把上面两个模块串起来,同时负责随机选取批次、记录迭代误差、返回最终结果。下面是主循环的精简版本:

function [D, A] = odl(X, dictSize, lambda, batchSize, maxIter) % 在线字典学习主函数 % X : 训练样本矩阵,每列为一个样本,大小为 m*n % dictSize : 字典原子数量,例如 256 % lambda : 稀疏正则化系数,例如 0.2 % batchSize: 每批次样本数,例如 50 % maxIter : 迭代轮数,map [m, n] = size(X); D = randn(m, dictSize); D = D ./ sqrt(sum(D.^2, 1)); A = zeros(dictSize, n); eta = 0.01; for t = 1:maxIter idx = randi(n, batchSize, 1); Xbatch = X(:, idx); Abatch = sparse_coding(D, Xbatch, lambda, 30); D = dict_update(D, Abatch, Xbatch, eta); if mod(t, 50) == 0 A(:, idx) = Abatch; reconErr = norm(X - D * A, 'fro')^2 / n; fprintf('iter %d recon error: %f\n', t, reconErr); end end A = sparse_coding(D, X, lambda, 100); end

主循环先随机抽取batchSize个样本,对这个批次做稀疏编码,然后更新字典。randi的抽样是放回抽样,允许同一轮中重复选到同一列,这在在线学习中是可接受的,因为每一步都在改变字典,重复样本对梯度的贡献也会被平均掉。每 50 轮用全部样本重新做一次稀疏编码,计算重建误差并输出,作为可视化的收敛指标。

参数 lambda 的选择会影响学习结果。lambda 过大会让系数全变成零,字典学不到内容;lambda 过小则系数不稀疏,字典趋向于训练样本的均值。这份代码没有内置交叉验证,我一般用网格搜索,比如在 0.05 到 0.5 之间按对数间隔取 5 个值,跑同样迭代次数看哪个重建误差最低。注意重建误差本身不是唯一指标,还要结合字典的可视化效果,比如原子是否清晰、是否包含明显的噪声模式。

4. 避坑与常见问题:跑这份 MATLAB 代码时踩过的坑

4.1 字典收敛停滞在初始化阶段

现象:训练 200 轮后重建误差还是最初值附近,字典可视化后是一团噪声。

原因:初始化字典随机性过强,而稀疏编码内部迭代次数太少,导致每轮得到的系数都极其稀疏甚至全零,字典更新梯度消失。另一个常见原因是学习率过大,初始几步梯度就把字典推到全零原子附近。

解决:把稀疏编码的内部迭代次数从 30 提到 100,观察系数非零比例。如果非零比例低于 5%,说明 lambda 太大,或者初始化字典的列没有归一化干净。检查初始化代码中D./sqrt(sum(D.^2,1))是否加了1e-12防止除零,这一步最容易因为某个原子恰好为全零向量而翻车。

4.2 训练后字典里出现大量重复原子

现象:可视化字典时看到好几列几乎是同一个方向的向量,原子数量明显稀疏。

原因:随机梯度更新中,某些原子因为初始值刚好处于有利位置,梯度一直带动它做小幅调整,而其他原子长期得不到有效更新。在线学习本身不鼓励原子之间的多样性,需要额外机制来避免"死原子"。

解决:在每轮字典更新后,检测原子之间的余弦相似度。如果两列原子的内积绝对值超过 0.95,就把其中一列替换成当前重建误差最大的样本的残差方向。代码实现时可以在dict_update.m的归一化之后加一个小函数,用D' * D计算 Gram 矩阵,找非对角元素中绝对值最大的几对,这是最直接的方式。

4.3 样本矩阵的维度方向搞反了

现象:运行主函数时报错Error using * / Matrix dimensions must agree,集中在D' * D或D * A处。

原因:这份代码约定训练样本是列向量,也就是X的每一列代表一个样本。很多人刚从图像处理习惯中切换过来,习惯把每行当作样本,导致字典初始化后维度不匹配。MATLAB 的错误信息只能提示维度不匹配,不会告诉你哪个方向反了。

解决:在主函数入口加一行断言assert(size(D, 1) == size(X, 1))。在读取自己的数据时,如果原数据是每行一个样本,先转置再训练。图像块切出来后也要确认方向:img2patch返回的应该是patchDim * patchDim行、patchCount列的矩阵。这种错误在迭代版代码里特别容易混,强烈建议把维度检查写进每个核心函数的第一行。

4.4 内存耗尽,尤其在可视化字典时崩溃

现象:运行show_dict时 MATLAB 直接无响应或报内存不足。

原因:字典矩阵本身并不大,但show_dict.m需要把每个原子重塑成图像块,再拼成一个大网格显示。当字典原子数是 1024 时,每个原子是 8×8,拼成 32×32 的网格,单是缩放显示就需要大量内存。另外,有些版本的imagesc会自动将数据复制为双精度,内存翻倍。

解决:显示前先对原子做归一化到 [0,1],用imshow(uint8(grid*255))而不是imagesc,后者会强制把图像矩阵转为 double。如果还崩溃,就把字典数量降到 128,或者把网格拼图函数里的cell2mat一次性拼图改成循环拼接。对这份代码来说,字典原子数常用 256,一般不会崩,除非你把训练样本维度拉到了 1024。

4.5 lambda 和迭代次数的噪声陷阱

现象:重建误差曲线先下降,但 100 轮之后突然上升,然后一直震荡。

原因:在线学习的随机性导致梯度噪声较大,固定学习率在后期无法收敛。更为隐蔽的是,lambda 没有随迭代动态调整,当字典变得更稀疏后,原定的 lambda 相对偏小,导致稀疏编码阶段过拟合。

解决:把学习率衰减加到主函数里,也就是在每轮迭代中eta = eta0 * 0.99^t。对 lambda 做简单预热:前 20 轮用lambda * 5让系数尽量稀疏,之后再降回目标值。这个技巧在很多在线稀疏编码实现里都有,虽然看起来有点违反直觉,但确实能避免早期噪声样本对字典的过度影响。跑完一轮完整的maxIter=500训练,再对比曲线就能明显看出差别。

5. 二次开发:把在线字典学习改造成图像去噪与持续学习工具

拿到这份代码后,最常见的改造需求是把它接到自己的数据上。第一步要替换的是数据预处理。假设你想做灰度图像去噪,可以先读入一张带噪声的图像,用img2patch.m将图像切成分块,然后把所有块拉直作为训练样本。切块时的重叠步长会影响去噪效果:步长等于块大小时是无重叠切块,速度快但去噪后容易出现块效应;步长设为块大小的一半,可以让相邻块之间互相约束,重建后再平均重叠区域,去噪质量明显提升。代码里默认的patchSize是 8,对应字典原子维度 64,这是传统实验中性价比最高的配置。

第二个改造点是替换稀疏编码求解器。现在sparse_coding.m用软阈值迭代,系数可能不是严格意义上最稀疏的。换成 OMP(正交匹配追踪)通常可以得到非零元更少的解,但要注意 OMP 需要指定稀疏度而不是 lambda,这会让超参数语义发生变化。改造时可以把sparse_coding.m的输入参数从 lambda 换成sparsity,在主循环中给每个样本固定稀疏度。实际跑下来,OMP 的收敛速度更快,因为不需要迭代,但每次求最小二乘的成本更高。如果训练集特别大,我一般先用软阈值版本跑一遍看字典形态,再用 OMP 版本微调。

第三个改造方向是让字典具备持续学习能力。在线字典学习天然适合增量场景:新数据到来时,不需要重训整个模型,只需用现有字典稀疏编码新样本,再在dict_update.m中以较小学习率做一次字典更新。实践时我会在每轮训练后把当前字典保存为.mat文件,下次加载时继续训练。这样做的风险是遗忘现象——字典会慢慢偏向最近见过的数据,对旧数据的重建误差上升。解决方法是维护一个小的重放缓冲区,从历史样本中随机抽取一小部分和新样本一起进入批次,这能显著缓解遗忘。你可以直接在odl.m的主循环里加一个bufferIdx数组,每轮训练时从中随机挑 10% 的样本补充进当前批次。

这段代码的最后一个优点是便于可视化验证。训练完成后,用show_dict.m查看字典原子,如果原子里出现了明显的边缘、纹理结构而不是纯噪声,说明字典学到的是数据本身的规律而不是过拟合到噪声上。对图像去噪应用,我会把重建误差曲线和去噪后的 PSNR 值一起打印出来,用utils/psnr.m对比原始干净图像和重建图像。如果 PSNR 比输入的含噪图像高出 2dB 以上,说明字典学习起到了正面作用。

我的血泪经验是:每次改完参数后,先跑一个 50 轮的小规模试验,用tic/toc估算总耗时,再用完整数据跑。否则很容易在 500 轮训练跑了半小时之后才发现 lambda 设错了,整个训练全部作废。从那以后我每次改参数都强制走一遍"小数据快速验证、可视化字典、再上全量"的流程,这个习惯帮我避开了很多无效训练。希望这份代码的拆解能让你少走一些弯路,祝跑通愉快。

本文还有配套的精品资源,点击获取

相关新闻

MCP AI监考重点监控的3类环境配置:虚拟机、远程桌面与容器沙箱

MCP AI监考重点监控的3类环境配置:虚拟机、远程桌面与容器沙箱

这两年在线考试系统越来越“卷”,我第一次看到MCP AI监考的环境检测报告时,说实话愣了一下。它不仅能盯着你的摄像头画面,还能直接告诉你:这台电脑是不是虚拟机、有没有开远程桌面、有没有跑模拟器。2025年才过了一半,…

2026/10/21 5:27:10 阅读更多 →
在线字典学习MATLAB实现:从稀疏编码到图像去噪

在线字典学习MATLAB实现:从稀疏编码到图像去噪

简介:这是一份基于MATLAB的在线字典学习实现代码,面向机器学习初学者和图像/信号处理方向的研究者,用于解决如何从序列数据中在线学习一组基字典的问题。与批处理方式不同,在线学习逐样本更新模型,适合内存有限或数据流…

2026/10/21 5:27:10 阅读更多 →
MuJoCo相机内参标定:用棋盘格在仿真中实现视觉系统精准对齐

MuJoCo相机内参标定:用棋盘格在仿真中实现视觉系统精准对齐

1. 先想清楚:仿真里为什么还要标定相机内参最近我在做一套视觉机械臂抓取的仿真验证,遇到一个特别尴尬的问题:MuJoCo 场景里明明可以直接指定相机视场角,渲染出来的图像看起来也完全正常,但把图像喂给视觉策略网络后&a…

2026/10/21 5:27:10 阅读更多 →

最新新闻

大模型岗面试风向:从八股到工程实战的考察要点与答题思路

大模型岗面试风向:从八股到工程实战的考察要点与答题思路

大模型岗的面试风向,这两年变化比很多人想象中要快得多。早几年问的是“Transformer里Attention怎么算”,现在再拿这套去准备,大概率会在二面三面栽跟头。我自己最近半年密集参与了多个大模型相关岗位的面试,也帮团队做过不少轮技…

2026/10/21 8:15:29 阅读更多 →
智慧高速公路整体解决方案:感知通信计算业务四层架构与落地接口清单

智慧高速公路整体解决方案:感知通信计算业务四层架构与落地接口清单

简介:这份2023智慧高速公路整体解决方案PPT,面向交通行业信息化规划人员、智慧高速项目方案设计与售前人员,以及关注车路协同、数字交通的研究者,系统梳理了智慧高速从政策背景到落地路径的完整框架。资源为单个pptx文件&#xff…

2026/10/21 8:15:29 阅读更多 →
STM32 Flash模拟EEPROM工业级掉电保存方案

STM32 Flash模拟EEPROM工业级掉电保存方案

简介:本资源是一份面向嵌入式初/中级工程师与电子专业学生的STM32 Flash模拟EEPROM技术实践指南,专为解决无内置EEPROM的STM32芯片(如F103系列)中关键参数掉电保存难题而设计。内容覆盖Flash与EEPROM特性对比、磨损均衡、坏块管理…

2026/10/21 8:15:29 阅读更多 →
PostgreSQL TableAM深入解析:从存储引擎原理到自定义实现

PostgreSQL TableAM深入解析:从存储引擎原理到自定义实现

1. 为什么PostgreSQL需要TableAM1.1 曾经只有一种“表”如果你在PostgreSQL社区待过几年,一定听过类似的吐槽:PostgreSQL什么都好,就是存储引擎只有一种。从任何角度看,它本质都是一个堆表(heap)系统&#…

2026/10/21 8:15:29 阅读更多 →
3DsMax木梳子建模全流程:从布线到木纹渲染实战

3DsMax木梳子建模全流程:从布线到木纹渲染实战

1. 为什么拿木梳子练手:建模之外的建模思维先说结论:木梳子是三维建模里被低估的绝佳练习素材。你别看它结构简单,无非一个弧形主体加一排齿,但真做起来,里面涉及的布线逻辑、对称处理、圆滑过渡、UV拆分这些环节&…

2026/10/21 8:15:29 阅读更多 →
微信小程序登录Demo全解析:从code到token的安全链路

微信小程序登录Demo全解析:从code到token的安全链路

做小程序开发的朋友,多多少少都在登录这件事上栽过跟头。微信小程序登录 demo 这个需求,看着挺简单——调一个wx.login,把 code 发给后端,后端换一下openid,再生成一个 token 返回。可真到自己写的时候,要处…

2026/10/21 8:14:26 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →