Transdutor RNN (RNN-T)

Visão geral

RNN Transducer (RNN‑T) é uma arquitetura neural e um critério de treinamento amplamente usados para reconhecimento automático de fala (automatic speech recognition, ASR) em fluxo (streaming) de baixa latência (low‑latency). Ele foi projetado para mapear uma sequência de quadros de características acústicas (áudio) para uma sequência de tokens de saída (caracteres, subpalavras ou palavras) sem exigir alinhamentos em nível de quadro (frame‑level alignments).

O RNN‑T é especialmente popular em ASR no dispositivo (on-device) e em tempo real (real-time) porque ele pode:

  • Processar áudio incrementalmente conforme ele chega (em fluxo)
  • Produzir hipóteses parciais com baixa latência
  • Aprender alinhamentos internamente, evitando alinhamentos forçados (forced alignments) durante o treinamento
  • Combinar modelagem acústica e um componente leve “semelhante a modelo de linguagem” em um único sistema ponta a ponta (end-to-end)

Conceitualmente, o RNN‑T pode ser visto como uma alternativa amigável ao processamento em fluxo para ASR com codificador–decodificador (encoder–decoder) baseado em atenção (attention-based), e uma alternativa mais expressiva à Classificação Temporal Conexionista (Connectionist Temporal Classification, CTC).

O problema central: alinhamentos desconhecidos entre quadros de áudio e tokens

Na fala, a entrada é uma sequência longa de quadros (por exemplo, passos de 10 ms), enquanto a saída é uma sequência muito mais curta de tokens (por exemplo, subpalavras). A parte difícil é que normalmente não sabemos qual quadro de áudio corresponde a qual token.

Pipelines tradicionais de ASR usavam componentes separados (modelo acústico + léxico de pronúncia + modelo de linguagem) e dependiam de mecanismos de alinhamento como estados de HMM. Modelos ponta a ponta como o RNN‑T, em vez disso, tratam o alinhamento como uma variável latente (latent variable) e o aprendem por meio de um objetivo diferenciável (differentiable objective).

O RNN‑T faz isso construindo uma distribuição de probabilidade sobre todos os alinhamentos válidos que mapeiam quadros de entrada para tokens de saída, incluindo um símbolo em branco (blank) especial que significa “não emitir nada neste passo de tempo”.

Arquitetura do RNN‑T

Um modelo RNN‑T tem três partes principais:

  1. Codificador (encoder) (também chamado de rede de transcrição): mapeia quadros acústicos para representações de alto nível
  2. Rede de predição (prediction network): consome tokens emitidos anteriormente para produzir uma representação do histórico de saída
  3. Rede conjunta (joint network): combina as representações do codificador e da rede de predição para produzir uma distribuição sobre os próximos tokens (incluindo o símbolo em branco)

Esses três componentes, em conjunto, definem probabilidades sobre sequências de tokens enquanto permitem inferência em fluxo (streaming inference).

Codificador: modelagem acústica para streaming

