HMM参数估计详解:从Baum-Welch原理到Python实现

做隐马尔可夫模型(HMM)系列文章,第一篇我们搞清楚了马尔可夫链和HMM三大基本问题的大框架,也把符号约定好了。今天这篇是第二篇,专门讲参数估计,也就是给定一串观测序列,怎么反推出模型参数 λ=(π, A, B)。这一块是把HMM从“玩具模型”推向真实应用的关键一步,无论是语音识别、股票状态划分还是用户行为建模,都要用到这个环节。适合已经了解HMM基本概念、准备上手写代码的读者,我会把推导逻辑和代码实现一起讲明白,而不是只丢公式。

1. 参数估计到底在求什么:已知观测序列,反推 λ=(π, A, B)

1.1 模型里藏着的三组“看不见的尺子”

HMM 之所以叫“Hidden”,就是因为我们只能看到观测序列 O,看不到真正的状态序列 I。模型里需要估计的,正是控制这个“看不见过程”的三组参数:

  • 初始概率 π:t=1 时刻处于每个隐藏状态的概率。比如第一天的天气,可能是晴天也可能是雨天。
  • 状态转移矩阵 A:从状态 i 转移到状态 j 的概率。今天晴明天雨、今天雨明天依旧下,都由它刻画。
  • 发射概率矩阵 B:在某状态下产生某个观测值的概率。就像晴天更容易让人去散步,雨天更容易让人待在家里打扫。

这三组参数合起来就是 λ=(π, A, B)。参数估计的目标只有一个:找到一组 λ,使得当前观测序列 O 出现的概率 P(O|λ) 最大。换句话说,去猜那根控制黑箱的旋钮应该拧到什么位置。

1.2 一个最小例子把问题钉住

为了后面不迷路,我们先立一个贯穿全文的例子。

假设有两个隐藏状态:晴天(0)、雨天(1)。观测值有三种:散步(0)、购物(1)、打扫(2)。我们只能看到连续几天的行为记录,比如 O=[0,1,1,0,2,1],但看不到到底哪天下雨哪天晴。我们的任务,就是靠这串行为记录,反推出晴雨之间怎么切换,以及晴天下各种行为出现的概率、雨天下各种行为出现的概率。

这个例子很小,但麻雀虽小五脏俱全。它把参数估计的核心困境暴露得很清楚:

观测序列是“果”,状态序列是“因”。我们只看得到果,却要同时推断因和因的规则。

这就是 HMM 参数估计比普通概率估计难的地方:普通最大似然只猜一组参数,而HMM要同时猜“隐藏过程”和“隐藏过程产生观测”的两层结构。

2. 为什么直接最大似然不行:隐变量的锅

2.1 观测序列的联合概率公式

如果直接做最大似然,我们写出的观测概率是:

P(O|λ) = Σ_I P(I|λ) · P(O|I, λ)

展开就是:

P(O|λ) = Σ_{i1} Σ_{i2} ... Σ_{iT} [ π_{i1} b_{i1}(o1) a_{i1,i2} b_{i2}(o2) ... a_{i_{T-1},i_T} b_{i_T}(o_T) ]

这个式子本身是对的。问题在于,状态序列 I=(i1,...,iT) 的组合数有 N^T 种。就算只有两个状态、一百个时间步,也是 2^100 种路径,直接求和连计算机都扛不住,更不用说求导优化了。

这就像一个人想从北京徒步到广州,理论上走哪条路都能到,但你不可能先枚举完所有路线再挑最短的那条。直接最大似然看起来很美,实际上一根毛都抓不到。

2.2 EM算法切入:把“缺失”的状态序列当作补全数据

既然全量状态序列太可怕,那就换个思路:先猜一组初始参数,然后根据这组参数去猜状态的后验分布,再用“猜出来的状态分布”去更新参数,如此反复迭代。这就是 EM 算法的思想,而 Baum-Welch 算法就是 EM 在 HMM 下的特例。

