디코딩 부분에 대한 자동 음성 인식에서 빔 - 검색 알고리즘에 사용 된 로직을 이해하려고 노력해 왔습니다. 내가 따라하려고 시도한 논문은 First-Pass Large Vocabulary Continuous Speech Recognition using Bi-Directional Recurrent DNNs, Lexicon-Free Conversational Speech Recognition with Neural Networks 및 Towards End-to-End Speech Recognition with Recurrent Neural Networks입니다. 문제는 알고리즘 뒤에있는 아이디어가 따르기 쉽지 않으며 논문에 제공된 의사 코드에 많은 오타가 있다는 것입니다. 또한 두 번째 논문의 this implementation은 뒤 따르기가 매우 어렵 기 때문에 언급 한 마지막 논문의 this one은 언어 모델을 포함하지 않습니다. 어떤 도움이 정말 이해할 수있을 것이다RNN 출력을 디코딩하는 빔 - 검색 알고리즘
class BeamSearch(object):
"""
Decoder for audio to text.
From: https://arxiv.org/pdf/1408.2873.pdf (hardcoded)
"""
def __init__(self, alphabet='" abcdefghijklmnopqrstuvwxyz'):
# blank symbol plus alphabet
self.alphabet = '-' + alphabet
# index of each char
self.char_to_index = {c: i for i, c in enumerate(self.alphabet)}
def decode(self, probs, k=100):
"""
Decoder.
:param probs: matrix of size Windows X AlphaLength
:param k: beam size
:returns: most probable prefix in A_prev
"""
# List of prefixs, initialized with empty char
A_prev = ['']
# Probability of a prefix at windows time t to ending in blank
p_b = {('', 0): 1.0}
# Probability of a prefix at windows time t to not ending in blank
p_nb = {('', 0): 0.0}
# for each time window t
for t in range(1, probs.shape[0] + 1):
A_new = []
# for each prefix
for s in Z:
for c in self.alphabet:
if c == '-':
p_b[(s, t)] = probs[t-1][self.char_to_index[self.blank]] *\
(p_b[(s, t-1)] +\
p_nb[(s, t-1)])
A_new.append(s)
else:
s_new = s + c
# repeated chars
if len(s) > 0 and c == s[-1]:
p_nb[(s_new, t)] = probs[t-1][self.char_to_index[c]] *\
p_b[(s, t-1)]
p_nb[(s, t)] = probs[t-1][self.char_to_index[c]] *\
p_b[(s, t-1)]
# spaces
elif c == ' ':
p_nb[(s_new, t)] = probs[t-1][self.char_to_index[c]] *\
(p_b[(s, t-1)] +\
p_nb[(s, t-1)])
else:
p_nb[(s_new, t)] = probs[t-1][self.char_to_index[c]] *\
(p_b[(s, t-1)] +\
p_nb[(s, t-1)])
p_nb[(s, t)] = probs[t-1][self.char_to_index[c]] *\
(p_b[(s, t-1)] +\
p_nb[(s, t-1)])
if s_new not in A_prev:
p_b[(s_new, t)] = probs[t-1][self.char_to_index[self.blank]] *\
(p_b[(s, t-1)] +\
p_nb[(s, t-1)])
p_nb[(s_new, t)] = probs[t-1][self.char_to_index[c]] *\
p_nb[(s, t-1)]
A_new.append(s_new)
A = A_new
s_probs = map(lambda x: (x, (p_b[(x, t)] + p_nb[(x, t)])*len(x)), A_new)
xs = sorted(s_probs, key=lambda x: x[1], reverse=True)[:k]
Z, best_probs = zip(*xs)
return Z[0], best_probs[0]
:
이 때문에 일부 누락 된 확률 실패 파이썬 내 구현입니다.
레이블 지정 경로 확률을 지정합니다. 하지만 같은 라벨을 만드는 모든 경로를 합산해야합니다. 의사 코드는 이에 대해 명확하지 않습니다. 나는 빔 검색을 LM으로 구현했다. 아마 이것이 도움이 될 것이다 : https://github.com/githubharald/CTCDecoder – Harry