O codificador recebe características acústicas (x_{1:T}) (por exemplo, log-Mel filterbanks) e produz vetores codificados (h_{1:T'}):

[ h_t = \mathrm{Encoder}(x_{1:t}) \quad \text{(streaming/causal)} ]

Pontos-chave:

  • Em ASR em fluxo, o codificador é causal (não olha para o áudio futuro) ou usa contexto em blocos (chunked) (antecipação limitada).
  • (T') pode ser menor que (T) devido à subamostragem (subsampling) (por exemplo, empilhamento de quadros ou convoluções com stride), o que reduz computação e melhora a latência.
  • Escolhas comuns de codificador:

Nota prática: Muitos sistemas modernos de “RNN‑T” usam um codificador Transformer/Conformer; o nome “RNN” é histórico, vindo dos primeiros projetos.

Rede de predição: modelagem do histórico de tokens

A rede de predição consome os tokens não brancos emitidos anteriormente (y_{1:u-1}) e produz um estado (g_u):

[ g_u = \mathrm{PredNet}(y_{1:u-1}) ]

Isso se comporta de forma semelhante a um pequeno modelo de linguagem neural, mas é treinado conjuntamente com o codificador em dados pareados de áudio-texto.

Características importantes:

  • Ela não consome quadros acústicos.
  • Ela só é atualizada quando o modelo emite um token não branco.
  • Arquiteturas típicas: uma camada de embeddings + uma LSTM/GRU ou um Transformer pequeno.

Rede conjunta: combinando áudio e histórico

Em qualquer ponto, o RNN‑T considera um par de índices:

  • (t): posição na sequência de áudio codificada (h_{1:T'})
  • (u): posição na sequência de tokens de saída (y_{1:U}) (quantos rótulos já foram emitidos)

A rede conjunta combina (h_t) e (g_u) para produzir valores de logit (logits) sobre o vocabulário mais o símbolo em branco:

[ z_{t,u} = \mathrm{Joint}(h_t, g_u) ] [ p(k \mid t,u) = \mathrm{softmax}(z_{t,u}) \quad k \in \mathcal{V} \cup {\varnothing} ]

Onde (\varnothing) é o símbolo em branco.

Uma rede conjunta comum é:

  • projeção linear de (h_t) e (g_u)
  • soma + não linearidade (por exemplo, tanh)
  • camada linear final até o tamanho do vocabulário

Essa estrutura produz uma grade 2D (frequentemente chamada de treliça (lattice) do RNN‑T) sobre ((t,u)).

Como os alinhamentos funcionam: símbolos em branco e “movimentos” em uma treliça

O RNN‑T define uma distribuição sobre alinhamentos permitindo dois tipos de transições a partir do estado ((t,u)):

  1. Emitir símbolo em branco (\varnothing): avança o tempo, mantém o mesmo comprimento de saída
    ((t,u) \rightarrow (t+1, u))

  2. Emitir um token (y_u): avança o comprimento de saída, mantém o mesmo tempo
    ((t,u) \rightarrow (t, u+1))

Esta é a ideia central amigável ao streaming:

  • Símbolos em branco significam “nenhum token emitido ainda; consuma mais áudio.”
  • Símbolos não brancos significam “emita um token agora; permaneça no mesmo passo de áudio.”

Um pequeno exemplo de alinhamento

Suponha que a saída-alvo seja as subpalavras: ["he", "llo"] (U=2). Conforme o áudio chega ao longo dos quadros (t=1..T'), um alinhamento possível poderia ser:

  • Em (t=1): símbolo em branco
  • Em (t=2): emitir "he"
  • Ainda em (t=2): símbolo em branco (ou emitir o próximo token imediatamente; depende do modelo)
  • Em (t=3): símbolo em branco
  • Em (t=4): emitir "llo"
  • Depois, símbolos em branco até o fim

Existem muitos alinhamentos válidos que produzem a mesma sequência de saída. O treinamento do RNN‑T soma sobre todos eles.

Objetivo de treinamento: maximizar a probabilidade da sequência sem rótulos por quadro

Dada a entrada (x) e os tokens-alvo (y), o RNN‑T define:

[ P(y \mid x) = \sum_{a \in \mathcal{A}(x,y)} P(a \mid x) ]

Onde:

  • (a) é um caminho de alinhamento através da treliça ((t,u))
  • (\mathcal{A}(x,y)) é o conjunto de todos os alinhamentos consistentes com (y)

O treinamento minimiza a log-verossimilhança negativa (negative log-likelihood):

[ \mathcal{L} = -\log P(y \mid x) ]

Forward-backward (programação dinâmica)

Somar diretamente sobre todos os alinhamentos é exponencial, então o RNN‑T usa um algoritmo de avanço-retrocesso (forward-backward algorithm) (como em HMMs e CTC) sobre a treliça:

  • Variável forward (\alpha(t,u)): probabilidade de alcançar ((t,u))
  • Variável backward (\beta(t,u)): probabilidade de completar a partir de ((t,u))

Em cada célula da treliça ((t,u)), as probabilidades vêm de:

  • transição de símbolo em branco a partir de ((t-1,u))
  • transição de rótulo a partir de ((t,u-1))

Isso produz gradientes exatos para a perda do RNN‑T via Retropropagação (Backpropagation), implementada de forma eficiente nos principais frameworks.

Detalhes práticos de treinamento

Escolhas e truques comuns em sistemas reais:

  • Subamostragem no codificador para reduzir (T') (crítico para memória/compute)
  • Vocabulário como subpalavras (equilibra flexibilidade e comprimento da sequência)
  • Regularização: dropout, suavização de rótulos (label smoothing), SpecAugment
  • Treinamento com lotes grandes + otimização distribuída (Descida do Gradiente (Gradient Descent))

Decodificação: gulosa e busca em feixe em um cenário de streaming

No tempo de inferência, queremos:

[ \hat{y} = \arg\max_y P(y \mid x) ]

A busca exata é intratável, então a decodificação prática usa aproximações.

Decodificação gulosa (greedy decoding) (mais rápida)

Uma abordagem gulosa simples em streaming, a cada passo de tempo:

  • Calcular a distribuição (p(\cdot \mid t,u))
  • Se o argmax for símbolo em branco: avançar (t)
  • Caso contrário, emitir o token, avançar (u) e atualizar o estado da rede de predição

A decodificação gulosa é de baixa latência e barata, mas pode reduzir a acurácia em comparação com a busca em feixe, especialmente para áudio ambíguo.

Decodificação com busca em feixe (beam search) (comum em produção)

A busca em feixe (beam search) mantém múltiplas hipóteses parciais (prefixos) e as expande. Para RNN‑T, a busca em feixe deve lidar com o comportamento especial do símbolo em branco e com o fato de que emitir rótulos não avança o tempo.

Uma busca em feixe típica para RNN‑T itera sobre passos de tempo (t) e, dentro de cada passo de tempo, realiza um número limitado de expansões de rótulos.

Ingredientes-chave:

  • Largura do feixe (beam width): número de hipóteses mantidas (por exemplo, 4–16 no dispositivo; maior no servidor)
  • Poda (pruning): descartar hipóteses de baixa probabilidade para ganhar velocidade
  • Fusão rasa (shallow fusion) opcional com modelo de linguagem externo: combinar a pontuação do RNN‑T com a do modelo de linguagem (veja abaixo)

Abaixo está um pseudocódigo simplificado (ilustrativo, não pronto para produção):

def rnnt_beam_search(encoded_frames, pred_net, joint, beam_size=8, max_sym_per_t=2):
    # Each hypothesis: (tokens, pred_state, logp)
    beam = [([], pred_net.init_state(), 0.0)]

    for h_t in encoded_frames:
        new_beam = beam

        # Allow limited label emissions at this time step
        for _ in range(max_sym_per_t):
            candidates = []
            for tokens, state, logp in new_beam:
                logits = joint(h_t, pred_net.output(state))
                probs = softmax(logits)

                # Blank: advance time (handled by carrying hypothesis forward)
                candidates.append((tokens, state, logp + log(probs["<blank>"])))

                # Non-blank expansions: emit token, update pred state
                for tok in top_k_tokens(probs, k=beam_size):
                    if tok == "<blank>":
                        continue
                    next_state = pred_net.step(state, tok)
                    candidates.append((tokens + [tok], next_state, logp + log(probs[tok])))

            new_beam = prune_to_top_k(candidates, beam_size)

        beam = new_beam

    return best_hypothesis(beam)

Decodificadores reais adicionam otimizações como cache de estados (state caching), mesclagem de prefixos (prefix merging) e computações conjuntas em lote (batched joint computations).

O papel do símbolo em branco durante a decodificação

O símbolo em branco não é exibido ao usuário. Ele serve a dois propósitos:

  • Permite que o modelo espere até ter evidência acústica suficiente
  • Habilita flexibilidade de alinhamento e streaming estável

Um modelo que emite símbolos em branco demais pode ser excessivamente conservador (maior latência); poucos símbolos em branco podem causar saídas prematuras ou instáveis. Sistemas em produção frequentemente ajustam parâmetros de decodificação e, às vezes, aplicam técnicas como escalonamento do símbolo em branco (blank scaling) ou heurísticas de detecção de término (endpointing).

Por que o RNN‑T é adequado para ASR em streaming de baixa latência

O RNN‑T se alinha naturalmente às restrições do reconhecimento de fala em tempo real:

1) Processamento incremental sem contexto completo do enunciado

Ao contrário de ASR sequência a sequência (sequence-to-sequence, seq2seq) baseado em atenção e não em streaming (que frequentemente aplica atenção sobre todo o enunciado codificado), o RNN‑T pode operar com:

  • um codificador causal/em blocos
  • uma rede de predição que depende apenas de tokens passados

Isso permite hipóteses parciais conforme o áudio chega.

2) Modelagem conjunta de acústica e histórico

A rede de predição dá ao modelo uma noção forte de “quais tokens são prováveis a seguir”, o que frequentemente melhora a acurácia em relação a suposições de independência condicional no estilo CTC puro.

3) Implantação eficiente no dispositivo

O RNN‑T pode ser projetado para ser:

  • de baixa memória (rede de predição pequena, codificador subamostrado)
  • de baixo custo computacional por quadro
  • estável sob restrições de streaming (antecipação limitada)

Por isso o RNN‑T é comum em assistentes de voz, ditado e legendas ao vivo em dispositivos móveis.

Relação com outras abordagens de ASR

RNN‑T vs CTC

Tanto RNN‑T quanto Classificação Temporal Conexionista (CTC) usam um símbolo em branco e somam sobre alinhamentos. A principal diferença:

  • CTC assume que as saídas em diferentes passos de tempo são condicionalmente independentes dado o input (sem um modelo explícito de histórico de rótulos).
  • RNN‑T condiciona tanto no input quanto nas saídas não brancas anteriores via a rede de predição.

Consequências práticas:

  • O RNN‑T frequentemente obtém melhor acurácia, especialmente em contextos mais longos e vocabulários mais ricos.
  • A decodificação do CTC é mais simples; a do RNN‑T é mais envolvida.

RNN‑T vs codificador–decodificador baseado em atenção

ASR baseado em atenção (por exemplo, LAS) pode ser altamente preciso, mas frequentemente é menos direto para streaming porque a atenção pode exigir contexto do enunciado completo (embora existam variantes de atenção em streaming).

O RNN‑T é uma “escolha padrão” quando você precisa de:

  • limites estritos de latência
  • saídas incrementais estáveis
  • comportamento robusto em streaming

Sistemas híbridos e modelos de linguagem externos

Embora a rede de predição se comporte como um modelo de linguagem interno, muitos sistemas melhoram a acurácia ao integrar um modelo de linguagem (language model, LM) externo usando fusão rasa:

[ \log P_{\text{total}} = \log P_{\text{RNNT}} + \lambda \log P_{\text{LM}} + \gamma \cdot \text{coverage/length terms} ]

Isso pode ajudar com palavras raras, nomes ou adaptação a domínios.

Conceito relacionado: Busca em Feixe.

Considerações práticas de implantação

Escolha de vocabulário

Tokenizações comuns:

  • Caracteres: simples, mas sequências longas
  • Subpalavras (BPE/unigram): ótimo equilíbrio para ASR
  • Palavras: vocabulário grande, problemas de fora do vocabulário (out-of-vocabulary, OOV) a menos que sejam tratados com cuidado

Subpalavras são comuns em sistemas RNN‑T de produção.

Projeto do codificador para streaming

Para manter a latência baixa:

  • Use convoluções causais ou autoatenção em blocos
  • Limite o contexto à direita (antecipação) a uma janela pequena
  • Subamostre cedo para reduzir a taxa de quadros

Um alvo comum de projeto é manter a latência algorítmica (da antecipação do modelo + buffering) dentro de dezenas de milissegundos, dependendo das restrições do produto.

Endpointing e resultados parciais

ASR em streaming precisa decidir:

  • quando emitir transcrições parciais (“resultados intermediários”)
  • quando um enunciado terminou (“detecção de fim de fala (endpointing)”)

O RNN‑T fornece probabilidades de emissão de tokens, mas a detecção de fim de fala frequentemente também usa:

  • heurísticas de comprimento de sequência de símbolos em branco (blank run-length heuristics)
  • um modelo separado de detecção de fim (endpointer model)
  • sinais de detecção de atividade de voz (voice activity detection, VAD)

Quantização e aceleração (no dispositivo)

Para mobile/embarcados:

  • quantização de pesos (quantization) (por exemplo, int8)
  • fusão de operadores (operator fusion)
  • cache de computações de predição/conjunta por hipótese
  • larguras de feixe pequenas com ajuste cuidadoso

Esses passos de engenharia frequentemente importam tanto quanto a arquitetura do modelo para desempenho em tempo real.

Armadilhas comuns e comportamentos do modelo

  • Trade-off entre deleção e inserção: ajustar o tamanho do feixe, o viés de símbolo em branco ou a fusão com modelo de linguagem pode deslocar o comportamento entre palavras ausentes (deleções) e palavras alucinadas (inserções).
  • Exposição a texto de domínio: como a rede de predição do RNN‑T é treinada com áudio-texto pareado, ela pode ter desempenho inferior em frases raras de um domínio específico, a menos que seja adaptada ou fundida com um modelo de linguagem externo.
  • Áudio de longa duração: streaming ajuda, mas contextos longos ainda podem ser desafiadores; alguns sistemas usam segmentação, reavaliação (rescoring) ou viés contextual (contextual biasing).

Onde o RNN‑T é usado

Aplicações típicas incluem:

  • Assistentes de voz: reconhecimento rápido após palavra de ativação (wake-word)
  • Ditado móvel: entrada de texto com baixa latência
  • Legendas ao vivo: transcrição em streaming para reuniões/mídia
  • Transcrição em call centers: assistência ao agente em tempo real
  • Wearables e dispositivos embarcados: orçamentos de computação apertados, restrições de privacidade

O RNN‑T é especialmente atraente quando você precisa de saída em tempo real e não pode arcar com idas e voltas ao servidor, tornando-o uma arquitetura-chave para ASR no dispositivo.

Resumo

O RNN‑T é uma arquitetura fundamental para ASR em streaming porque:

  • Modela fala-para-texto com alinhamentos latentes usando um símbolo em branco
  • Combina um codificador (acústica), rede de predição (histórico de tokens) e rede conjunta (fusão) para prever o próximo símbolo
  • Treina ponta a ponta via programação dinâmica de avanço-retrocesso em uma treliça 2D
  • Suporta decodificação em streaming eficiente com decodificação gulosa ou busca em feixe
  • Se ajusta melhor a restrições de baixa latência e no dispositivo do que muitas abordagens sequência a sequência não em streaming

Para conceitos adjacentes, veja Classificação Temporal Conexionista (CTC), Busca em Feixe, Redes Neurais Recorrentes e Arquitetura Transformer.