DDSD em português brasileiro: BERTimbau

English summary. Brazilian Portuguese text classifier for device-directed speech detection (DDSD): given the transcript of an utterance, it predicts whether it was addressed to the computer (DD) or not (NDD), for voice assistants without a wake word. BERTimbau (neuralmind/bert-base-portuguese-cased) fine-tuned on a synthetic corpus whose sentence-length bias was corrected. Normalize the input as in training (no accents, lowercase, punctuation and symbols replaced by spaces) and decide with the threshold stored in config.json (decision_threshold = 0.685), not with argmax. Internal test accuracy: 98.32%; false activations on real conversation transcripts: 6.3%. Part of a bachelor's thesis (SENAC Santo Amaro, 2026).

Classificador de texto que decide se uma fala, já transcrita, foi dirigida ao computador (DD) ou não (NDD), para assistentes de voz sem palavra de ativação. É o BERTimbau com fine-tuning no corpus sintético phelipescript/ddsd-ptbr-corpus, na configuração com_correcao, que corrige o viés de comprimento. Faz parte do TCC Detecção de Fala Direcionada ao Computador Pessoal em Português Brasileiro: Uma Abordagem Textual para Assistentes de Voz sem Palavra de Ativação (Bacharelado em Ciência da Computação, SENAC Santo Amaro, 2026).

  • DD: pedido ao computador, como “abre o navegador e procura a previsão do tempo”.
  • NDD: qualquer outra fala: conversa com outra pessoa, comentário, pensar alto.

No sistema em tempo real do TCC (microfone → detector de voz → Whisper large-v3-turbo → classificador → decisão), é o classificador padrão.

Como usar

Exemplo executado com Python 3.13, transformers 5.20.1 e torch 2.14.1:

import unicodedata

import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer


def normalizar(texto: str) -> str:
    """Normalização do treino: sem acento, minúsculas, pontuação e símbolos viram espaço."""
    texto = "".join(c for c in unicodedata.normalize("NFKD", texto) if unicodedata.category(c) != "Mn")
    texto = "".join(" " if unicodedata.category(c)[0] in "PS" else c for c in texto.lower())
    return " ".join(texto.split())


repo = "phelipescript/ddsd-ptbr-bertimbau"
tokenizer = AutoTokenizer.from_pretrained(repo)
modelo = AutoModelForSequenceClassification.from_pretrained(repo).eval()
limiar = modelo.config.decision_threshold  # escolhido na validação; não use 0,5

frases = [
    "Abre o navegador e procura a previsão do tempo, por favor.",
    "Me lembra de ligar pro dentista amanhã às dez.",
    "Você viu o jogo de ontem?",
    "Travou de novo, que saco.",
]
for frase in frases:
    entrada = tokenizer(normalizar(frase), truncation=True, max_length=128, return_tensors="pt")
    with torch.inference_mode():
        p_dd = torch.softmax(modelo(**entrada).logits, dim=-1)[0, 1].item()
    print(f"{p_dd:.3f}  {'DD ' if p_dd >= limiar else 'NDD'}  {frase}")

Saída:

1.000  DD   Abre o navegador e procura a previsão do tempo, por favor.
0.998  DD   Me lembra de ligar pro dentista amanhã às dez.
0.000  NDD  Você viu o jogo de ontem?
0.000  NDD  Travou de novo, que saco.

Dois cuidados, porque o modelo foi treinado e avaliado assim:

  1. Normalize o texto com a função normalizar do exemplo: sem acento, em minúsculas e com pontuação e símbolos trocados por espaço.
  2. Decida pelo limiar config.decision_threshold (0,685), escolhido na validação. O pipeline("text-classification") do transformers decide por argmax, o que equivale a um limiar de 0,5.

Treino

Modelo base neuralmind/bert-base-portuguese-cased, 108,9 mi de parâmetros
Corpus phelipescript/ddsd-ptbr-corpus, configuração com_correcao: 93.150 frases de treino (metade DD e metade NDD) e 11.672 de validação (metade DD e metade NDD)
Semente 44; das sementes 42, 43 e 44, a de maior F1 macro na validação
Hiperparâmetros taxa de aprendizado 2e-5, lote 32, até 4 épocas, até 128 tokens, aquecimento de 10%, dropout 0,1, weight decay 0,01, agendador linear, precisão mista bf16
Checkpoint passo 8.733 (época 3 de 4), o de maior F1 macro na validação; parada antecipada com paciência 2
Limiar de decisão 0,685: o que maximiza a F1 macro na validação, numa grade de 0,005 a 0,995 (passo 0,005)
Hardware Apple M5 (GPU via MPS), 16 GB de memória unificada; 55 min de treino

Os valores por época e as métricas completas estão em treinamento.json.

Resultados

Teste interno

11.616 frases sintéticas do teste com_correcao (metade DD e metade NDD), avaliadas uma única vez, com o limiar congelado.

Métrica Este modelo (semente 44) Média das 3 sementes ± desvio
Acurácia 98,32% 98,22% ± 0,10 p.p.
F1 macro 0,9832 0,9822 ± 0,0010
ROC-AUC 0,9979 0,9977 ± 0,0002
EER 1,72% 1,78% ± 0,06 p.p.

