CTCDecode - это реализация декодирования поиска пучка CTC (соединение временной классификации) для Pytorch. C ++ Код заимствовал либерально из темно -скоростных веслей. Он включает в себя поддержку сменной бомбардировщики, позволяющая поиск стандартного луча и декодирование на основе Kenlm. Если вы новичок в понятиях CTC и BEAM Search, пожалуйста, посетите раздел ресурсов, где мы связываем несколько учебных пособий, объясняющих, почему они нужны.
Библиотека в значительной степени автономна и требует только питорха. Создание библиотеки C ++ требует GCC или Clang. Поддержка моделирования языка Kenlm также при условии включена, и включена по умолчанию.
Приведенная ниже установка также работает для Google Colab.
# get the code
git clone --recursive https://github.com/parlance/ctcdecode.git
cd ctcdecode && pip install . from ctcdecode import CTCBeamDecoder
decoder = CTCBeamDecoder (
labels ,
model_path = None ,
alpha = 0 ,
beta = 0 ,
cutoff_top_n = 40 ,
cutoff_prob = 1.0 ,
beam_width = 100 ,
num_processes = 4 ,
blank_id = 0 ,
log_probs_input = False
)
beam_results , beam_scores , timesteps , out_lens = decoder . decode ( output )CTCBeamDecoderlabels - это токены, которые вы использовали для обучения своей модели. Они должны быть в том же порядке, что и ваши результаты. Например, если ваши жетоны являются английскими буквами, и вы использовали 0 в качестве пустого токена, то вы пропустите в списке («_ Abcdefghijklmopqrstuvwxyz») в качестве аргумента на этикеткеmodel_path - это путь к вашей внешней модели языка Kenlm (LM). По умолчанию нет.alpha -взвешивание, связанное с вероятностями LMS. Вес 0 означает, что LM не имеет никакого эффекта.beta -вес, связанный с количеством слов в нашем луче.cutoff_top_n Номер отсечения при обрезке. Только символы Top cutoff_top_n с наибольшей вероятностью в словаре будут использоваться в поиске пучка.cutoff_prob при обрезке. 1.0 означает отсутствие обрезки.beam_width Это управляет тем, насколько широкий поиск луча. Более высокие значения с большей вероятностью найдут верхние балки, но они также сделают ваш поиск пучка в геометрической прогрессии медленнее. Кроме того, чем дольше ваши результаты, тем больше времени займут большие балки. Это важный параметр, который представляет собой компромисс, который вам необходимо сделать на основе вашего набора данных и потребностей.num_processes параллелизирует партию с помощью работников num_processes. Вы, вероятно, хотите передать количество процессоров, которые есть у вашего компьютера. Вы можете найти это в Python с import multiprocessing затем n_cpus = multiprocessing.cpu_count() . По умолчанию 4.blank_id Это должен быть индекс токена CTC Blank (вероятно, 0).log_probs_input Если ваши выходы прошли через Softmax и представляют вероятности, это должно быть ложным, если они проходят через Logsoftmax и представляют отрицательную вероятность журнала, вам нужно передать true. Если вы этого не понимаете, запустите print(output[0][0].sum()) , если это отрицательное число, у вас, вероятно, есть NLL, и вам нужно передать true, если оно суммирует до ~ 1.0, вы должны пройти ложь. По умолчанию false.decodeoutput должен быть выходной активацией из вашей модели. Если ваш вывод прошел через слой Softmax, вам не нужно изменять его (за исключением, возможно, для транспонирования), но если ваш output представляет отрицательные вероятности журнала (необработанные логиты), вам нужно либо передать его через дополнительный torch.nn.functional.softmax , либо вы можете передавать log_probs_input=False . Ваш вывод должен быть размером с x n_timesteps x n_labels, поэтому вам может потребоваться транспонировать его, прежде чем передавать его декодеру. Обратите внимание, что если вы передаете ситуацию в неправильном порядке, поиск луча, вероятно, все еще будет работать, вы просто получите результаты бессмысленных.decode 4 вещи возвращаются из decode
beam_results - SHARD: PATCARIZE X N_BEAMS X N_TIMESTEPS Партия, содержащая серию символов (это INT, вам все равно нужно декодировать их обратно в свой текст), представляющая результаты данного поиска луча. Обратите внимание, что балки почти всегда короче, чем общее количество временных точек, а дополнительные данные не являются чувствительными, поэтому, чтобы увидеть верхнюю луч (в виде метки int) из первого элемента в партии, вам необходимо запустить beam_results[0][0][:out_len[0][0]] .beam_scores - ФОРМА: ПАТЧИНА x N_BEAMS Партия с приблизительной оценкой CTC каждого луча (посмотрите на код здесь для получения дополнительной информации). Если это правда, вы можете получить уверенность модели, что луч верен с p=1/np.exp(beam_score) .timesteps - Форма: пакетный x n_beams TimeStep, при котором n -й выходной символ имеет пиковую вероятность. Может использоваться в качестве выравнивания между аудио и стенограммой.out_lens - SHARD: PATCARIFE X N_BEAMS. out_lens[i][j] - это длина JTH BEAM_RESULT, пункта I вашей партии. from ctcdecode import OnlineCTCBeamDecoder
decoder = OnlineCTCBeamDecoder (
labels ,
model_path = None ,
alpha = 0 ,
beta = 0 ,
cutoff_top_n = 40 ,
cutoff_prob = 1.0 ,
beam_width = 100 ,
num_processes = 4 ,
blank_id = 0 ,
log_probs_input = False
)
state1 = ctcdecode . DecoderState ( decoder )
probs_seq = torch . FloatTensor ([ probs_seq ])
beam_results , beam_scores , timesteps , out_seq_len = decoder . decode ( probs_seq [:, : 2 ], [ state1 ], [ False ])
beam_results , beam_scores , timesteps , out_seq_len = decoder . decode ( probs_seq [:, 2 :], [ state1 ], [ True ])Онлайн -декодер копирует интерфейс CTCBeamDecoder, но он требует последовательностей IS_EOS_S.
Состояния используются для накопления последовательностей кусков, каждый из которых соответствует одному источнику данных. IS_EOS_S сообщает декодеру, перестали ли кусочки быть выдвинуты к соответствующему состоянию.
Получите верхнюю луч для первого элемента в вашей партии beam_results[0][0][:out_len[0][0]]
Получите 50 лучших балок для первого предмета в своей партии
for i in range ( 50 ):
print ( beam_results [ 0 ][ i ][: out_len [ 0 ][ i ]]) Обратите внимание, что это будет список INT, которые нуждаются в декодировании. Скорее всего, у вас уже есть функция для декодирования от Int в текст, но если не вы можете сделать что -то вроде. "".join[labels[n] for n in beam_results[0][0][:out_len[0][0]]] используя этикетки, которые вы передали в CTCBeamDecoder