Monday 11 September 2017

Algoritmo De Média Móvel Recursiva


O principal defeito no seu programa é que o cálculo recursivo está incorreto. Para calcular a média, você deve obter a soma do valor atual e os valores restantes. Então divida essa soma pelo número de valores. O número de valores é num. O valor atual é o que o número de cálculo () retorna. A soma dos valores restantes é num-1 multiplicada pela média dos valores remanescentes. A média dos valores restantes é calculada fazendo uma chamada recursiva para a média (). Assim, escrevemos o seguinte: Um programa completo que usa essa função pode ser assim: note que esta não é uma ótima maneira de calcular a média porque você perde a precisão toda vez que você divide a soma atual por número. Quando esta média é multiplicada novamente à medida que a chamada recursiva retorna, os dígitos significativos que você perdeu na divisão não são restaurados. Você está destruindo informações dividindo e multiplicando a soma. Para maior precisão, você gostaria de acompanhar a soma enquanto você passa pelos elementos, então divida no final. Outro ponto a considerar é o que se entende por uma média móvel. O que implementamos acima não é uma média móvel, mas uma média fixa. É a média de uma janela fixa de elementos. Se você mover a janela por uma posição, você deve começar tudo e calcular a soma novamente. A maneira correta de implementar uma janela em movimento é acompanhar todos os elementos da janela. Quando você desloca a janela para uma posição para a direita, remove o elemento mais à esquerda da janela e subtrai seu valor da soma, depois adiciona o novo elemento mais à direita da janela e adiciona o valor à soma. Isso é o que faz dela uma soma móvel. Dividir a soma móvel pelo número de elementos dá-lhe a média móvel. A maneira natural de implementar uma janela em movimento é com uma fila porque você pode adicionar novos elementos à cabeça e exibir elementos antigos da cauda. Respondeu 22 de novembro às 17: 44 Eu quero implementar um algoritmo iterativo, que calcula a média ponderada. A lei do peso específico não importa, mas deve ser perto de 1 para os valores mais recentes e perto de 0 para os mais antigos. O algoritmo deve ser iterativo. Ou seja, não deve lembrar todos os valores anteriores. Deve saber apenas um valor mais recente e qualquer informação agregada sobre o passado, como valores anteriores da média, somas, contagens, etc. Por exemplo, o seguinte algoritmo pode ser: Ele dará um peso exponencial decrescente, o que pode não ser bom. É possível ter um peso decrescente ou algo assim. Os requisitos para a legislação de pesagem são os seguintes: 1) O peso diminui para o passado 2). Eu tenho alguma duração média ou característica, de modo que os valores mais antigos, essa duração, são muito menores do que os mais recentes. 3) Eu Deve ser capaz de definir esta duração, eu preciso do seguinte. Suponha que vi são valores, onde v1 é o primeiro. Suponhamos também que sejam pesos. Mas wO é o ÚLTIMO. Então, depois que o primeiro valor veio, eu tenho a primeira média. Depois do segundo valor v2, eu deveria ter média. Com o próximo valor, eu deveria ter Nota, esse perfil de peso está se movendo comigo, enquanto eu estou me movendo ao longo da seqüência de valores. Isto é, Cada valor não tem seu próprio peso o tempo todo. Meu objetivo é ter esse peso mais baixo enquanto vai para o passado. Gt Mas minha tarefa é ter uma média recalculada cada vez que um novo valor chega tendo valores antigos refletidos. OP Sua tarefa é quase sempre impossível, mesmo com esquemas de pontuação excepcionalmente simples. Você está pedindo, com memória O (1), médias de rendimento com um esquema de ponderação em mudança. Por exemplo, à medida que novos valores estão sendo transmitidos, para algumas seqüências de pesos que mudam arbitrariamente. Isso é impossível devido à injetividade. Depois de combinar os números juntos, você perde uma enorme quantidade de informações. Por exemplo, mesmo se você tivesse o vetor de peso. Você não conseguiu recuperar o vetor do valor original, ou vice-versa. Existem apenas dois casos em que posso pensar onde você poderia fugir com isso: pesos constantes como 2,2,2. 2: isso é equivalente a um algoritmo de média on-line, que você não quer porque os valores antigos não estão sendo ponderados. Os pesos relativos de respostas anteriores não mudam. Por exemplo, você poderia fazer pesos de 8,4,2,1. E adicione um novo elemento com peso arbitrário como. 1. mas você deve aumentar todo o anterior pelo mesmo fator multiplicativo, como 16,8,4,21. Assim, em cada etapa, você está adicionando um novo peso arbitrário e um novo arbitrário de atualização do passado, de modo que você tenha 2 graus de liberdade (apenas 1 se precisar manter seu produto ponto normalizado). Os vetores de peso que você obtém pareciam: Assim, qualquer esquema de ponderação que você pode fazer parece funcionar (a menos que você precise manter o item normalizado pela soma dos pesos, caso em que você deve dividir a nova média pelo novo Soma, que você pode calcular, mantendo apenas a memória O (1)). Simplesmente multiplique a média anterior pelo novo s (que irá distribuir implicitamente sobre o ponto-produto nos pesos) e abordar o novo wnewValue. Respondeu 29 de março às 21:27 Aqui estou supondo que você deseja que os pesos somem para 1. Enquanto você pode gerar um peso relativo sem que ele mude no futuro, você pode acabar com uma solução que imita esse comportamento. Ou seja, suponha que você definiu seus pesos como uma seqüência e definiu a entrada como seqüência. Considere a forma: soma (s0i0 s1i1 s2i2. Snin) soma (s0 s1 s2. Sn). Observe que é trivialmente possível calcular isso de forma incremental com alguns contadores de agregação: Claro, calculeWeightFromCounter () nesse caso não deve gerar pesos que somem a um - o truque aqui é que nós, na média, dividindo pela soma dos pesos De modo que no final, os pesos virtualmente parecem somar a um. O verdadeiro truque é como você calculaWeightFromCounter (). Você poderia simplesmente devolver o próprio contador, por exemplo, no entanto, note que o último número ponderado não estaria perto da soma dos contadores necessariamente, então você não pode acabar com as propriedades exatas que deseja. (É difícil dizer que, como mencionado, você deixou um problema bastante aberto.) Respondeu 28 de março às 21:45 O problema é que os pesos estão mudando com cada novo valor. No seu caso, eles não são. Ndash Suzan Cioc 29 de março 12 às 14:43 Os pesos reais utilizados estão mudando com cada valor novo - as quotweightsquot estão sendo divididas por um número sucessivamente maior, reforçando assim que os pesos reais utilizados sempre somem para 1. ndash Kaganar 29 de março 12 Às 14:45 Isso é muito longo para postar em um comentário, mas pode ser útil saber. Suponha que você tenha: w0vn. Wnv0 (bem, chame isso w0..nvn..0 para breve) Então o próximo passo é: w0vn1. Wn1v0 (e isso é w0..n1vn1..0 para baixo) Isso significa que precisamos de uma maneira de calcular w1..n1vn..0 de w0..nvn..0. É certamente possível que vn..0 seja 0. 0, z, 0. 0 onde z esteja em algum local x. Se não tivermos nenhum armazenamento extra, então f (zw (x)) zw (x 1) onde w (x) é o peso para a localização x. Reorganizando a equação, w (x 1) f (zw (x)) z. Bem, w (x 1) melhor ser constante para uma constante x, então f (zw (x)) z melhor ser constante. Portanto, f deve permitir que z se propague - isto é, f (zw (x)) zf (w (x)). Mas aqui novamente temos um problema. Observe que se z (que poderia ser qualquer número) pode se propagar através de f. Então w (x) certamente pode. Então f (zw (x)) w (x) f (z). Assim f (w (x)) w (x) f (z). Mas para uma constante x. W (x) é constante e, portanto, f (w (x)) melhor ser constante, também. W (x) é constante, então f (z) é melhor ser constante, de modo que w (x) f (z) seja constante. Assim, f (w (x)) w (x) c onde c é uma constante. Então, f (x) cx onde c é uma constante quando x é um valor de peso. Ou seja, cada peso é um múltiplo do anterior. Assim, os pesos assumem a forma w (x) mbx. Observe que isso pressupõe que a única informação que f tem é o último valor agregado. Note que, em algum momento, você será reduzido a este caso, a menos que esteja disposto a armazenar uma quantidade de dados não constantes que representem sua entrada. Você não pode representar um vetor de comprimento infinito de números reais com um número real, mas você pode aproximá-los de alguma forma em uma quantidade constante e finita de armazenamento. Mas isso seria apenas uma aproximação. Embora eu não tenha provado com rigor, é minha conclusão de que o que você quer é impossível fazer com um alto grau de precisão, mas você pode usar o log (n) espaço (o que também pode ser O (1) para muitos Aplicações práticas) para gerar uma aproximação de qualidade. Você pode usar ainda menos. Respondeu 29 de março às 23:01 Tentei praticamente codificar algo (em Java). Como já foi dito, seu objetivo não é possível. Você só pode contar a média de alguns dos últimos valores lembrados. Se você não precisa ser exato, você pode aproximar os valores mais antigos. Eu tentei fazê-lo lembrando os últimos 5 valores exatamente e os valores mais antigos somente SUMmed por 5 valores, lembrando as últimas 5 SUMs. Então, a complexidade é O (2n) para lembrar os últimos valores nnn. Esta é uma aproximação muito áspera. Você pode modificar os tamanhos de matriz lastValues ​​e lasAggregatedSums conforme desejado. Veja esta imagem de ascii-art tentando exibir um gráfico de últimos valores, mostrando que as primeiras colunas (dados mais antigos) são lembradas como valor agregado (não individualmente) e somente os 5 valores mais adiantados são lembrados individualmente. Desafio 1. O meu exemplo não conta com pesos, mas acho que não deveria ser um problema para você adicionar pesos adequados para o último. O único problema é que, se você quiser pesos mais baixos para valores mais antigos, seria mais difícil porque a matriz gira, então Não é direto saber qual peso para qual membro da matriz. Talvez você possa modificar o algoritmo para mudar sempre os valores na matriz em vez de girar. Em seguida, adicionar pesos não deve ser um problema. Desafio 2. As matrizes são inicializadas com 0 valores, e esses valores estão contando a média desde o início, mesmo quando não recebemos valores suficientes. Se você estiver executando o algoritmo por um longo período de tempo, você provavelmente não incomodará que esteja aprendendo por algum tempo no início. Se você fizer isso, você pode postar uma modificação -) respondeu 21 de janeiro 14 às 15:59 Sua resposta 2017 Stack Exchange, Inc O cientista e engenheiros Guia de processamento de sinal digital Por Steven W. Smith, Ph. D. Uma tremenda vantagem do filtro de média móvel é que ele pode ser implementado com um algoritmo que é muito rápido. Para entender esse algoritmo, imagine passar um sinal de entrada, x, através de um filtro de média móvel de sete pontos para formar um sinal de saída, y. Agora, veja como dois pontos de saída adjacentes, y 50 e y 51 são calculados: são quase os mesmos pontos de cálculo x 48 a x 53 devem ser adicionados para y 50 e novamente para y 51. Se y 50 já foi calculado , A maneira mais eficiente de calcular y 51 é: Uma vez que y 51 foi encontrado usando y 50, então y 52 pode ser calculado a partir da amostra y 51, e assim por diante. Depois que o primeiro ponto é calculado em y, todos os outros pontos podem ser encontrados com apenas uma única adição e subtração por ponto. Isso pode ser expresso na equação: Observe que esta equação usa duas fontes de dados para calcular cada ponto na saída: pontos da entrada e pontos previamente calculados da saída. Isso é chamado de equação recursiva, o que significa que o resultado de um cálculo é usado em cálculos futuros. (O termo recursivo também tem outros significados, especialmente em ciência da computação). O Capítulo 19 discute uma variedade de filtros recursivos com mais detalhes. Esteja ciente de que o filtro recursivo médio móvel é muito diferente dos filtros recursivos típicos. Em particular, a maioria dos filtros recursivos tem uma resposta de impulso infinitamente longa (IIR), composta de sinusoides e exponenciais. A resposta de impulso da média móvel é um pulso retangular (resposta de impulso finito, ou FIR). Este algoritmo é mais rápido do que outros filtros digitais por vários motivos. Primeiro, existem apenas dois cálculos por ponto, independentemente do comprimento do kernel de filtro. Em segundo lugar, a adição e a subtração são as únicas operações matemáticas necessárias, enquanto a maioria dos filtros digitais requer uma multiplicação demorada. Em terceiro lugar, o esquema de indexação é muito simples. Cada índice na Eq. 15-3 é encontrado por adicionar ou subtrair constantes inteiras que podem ser calculadas antes do início da filtragem (ou seja, p e q). Além disso, todo o algoritmo pode ser realizado com representação inteira. Dependendo do hardware utilizado, os números inteiros podem ser mais do que uma ordem de grandeza mais rápida que o ponto flutuante. Surpreendentemente, a representação de números inteiros funciona melhor do que o ponto flutuante com esse algoritmo, além de ser mais rápido. O erro de arredondamento da aritmética de ponto flutuante pode produzir resultados inesperados se você não for cuidadoso. Por exemplo, imagine um sinal de 10 000 amostras sendo filtrado com este método. A última amostra no sinal filtrado contém o erro acumulado de 10.000 adições e 10.000 subtrações. Isso aparece no sinal de saída como um deslocamento de derivação. Inteiros não têm esse problema porque não há erro de arredondamento na aritmética. Se você deve usar ponto flutuante com este algoritmo, o programa na Tabela 15-2 mostra como usar um acumulador de dupla precisão para eliminar essa deriva.

No comments:

Post a Comment