Friday 27 October 2017

Mudança De Filtro Médio Java


Uma Implementação de Implantação Mínima Simples em Java Em várias ocasiões, queria calcular métricas simples em minhas aplicações Java, por exemplo, o número de hits por hora ou erros ao longo de um período de tempo. Embora o cálculo de métricas simples não seja extremamente difícil, é apenas um trabalho extra e Id, antes, gastar esse tempo no domínio do problema. Fiquei surpreso ao não encontrar soluções amplamente aceitas para métricas em Java. Eu encontrei Metrics, mas parecia um pouco complicado e não bem documentado. Tudo o que eu realmente queria era calcular uma média móvel. Pensei um pouco mais sobre o problema e decidi não ser um problema difícil. Heres minha solução Isso funciona criando uma matriz de tamanho de freqüência de atualização de janela, então um segmento define a contagem para o próximo índice na matriz na freqüência de atualização. A contagem para o intervalo é simplesmente arrayi - arrayi1, que é a contagem mais recente menos a contagem mais antiga. Por um intervalo de 10 minutos, a contagem mais antiga (i1) é exatamente 10 minutos de idade. Para adicionar uma média móvel ao nosso código, primeiro precisa de um contador, usando o AtomicLong. Este contador deve ser incrementado com base nos eventos que você está interessado na computação (por exemplo, pedidos POST para um serviço REST). Precisamos fornecer a implementação com acesso ao contador e isso é realizado através da interface GetCount. Aqui vou criar uma média móvel com uma janela de 5 minutos que atualiza a cada segundo. E para obter a média atual, simplesmente chamamos o método getAverage: um detalhe de implementação de chave é como o tamanho da matriz é determinado: dividindo a janela pela freqüência de atualização. Portanto, uma grande janela com frequência de atualização frequente pode consumir uma quantidade significativa de memória. Neste exemplo, o tamanho da matriz é razoável 300. No entanto, se criarmos uma média móvel de 24 horas com um intervalo de 1 segundo, o tamanho seria 86400. Uma freqüência de atualização mais razoável por um período de 24 horas pode ser a cada 5 minutos (tamanho da matriz de 288 ). Outra consideração de escolher a janela e a freqüência de atualização é que a janela deve ser divisível pela freqüência. Por exemplo, uma janela de 2 minutos com uma frequência de atualização de 6 segundos é ok, mas uma freqüência de atualização de 7 segundos não é, uma vez que não é divisível por 120. Uma IllegalArgumentException é lançada se a freqüência de atualização do módulo da janela não for zero. Esta implementação requer um tópico por média móvel, o que não é muito eficiente. Uma solução melhor seria compartilhar um fio em muitas médias. Atualização. Eu atualizei o código para compartilhar um tópico aqui. Por fim, há um problema de estado inicial: ainda não temos dados para toda a janela. Por exemplo, se você tiver uma janela de 5 minutos e apenas 15 segundos de dados. Esta implementação retorna nula até que possamos 5 minutos de dados. Outra abordagem é estimar a média. Suponhamos ter uma contagem de 10 em 30 segundos, então podemos estimar a média como 40 em 2 minutos. No entanto, existe o risco de erros significativos extrapolando dados incompletos. Por exemplo, se tivéssemos uma explosão de 20 batidas em 2 segundos, pode-se estimar 1200 por 2 minutos, o que, com toda a probabilidade, está fora. Eu essencialmente tenho uma série de valores como este: a matriz acima é simplificada demais, eu estou coletando 1 Valor por milissegundo no meu código real e preciso processar a saída em um algoritmo que escrevi para encontrar o pico mais próximo antes de um ponto no tempo. Minha lógica falha porque no meu exemplo acima, 0.36 é o pico real, mas meu algoritmo olhava para trás e veria o último número 0.25 como o pico, pois há uma diminuição para 0.24 antes dele. O objetivo é levar esses valores e aplicar um algoritmo para eles, que os suavizará um pouco para que eu tenha mais valores lineares. (Ie: Id como os meus resultados para serem curvy, não jaggedy) Eu fui dito para aplicar um filtro exponencial de média móvel aos meus valores. Como posso fazer isso. É muito difícil para mim ler equações matemáticas, eu lido muito melhor com o código. Como faço para processar valores na minha matriz, aplicando um cálculo exponencial da média móvel para os fazer sair, solicitado 8 de fevereiro às 20:27 Para calcular uma média móvel exponencial. Você precisa manter algum estado ao redor e você precisa de um parâmetro de ajuste. Isso exige uma pequena classe (supondo que você esteja usando o Java 5 ou posterior): instanciar com o parâmetro de decaimento desejado (pode ser necessário que a sintonização esteja entre 0 e 1) e depois use a média () para filtrar. Ao ler uma página sobre uma recorrência matemática, tudo o que você realmente precisa saber ao transformá-lo em código é que os matemáticos gostam de escrever índices em arrays e seqüências com subscritos. (Eles também têm algumas outras notações, o que não ajuda.) No entanto, o EMA é bastante simples, pois você só precisa se lembrar de um valor antigo, não é necessário nenhum arrays de estados complicados. Respondeu 8 de fevereiro às 20:42 TKKocheran: praticamente. Não é bom quando as coisas podem ser simples (Se começar com uma nova seqüência, obtenha uma nova média). Observe que os primeiros termos da seqüência média saltarão em torno de um bit devido a efeitos de limites, mas você obtém aqueles com outras médias móveis também. No entanto, uma boa vantagem é que você pode envolver a lógica média móvel na média e experimentar sem incomodar demais o seu programa. Ndash Donal Fellows 9 de fevereiro às 0:06 Estou tendo dificuldade em entender suas perguntas, mas vou tentar responder de qualquer maneira. 1) Se o seu algoritmo encontrou 0,25 em vez de 0,36, então é errado. É errado porque assume um aumento ou diminuição monotônico (que sempre está subindo ou sempre está indo para baixo). A menos que você tenha média de todos os seus dados, seus pontos de dados --- como você os apresenta --- são não-lineares. Se você realmente quer encontrar o valor máximo entre dois pontos no tempo, então corte sua matriz de tmin para tmax e encontre o máximo desse subarray. 2) Agora, o conceito de médias móveis é muito simples: imagine que eu tenho a seguinte lista: 1.4, 1.5, 1.4, 1.5, 1.5. Eu posso suavizar, levando a média de dois números: 1.45, 1.45, 1.45, 1.5. Observe que o primeiro número é a média de 1,5 e 1,4 (segundo e primeiro número), a segunda (nova lista) é a média de 1,4 e 1,5 (terceira e segunda lista antiga) a terceira (nova lista) a média de 1,5 e 1,4 (Quarto e terceiro), e assim por diante. Eu poderia ter feito período três ou quatro, ou n. Observe como os dados são muito mais suaves. Uma boa maneira de ver as médias móveis no trabalho é ir para o Google Finance, selecionar um estoque (tente Tesla Motors bastante volátil (TSLA)) e clique em técnicas na parte inferior do gráfico. Selecione a média móvel com um período determinado e a média móvel exponencial para comparar suas diferenças. A média móvel exponencial é apenas uma outra elaboração deste, mas considera os dados mais antigos inferiores aos novos dados, esta é uma maneira de polarizar o alisamento para trás. Leia a entrada da Wikipedia. Então, isso é mais um comentário do que uma resposta, mas a pequena caixa de comentários foi apenas pequena. Boa sorte. Se você estiver tendo problemas com a matemática, você poderia ir com uma média móvel simples em vez de exponencial. Então, a saída que você obtém seria os últimos x termos divididos por x. Pseudocódigo não testado: note que você precisará lidar com as partes de início e término dos dados, pois claramente você não pode significar os últimos 5 termos quando estiver no seu segundo ponto de dados. Além disso, existem maneiras mais eficientes de calcular essa média móvel (soma sumária - a mais nova), mas é para obter o conceito de o que está acontecendo. Respondeu 8 de fevereiro às 20:41 Sua resposta 2017 Stack Exchange, IncMuito mais simples: classe pública MovingAverageInSlidingWIndow int windowsize Fila de fila int sum public MovingAverageInSlidingWIndow (int windowsize) this. windowsize windowsize this. queue new LinkedList () this. sum 0 find Média móvel depois de inserir o item n no fluxo de dados privado double findMovingAverage (int n) if (queue. size () gt windowsize - 1) sum sum - queue. poll () queue. offer (n) sum sum n return (double) sum Queue. size () public static void main (String args) int windowsize 3 MovingAverageInSlidingWIndow m new MovingAverageInslidingWIndow (windowsize) para (int i 1 i lt 20 i) System. out. println (quotAfter Adicionando quot i quot para a fila: Average is : Quot m. findMovingAverage (i)) Podemos simplesmente persistir a soma atual de elementos na fila na variável global. Assim, reduzindo a computação no próximo () método. Classe pública MovingAverage LinkedList fila int size int sum 0 contém soma da fila Inicialize sua estrutura de dados aqui. Public MovingAverage (tamanho int) this. queue new LinkedList () this. size tamanho public double next (int val) queue. offer (val) sum val if (queue. size () gtthis. size) sum - queue. poll ()

No comments:

Post a Comment