#markov #hmm #viterbi

nightly hmmmm

高效且易于使用的隐马尔可夫模型

3 个版本

0.1.2 2022 年 11 月 17 日
0.1.1 2022 年 11 月 17 日
0.1.0 2022 年 11 月 17 日

#582 in 数学

MIT 许可证

17KB
340

hmmmm 🤔

Crates.io GitHub Workflow Status (branch) Crates.io Crates.io

又一个恰如其分的名为 Hidden-Markov Model 的 Rust 库。

重要提示:此包依赖于功能 generic_const_exprs。目前,此包的使用仅限于与 nightly Rust 频道一起使用。

使用方法

安装

cargo add hmmmm --features derive

状态 + 观察值

要创建一个 Hmm,我们首先需要两个枚举,分别对应隐马尔可夫模型的状态和观察值。这可以通过使用 hmmmm_derive 包中的 #[derive(State)]#[derive(Observation)] 过程宏来完成

#[repr(u8)]
#[derive(State)]
enum Condition {
  Healthy,
}

#[repr(u8)]
#[derive(Observation)]
enum Feeling {
  Normal,
  Cold,
  Dizzy,
}

注意,枚举定义需要 repr(u8) 属性,因为我们需要的枚举是: 1) 尽可能小,以实现高效计算; 2) 可以轻松转换为其自身和 u8 / usize。如果枚举上没有这个属性,衍生宏将会抛出编译错误。

概率

Hmm 需要 3 个不同的概率矩阵

  1. 初始(状态)概率 - [f64; N]
  2. 转移概率 - [[f64; N]; N]
  3. 发射概率 - [[f64; M]; N]

其中 N 是可能的状态数量,O 是可能的观察值数量。

这些可以

  • 手动声明,例如。
let pr_initial: [f64; 2] = [0.6, 0.4]; // [Healthy, Fever]
  • 通过 hmmmm::utils 中的方法声明,例如:
let pr_initial: [f64; 2] = pr_i(|cond| match cond {
  Condition::Healthy => 0.6,
  Condition::Fever => 0.4,
});

构建HMM模型

现在我们有了状态、观察值和相应的概率矩阵,我们可以构建我们的 Hmm

let pr_initial: [f64; 2] = [0.6, 0.4];
let pr_transition: [[f64; 2]; 2] = [
  [0.7, 0.3],
  [0.4, 0.6]
];
let pr_emission: [[f64; 3]; 2] = [
  [0.5, 0.4, 0.1],
  [0.1, 0.3, 0.6]
]

let hmm = Hmm::<Condition, Feeling>::new(
  pr_initial,
  pr_transition,
  pr_emission
);

算法

维特比算法

维基百科

维特比算法在给定观察值序列的情况下,获取了隐藏状态的似然序列的最大后验估计(MAP)。

输入:观察值序列 - &Vec<O>

输出:包含MAP隐藏状态序列对数概率(以2为底)和相应的隐藏状态序列的元组 - (f64, Vec<S>)

示例

/* Using the HMM `hmm` from the previous section */

let signal = vec![Feeling::Normal, Feeling::Cold, Feeling::Dizzy];
let (pr, sequence) = hmm.map_estimate::<Viterbi>(&signal);

/*

pr = −6.04739805022
sequence = [Condition::Healthy, Condition::Healthy, Condition::Fever]

*/

依赖项

~370–710KB
~13K SLoC