Transcrições de conversas reais

Frases das transcrições do CORAA, do NURC-SP e do TAGARELA. São todas conversa entre pessoas (NDD), então toda ativação é falsa. Falsas ativações:

Corpus Frases Este modelo BERTimbau sem correção
CORAA 1.000 4,7% 34,9%
NURC-SP 1.000 6,6% 20,5%
TAGARELA 912 7,8% 26,1%
Total 2.912 6,3% 27,2%

Das 3 sementes, esta é a de mais falsas ativações nessas transcrições: 6,3%, contra 5,0% (semente 42) e 5,7% (semente 43).

Por tamanho da frase:

Palavras Frases Este modelo BERTimbau sem correção
2 144 6,9% 87,5%
3 210 8,6% 79,0%
4 266 5,3% 58,3%
5 226 5,3% 44,7%
6 239 5,4% 36,8%
7–8 407 5,7% 24,6%
9–10 321 5,6% 9,0%
11–13 344 4,7% 3,5%
14–17 276 4,3% 2,9%
18–24 259 8,5% 1,9%
25–50 208 12,0% 1,0%
mais de 50 12 8,3% 0,0%

Nas frases de 11 palavras ou mais, este modelo ativa mais que a versão sem correção. No corpus sem correção, frase longa era quase sempre NDD, e o modelo treinado nele aprendeu isso. O treino com correção não tem frases de 25 palavras ou mais.

Sistema completo

Áudio → detector de voz → Whisper large-v3-turbo → classificador, no sistema em tempo real do TCC. O áudio gravado toca no ritmo normal no buffer do microfone; dali em diante, é o sistema real.

Conjunto Pedidos atendidos (DD) Falsas ativações (NDD) Falsas ativações: BERTimbau sem correção
Voz real 95,0% (76 de 80) 7,7% (8 de 104) 26,0% (27 de 104)
Voz sintética 96,5% (357 de 370) 1,9% (7 de 370) 34,3% (127 de 370)
Áudio dos corpora públicos — 6,5% (39 de 600) 29,2% (175 de 600)
  • Voz real: uma única voz. As mesmas 20 frases DD e 20 NDD do teste, lidas em 4 cenários (sala quieta, ruído de fundo, iPhone e ~2 m), mais as 24 falas de um roteiro de conversa (NDD).
  • Voz sintética: 740 frases do teste em 3 vozes neurais pt-BR do edge-tts.
  • Áudio dos corpora públicos: 600 trechos de conversa espontânea (300 do CORAA e 300 do NURC-SP), todos NDD.

Sessão ao vivo

9,5 min ao microfone, seguindo um roteiro, com uma única voz: 36 de 41 pedidos atendidos e 4 de 45 falsas ativações. Dos 5 pedidos perdidos, 4 são erros de transcrição do Whisper e 1 é erro do classificador.

Limitações

  • Corpus 100% sintético: as frases foram geradas por LLMs e têm o estilo deles, diferente da fala espontânea transcrita.
  • Limiar: escolhido na validação sintética, ele se transfere de forma imperfeita para a fala real.
  • Voz real: uma única voz, com frases lidas; a avaliação não tem pedidos espontâneos.
  • Só texto: a decisão depende da transcrição, e erros do reconhecimento de fala mudam a decisão.
  • Sem contexto: cada fala é julgada sozinha, sem o histórico da conversa.

Modelos e dados relacionados

Repositório Conteúdo
phelipescript/ddsd-ptbr-bertimbau BERTimbau com correção (padrão do sistema)
phelipescript/ddsd-ptbr-albertina Albertina com correção
phelipescript/ddsd-ptbr-debertinha DeBERTinha com correção
phelipescript/ddsd-ptbr-tfidf TF-IDF com Regressão Logística e com SVM
phelipescript/ddsd-ptbr-bertimbau-sem-correcao BERTimbau sem correção (controle)
phelipescript/ddsd-ptbr-albertina-sem-correcao Albertina sem correção (controle)
phelipescript/ddsd-ptbr-debertinha-sem-correcao DeBERTinha sem correção (controle)
phelipescript/ddsd-ptbr-corpus o corpus, com e sem correção, e as fontes brutas

Licença

MIT, a mesma do modelo base.

Citação

@misc{souza2026ddsd,
  author       = {Phelipe Pereira de Souza},
  title        = {Detecção de Fala Direcionada ao Computador Pessoal em Português Brasileiro: Uma Abordagem Textual para Assistentes de Voz sem Palavra de Ativação},
  year         = {2026},
  note         = {Trabalho de Conclusão de Curso, Bacharelado em Ciência da Computação, SENAC Santo Amaro},
  howpublished = {\url{https://huggingface.co/phelipescript/ddsd-ptbr-bertimbau}}
}
Downloads last month
11
Safetensors
Model size
0.1B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for phelipescript/ddsd-ptbr-bertimbau

Finetuned
(250)
this model

Dataset used to train phelipescript/ddsd-ptbr-bertimbau

Collection including phelipescript/ddsd-ptbr-bertimbau