Подробное объяснение CRNN
предисловие
Эта статья в основном основана наbestrivern
Блог понимает сеть CRNN + CTC, углубляет понимание сети и систематизирует полученные идеи.
I. Обзор
Существует две основные структуры для широко используемых алгоритмов распознавания текста:
- CNN+RNN+CTC(CRNN+CTC)
- CNN+Seq2Seq+Attention
В этой статье описан первый способ.
CRNN — это структура сверточной рекуррентной нейронной сети, используемая для решения задач, основанных на图像的序列识别
проблемы, особенно проблемы с распознаванием текста сцены.
В статье считается, что распознавание текста является методом прогнозирования последовательностей, поэтому для прогнозирования последовательностей используется сеть RNN.После того, как функции изображения извлечены с помощью CNN, RNN используется для прогнозирования последовательности, и, наконец, окончательный результат получается с помощью уровня трансляции CTC.. Грубо говоря, это структура CNN+RNN+CTC.
Полное имя CRNNConvolutional Recurrent Neural Network, который в основном используется для сквозного распознавания текстовых последовательностей неопределенной длины, без предварительного вырезания одного текста, но превращая распознавание текста в задачу обучения последовательности, зависящую от последовательности, которая представляет собой распознавание последовательности на основе изображения.
2. Структура сети CRNN
Вся структура сети CRNN состоит из трех частей, снизу вверх:
- CNN (сверточный слой), который использует глубокую CNN для извлечения признаков из входного изображения и получения карт признаков;
- RNN (рекуррентный слой) использует двунаправленную RNN (BLSTM) для прогнозирования последовательностей признаков, изучает каждый вектор признаков в последовательности и выводит предсказанное распределение меток (истинных значений);
- Потеря CTC (уровень транскрипции), используя потерю CTC, преобразует ряд распределений меток, полученных из рекуррентного слоя, в конечную последовательность меток.
В чем сложность сквозного распознавания текста? Как решить проблему выравнивания последовательностей неопределенной длины! CRNN OCR на самом деле заимствован из системы распознавания речи для решения
不定长语音序列
идеи. Подобно проблеме распознавания речи, OCR можно смоделировать как зависящую от времени задачу распознавания слова или фразы. Алгоритм обучения RNN на основе коннекционистской временной классификации (CTC) значительно превосходит традиционный алгоритм распознавания речи в области распознавания речи. Некоторые ученые пытались применить функцию потери CTC для распознавания OCR, и CRNN является одним из репрезентативных алгоритмов.Алгоритм CRNN вводит входное изображение нормализованной высоты 100 * 32, извлекает карту признаков на основе 7-слойной CNN (обычно используется VGG16) и делит карту признаков на столбцы (Map-to-Sequence), каждый столбец из 512 -размерные функции, вход в двунаправленный LSTM из 256 единиц в каждом на двух уровнях для классификации. В процессе обучения достигается приблизительное мягкое выравнивание позиций символов и меток классов с помощью функции потери CTC.CRNN использует метод моделирования LSTM + CTC при распознавании речи.Разница в том, что признаки, вводимые в LSTM, из акустических признаков (MFCC и т. д.) в речевом поле, заменяются векторами признаков изображения, извлеченными сетью CNN. . Самый большой вклад алгоритма CRNN заключается в объединении потенциала CNN для разработки признаков изображения с потенциалом LSTM для сериализованного распознавания. Он не только извлекает надежные функции, но также позволяет избежать чрезвычайно сложной односимвольной сегментации и односимвольного распознавания в традиционных алгоритмах за счет распознавания последовательности.В то же время сериализованное распознавание также включает временные зависимости (неявно используя корпус). На этапе обучения CRNN равномерно масштабирует обучающие изображения до 100×32 (ш×в); на этапе тестирования, в ответ на проблему снижения скорости распознавания, вызванную растяжением символов, CRNN поддерживает соотношение размеров входного изображения, но высота изображения должна быть унифицирована до 32 пикселей, размер сверточной карты признаков динамически определяет временную длину LSTM. Вот пример
Теперь введите изображение, чтобы ввести функции в повторяющиеся слои, сделайте следующее:
- Сначала изображение будет масштабировано до размера 32×Ш×1.
- Затем после CNN оно становится 1×(W/4)×512
- Затем для LSTM установитеT=(W/4), D=512, функции могут быть введены в LSTM.
- Обратите внимание на букву Т в этом месте, посмотрите позже, запомните ее значение
- LSTM имеет 256 скрытых узлов,
经过LSTM后变为长度为T × nclass的向量
,После обработки softmax каждый элемент вектора-столбца представляет вероятность предсказания соответствующего символа.,Наконец, результат предсказания этого T может быть без избыточности объединен в полный результат распознавания..
1. Си-эн-эн
Структурная схема сверточного слоя:
Здесь есть приятное изменение, всего имеется четыре максимальных слоя объединения, но последние два池化层的窗口尺寸由 2x2 改为 1x2,也就是图片的高度减半了四次(除以$2^4$),而宽度则只减半了两次(除以$2^2$),这是因为文本图像多数都是高较小而宽较长,所以其feature map也是这种高小宽长的矩形形状,如果使用1×2的池化窗口可以尽量保证不丢失在宽度方向的信息,更适合英文字母识别(比如区分i和l)
.
CRNN также представляетBatchNormalization
модуль для ускорения сходимости модели и сокращения процесса обучения.
Входное изображение представляет собой изображение в градациях серого (один канал); высота 32, что является фиксированным, изображениеПосле прохождения CNN высота становится равной 1, что немаловажно; ширина 160,Ширина также может быть другим значением, но должна быть унифицирована., поэтому размер данных входной CNN равен (канал, высота, ширина) = (1, 32, 160).
Выходной размер CNN(512, 1, 40)
. То есть CNN в итоге получает 512 карт признаков, каждая карта признаков имеет высоту 1 и ширину 40.
Примечание. Последний сверточный слой представляет собой свертка 2 * 2, s = 1, p = 0, что также эквивалентно масштабированию карты объектов до 1/2 исходной, поэтому весь слой CNN уменьшает h изображения. к оригиналу, поэтому высота карты характеристик, выводимой окончательной CNN, равна 1.
assert imgH % 16 == 0, 'imgH has to be a multiple of 16'
В программе h изображения должно быть целым числом, кратным 16.
assert h == 1, "the height of conv must be 1"
Во время прямого распространения h карты признаков, полученной CNN, должно быть равно 1.
Масштаб карты характеристик, полученный окончательной CNN, составляет 512x1x40.
2.Map-to-Sequence
МыКарта объектов, полученная CNN, не может быть напрямую отправлена в RNN для обучения.Да, требуются некоторые корректировки,Извлеките последовательность векторов признаков, требуемых RNN, в соответствии с картой признаков..
нужно это сейчасИзвлеките последовательность векторов признаков из карты признаков, созданной моделью CNN., каждый вектор признаков (например, красный прямоугольник на рисунке выше) находится на карте признаков.по столбцуСгенерированный слева направо, каждый столбец содержит 512-мерные признаки, что означает第 i 个特征向量是所有的特征图第 i 列像素的连接,这些特征向量就构成一个序列
.
Поскольку сверточные слои, слои с максимальным объединением и функции активации выполняются в локальных областях, они инвариантны к трансляции. следовательно,Каждый столбец карты признаков (то есть вектор признаков) соответствует прямоугольной области исходного изображения (называемой рецептивным полем)., и эти прямоугольные области расположены в том же порядке, что и соответствующие столбцы на карте объектов слева направо.Каждый вектор в последовательности признаков связан с рецептивным полем..
В частности, эти 40 векторов последовательности с шагом=4 соответственно соответствуют исходному изображению и используются для классификации соответствующих областей исходного изображения.
собственное понимание
Для этого места, как на рисунке ниже, вертикальная область соответствует последовательности признаков.
В частности, эти 40 векторов последовательности с шагом=4 соответствуют исходному изображению и используются для классификации соответствующих областей исходного изображения. -----
这句话说明的是我的一个序列对应一个竖向的区域,之前的宽度是160,我们以步长为4移动,恰好分割出来40个序列特征
Эти последовательности векторов признаков используются в качестве входных данных рекуррентного слоя, и каждый вектор признаков используется в качестве входных данных RNN на временном шаге.
собственное понимание
Причина введения RNN после CNN?
Потому что я никогда не понимал, какое отношение имеет ввод (последовательность признаков) рекуррентной сети к, по сути, нашему
特征序列就是160的宽平均分成40份,是一个连续序列,前后之间是有顺序关系的,所以我们可以使用RNN对这种序列进行特征的抽取,在加上一个softmax完成分类的操作
3.RNN
Поскольку RNN имеет проблему исчезновения градиента и не может получить больше контекстной информации, CRNN используетLSTM
, особый дизайн LSTM позволяет ему фиксировать долгосрочные зависимости.
LSTM является однонаправленным, он использует только прошлую информацию. Однако в последовательностях на основе изображений контексты двух направлений взаимополезны и дополняют друг друга. Объедините два LSTM, один прямой и один обратный, в один двунаправленный LSTM. Кроме того, несколько уровней двунаправленных LSTM могут быть объединены друг с другом, а глубокие структуры допускают более высокие уровни абстракции, чем поверхностные.
Вот двунаправленная сеть LSTM с двумя слоями по 256 единиц:
С помощью вышеуказанного шага мы получили 40 векторов признаков, каждый из которых имеет длину 512. В LSTM для классификации передается один временной шаг, всего 40 временных шагов.
мы знаем一个特征向量就相当于原图中的一个小矩形区域,RNN 的目标就是预测这个矩形区域为哪个字符,即根据输入的特征向量,进行预测,得到所有字符的softmax概率分布
,Это вектор длины числа классов символов, в качестве входных данных для слоя CTC.
Поскольку каждый временной шаг будет иметь входной вектор признаков, выведите распределение вероятностей по всем символам, поэтому выход представляет собой матрицу апостериорной вероятности из 40 векторов длины, равной количеству классов символов.
собственное понимание
Почему размерность сгенерированной матрицы апостериорной вероятности T * n?
因为一个LSTM的输入是一个特征向量,输出是一个字符的预测,预测每一个字符的出现的概率,这里的网络结构不得不提及下,实际上是(两个)双层的LSTM层+softmax层,一个LSTM会得到所有字符的概率n个值,这样一共有T个序列,所以会有T个n个值,维度就是 T * n
Как показано ниже:
Затем эта матрица апостериорной вероятности передается в слой транскрипции.
Исходный код этой части выглядит следующим образом:
self.rnn = nn.Sequential(
BidirectionalLSTM(512, nh, nh),
BidirectionalLSTM(nh, nh, nclass))
Затем параметры устанавливаются следующим образом:
nh=256
nclass = len(opt.alphabet) + 1
nc = 1
Реализация двунаправленного LSTM выглядит следующим образом:
class BidirectionalLSTM(nn.Module):
def __init__(self, nIn, nHidden, nOut):
super(BidirectionalLSTM, self).__init__()
self.rnn = nn.LSTM(nIn, nHidden, bidirectional=True)
self.embedding = nn.Linear(nHidden * 2, nOut)
def forward(self, input):
recurrent, _ = self.rnn(input)
T, b, h = recurrent.size()
t_rec = recurrent.view(T * b, h)
output = self.embedding(t_rec) # [T * b, nOut]
output = output.view(T, b, -1)
return output
Таким образом, вывод = [40 * 256 256], полученный первым LSTM, а затем представление становится выводом = [40 256 256].
Результат, полученный вторым LSTM, равен output=[40*256,nclass], а затем представление становится output=[40,256,nclass]
4. Потеря СТС (重点
)
Это самая сложная часть CRNN, это слой транскрипции, а транскрипция将 RNN 对每个特征向量所做的预测转换成标签序列
процесс. Математически,Транскрипция заключается в поиске последовательности тегов с наибольшей вероятностной комбинацией на основе предсказания каждого кадра..
Сложность сквозного распознавания OCR заключается в том, как справиться с выравниванием последовательностей неопределенной длины! OCR может быть смоделирован как задача текстового изображения, зависящая от временных рядов, а затем CNN и RNN совместно обучаются от начала до конца с использованием функции потерь CTC (Connectionist Temporal Classification, CTC).
4.1 Механизм слияния последовательностей
Теперь нам нужно перевести последовательность, выдаваемую RNN, в окончательный результат распознавания.Когда RNN выполняет классификацию временных рядов, неизбежно будет много избыточной информации.Например, буква распознается дважды подряд, что требует набор изрезервный механизм.
Например, если мы хотим распознать приведенный выше текст, в RNN есть 5 временных шагов, в идеале t0, t1, t2 должны быть сопоставлены с «a», t3, t4 должны быть сопоставлены с «b», а затем эти символы должны быть сопоставлены с Последовательности объединяются, чтобы получить «aaabb», и мы объединяем последовательные повторяющиеся символы в один, тогда конечным результатом является «ab».
Это кажется лучшим методом, но есть проблема: если это такие слова, как book и hello, после слияния последовательных символов вы получите bok и helo, что, очевидно, невозможно, поэтому CTC имеет пустой механизм для решить эту проблему.
Мы используем символ «-» для обозначения пробела,Когда RNN выводит последовательность, вставьте «-» между повторяющимися символами в текстовых метках., например, выходная последовательность "bbooo-ookk", тогда она окончательно будет отображена на "book", т.е.Если разделены пустые символы, последовательные одинаковые символы не будут объединены..
То есть удалить последовательные повторяющиеся символы из последовательности символов, а затем удалить все символы «-» из пути, это называется процессом декодирования, а кодирование реализуется нейронной сетью. Введя механизм пробелов, мы можем очень хорошо решить проблему повторяющихся символов.
собственное понимание
Кодирование: нейронные сети для реализации
Декодировать: удалить все повторяющиеся символы и пробелы в пути
Одна и та же текстовая метка может иметь несколько различных комбинаций выравнивания символов, например, «aa-b», «aabb» и «-abb» представляют один и тот же текст («ab»), но с другим выравниванием, чем изображение. В более общем смысле,Для текстовой метки существует один или несколько путей.
4.2 Фаза обучения
На этапе обучения нам необходимо概率分布向量和相应的文本标签得到损失函数
, чтобы обучить модель нейронной сети, давайте посмотрим, как получить функцию потерь.
Как показано выше, для простейшего распознавания символов с временным рядом 2 имеется два временных шага (t0, t1) и три возможных символа — «a», «b» и «-», мы получаем два вектора распределения вероятностей, если принимается метод декодирования пути с максимальной вероятностью, вероятность «--» является наибольшей, то есть вероятность того, что реальный символ является пустым, составляет 0,6 * 0,6 = 0,36.
Но существует несколько комбинаций выравнивания для символа «а», «аа», «а-» и «-а», все они представляют «а», поэтому вероятность вывода «а» должна быть суммой трех:
0.4 * 0.4 + 0.4 * 0.6 + 0.6 * 0.4 = 0.16 + 0.24 + 0.24 = 0.64
Значит вероятность "а" выше вероятности пустого "-"!如果标签文本为“a”,则通过计算图像中为“a”的所有可能的对齐组合(或者路径)的分数之和来计算损失函数
.
Таким образом, для RNN задана входная матрица распределения вероятностей:T 是序列长度
, общая вероятность окончательного сопоставления с текстом метки l равна:
, , , , , , , , , ,
в代表从序列到序列的映射函数 B 变换后是文本 l 的所有路径集合
,иявляется одним из путей.Вероятность каждого пути является произведением очков соответствующего персонажа на каждом временном шаге..
Как и в общей классификации,CTC的损失函数O定义为负的最大似然
, для удобства расчета примем вероятностьлогарифм.
мыНеобходимо обучить сеть, чтобы максимизировать это значение вероятности.По аналогии с обычной классификацией функция потерь CTC определяется как отрицательная функция максимального правдоподобия вероятности.Для удобства расчета функция правдоподобия принимается как对数
.
, , , , , , , , ,
Вычисляя функцию потерь, предыдущая нейронная сеть может быть распространена обратно, а параметры нейронной сети обновляются в соответствии с оптимизатором, используемым для поиска символа, соответствующего наиболее вероятной области пикселей..
Этот способ преобразования отображения и суммы всех возможных вероятностей пути избавляет CTC от необходимости точно сегментировать исходную последовательность входных символов..
4.3 Этап тестирования
собственное понимание
Обратите внимание на это место, фаза обучения рассчитана для всех путей, но в части тестирования, чтобы быстро получить результаты, мы используем динамическое программирование для получения максимально быстрых результатов.
существуеттестовая фаза, процесс отличается от этапа обучения, где мы используем обученную нейронную сеть для распознавания новых текстовых изображений. В настоящее время мы не знаем никакого текста заранее.Если мы вычислим все пути каждого возможного текста, как указано выше, для очень длинных временных шагов и очень длинных последовательностей символов, объем вычислений будет очень большим, что не является осуществимое решение.
Эта часть важна:知道 RNN 在每一个时间步的输出为所有字符类别的概率分布,即一个包含每个字符分数的向量,我们取其中最大概率的字符作为该时间步的输出字符,然后
Объедините символ, полученный из всех временных шагов, чтобы получить путь последовательности, то есть путь максимальной вероятности.,再根据上面介绍的
Метод слияния последовательностей得到最终的预测文本结果
На этапе вывода он переводится CTC, то есть информация о признаках последовательности, полученная сетью, преобразуется в окончательный распознаваемый текст., все текстовое изображение может быть распознано.
Например, на приведенном выше рисунке есть 5 временных шагов, а категории символов - «а», «б» и «-» (пробел). Для распределения вероятностей каждого временного шага мы берем символ с наибольшим счет, таким образом, мы получаем путь последовательности "aaa-b", сначала удаляем соседние повторяющиеся символы, чтобы получить "ab", затем удаляем пустые символы, чтобы получить окончательный результат: "ab".
4.4 Резюме
В процессе прогнозирования сначала используйте стандартную сеть CNN для извлечения文本图像的特征
, а затем используйте BLSTM, чтобы объединить векторы признаков в提取字符序列的上下文特征
, затем получить каждый столбец特征的概率分布
, и, наконец, через слой транскрипции(CTC)进行预测得到文本序列
.
Использование BLSTM и CTC для изучения контекстных отношений в текстовых изображениях может эффективно повысить точность распознавания текста и сделать модель более надежной.
На этапе обучения CRNN равномерно масштабирует обучающее изображение до 160 × 32 (ш × в); на этапе тестирования, в ответ на проблему, заключающуюся в том, что растяжение символов снижает скорость распознавания, CRNN поддерживает соотношение размеров входного изображения, но высота изображения по-прежнему должна быть унифицирована как 32 пикселя, размер сверточной карты признаков динамически определяет временную длину (временной шаг) LSTM.
V. Дополнительные инструкции
5.1 Кодирование RCNN
собственное понимание
Картинка блогера очень хорошо обобщается, и процесс стереоскопического CNN + LSTM + Softmax
Если предположить, что нужно распознать 26 английских букв, то количество категорий = 27 (и пустой символ)
Предполагая, что вывод CNN основан на 50 последовательностях (здесь читатели не могут это прочитать, перейдите в RNN, чтобы распознать рукописные цифры), последовательность слишком велика, а обучение неточно, и в результате распознавания будут пропущены буквы. Последовательность слишком маленькая, обучение не точное, и распознавание будет многобуквенным.
5.2 Подробное объяснение CTC
Как показано на рисунке ниже, для облегчения понимания читателем структура RNN упрощена.Существует только один слой LSTM в одном направлении.Единицей акустического моделирования выбрана буква {az}, а символ Набор единиц моделирования расширен, и выход из вывода определен.Функция отображения «многие к одному» слоя в окончательную последовательность меток, так что выходной слой RNN может быть сопоставлен с окончательной последовательностью меток.
Функция сопоставления «многие к одному»:
- Дедупликация последовательных одинаковых символов
- удалить пустые символы
Следовательно, если вы хотите вычислить ?(?│?), вы можете суммировать вероятность всех соответствующих выходных последовательностей (то есть «путь», сопоставленный с конечной меткой), как показано на следующем рисунке.
Как показано на рисунке ниже, на основе предположения об условной независимости RNN можно получить определение функции потерь CTC:
собственное понимание (
原理核心的部分
)На самом деле это место такое, как мы видим на картинке выше.- это вероятность достижения x по пути, поэтому формула , так как мы много к одному, в конечном итоге будет несколько путей к x, а вероятность конечной метки равна сумме вероятностей всех путей, поэтому формула является функцией отображения множества всех путей
Функция потерь нашего окончательного CTC Поскольку мы знаем, что CTC должен решить максимальное произведение каждой вероятности, выводимой RNN, и функцию правдоподобия, поэтому, если мы хотим минимизировать потери, мы используем идею отрицательного логарифма, и формулаНаконец-то разобрались
Предполагая, что в качестве структуры RNN выбран однослойный LSTM, окончательная структура модели выглядит следующим образом:
Вышеприведенная картинка является хорошим объяснением процесса RNN + CTC, над которым стоит задуматься.
5.3 Динамическое программирование CTC упрощает процесс расчета
Из-за высокой сложности прямого перебора ?(?│?) автор рисуетHMM的Forward-Backward
Идеи алгоритма, используя алгоритм динамического программирования для решения.
Как показано на рисунке ниже, чтобы более наглядно представить пространство поиска задачи, используйтеОсь x представляет временной ряд,Ось Y представляет выходную последовательность, и стандартизируйте выходную последовательность. Пробел добавляется в середину, начало и конец выходной последовательности. Используйте l для представления окончательной метки и l' для представления расширенной формы.2|l| + 1 = 2|l’|
, например: l=яблоко => l’=a_p_p_l_e
Не все пути на рисунке являются допустимыми путями, и все допустимые пути должны соответствовать некоторым ограничениям, как показано на следующем рисунке:
- Преобразование может идти только в нижнем правом направлении, другие направления не допускаются.
- Между одинаковыми символами должен быть хотя бы один пробел.
- Непустые символы нельзя пропускать
- Начальная точка должна начинаться с первых двух символов
- Конечная точка должна находиться в пределах двух последних символов
Следовательно, в соответствии с приведенными выше правилами ограничения, пройдите все допустимые пути, сопоставленные с «яблоком», конечная временная последовательность T = 8 и все пути с меткой = «яблоко» будут следующими:
Далее, как вычислить сумму вероятностей этих путей? Обход грубой силы? Разделяй и властвуй? Автор опирается на идею алгоритма Forward-Backward HMM, используя动态规划算法
Для решения множество путей можно разделить на前向
и后向
Две части, как показано на рисунке ниже:
на картинкеозначает:Доступна сипреобразуется и, в конечном счете, умножается назначение вероятности текущей точки ---
非空字符只能来自本层或者上一个字母层
на картинкеозначает:Доступна сипреобразуется и, в конечном счете, умножается назначение вероятности текущей точки ---
相邻两个字母是相同字母时,来源只能是上层的空和本层自己
на картинкеозначает:Доступна сиипреобразуется и, в конечном счете, умножается назначение вероятности текущей точки ---
相邻两个字母是不同字母时,来源只能是上层的空和本层自己,或者是上两层的跳跃
После решения прямой вероятности с помощью динамического программирования вы можете использовать前向概率来计算CTC Loss
функцию, как показано ниже:
рекурсивное мышление
Аналогичным образом мы можем определить обратную вероятность и использовать反向概率来计算CTC Loss
функцию, как показано ниже:
Удалите направление стрелки и объедините прямую вероятность и обратную вероятность для расчета функции потерь CTC., что является очень важным шагом для расчета вывода функции потерь CTC, как показано на следующем рисунке:
Вероятностный синтез всех путей, проходящих через точку p в момент времени t=4:Его можно рассматривать как сумму вероятностей всех прямых путейи обратно все суммы вероятностейСинтез, знаменатель тот же, комбинация приведенная выше формула
Через время t=4, пройдя все S, может быть достигнут вероятностный синтез всех путей в момент времени t4:
С помощью приведенного выше вывода мы можем получить рекурсивную формулу: функция потерь CTC рассчитывается для прямой и обратной вероятности, а также прямой вероятности и обратной вероятности в любое время.
Подводя итог, функция CTC Loss рассчитывается в соответствии с форвардной вероятностью, и получаются следующие выводы (重点
):
Функция CTC Loss рассчитывается по обратной вероятности, и получаются следующие выводы:
Рассчитывается на основе прямой вероятности и обратной вероятности в любое времяCTC Loss函数
, и сделаны следующие выводы:
На данный момент мы получили эффективный метод расчета CTC Loss, а затем выведем его.
Красная часть рисунка ниже является основной частью вывода функции потерь CTC (не настаивайте на понимании, основное внимание уделяется формуле расчета потерь выше):
Процесс вывода функции CTC Loss относительно элементов выходного слоя RNN показан на следующем рисунке:
На данный момент объяснение CTC Loss в тренировочном процессе завершено.
Существует два основных метода расшифровки CTC Loss в процессе тестирования:
CTC Prefix Search Decoding CTC Beam Search Decoding