Friday 19 January 2018

Algoritmo de velocidade móvel em movimento recursivo


Eu ainda estou trabalhando para explorar a coisa F - tentando descobrir como pensar em F em vez de apenas traduzir de outras línguas que eu conheço. Ive recentemente pensando nos casos em que você não possui um mapa de 1: 1 entre antes e depois. Casos em que List. map cai. Um exemplo disto é as médias móveis, onde, normalmente, você terá resultados len-n1 para uma lista de comprimento len quando a média sobre n itens. Para os gurus lá fora, esta é uma boa maneira de fazê-lo (usando a fila apertada de Jomo Fisher) (Talvez seja melhor para implementar um MovingAverageQueue ao herdar do Fifo) perguntou 17 de novembro às 11:12 Eu tive que declarar Ele deixa MovingAverage n (s. Seqltfloatgt) para colocar isso em um módulo de utilidade, longe do site de chamadas, para aplacar o sistema de tipos. Tanto quanto posso dizer, isso só funciona com flutuadores, devido a uma limitação da Array. average. MSDN afirma que posso substituir isso com Array. averageBy para usar isso em uma seqüência int, mas isso dá um erro diferente. Brian, você pode reformular essa resposta para trabalhar em contextos genéricos, para que ele funcione com seq-of-any-arithmetic-type, sem tipo de inferência ndash Warren Young 27 de junho às 19:04 Devo ressaltar que minha necessidade de Esta função de média móvel é obter uma janela curta (30ish) sobre uma seqüência de números inteiros que são quase todos em milhões, então eu não preciso de ponto flutuante. Mesmo um único dígito à direita do ponto decimal não é útil na minha aplicação. Convertendo meus inteiros para FP e o resultado de volta para int apenas para aplacar a apelação do doesn39t da biblioteca padrão F. Ndash Warren Young 27 de junho às 19:30 Se você se preocupa com o desempenho, então você pode calcular uma média móvel de forma eficiente usando algo assim (assumindo que estavam calculando uma média móvel em uma janela de 3 dias). A parte mais difícil disso é segurar No seu anterior total em execução e no número N-janela. Eu criei o seguinte código: Esta versão não é tão bonita quanto o código Haskell, mas deve evitar problemas de desempenho associados à recompor sua janela em cada execução. Ele mantém um total em execução e mantém os números usados ​​anteriormente em uma fila, por isso deve ser muito rápido. Apenas por diversão, escrevi um benchmark simples: se você se preocupa com o desempenho e como código elegante, tente usar FSUnit, podemos testá-lo. O truque do algoritmo é a primeira soma dos primeiros números e, em seguida, mantenha um total em execução adicionando a cabeça Da janela e subtraindo a cauda da janela. A janela deslizante é conseguida fazendo um auto zip na sequência, mas com o segundo argumento para zip avançado pelo tamanho da janela. No final do pipeline, dividimos apenas o total em execução pelo tamanho da janela. A varredura de notas é como dobrar, mas produz cada versão do estado em uma seqüência. Uma solução ainda mais elegante, embora possível, com sucesso no desempenho é fazer a observação de que, se não formos o zero, não precisamos calcular a soma inicial. Poderia haver um sucesso de desempenho devido à segunda indireção relacionada ao envolvimento das duas seqüências, mas talvez não seja significativa dependendo do tamanho da janela respondida 31 de agosto 12 às 8: 06O 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 essa média se multiplicar 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 uma 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, você remove o elemento mais à esquerda da janela e subtrai seu valor da soma, depois adiciona o novo elemento mais à direita da janela e adiciona seu 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 O guia de cientistas e engenheiros para 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 adicionando ou subtraindo constantes inteiras que podem ser calculadas antes do início da filtragem (ou seja, p e q). Por enquanto, 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 amostra de 10 000 que está 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. Inteiros não têm esse problema porque não há erro de arredondamento na aritmética. Se você deve usar ponto flutuante com esse 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