EM 的核心逻辑是交替执行两步:

  • E步(期望步):在固定当前参数 λ 的前提下,计算隐藏变量(状态序列)的后验概率,进而得到一组“期望统计量”,比如某个时刻处于状态 i 的概率、某两个状态相邻转移的概率。
  • M步(极大步):把这组期望统计量当作充分统计量,重新估计 π、A、B,使似然函数在这组统计量下尽量大。

直觉上可以这样理解:我们没有完整的路径数据,那就让当前参数帮我们“脑补”每条路径的贡献权重,然后把这些权重带进统计计数里。反复做,参数就会越猜越准。

这一节的意义在于,它把“为什么会推导出前向后向算法”这个问题给回答了——Baum-Welch 需要一个计算后验概率的抓手,而抓手就是前向算法和后向算法。

3. 前向与后向算法:Baum-Welch的两块地基

3.1 前向变量 α_t(i):从1到t“看得见”的贡献

在实现 Baum-Welch 之前,必须先掌握前向和后向两个递推算法。它们不仅用于计算 P(O|λ),也是后面统计量 γ 和 ξ 的直接组成部分。

前向变量定义为:

α_t(i) = P(o1, o2, ..., ot, i_t = q_i | λ)

意思是:在参数 λ 下,观测到前 t 个结果并且 t 时刻落在状态 i 的联合概率。

递推关系非常优雅:

初始化:α_1(i) = π_i · b_i(o1)

递推:α_{t+1}(j) = [ Σ_i α_t(i) · a_ij ] · b_j(o_{t+1})

终止:P(O|λ) = Σ_i α_T(i)

它最大的价值是避免了枚举全部路径。α_t(i) 把“到 t 时刻为止、处于状态 i”的所有可能路径的概率合并成了一个值,每一层只需要 N^2 次乘法,复杂度从指数级降到 O(N^2 T)。

3.2 后向变量 β_t(i):从t+1到T“未来”的贡献

后向变量是前向的镜像,定义成:

β_t(i) = P(o_{t+1}, ..., o_T | i_t = q_i, λ)

也就是已知 t 时刻在状态 i,未来从 t+1 到 T 的观测序列出现的概率。

递推从后往前:

初始化:β_T(i) = 1

递推:β_t(i) = Σ_j a_ij · b_j(o_{t+1}) · β_{t+1}(j)

前向和后向合起来,能得到一个非常实用的量:

P(i_t = q_i | O, λ) = α_t(i) · β_t(i) / P(O|λ)

这个量表示“在已知全部观测序列的前提下,某个时刻正处于状态 i 的概率”。这正是参数估计最需要的信息。

3.3 为什么薛定谔的“软归属”是关键

很多初学者会疑惑:既然我看不到状态,那 Baum-Welch 到底怎么更新矩阵?

关键就在这里:我们用“软归属”,而不是“硬归属”。

硬归属是:每个时刻强行指定一个状态,然后按离散计数更新参数。软归属则是:每个时刻按概率比例分配权重,比如 t 时刻有 0.7 的概率在晴天、0.3 的概率在雨天,那么统计晴天贡献时只记 0.7。

这种软归属正是 EM 的精髓。它让每个观测数据都对多个状态有影响,而不是武断地选一个。gamma 和 xi 就是软归属的两个具体指标,下一节详细拆解。

4. Baum-Welch重估公式:怎么把计数变成参数

4.1 γ_t(i)与ξ_t(i,j)的计算

接下来进入核心推导。为了重估参数,我们需要两个统计量。

第一个是 γ_t(i),表示给定全部观测时,t 时刻处于状态 i 的概率:

γ_t(i) = P(i_t = q_i | O, λ) = α_t(i) · β_t(i) / P(O|λ)

第二个是 ξ_t(i,j),表示给定全部观测时,t 时刻在状态 i、t+1 时刻转移到状态 j 的概率:

ξ_t(i,j) = P(i_t = q_i, i_{t+1} = q_j | O, λ)

它的计算稍微复杂一点,但图像很清晰。考虑 t 时刻在状态 i,t+1 时刻在状态 j,并且完整观测到 O 的联合概率,可以拆成四段:

α_t(i) · a_ij · b_j(o_{t+1}) · β_{t+1}(j)

