DDSD em português brasileiro: TF-IDF (Regressão Logística e SVM)

English summary. The two TF-IDF baselines of a Brazilian Portuguese device-directed speech detection (DDSD) thesis: given the transcript of an utterance, they predict whether it was addressed to the computer (DD) or not (NDD). Word 1–3-gram TF-IDF (50,000 terms) with logistic regression or a calibrated linear SVM, trained on the length-corrected synthetic corpus. The files are joblib pickles: load them only if you trust the source, with scikit-learn 1.9.1. Normalize the input as in training and use the stored thresholds (0.48 and 0.46).

Os dois baselines do TCC, que decidem se uma fala transcrita foi dirigida ao computador (DD) ou não (NDD): TF-IDF de palavras (1 a 3-gramas, 50.000 termos, tf sublinear, normalização L2) com Regressão Logística ou com SVM linear com probabilidades calibradas. O C de cada um saiu de uma busca em grade com validação cruzada de 5 partes no treino de phelipescript/ddsd-ptbr-corpus (configuração com_correcao). Os dois podem ser o classificador do sistema em tempo real do TCC no lugar do BERTimbau.

Arquivo Estimador C F1 macro na validação cruzada Limiar de decisão
regressao_logistica.joblib LogisticRegression 10 0,9585 0,48
svm.joblib CalibratedClassifierCV 1 0,9608 0,46

Cada arquivo guarda um dicionário com vectorizer, model, threshold e kind. Os parâmetros completos estão em regressao_logistica.json e svm.json.

Atenção: .joblib é um pickle, e carregar um pickle executa código. Carregue só arquivos de origem confiável, com o scikit-learn 1.9.1 (outras versões podem não abrir o arquivo ou mudar o resultado).

Como usar

Exemplo executado com Python 3.13, scikit-learn 1.9.1, joblib 1.6.0 e huggingface_hub 2.2.0:

import unicodedata
from pathlib import Path

import joblib
from huggingface_hub import snapshot_download


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())


pasta = Path(snapshot_download("phelipescript/ddsd-ptbr-tfidf"))
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 arquivo in ("regressao_logistica.joblib", "svm.joblib"):
    pacote = joblib.load(pasta / arquivo)  # é um pickle: só carregue arquivos de origem confiável
    vetorizador, modelo, limiar = pacote["vectorizer"], pacote["model"], pacote["threshold"]
    print(f"{arquivo} (limiar {limiar})")
    for frase in frases:
        p_dd = modelo.predict_proba(vetorizador.transform([normalizar(frase)]))[0, 1]
        print(f"{p_dd:.3f}  {'DD ' if p_dd >= limiar else 'NDD'}  {frase}")

Saída:

regressao_logistica.joblib (limiar 0.48)
1.000  DD   Abre o navegador e procura a previsão do tempo, por favor.
0.956  DD   Me lembra de ligar pro dentista amanhã às dez.
0.006  NDD  Você viu o jogo de ontem?
0.016  NDD  Travou de novo, que saco.
svm.joblib (limiar 0.46)
0.996  DD   Abre o navegador e procura a previsão do tempo, por favor.
0.939  DD   Me lembra de ligar pro dentista amanhã às dez.
0.011  NDD  Você viu o jogo de ontem?
0.029  NDD  Travou de novo, que saco.

Normalize o texto com a função normalizar do exemplo e decida pelo limiar guardado em cada arquivo (threshold), escolhido na validação.

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 Regressão Logística SVM
Acurácia 96,09% 96,15%
F1 macro 0,9609 0,9615
ROC-AUC 0,9913 0,9906
EER 3,93% 4,01%

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.

Corpus Frases Regressão Logística SVM
CORAA 1.000 6,3% 6,8%
NURC-SP 1.000 6,3% 6,6%
TAGARELA 912 5,6% 6,4%
Total 2.912 6,1% 6,6%

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 Rótulo Regressão Logística SVM
Voz real pedidos atendidos (DD) 87,5% (70 de 80) 87,5% (70 de 80)
Voz real falsas ativações (NDD) 5,8% (6 de 104) 8,7% (9 de 104)
Voz sintética pedidos atendidos (DD) 93,2% (345 de 370) 94,3% (349 de 370)
Voz sintética falsas ativações (NDD) 4,1% (15 de 370) 5,1% (19 de 370)
Áudio dos corpora públicos falsas ativações (NDD) 8,5% (51 de 600) 8,7% (52 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.

Limitações

  • Corpus 100% sintético: as frases foram geradas por LLMs e têm o estilo deles, diferente da fala espontânea transcrita.
  • Erros de transcrição: no TCC, o acerto dos TF-IDF caiu mais que o dos Transformers quando o texto veio do Whisper, e não da frase lida.
  • Vocabulário fixo: palavras fora dos termos do treino não contam.
  • Voz real: uma única voz, com frases lidas; a avaliação não tem pedidos espontâneos.

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.

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-tfidf}}
}
Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train phelipescript/ddsd-ptbr-tfidf

Collection including phelipescript/ddsd-ptbr-tfidf