Tôi đang thực hiện một dự án Python trong đó tôi muốn sử dụng Thuật toán Viterbi. Có ai biết về một thực hiện đầy đủ Python của thuật toán Viterbi? Tính chính xác của một trên Wikipedia dường như được đề cập trên trang thảo luận. Có ai có một con trỏ?Thực hiện Python Thuật toán Viterbi
Trả lời
Hmm Tôi có thể đăng bài của tôi. Nó không đẹp mặc dù, xin vui lòng cho tôi biết nếu bạn cần làm rõ. Gần đây tôi đã viết phần này cho phần gắn thẻ giọng nói cụ thể.
class Trellis:
trell = []
def __init__(self, hmm, words):
self.trell = []
temp = {}
for label in hmm.labels:
temp[label] = [0,None]
for word in words:
self.trell.append([word,copy.deepcopy(temp)])
self.fill_in(hmm)
def fill_in(self,hmm):
for i in range(len(self.trell)):
for token in self.trell[i][1]:
word = self.trell[i][0]
if i == 0:
self.trell[i][1][token][0] = hmm.e(token,word)
else:
max = None
guess = None
c = None
for k in self.trell[i-1][1]:
c = self.trell[i-1][1][k][0] + hmm.t(k,token)
if max == None or c > max:
max = c
guess = k
max += hmm.e(token,word)
self.trell[i][1][token][0] = max
self.trell[i][1][token][1] = guess
def return_max(self):
tokens = []
token = None
for i in range(len(self.trell)-1,-1,-1):
if token == None:
max = None
guess = None
for k in self.trell[i][1]:
if max == None or self.trell[i][1][k][0] > max:
max = self.trell[i][1][k][0]
token = self.trell[i][1][k][1]
guess = k
tokens.append(guess)
else:
tokens.append(token)
token = self.trell[i][1][token][1]
tokens.reverse()
return tokens
Tôi đã tìm thấy code sau trong kho lưu trữ ví dụ Artificial Intelligence: A Modern Approach. Có cái gì đó giống như những gì bạn đang tìm kiếm không?
def viterbi_segment(text, P):
"""Find the best segmentation of the string of characters, given the
UnigramTextModel P."""
# best[i] = best probability for text[0:i]
# words[i] = best word ending at position i
n = len(text)
words = [''] + list(text)
best = [1.0] + [0.0] * n
## Fill in the vectors best, words via dynamic programming
for i in range(n+1):
for j in range(0, i):
w = text[j:i]
if P[w] * best[i - len(w)] >= best[i]:
best[i] = P[w] * best[i - len(w)]
words[i] = w
## Now recover the sequence of best words
sequence = []; i = len(words)-1
while i > 0:
sequence[0:0] = [words[i]]
i = i - len(words[i])
## Return sequence of best words and overall probability
return sequence, best[-1]
Tôi vừa sửa lỗi triển khai thực hiện Viterbi in Wikipedia. Từ phiên bản ban đầu (không chính xác), tôi mất một lúc để tìm ra nơi tôi đã đi sai nhưng cuối cùng tôi đã quản lý nó, một phần nhờ vào việc Kevin Murphy thực hiện viterbi_path.m
trong số MatLab HMM toolbox.
Trong bối cảnh của một đối tượng HMM với các biến số như:
hmm = HMM()
hmm.priors = np.array([0.5, 0.5]) # pi = prior probs
hmm.transition = np.array([[0.75, 0.25], # A = transition probs./2 states
[0.32, 0.68]])
hmm.emission = np.array([[0.8, 0.1, 0.1], # B = emission (observation) probs./3 obs modes
[0.1, 0.2, 0.7]])
Các Python chức năng để chạy Viterbi (best-path) thuật toán là dưới đây:
def viterbi (self,observations):
"""Return the best path, given an HMM model and a sequence of observations"""
# A - initialise stuff
nSamples = len(observations[0])
nStates = self.transition.shape[0] # number of states
c = np.zeros(nSamples) #scale factors (necessary to prevent underflow)
viterbi = np.zeros((nStates,nSamples)) # initialise viterbi table
psi = np.zeros((nStates,nSamples)) # initialise the best path table
best_path = np.zeros(nSamples); # this will be your output
# B- appoint initial values for viterbi and best path (bp) tables - Eq (32a-32b)
viterbi[:,0] = self.priors.T * self.emission[:,observations(0)]
c[0] = 1.0/np.sum(viterbi[:,0])
viterbi[:,0] = c[0] * viterbi[:,0] # apply the scaling factor
psi[0] = 0;
# C- Do the iterations for viterbi and psi for time>0 until T
for t in range(1,nSamples): # loop through time
for s in range (0,nStates): # loop through the states @(t-1)
trans_p = viterbi[:,t-1] * self.transition[:,s]
psi[s,t], viterbi[s,t] = max(enumerate(trans_p), key=operator.itemgetter(1))
viterbi[s,t] = viterbi[s,t]*self.emission[s,observations(t)]
c[t] = 1.0/np.sum(viterbi[:,t]) # scaling factor
viterbi[:,t] = c[t] * viterbi[:,t]
# D - Back-tracking
best_path[nSamples-1] = viterbi[:,nSamples-1].argmax() # last state
for t in range(nSamples-1,0,-1): # states of (last-1)th to 0th time step
best_path[t-1] = psi[best_path[t],t]
return best_path
Nhận xét bởi [jahrulesoverall] (http://stackoverflow.com/users/6925587/jahrulesoverall) được đăng không chính xác trong câu trả lời, * quan sát (0) là sai phải không? nên được quan sát [0] và quan sát [t]? * –
Tôi không hiểu làm thế nào bạn không nhận được một lỗi khi thực hiện 'psi [best_path [t], t]' vì 'best_path' là kiểu float và bạn có thể chỉ với chỉ số ints? –
@MikeVella Tôi đã thêm: 'bp = np.zeros (nSamples) .astype (int)' – Ant
Đây là một câu hỏi cũ , nhưng không có câu trả lời nào khác là khá những gì tôi cần vì ứng dụng của tôi không có trạng thái quan sát cụ thể.
Theo dõi @Rhubarb, tôi cũng đã triển khai lại Matlab implementation của Kevin Murphey (xem viterbi_path.m
), nhưng tôi đã giữ nó gần hơn với bản gốc. Tôi đã bao gồm một trường hợp thử nghiệm đơn giản là tốt.
import numpy as np
def viterbi_path(prior, transmat, obslik, scaled=True, ret_loglik=False):
'''Finds the most-probable (Viterbi) path through the HMM state trellis
Notation:
Z[t] := Observation at time t
Q[t] := Hidden state at time t
Inputs:
prior: np.array(num_hid)
prior[i] := Pr(Q[0] == i)
transmat: np.ndarray((num_hid,num_hid))
transmat[i,j] := Pr(Q[t+1] == j | Q[t] == i)
obslik: np.ndarray((num_hid,num_obs))
obslik[i,t] := Pr(Z[t] | Q[t] == i)
scaled: bool
whether or not to normalize the probability trellis along the way
doing so prevents underflow by repeated multiplications of probabilities
ret_loglik: bool
whether or not to return the log-likelihood of the best path
Outputs:
path: np.array(num_obs)
path[t] := Q[t]
'''
num_hid = obslik.shape[0] # number of hidden states
num_obs = obslik.shape[1] # number of observations (not observation *states*)
# trellis_prob[i,t] := Pr((best sequence of length t-1 goes to state i), Z[1:(t+1)])
trellis_prob = np.zeros((num_hid,num_obs))
# trellis_state[i,t] := best predecessor state given that we ended up in state i at t
trellis_state = np.zeros((num_hid,num_obs), dtype=int) # int because its elements will be used as indicies
path = np.zeros(num_obs, dtype=int) # int because its elements will be used as indicies
trellis_prob[:,0] = prior * obslik[:,0] # element-wise mult
if scaled:
scale = np.ones(num_obs) # only instantiated if necessary to save memory
scale[0] = 1.0/np.sum(trellis_prob[:,0])
trellis_prob[:,0] *= scale[0]
trellis_state[:,0] = 0 # arbitrary value since t == 0 has no predecessor
for t in xrange(1, num_obs):
for j in xrange(num_hid):
trans_probs = trellis_prob[:,t-1] * transmat[:,j] # element-wise mult
trellis_state[j,t] = trans_probs.argmax()
trellis_prob[j,t] = trans_probs[trellis_state[j,t]] # max of trans_probs
trellis_prob[j,t] *= obslik[j,t]
if scaled:
scale[t] = 1.0/np.sum(trellis_prob[:,t])
trellis_prob[:,t] *= scale[t]
path[-1] = trellis_prob[:,-1].argmax()
for t in range(num_obs-2, -1, -1):
path[t] = trellis_state[(path[t+1]), t+1]
if not ret_loglik:
return path
else:
if scaled:
loglik = -np.sum(np.log(scale))
else:
p = trellis_prob[path[-1],-1]
loglik = np.log(p)
return path, loglik
if __name__=='__main__':
# Assume there are 3 observation states, 2 hidden states, and 5 observations
priors = np.array([0.5, 0.5])
transmat = np.array([
[0.75, 0.25],
[0.32, 0.68]])
emmat = np.array([
[0.8, 0.1, 0.1],
[0.1, 0.2, 0.7]])
observations = np.array([0, 1, 2, 1, 0], dtype=int)
obslik = np.array([emmat[:,z] for z in observations]).T
print viterbi_path(priors, transmat, obslik) #=> [0 1 1 1 0]
print viterbi_path(priors, transmat, obslik, scaled=False) #=> [0 1 1 1 0]
print viterbi_path(priors, transmat, obslik, ret_loglik=True) #=> (array([0, 1, 1, 1, 0]), -7.776472586614755)
print viterbi_path(priors, transmat, obslik, scaled=False, ret_loglik=True) #=> (array([0, 1, 1, 1, 0]), -8.0120386579275227)
Lưu ý rằng việc triển khai này không trực tiếp sử dụng xác suất phát nhưng sử dụng biến số obslik
. Nói chung, emissions[i,j] := Pr(observed_state == j | hidden_state == i)
cho một trạng thái được quan sát cụ thể i
, làm cho emissions.shape == (num_hidden_states, num_obs_states)
.
Tuy nhiên, với một chuỗi observations[t] := observation at time t
, tất cả Thuật toán Viterbi yêu cầu là khả năng quan sát đó cho từng trạng thái ẩn. Do đó, obslik[i,t] := Pr(observations[t] | hidden_state == i)
. Giá trị thực tế của trạng thái quan sát là không cần thiết.
Tôi đã sửa đổi câu trả lời của @ Rhubarb cho điều kiện mà xác suất cận biên đã được biết (ví dụ: bằng cách tính toán thuật toán Tua lùi).
def viterbi (transition_probabilities, conditional_probabilities):
# Initialise everything
num_samples = conditional_probabilities.shape[1]
num_states = transition_probabilities.shape[0] # number of states
c = np.zeros(num_samples) #scale factors (necessary to prevent underflow)
viterbi = np.zeros((num_states,num_samples)) # initialise viterbi table
best_path_table = np.zeros((num_states,num_samples)) # initialise the best path table
best_path = np.zeros(num_samples).astype(np.int32) # this will be your output
# B- appoint initial values for viterbi and best path (bp) tables - Eq (32a-32b)
viterbi[:,0] = conditional_probabilities[:,0]
c[0] = 1.0/np.sum(viterbi[:,0])
viterbi[:,0] = c[0] * viterbi[:,0] # apply the scaling factor
# C- Do the iterations for viterbi and psi for time>0 until T
for t in range(1, num_samples): # loop through time
for s in range (0,num_states): # loop through the states @(t-1)
trans_p = viterbi[:, t-1] * transition_probabilities[:,s] # transition probs of each state transitioning
best_path_table[s,t], viterbi[s,t] = max(enumerate(trans_p), key=operator.itemgetter(1))
viterbi[s,t] = viterbi[s,t] * conditional_probabilities[s][t]
c[t] = 1.0/np.sum(viterbi[:,t]) # scaling factor
viterbi[:,t] = c[t] * viterbi[:,t]
## D - Back-tracking
best_path[num_samples-1] = viterbi[:,num_samples-1].argmax() # last state
for t in range(num_samples-1,0,-1): # states of (last-1)th to 0th time step
best_path[t-1] = best_path_table[best_path[t],t]
return best_path
- 1. Thực hiện Python cho Thuật toán Dừng và Chờ
- 2. Thực hiện Thuật toán Cube Marching?
- 3. Thực hiện thuật toán Bentley-Ottmann
- 4. Thực hiện thuật toán hình chữ nhật tối đa
- 5. Tìm C++ thực hiện thuật toán cây khoảng thời gian
- 6. Kiểm tra mạch khi thực hiện thuật toán Kruskalls
- 7. Thuật toán băm để thực hiện bảng băm
- 8. Thuật toán để thực hiện câu lệnh C# yield
- 9. Cách thực hiện Thuật toán Dijkstra trong Haskell
- 10. Có ai biết thực hiện thuật toán của yarowsky không?
- 11. Thực hiện thuật toán tam giác của Chazelle
- 12. Thuật toán Hungary trong Python
- 13. Thuật toán tfidf cho python
- 14. Thuật toán PLS-DA trong python
- 15. Bindings OpenCV Python cho thuật toán GrabCut
- 16. Dịch thuật toán C sang Python
- 17. hiệu suất thuật toán python shuffle
- 18. Thuật toán AdaBoost ML triển khai python
- 19. Bộ giải mã Viterbi
- 20. Thuật toán để phát hiện hướng ảnh
- 21. thực hiện NotifyPropertyChanged không dây ma thuật
- 22. Tìm đường dẫn đầu - k viterbi trong HMM
- 23. Binary GCD Thuật toán so với Euclid của thuật toán trên máy tính hiện đại
- 24. Thực hiện phân biệt tự động cho phái sinh thứ 2: thuật toán để duyệt qua biểu đồ tính toán?
- 25. Triển khai Python của thuật toán đóng gói
- 26. Triển khai Python của thuật toán căn chỉnh BLAST?
- 27. Python - Thuật toán tìm các khe thời gian
- 28. Triển khai thuật toán python khoa học trên Amazon ec2
- 29. Thuật toán Facemash
- 30. Thuật toán trong C
Tôi hơi bối rối vì sao điều này cao hơn bài đăng NLTK, việc triển khai của họ có đúng không? OP bạn có tìm thấy mã hoàn toàn không có giấy tờ của tôi thỏa đáng không? – placeybordeaux
Có lẽ lý do là dễ dàng hơn để hack xung quanh để có được thích nghi với nhu cầu của một người hơn so với mã NLTK. – chiffa
@placeybordeaux Chức năng này 'hmm.t (k, token) 'làm gì? Tôi đã cố gắng để tái tạo mã nhưng tôi không thể tìm ra những gì 'hmm.t (k, token)' làm. Bạn có thể cung cấp một ví dụ cho nó? – Mohammed