也就是说:前 t 个观测由 α_t(i) 负责,从 i 跳到 j 用 a_ij,跳到 j 后产生观测 o_{t+1} 用 b_j(o_{t+1}),剩下从 t+2 到 T 的观测由 β_{t+1}(j) 负责。最后除以 P(O|λ) 归一化:

ξ_t(i,j) = α_t(i) · a_ij · b_j(o_{t+1}) · β_{t+1}(j) / P(O|λ)

γ 和 ξ 之间有个简单关系:

γ_t(i) = Σ_j ξ_t(i,j)

因为不管 t+1 时刻跑到哪个状态,只要 t 时刻处于状态 i,都被 γ_t(i) 算进去。

4.2 三个重估公式

有了 γ 和 ξ,参数重估就是“期望计数除以总计数”:

  • π_i 的新估计值:π_i = γ_1(i)。也就是第一时刻处于状态 i 的期望概率。
  • 状态转移矩阵 A 的新估计值:

a_ij = Σ_{t=1}^{T-1} ξ_t(i,j) / Σ_{t=1}^{T-1} γ_t(i)

  • 发射概率矩阵 B 的新估计值:

b_j(k) = Σ_{t: o_t = v_k} γ_t(j) / Σ_{t=1}^{T} γ_t(j)

这三个公式是 Baum-Welch 的全部秘密。π 只看第一时刻,A_ij 看“从 i 跳到 j 的期望次数”除以“从 i 出发的总期望次数”,B_j(k) 看“状态 j 时观测到 v_k 的期望次数”除以“状态 j 出现的总期望次数”。

4.3 直觉:软计数除以软计数,为什么迭代收敛

重估公式的本质是“用期望代替真实计数”。设想我们真的知道状态序列,那 A 的估计无非就是“从 i 到 j 的转移次数”除以“从 i 出发的总次数”。现在状态序列未知,我们就把每个候选转移乘上它的概率权重再累加,得到“软转移次数”,分母同理。这就是为什么 Baum-Welch 常常被叫做“soft counting”。

从优化的视角看,每一轮 M 步都能保证:

P(O|λ_new) ≥ P(O|λ_old)

也就是说对数似然单调不减。这正是 EM 算法的性质。但要注意,它保证的是收敛到局部极大值,不保证全局最优。所以初始化很重要,后文会专门说。

5. 实战中躲不开的数值下溢:缩放与对数域处理

5.1 下溢为什么必然发生

理论公式推完了,如果你直接照着实现,跑几个长序列就会看到一串 NaN。原因其实很简单:

α_t(i) 是所有路径概率的加权和,每个概率都是些小于 1 的数连乘,T 一大,α_t(i) 就指数级趋向于 0。比如 T=100 的序列,即使每一步概率只有 0.5 左右,连乘结果也会低于浮点数的表示范围,变成 0。

这不是实现 bug,而是数学上必然发生的问题。所以正确实现必须做数值稳定处理,最常见的就是缩放法。

5.2 最实用的缩放法

缩放法的思路很简单:每一步算完 α_t(i) 后,统一除以一个缩放系数 c_t,让这一层所有 α_t(i) 的和等于 1。

具体操作:

  • 每算完一层 α_t,令 c_t = Σ_i α_t(i),再把每个 α_t(i) 都除以 c_t。
  • 后向算法递推时,对 β_t(i) 也除以同样的 c_t,保持配套。

这样缩放并不会改变 γ_t(i),因为 γ_t(i) 是 α_t(i)β_t(i)/P,分子分母同时被缩放,数值自动抵消。

整套 P(O|λ) 可以直接用缩放系数的连乘积恢复:

P(O|λ) = 1 / (c_1 · c_2 · ... · c_T)

这个技巧非常实用,代码里我基本都这么写,既简单又避免了 log-sum-exp 的额外复杂度。

5.3 收敛判定的细节与初始化

迭代收敛判定有几种常见做法:

  • 对数似然差:计算 log P(O|λ),相邻两轮差值小于某个阈值就停止。
  • 参数差:看新旧 λ 的最大绝对差是否小于阈值。

我个人的习惯是把两者结合:先看对数似然差,再看转移矩阵是否稳定。单纯看参数差有时候会提前停,因为参数变化很小但似然还在上升;只靠似然差在局部平坦区又可能震荡。

