Estou tentando calcular a média móvel de um sinal. O valor do sinal (um duplo) é atualizado em tempos aleatórios. Eu estou procurando uma maneira eficiente de calcular a sua média ponderada em tempo sobre uma janela de tempo, em tempo real. Eu poderia fazer isso sozinho, mas é mais desafiador do que eu pensava. A maioria dos recursos que eu encontrei na internet estão calculando a média móvel do sinal periódico, mas as atualizações de minas em tempo aleatório. Alguém sabe bons recursos para o que o truque é o seguinte: Você recebe atualizações em tempos aleatórios através de void update (tempo int, valor float). No entanto, você também precisa acompanhar quando uma atualização cai fora da janela de tempo, então você define um alarme que chamado no tempo N que remove a atualização anterior de ser sempre considerado novamente na computação. Se isso acontecer em tempo real, você pode solicitar que o sistema operacional faça uma chamada para um método void dropoffoldestupdate (int time) para ser chamado no momento N Se esta é uma simulação, você não pode obter ajuda do sistema operacional e você precisa Faça-o manualmente. Em uma simulação você chamaria métodos com o tempo fornecido como um argumento (que não se correlaciona com o tempo real). No entanto, uma suposição razoável é que as chamadas são garantidas de tal forma que os argumentos de tempo estão aumentando. Neste caso, você precisa manter uma lista ordenada de valores de tempo de alarme e, para cada chamada de atualização e leitura, verifique se o argumento de tempo é maior que o cabeçalho da lista de alarmes. Embora seja maior você faz o processamento relacionado com o alarme (deixe cair a atualização mais antiga), remova a cabeça e verifique novamente até que todos os alarmes antes do tempo determinado sejam processados. Em seguida, faça a chamada de atualização. Até agora tenho assumido que é óbvio o que você faria para a computação real, mas vou elaborar apenas no caso. Eu suponho que você tem um método float read (tempo int) que você usa para ler os valores. O objetivo é tornar essa chamada o mais eficiente possível. Portanto, você não calcula a média móvel sempre que o método de leitura é chamado. Em vez disso, você precompute o valor a partir da última atualização ou o último alarme e ajustar esse valor por um par de operações ponto flutuante para conta para a passagem do tempo desde a última atualização. (Isto é, um número constante de operações excepto para talvez processar uma lista de alarmes acumulados). Esperemos que isso seja claro - este deve ser um algoritmo bastante simples e bastante eficiente. Otimização adicional. Um dos problemas restantes é se um grande número de atualizações acontecer dentro da janela de tempo, então há um longo tempo para que não há nem lê nem atualizações e, em seguida, uma leitura ou atualização vem junto. Neste caso, o algoritmo acima será ineficaz na atualização incremental do valor para cada uma das atualizações que está caindo. Isso não é necessário, porque nós só nos preocupamos com a última atualização além da janela de tempo, então se houver uma maneira eficiente de deixar todas as atualizações mais antigas, que ajudaria. Para fazer isso, podemos modificar o algoritmo para fazer uma busca binária de atualizações para encontrar a atualização mais recente antes da janela de tempo. Se houver relativamente poucas atualizações que precisam ser descartadas, então um pode atualizar incrementalmente o valor para cada atualização descartada. Mas se houver muitas atualizações que precisam ser descartadas, então um pode recalcular o valor do zero após deixar as atualizações antigas. Apêndice sobre Computação Incremental: Eu deveria esclarecer o que eu quero dizer por computação incremental acima na sentença tweak este valor por um par de operações de ponto flutuante para explicar a passagem do tempo desde a última atualização. Cálculo inicial não incremental: então iterar sobre as atualizações relevantes por ordem crescente de tempo: movimentação (sum lastupdate timesincelastupdate) / windowlength. Agora, se exatamente uma atualização cair da janela, mas nenhuma nova atualização chegar, ajuste a soma como: (note que é priorupdate que tem seu timestamp modificado para iniciar o último início da janela). E se exatamente uma atualização entra na janela, mas nenhuma nova atualização cai, ajuste a soma como: Como deve ser óbvio, este é um esboço aproximado, mas espero que ele mostra como você pode manter a média tal que é O (1) operações por atualização Sobre uma base amortizada. Mas observe otimização adicional no parágrafo anterior. Observe também as questões de estabilidade mencionadas em uma resposta mais antiga, o que significa que os erros de ponto flutuante podem se acumular em um grande número dessas operações incrementais, de modo que há uma divergência em relação ao resultado da computação completa que é significativa para a aplicação. Se uma aproximação é OK e há um tempo mínimo entre as amostras, você pode tentar super-amostragem. Tenha uma matriz que represente intervalos de tempo uniformemente espaçados que sejam mais curtos que o mínimo, e em cada período de tempo armazene a amostra mais recente que foi recebida. Quanto menor o intervalo, mais próxima será a média do valor real. O período não deve ser maior que a metade do mínimo ou há uma chance de faltar uma amostra. Respondeu Dec 15 11 at 18:12 respondeu Dec 15 11 at 22:38 Obrigado pela resposta. Uma melhoria que seria necessário para realmente quotcachequot o valor da média total para que don39t loop o tempo todo. Além disso, pode ser um ponto menor, mas não seria mais eficiente usar um deque ou uma lista para armazenar o valor, uma vez que assumimos que a atualização virá na ordem correta. A inserção seria mais rápida do que no mapa. Ndash Arthur 16 dez às 8:55 Sim, você poderia armazenar em cache o valor de soma. Subtraia os valores das amostras que você apaga, adicione os valores das amostras inseridas. Além disso, sim, um dequeltpairltSample, Dategtgt pode ser mais eficiente. Eu escolhi o mapa para a legibilidade, ea facilidade de invocar map :: upperbound. Como sempre, escreva o código correto primeiro e, em seguida, perfile e mude as alterações incrementais. Ndash Rob Dec 16 11 at 15:00 Nota: Aparentemente esta não é a maneira de abordar isso. Deixando aqui para referência sobre o que está errado com esta abordagem. Verifique os comentários. UPDATED - com base no comentário Olis. Não tenho certeza sobre a instabilidade que ele está falando embora. Use um mapa ordenado de tempos de chegada contra valores. Na chegada de um valor adicione a hora de chegada ao mapa ordenado junto com seu valor e atualize a média móvel. Aviso este é pseudo-código: Lá. Não totalmente desenvolvido, mas você começa a idéia. Coisas a observar. Como eu disse o acima é pseudo código. Você precisará escolher um mapa apropriado. Não remova os pares à medida que você iterar através como você irá invalidar o iterador e terá que começar novamente. Veja Olis comentário abaixo também. Este trabalho não funciona: ele não leva em conta que proporção do comprimento da janela de cada valor existe para. Além disso, essa abordagem de adição e subtração é apenas estável para tipos inteiros, não para flutuadores. Ndash Oliver Charlesworth Dec 15 11 em 12:29 OliCharlesworth - desculpe eu perdi alguns pontos-chave na descrição (duplo e ponderada em tempo). Eu vou atualizar. Obrigado. Ndash Dennis Dec 15 11 at 12:33 A ponderação de tempo é ainda outro problema. Mas isso não é o que eu estou falando. Eu estava me referindo ao fato de que quando um novo valor entra pela primeira vez na janela de tempo, sua contribuição para a média é mínima. Sua contribuição continua a aumentar até que um novo valor entre. Ndash Oliver Charlesworth 15 dez às 12:35
No comments:
Post a Comment