CTCDECODE es una implementación de la decodificación de búsqueda de haz CTC (Connectionist Temporals) para Pytorch. El código C ++ tomó prestado generalmente del punto de profundidad de las paletas de las paletas. Incluye soporte de anotador ajustable que habilita la búsqueda de haz estándar y la decodificación basada en Kenlm. Si es nuevo en los conceptos de CTC y Beam Search, visite la sección de recursos donde vinculamos algunos tutoriales que explican por qué son necesarios.
La biblioteca es en gran medida autónoma y solo requiere Pytorch. La construcción de la biblioteca C ++ requiere GCC o CLANG. El soporte de modelado de idiomas KENLM también se incluye opcionalmente y está habilitado de forma predeterminada.
La siguiente instalación también funciona para 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 son las fichas que usó para entrenar a su modelo. Deben estar en el mismo orden que sus salidas. Por ejemplo, si sus tokens son las letras inglesas y usó 0 como token en blanco, entonces pasaría en la lista ("_ ABCDEFGHIJKLMOPQRSTUVWXYZ") como su argumento a las etiquetasmodel_path es la ruta a su modelo de lenguaje KENLM externo (LM). El valor predeterminado es ninguno.alpha asociada con las probabilidades de LMS. Un peso de 0 significa que el LM no tiene ningún efecto.beta asociado con el número de palabras dentro de nuestro haz.cutoff_top_n Número de corte en la poda. Solo los caracteres superiores de corte_top_n con la mayor probabilidad en el vocabulario se utilizarán en la búsqueda del haz.cutoff_prob Probabilidad de corte en la poda. 1.0 significa que no hay poda.beam_width esto controla cuán amplia es la búsqueda del haz. Los valores más altos tienen más probabilidades de encontrar vigas superiores, pero también harán que su búsqueda de haz sea exponencialmente más lenta. Además, cuanto más largas sean sus salidas, más tiempo llevan las vigas grandes. Este es un parámetro importante que representa una compensación que debe hacer en función de su conjunto de datos y necesidades.num_processes paralelizan el lote utilizando trabajadores num_processes. Probablemente desee pasar el número de CPU que tiene su computadora. Puede encontrar esto en Python con import multiprocessing , luego n_cpus = multiprocessing.cpu_count() . Predeterminado 4.blank_id Este debería ser el índice del token en blanco CTC (probablemente 0).log_probs_input Si sus salidas han pasado a través de un Softmax y representan probabilidades, esto debería ser falso, si pasan a través de un LogsoftMax y representan la probabilidad negativa de log, debe pasar verdadero. Si no comprende esto, ejecute print(output[0][0].sum()) , si es un número negativo que probablemente tenga NLL y deba pasar verdadero, si se suma a ~ 1.0, debe pasar falso. Falso predeterminado.decodeoutput debe ser las activaciones de salida de su modelo. Si su salida ha pasado a través de una capa SoftMax, no debería necesitar alterarla (excepto tal vez para transponerse), pero si su output representa las probabilidades negativas del registro (logits sin procesar), debe pasarlo a través de una torch.nn.functional.softmax log_probs_input=False . Su salida debe ser BatchSize X N_Timesteps x N_Labels, por lo que es posible que deba transponerlo antes de pasarlo al decodificador. Tenga en cuenta que si pasa las cosas en el orden incorrecto, la búsqueda del haz probablemente aún se ejecutará, solo recuperará los resultados sin sentido.decode 4 cosas se devuelven de decode
beam_results - Forma: BatchSize x n_beams x n_timesteps Un lote que contiene la serie de caracteres (estos son ints, aún necesita decodificarlos a su texto) que representa los resultados de una búsqueda de haz dada. Tenga en cuenta que las vigas son casi siempre más cortas que el número total de times de tiempo, y los datos adicionales no son sensibles, por lo que para ver el haz superior (como etiquetas int) desde el primer elemento en el lote, debe ejecutar beam_results[0][0][:out_len[0][0]] .beam_scores - Forma: BatchSize x n_beams un lote con la puntuación CTC aproximada de cada haz (mire el código aquí para obtener más información). Si esto es cierto, puede obtener la confianza del modelo de que el haz es correcto con p=1/np.exp(beam_score) .timesteps - Forma: BatchSize x n_beams El paso de tiempo en el que el enésimo carácter de salida tiene probabilidad máxima. Se puede usar como alineación entre el audio y la transcripción.out_lens - Forma: BatchSize x n_beams. out_lens[i][j] es la longitud del jth beam_result, del elemento I de tu lote. 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 ])El decodificador en línea es copiar la interfaz CTCBeamDecoder, pero requiere secuencias de estados e IS_EOS_S.
Los estados se utilizan para acumular secuencias de fragmentos, cada uno correspondiente a una fuente de datos. IS_EOS_S le dice al decodificador si los trozos han dejado de ser empujado al estado correspondiente.
Obtenga la viga superior para el primer elemento en su lote beam_results[0][0][:out_len[0][0]]
Obtenga las 50 vigas superiores para el primer artículo en su lote
for i in range ( 50 ):
print ( beam_results [ 0 ][ i ][: out_len [ 0 ][ i ]]) Tenga en cuenta que estos serán una lista de INTS que necesitan decodificación. Es probable que ya tenga una función para decodificar desde int hasta el texto, pero si no puede hacer algo como. "".join[labels[n] for n in beam_results[0][0][:out_len[0][0]]] Uso de las etiquetas que pasó a CTCBeamDecoder