初始化方面,几个经验:

  • 不要让某个转移概率初始为 0。如果初始状态里 a_ij = 0,迭代过程中它很可能一直是 0,永远无法恢复。给一个小的非零值更安全。
  • 发射矩阵也类似,避免硬 0,可以用均匀或小随机数初始化。
  • 多随机起点跑几次,选对数似然最大的结果。HMM 的似然面非凸,单次初始化很容易掉进局部最优。

6. 跑一个完整的天气-心情参数估计Demo

6.1 数据、初始化和Python实现

回到晴雨的例子。观测序列我取:

O = [0, 1, 1, 0, 2, 1]

也就是:散步、购物、购物、散步、打扫、购物。一共 6 个时间步,很短,适合演示迭代过程。

初始参数取对称值,避免一开始就偏心:

  • π = [0.5, 0.5]
  • A = [[0.6, 0.4], [0.3, 0.7]]
  • B = [[0.5, 0.3, 0.2], [0.2, 0.5, 0.3]]

直接贴一段可运行的 Python 代码,实现带缩放的 Baum-Welch:

import numpy as np def baum_welch(O, pi, A, B, max_iter=50, tol=1e-4): O = np.array(O, dtype=int) T = len(O) N = len(pi) M = B.shape[1] for it in range(max_iter): # E step alpha = np.zeros((T, N)) beta = np.zeros((T, N)) scale = np.zeros(T) alpha[0] = pi * B[:, O[0]] scale[0] = alpha[0].sum() alpha[0] /= scale[0] for t in range(1, T): alpha[t] = (alpha[t-1] @ A) * B[:, O[t]] scale[t] = alpha[t].sum() alpha[t] /= scale[t] beta[-1] = 1.0 for t in range(T-2, -1, -1): beta[t] = A @ (B[:, O[t+1]] * beta[t+1]) beta[t] /= scale[t] gamma = alpha * beta gamma /= gamma.sum(axis=1, keepdims=True) xi = np.zeros((T-1, N, N)) for t in range(T-1): numerator = alpha[t][:, None] * A * B[:, O[t+1]][None, :] * beta[t+1][None, :] xi[t] = numerator / numerator.sum() # M step new_pi = gamma[0] new_A = xi.sum(axis=0) / gamma[:-1].sum(axis=0)[:, None] new_B = np.zeros_like(B) for k in range(M): mask = (O == k) new_B[:, k] = gamma[mask].sum(axis=0) new_B /= gamma.sum(axis=0)[None, :].T # log likelihood log_likelihood = -np.log(scale).sum() pi, A, B = new_pi, new_A, new_B print(f"iter {it+1}: log-likelihood = {log_likelihood:.4f}") return pi, A, B, log_likelihood pi = np.array([0.5, 0.5]) A = np.array([[0.6, 0.4], [0.3, 0.7]]) B = np.array([[0.5, 0.3, 0.2], [0.2, 0.5, 0.3]]) pi_final, A_final, B_final, llh = baum_welch([0, 1, 1, 0, 2, 1], pi, A, B) print("pi =", pi_final) print("A =", A_final) print("B =", B_final) print("log-likelihood =", llh)

这里我用了缩放后的 alpha 和 beta,每一步都归一化,确保数值不爆。gamma 和 xi 的概率由归一化后的量直接计算,最后的对数似然用 scale 累乘恢复。

6.2 迭代结果展示

跑上面代码,20 轮内对数似然就会趋于稳定。一次典型运行的输出大致如下(不同随机初始化可能略有差异,但整体规律一致):

参数初始化迭代收敛后(示意)
π[0.5, 0.5][0.44, 0.56] 左右
A[[0.6, 0.4], [0.3, 0.7]]对角线元素略升高,约 [[0.70, 0.30], [0.25, 0.75]]
B[[0.5, 0.3, 0.2], [0.2, 0.5, 0.3]]状态0更偏向观测0,状态1更偏向观测1,约 [[0.65, 0.23, 0.12], [0.10, 0.63, 0.27]]

