viterbi,维特比算法通俗理解

本文介绍了维特比算法,一种用于解决篱笆网络有向图中最短路径问题的动态规划算法。该算法对于使用隐含马尔可夫模型描述的问题至关重要,如数字通信和语音识别等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

维特比算法说白了就是动态规划实现最短路径,只要知道“动态规划可以降低复杂度”这一点就能轻松理解维特比算法

维特比算法是一个特殊但应用最广的动态规划算法,利用动态规划,可以解决任何一个图中的最短路径问题。而维特比算法是针对一个特殊的图——篱笆网络的有向图(Lattice )的最短路径问题而提出的。 它之所以重要,是因为凡是使用隐含马尔可夫模型(Hidden Markov Model,HMM)描述的问题都可以用它来解码,包括今天的数字通信、语音识别、机器翻译、拼音转汉字、分词等。——《数学之美》 ps 多处摘录此书,不再赘述。

篱笆网络有向图的特点是同一列节点有多个,并且和上一列节点交错地连接起来。同一列节点代表同一个时间点上不同的状态的并列,大概因为这种一列一列整齐的节点和交错的边很像篱笆而得名。

假设上图每一列分别有n1……nn个节点,如果不使用动态的话,那么计算复杂度就是O(n1*n2……nn)。

而维特比算法的精髓就是,既然知道到第i列所有节点Xi{j=123…}的最短路径,那么到第i+1列节点的最短路径就等于到第i列j个节点的最短路径+第i列j个节点到第i+1列各个节点的距离的最小值。

这是一句大白话,所谓中文伪码。

分析一下复杂度,假设整个篱笆有向图中每一列节点最多有D个(也就是图的宽度为D),并且图一共有N列,那么,每次计算至多计算D*D次(从i列的D个节点中挑一个计算到i+1列D个节点的距离)。至多计算N次。那么复杂度骤减为O(ND2),远远小于穷举O(DN)。

如果你需要一段开箱即用的维特比算法代码,请参考《通用维特比算法的Java实现》。

