Suavizando dados de séries temporais

14

Estou criando um aplicativo para Android que registra dados do acelerômetro durante o sono, para analisar as tendências do sono e, opcionalmente, acordar o usuário perto do tempo desejado durante o sono leve.

Já construí o componente que coleta e armazena dados, além do alarme. Eu ainda preciso abordar a fera de exibir e salvar dados do sono de uma maneira realmente significativa e clara, que de preferência também se presta à análise.

Algumas fotos dizem duas mil palavras: (só posso postar um link devido à baixa rep)

Aqui estão os dados não filtrados, a soma do movimento, coletados em intervalos de 30 segundos

E os mesmos dados, suavizados por minha própria manifestação de suavização da média móvel

editar) os dois gráficos refletem a calibração - há um filtro mínimo de 'ruído' e um filtro de corte máximo, além de um nível de disparo de alarme (a linha branca)

Infelizmente, nenhuma dessas soluções é ótima - a primeira é um pouco difícil de entender para o usuário médio e a segunda, que é mais fácil de entender, esconde muito do que realmente está acontecendo. Em particular, a média remove os detalhes dos picos de movimento - e acho que esses podem ser significativos.

Então, por que esses gráficos são tão importantes? Essas séries temporais são exibidas durante toda a noite como feedback para o usuário e serão armazenadas para revisão / análise posteriormente. A suavização reduzirá idealmente o custo da memória (RAM e armazenamento) e tornará a renderização mais rápida nesses telefones / dispositivos sem recursos.

Claramente, há uma maneira melhor de suavizar os dados - tenho algumas idéias vagas, como usar a regressão linear para descobrir mudanças 'nítidas' no movimento e modificar minha suavização da média móvel de acordo. Eu realmente preciso de mais algumas orientações e sugestões antes de mergulhar de cabeça em algo que possa ser resolvido da melhor maneira possível.

Obrigado!

Jon
fonte

Respostas:

16

Primeiro, os requisitos para compactação e análise / apresentação não são necessariamente os mesmos - de fato, para a análise, você pode querer manter todos os dados brutos e ter a capacidade de dividir e cortar de várias maneiras. E o que funciona melhor para você dependerá muito do que você deseja obter com isso. Mas há vários truques padrão que você pode tentar:

  • Use diferenças em vez de dados brutos
  • Use limiar para remover ruído de baixo nível. (Combine com diferenciação para ignorar pequenas alterações.)
  • Use a variação ao longo de alguma janela de tempo, em vez da média, para capturar o nível de atividade em vez do movimento
  • Altere a base de tempo de intervalos fixos para execuções de comprimento variável e acumule em um único ponto de dados sequências de alterações para as quais algum critério se aplica (por exemplo, diferenças na mesma direção, até algum limite)
  • Transforme dados de valores reais em ordinais (por exemplo, baixo, médio, alto); você também pode fazer isso em caixas de tempo em vez de amostras individuais - por exemplo, nível de atividade para cada trecho de 5 minutos
  • Use um kernel de convolução * apropriado para suavizar mais sutilmente que sua média móvel ou escolher recursos de interesse, como mudanças bruscas.
  • Use uma biblioteca FFT para calcular um espectro de potência

O último pode ser um pouco caro para os seus propósitos, mas provavelmente forneceria algumas opções de apresentação muito úteis, em termos de "ritmos do sono" e assim por diante. (Não sei quase nada sobre o Android, mas é concebível que alguns / muitos / todos os aparelhos possam ter construído em hardware DSP do qual você possa tirar proveito.)


* Dada a convolução central do processamento do sinal digital, é surpreendentemente difícil encontrar uma introdução acessível on-line. Ou pelo menos em 3 minutos de pesquisa no Google. Sugestões são bem-vindas!

walkytalky
fonte
10

Existem muitos algoritmos de suavização não paramétricos, incluindo splines e loess. Mas eles também suavizarão as mudanças repentinas. O mesmo acontece com os filtros passa-baixo. Eu acho que você pode precisar de um wavelet mais suave que permita saltos repentinos, mas ainda suaviza o ruído.

Confira Percival e Walden (2000) e o pacote R associado . Embora você queira uma solução java, os algoritmos no pacote R são de código aberto e você pode traduzi-los.

Rob Hyndman
fonte
3

Isso é algo tangencial para o que você está perguntando, mas pode valer a pena dar uma olhada no filtro Kalman.

NPE
fonte
1

A suavização de Savitzky-Golay pode ser uma boa resposta. É uma implementação extremamente eficiente de mínimos quadrados suavizando uma janela de tempo deslizante (uma convolução sobre esses dados) que se resume a apenas multiplicar os dados em cada janela de tempo por constantes fixas. Você pode ajustar valores, derivadas, segundas derivadas e superiores.

Você escolhe o quão espetado deseja que os resultados sejam, com base no tamanho da janela de tempo deslizante e no grau do ajuste polinomial nessa janela de tempo. Isso foi originalmente desenvolvido para cromatografia, onde os picos são uma parte essencial dos resultados. Uma propriedade desejável da suavização SG é que os locais dos picos sejam preservados. Por exemplo, uma janela de 5 a 11 pontos com um ajuste de curva cúbica reduz o ruído, mas ainda preserva os picos.

Há um bom artigo na Wikipedia, embora seja referido como filtro Savitzky-Golay (fazendo uma leve violência à terminologia normal da teoria de controle de sistemas e análise de séries temporais, bem como do artigo original, onde é chamado corretamente de suavização). Esteja ciente de que existe (um argumento sobre) um erro no artigo da Wikipedia sobre fórmulas para estimativas de segunda derivada - consulte a seção Discussão desse artigo. EDIT: O artigo da Wikipedia foi corrigido

gms
fonte