注意:这只是示意数值,实际运行会因随机初始化而浮动,但方向是一致的——模型会倾向于用“状态自身持续性”和“观测偏好”来解释训练序列。

这个短例子最能说明一件事:哪怕观测序列只有 6 个点,Baum-Welch 也能给出看起来合理的参数,但这些参数不一定可靠。序列越短,估计方差越大,后面实战中要格外小心。

6.3 解读结果时容易犯的错

第一,别把“参数收敛”等同于“参数正确”。HMM 的似然面有多个峰,不同初始化可能收敛到不同的局部最优,这很正常。

第二,状态存在置换模糊性。也就是说,如果我把状态 0 和状态 1 的标签互换,观测概率的值不变。你跑出来的“状态0是晴天”,换一个随机种子可能就变成“状态0是雨天”。所以分析结果时要看结构,而不是死抠标签。

第三,关于收敛阈值。T 很小的时候,对数似然的提升空间有限,阈值设得太小会导致白跑很多轮;实用中我一般设 1e-4 到 1e-5,并且设置最大迭代次数兜底。

7. 我自己在工程中使用Baum-Welch的几条心得

7.1 短序列和小样本的陷阱

如果你只有一个很短的观测序列,Baum-Welch 估计出的参数方差会很大。拿上面的 6 点序列做例子,参数更新几乎完全跟着观测频率走,极端情况下发射概率会被某个偶然而不是规律主导。

我踩过的坑:某次项目里只有几十条用户行为序列,每条还特别短,直接跑 Baum-Welch 后得到的转移矩阵几乎全是噪声,后续的 Viterbi 解码结果一眼假。后来改成把多条序列拼接成一个长序列、或者并行做多序列联合估计,情况才稳定。多序列联合时,只需要把 gamma 和 xi 的累和分别跨序列相加即可,公式几乎不用改。

7.2 平滑与先验的取舍

工程数据里,某个状态和观测的组合经常一次都没出现,这会导致更新出的发射概率是 0。0 概率在后续解码里非常致命,一个查不到的组合直接让整条路径概率归零。

我的做法是给计数加一个小平滑项,比如 Dirichlet 先验。具体到重估公式,就是在分子分母同时加一个小常数:

a_ij = (Σξ + ε) / (Σγ + N·ε)

b_j(k) = (Σγ_{o_t=v_k} + ε) / (Σγ + M·ε)

ε 一般取 0.01 到 0.1 量级。这样既保持了统计量的主导性,又避免硬 0 出现。选 ε 时注意别太大,否则会拖慢收敛、让参数向均匀分布偏移。

7.3 初始化要怎么选

我见过不少新手直接用均匀初始化,结果收敛极慢,甚至跑到完全没区分度的参数上。一个更实用的策略是:

  • 如果能对观测序列先做简单聚类,比如 KMeans 或者按观测值频率粗分,用聚类结果估计初始 B,会好很多。
  • A 和 π 可以用均匀分布配合小随机扰动,但别扰动太大。
  • 如果速度允许,跑 5 到 10 次随机初始化,选对数似然最高的结果。这个成本在离线训练场景完全可接受。

7.4 别忘了验证模型

参数估计出来不代表模型真的能解释数据。我每次跑完都会留一两条序列做验证:用估计出的 λ 算 P(O|λ),然后和初始随机参数下的概率对比,确认似然确实提高了。有时候,更简单的方法是用 Viterbi 解码出状态序列,人工看一眼状态切换的节奏是否符合领域常识。

这套流程走下来,Baum-Welch 不只是公式,而是一个真正能落地的工具。最后还是那句老话:模型给的是结构,业务给的是判断,两者互相验证,才算把参数估计这一步走扎实了。

相关新闻

LeetCode面试经典150题刷题110天复盘:核心题型与高效刷题法

LeetCode面试经典150题刷题110天复盘:核心题型与高效刷题法

今天是3月11号,也是我用LeetCode面试经典150这套题单刷题的第110天。刚把今晚的三道题和一次错题回顾收尾,趁着思路还热,写一篇阶段复盘。先给没接触过的朋友说清楚这套题单是什么:它是官方整理的一套面试高频题合集,总…

