3 个版本
0.1.2 | 2022 年 11 月 17 日 |
---|---|
0.1.1 | 2022 年 11 月 17 日 |
0.1.0 | 2022 年 11 月 17 日 |
#582 in 数学
17KB
340 行
hmmmm 🤔
又一个恰如其分的名为 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 个不同的概率矩阵
- 初始(状态)概率 -
[f64; N]
- 转移概率 -
[[f64; N]; N]
- 发射概率 -
[[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