6 — LDA (Levinson–Durbin Algorithm)
O que significa LDA neste contexto
Aqui LDA não é Linear Discriminant Analysis (muito comum em ML).
No artigo de referência, LDA refere-se ao Levinson–Durbin Algorithm, o algoritmo clássico usado para resolver eficientemente as equações de Yule–Walker geradas pelo método de autocorrelação.
O problema a ser resolvido é:
Dado o vetor de autocorrelação ( r[0..p] ), encontrar os coeficientes LPC ( a_1, a_2, \dots, a_p ) que minimizam o erro de predição linear.
Resolver isso por métodos genéricos (eliminação de Gauss, inversão de matriz) é caro e numericamente frágil.
O Levinson–Durbin explora a estrutura Toeplitz da matriz de autocorrelação.
Por que Levinson–Durbin é essencial
Três motivos tornam o algoritmo indispensável:
- Complexidade reduzida
- Inversão direta: \( O(p^3) \)
- Levinson–Durbin: \( O(p^2) \)
- Estabilidade garantida
- Produz filtros tudo-polo estáveis
- Reflexão (reflection coefficients) com módulo < 1
- Adequação a tempo real
- Usado historicamente em:
- Codecs de voz
- Telefonia
- Sistemas embarcados
- DSPs dedicados
- Usado historicamente em:
Sem Levinson–Durbin, LPC e LPCC não seriam práticos em firmware.
Estrutura recursiva do algoritmo
O algoritmo constrói o modelo ordem por ordem:
- Ordem 1 → melhor preditor com 1 atraso
- Ordem 2 → melhora usando 2 atrasos
- …
- Ordem ( p )
Em cada iteração são calculados:
- Coeficiente de reflexão \( k_m \)
- Coeficientes LPC intermediários
- Energia do erro \( E_m \)
A recursão central é:
\[
k_m = \frac{r[m] – \sum_{i=1}^{m-1} a_i^{(m-1)} r[m-i]}{E_{m-1}}
\]
\[
a_i^{(m)} = a_i^{(m-1)} – k_m a_{m-i}^{(m-1)}
\]
\[
a_m^{(m)} = k_m
\]
\[
E_m = (1 – k_m^2) E_{m-1}
\]
Interpretação física do coeficiente de reflexão
O coeficiente de reflexão \( k_m \):
- Mede quanta energia retorna ao adicionar um novo atraso
- Está diretamente ligado à:
- Estabilidade
- Robustez numérica
- Qualidade do modelo
Se \( |k_m| \ge 1 \):
- O modelo se torna instável
- O sinal não é bem representado por um AR puro
Implementação completa em C — Levinson–Durbin
A seguir, uma implementação realista, adequada para sistemas embarcados:
#include <stddef.h>
/**
* Algoritmo de Levinson-Durbin
*
* r : vetor de autocorrelação (r[0..p])
* p : ordem do modelo
* a : coeficientes LPC (saída, tamanho p)
* err : energia do erro de predição (saída)
*
* Retorna 0 em sucesso, -1 em falha numérica
*/
int levinson_durbin(const float *r,
size_t p,
float *a,
float *err)
{
float E = r[0];
if (E <= 0.0f)
return -1;
for (size_t i = 0; i < p; i++)
a[i] = 0.0f;
for (size_t m = 1; m <= p; m++) {
float acc = 0.0f;
for (size_t i = 1; i < m; i++)
acc += a[i - 1] * r[m - i];
float k = (r[m] - acc) / E;
// Atualiza coeficientes
for (size_t i = 0; i < m / 2; i++) {
float tmp1 = a[i];
float tmp2 = a[m - i - 2];
a[i] = tmp1 - k * tmp2;
a[m - i - 2] = tmp2 - k * tmp1;
}
a[m - 1] = k;
E *= (1.0f - k * k);
if (E <= 0.0f)
return -1;
}
*err = E;
return 0;
}
Observações importantes sobre o código
- Usa apenas:
- Somatórios
- Multiplicações
- Divisões
- Não requer FFT
- Funciona bem com
floatem:- Cortex-M4/M7
- RISC-V com FPU
- Pode ser adaptado para
fixed-pointse necessário
O valor err é fundamental, pois será usado diretamente no cálculo do LPCC (c₀).
Papel do Levinson–Durbin no pipeline completo
Agora o encadeamento fica matematicamente fechado:
Sinal
↓
Autocorrelação (AC)
↓
Levinson–Durbin (LDA)
↓
Coeficientes LPC + erro
↓
Conversão LPC → LPCC
Cada etapa é:
- Bem definida
- Computacionalmente viável
- Estável
7 — PE (Prediction Error)
O que significa PE
PE é o acrônimo de Prediction Error (Erro de Predição).
No contexto de LP, LPC e LPCC, o erro de predição não é ruído residual sem importância — ele é uma variável estatística fundamental que mede o quão bem o modelo explica o sinal.
Formalmente, o erro de predição é:
\[
e[n] = x[n] – \sum_{k=1}^{p} a_k x[n-k]
\]
onde:
- \( x[n] \) é o sinal real
- \( a_k \) são os coeficientes LPC
- \( e[n] \) é o erro instantâneo
O que realmente importa não é \( e[n] \) isolado, mas sua energia média.
Energia do erro de predição
A grandeza central é a variância do erro:
\[
\sigma^2 = \mathbb{E}{e^2[n]}
\]
No algoritmo de Levinson–Durbin, essa quantidade aparece como:
- \( E_0 = r[0] \) (energia total do sinal)
- \( E_p \) → energia residual após modelagem LPC de ordem ( p )
Essa energia residual representa o que o modelo não conseguiu explicar.
Interpretação física do erro de predição
A interpretação correta do erro depende da aplicação:
Em fala
- LPC modela o trato vocal (filtro)
- O erro representa a excitação:
- Pulsos periódicos (voz)
- Ruído (sons fricativos)
Em vibração mecânica
- LPC modela a estrutura
- O erro representa:
- Impactos
- Excitação externa
- Eventos transitórios
Ou seja:
Erro de predição = fonte não modelada
Isso é extremamente valioso do ponto de vista de diagnóstico.
Relação direta entre PE e LPCC (coeficiente c₀)
No LPCC, o primeiro coeficiente cepstral é:
\[
c_0 = \ln(\sigma^2)
\]
Esse termo:
- Carrega informação de energia
- Normaliza diferenças de ganho
- Permite comparação entre janelas
Em muitas aplicações:
- \( c_0 \) é mantido
- Ou descartado propositalmente para remover influência de amplitude
Essa decisão é de engenharia, não matemática.
PE como métrica de qualidade do modelo
A energia do erro permite avaliar:
- Se a ordem \( p \) é suficiente
- Se o sinal é bem modelado como AR
- Se há mudanças estruturais no sinal
Exemplo prático:
- Aumento abrupto de \( \sigma^2 \)
→ mudança de regime
→ falha mecânica
→ transiente anômalo
Isso explica o uso de LPC/LPCC em monitoramento de condição.
Exemplo em C — cálculo explícito do erro médio
Embora Levinson–Durbin já forneça ( \sigma^2 ), às vezes é útil calcular o erro diretamente:
/**
* Calcula a variância do erro de predição
*/
float prediction_error_variance(const float *x,
size_t N,
const float *a,
size_t p)
{
float sum = 0.0f;
for (size_t n = p; n < N; n++) {
float pred = 0.0f;
for (size_t k = 1; k <= p; k++) {
pred += a[k - 1] * x[n - k];
}
float e = x[n] - pred;
sum += e * e;
}
return sum / (float)(N - p);
}
Esse cálculo é útil para:
- Validação
- Debug
- Avaliação offline
PE e estabilidade numérica
Alguns pontos críticos em firmware:
- Se \( \sigma^2 \to 0 \):
- Risco de
log(0) - Saturação numérica
- Risco de
- Soluções práticas:
- Clamping mínimo
- Normalização do sinal
- Janela adequada
Esses cuidados são essenciais antes de calcular LPCC.
Relação final no pipeline
Agora o fechamento conceitual:
Autocorrelação → Levinson–Durbin
↓
Coeficientes LPC
↓
Erro de predição σ²
↓
LPCC (c₀ = ln σ²)
O erro não é um detalhe, ele é parte estrutural do vetor de características.
Conclusão desta seção
Nesta seção você viu:
- O significado real de PE
- Sua definição matemática
- Interpretação física
- Papel central no LPCC
- Exemplos práticos em C