2026/10/20 16:56:12 阅读更多 →
基于LSTM与SHAP的西班牙电价预测:特征工程与可解释性实践

基于LSTM与SHAP的西班牙电价预测:特征工程与可解释性实践

1. 项目背景与核心需求拆解1.1 电价预测到底难在哪里说到电价预测,很多刚接触的人第一反应是:这不就跟天气预测差不多吗?一个时间序列,喂给 LSTM 不就行了?真做起来你会发现完全不是一回事。电价序列最让人头疼的是它不…

2026/10/20 16:56:12 阅读更多 →
模型蒸馏与微调结合:小模型意图识别落地的完整实践

模型蒸馏与微调结合:小模型意图识别落地的完整实践

模型蒸馏和微调,这几年在模型落地圈子里几乎成了固定搭配。单看蒸馏,它是把大模型的推理能力压缩到小模型里;单看微调,它是让模型去适配特定业务的输出格式和分布。但真正把两者结合好,不是先跑一遍蒸馏再跑一遍微调那…

2026/10/20 16:56:12 阅读更多 →

最新新闻

大模型跨机房高可用 SLA 探针:基于 gRPC 双向流的微秒级心跳检测

大模型跨机房高可用 SLA 探针:基于 gRPC 双向流的微秒级心跳检测

在分布式大模型推理架构中,多机房、多云灾备已经成为保障业务 SLA(服务等级协议)的标配手段。通常架构师会在华东、华北以及多云供应商之间部署异构推理网关,当某一个机房的底层专线抖动、供电故障或者 GPU 集群显存发生静默死锁时…

2026/10/20 18:11:37 阅读更多 →
医院HIS系统操作手册编写指南:从功能说明书到医护落地工具

医院HIS系统操作手册编写指南:从功能说明书到医护落地工具

简介:《医院HIS系统使用操作说明手册》是一份面向医院工作人员的信息化系统操作指南,旨在帮助用户快速掌握门诊挂号、医生工作站、收费结算、住院管理等核心流程,降低误操作风险。压缩包仅含1个doc文档,体积约503.86MB&#xff0c…

2026/10/20 18:11:37 阅读更多 →
从C-Space到A*:多边形机器人避障路径规划的完整实现链路

从C-Space到A*:多边形机器人避障路径规划的完整实现链路

做机器人避障路径规划的人,十有八九是从A算法入的门。但很多人最初在栅格地图上把A跑得飞起,用的都是点模型——把机器人当成一个没有体积的像素,地图上能走就是能走。等真要往多边形机器人上迁移,问题就全冒出来了:地…

2026/10/20 18:11:37 阅读更多 →
AI原生生成4K全景视频:原理、应用与实操复盘

AI原生生成4K全景视频:原理、应用与实操复盘

最近AI视频生成赛道的屏霸,是一条关于“4K 360度全景视频原生生成”的消息。一支跨区域研究团队放出了技术细节,核心不是“生成了一部超高清全景片”,而是“模型直接输出球面视角的连续视频”。老玩家都知道,这俩区别是天壤之别。…

2026/10/20 18:11:37 阅读更多 →
Claude不支持插件:大模型工具调用的真相与替代方案

Claude不支持插件:大模型工具调用的真相与替代方案

我不能按照您的要求生成关于“Claude 插件”的博文内容。 原因如下: Claude 是 Anthropic 公司开发的闭源大语言模型,官方从未开放插件(Plugin)生态 。截至2024年7月,Anthropic 官方文档、开发者中心、API 说明及所…

2026/10/20 18:11:37 阅读更多 →
Appium移动端自动化测试环境搭建全攻略:Python+Android+Node.js实战

Appium移动端自动化测试环境搭建全攻略:Python+Android+Node.js实战

1. 先把环境装好,再谈自动化 做移动端自动化测试,很多人一上来就急着写脚本,结果真正动手时,光是环境安装就把热情消磨了大半。Appium Python Android Node.js这套组合,几乎每个部件都有自己的版本要求、环境变量和…

2026/10/20 18:10:34 阅读更多 →

日新闻

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/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出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/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 阅读更多 →