以下是一个使用PyTorch实现BiLSTM-CRF模的标准demo,并附有逐行注释和通俗易懂的说明: ```python import torch import torch.nn as nn # 定义BiLSTM-CRF模型 class BiLSTM_CRF(nn.Module): def __init__(self, num_tags, vocab_size, embedding_dim, hidden_dim): super(BiLSTM_CRF, self).__init__() self.embedding = nn.Embedding(vocab_size, embedding_dim) self.lstm = nn.LSTM(embedding_dim, hidden_dim // 2, bidirectional=True, batch_first=True) self.hidden2tag = nn.Linear(hidden_dim, num_tags) self.transitions = nn.Parameter(torch.randn(num_tags, num_tags)) self.start_transitions = nn.Parameter(torch.randn(num_tags)) self.end_transitions = nn.Parameter(torch.randn(num_tags)) self.num_tags = num_tags self.hidden_dim = hidden_dim def _forward_alg(self, feats): T = feats.size(1) dp = torch.full((1, self.num_tags), -10000.) dp[0][self.start_tag] = 0. for t in range(T): dp = dp + feats[:, t].unsqueeze(1) + self.transitions dp = torch.logsumexp(dp, dim=2).unsqueeze(2) dp = dp + self.end_transitions return torch.logsumexp(dp, dim=2)[0] def _score_sentence(self, feats, tags): T = feats.size(1) score = torch.zeros(1) tags = torch.cat([torch.tensor([self.start_tag], dtype=torch.long), tags]) for t in range(T): score = score + self.transitions[tags[t+1], tags[t]] + feats[:, t, tags[t+1]] score = score + self.end_transitions[tags[-1]] return score def _viterbi_decode(self, feats): backpointers = [] T = feats.size(1) dp = torch.full((1, self.num_tags), -10000.) dp[0][self.start_tag] = 0. for t in range(T): next_tag_var = dp + self.transitions viterbivars_t, bptrs_t = torch.max(next_tag_var, dim=2) dp = viterbivars_t + feats[:, t] backpointers.append(bptrs_t.tolist()) terminal_var = dp + self.end_transitions path_score, best_tag_id = torch.max(terminal_var, dim=1) best_path = [best_tag_id.item()] for bptrs_t in reversed(backpointers): best_tag_id = bptrs_t[0][best_tag_id.item()] best_path.append(best_tag_id) start = best_path.pop() assert start == self.start_tag best_path.reverse() return path_score, best_path def forward(self, sentence): lstm_feats = self._get_lstm_features(sentence) score, tag_seq = self._viterbi_decode(lstm_feats) return score, tag_seq def _get_lstm_features(self, sentence): embeds = self.embedding(sentence) lstm_out, _ = self.lstm(embeds) lstm_feats = self.hidden2tag(lstm_out) return lstm_feats # 定义隐状态和观测状态 states = ['B', 'I', 'O'] observations = ['PER', 'LOC', 'ORG'] # 定义标签数量、词汇表大小、词向量维度和隐藏状态维度 num_tags = len(states) vocab_size = len(observations) embedding_dim = 100 hidden_dim = 256 # 初始化BiLSTM-CRF模型 model = BiLSTM_CRF(num_tags, vocab_size, embedding_dim, hidden_dim) # 定义输入句子 sentence = torch.tensor([[1, 2, 0, 0, 0]]) # 假设输入句子是[1, 2, 0, 0, 0] # 使用BiLSTM-CRF模型进行解码 score, tag_seq = model(sentence) print(score) print(tag_seq) ``` 模型解释和原理技术说明: 1. BiLSTM-CRF是一种结合了双向长短时记忆网络(BiLSTM)和条件随机场(CRF)的序列标注模型,常用于命名实体识别、词性标注等任务。 2. 在上述代码中,首先导入了PyTorch库中的`nn.Module`模块。 3. 定义了一个BiLSTM_CRF模型类,继承自`nn.Module`。 4. 在BiLSTM_CRF模型类的初始化方法中,定义了模型的各个组件,包括嵌入层(Embedding)、双向LSTM层(LSTM)、线性映射层(Linear)、转移矩阵(transitions)、起始转移概率(start_transitions)和结束转移概率(end_transitions)。 5. `_forward_alg`方法实现了前向算法,用于计算给定观测序列的分数。 6. `_score_sentence`方法用于计算给定观测序列和标签序列的得分。 7. `_viterbi_decode`方法实现了维特比算法,用于解码最优路径。 8. 在前向传播方法中,首先获取句子的嵌入表示,并通过双向LSTM层得到每个位置的特征表示。 9. 将LSTM输出结果经过线性映射层得到发射概率。 10. 使用维特比算法进行解码,得到最优路径的分数和标签序列。 11. 初始化BiLSTM_CRF模型实例,并定义隐状态和观测状态的集合、标签数量、词汇表大小、词向量维度和隐藏状态维度。 12. 定义输入句子。 13. 调用BiLSTM_CRF模型的前向传播方法进行解码,得到最优路径的分数和标签序列。 14. 打印最优路径的分数和标签序列。 通过以上代码和解释,一个NLP新手可以了解到: - BiLSTM-CRF是一种结合了双向长短时记忆网络(BiLSTM)和条件随机场(CRF)的序列标注模型,常用于命名实体识别、词性标注等任务。 - 在使用PyTorch实现BiLSTM-CRF模型时,需要定义一个继承自`nn.Module`的自定义模型类,并实现前向传播方法和一些辅助方法。 - 模型类中定义了各个组件,包括嵌入层、双向LSTM层、线性映射层、转移矩阵和起始/结束转移概率。 - 前向传播方法中,首先获取句子的嵌入表示,并通过双向LSTM层得到每个位置的特征表示。 - 然后,将LSTM输出结果经过线性映射层得到发射概率。 - 最后,使用维特比算法进行解码,得到最优路径的分数和标签序列。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值