Wednesday 6 December 2017

Simple moving average 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, mande-se estimar 1200 por 2 minutos, o que, com toda a probabilidade, está fora. Método móvel em média Java Se você estiver procurando um EMA otimizado para dados de transmissão, obtidos De um arquivo ou serviço de cotação, a seguinte classe de amostra irá fazer você bem, ao contrário de usar cálculos de força bruta. Esta abordagem é particularmente útil se você estiver processando dados em tempo real. EMAs, um caso especial de médias móveis ponderadas, têm o benefício de que a ponderação relativa para cada período sucessivo diminui por um fator constante f 2 (N1), onde N é o número de períodos durante os quais o EMA deve ser aplicado. Dado que, você pode calcular o EMA atual (ou seja, para o período atual) usando a seguinte fórmula iterativa: eman fprice (1-f) eman-1 A seguinte classe de amostra implementa essa natureza iterativa da EMA e minimiza os requisitos computacionais em relação ao brute - Métodos de força ou métodos de pós-processamento. Número int privadoPeriodos 0 int privado totalPeriodos 0 private double runningEMA 0.0 private double factor 0.0 public EMA (int numPeriods) this. numPeriods numPeriods factor 2.0 (numPeriods 1.0) Repor cálculos para gerar EMA para o período determinado. Public void reset (int numPeriods) Retorna EMA para o período definido durante o construtor. Se os períodos processados ​​forem inferiores ao intervalo EMA, zero será retornado. Público duplo calcular (preço duplo) runningEMA factorprice (1-factor) runningEMA se (totalPeriods lt numPeriods) De onde você fornece os dados de preço e o que você faz com os resultados da EMA depende de você. Por exemplo, se você tivesse os dados de preço em uma matriz e desejasse calcular uma EMA em outra matriz, o seguinte trecho funcionará: preços duplos. Provido de cálculos, arquivo ou serviço de cotação duplo ema novo doubleprices. length EMA ema novo EMA (50) 50 período EMA para (int idx0 iltprices. length idx) emaidx ema (pricesidx) Boa sorte e melhores desejos para o seu projeto. Cloudera Blog de Engenharia Média de Movimento Simples, Classificação Secundária e MapReduce (Parte 3) Esta é a peça final de uma série de blog de três partes. Se você gostaria de ver as peças anteriores para esta série, use o seguinte link: Anteriormente, expliquei como usar o Excel e R como ferramentas de análise para calcular a média móvel simples de um pequeno conjunto de preços de fechamento de ações. Nesta peça final da série de blog das três partes, aprofundarei o uso do MapReduce para encontrar a Média de Movimento Simples do nosso pequeno conjunto de dados de amostra. Então, vou mostrar-lhe como usar o mesmo código, você poderá calcular a Média de Movimento Simples de cada preço de estoque de fechamento desde 1980. Abaixe o Coelho com Hadoop Nos exemplos acima, examinamos o cálculo da média móvel simples De uma quantidade relativamente pequena de dados. Para muita análise, excel e R são ferramentas muito eficazes, mas, à medida que escalamos para armazenamento de dados gigabyte, terabyte e petabyte, nós enfrentamos alguns problemas com a localidade de dados, velocidade do disco e velocidade de processamento. Para ilustrar esses fatores, podemos tirar uma máquina mítica que tenha um único disco petabyte, que operou de forma semelhante às velocidades do disco hoje. Para os propósitos deste exemplo, use uma velocidade de leitura de 40 MB. Digamos que é nosso trabalho verificar esses dados e produzir uma média móvel simples, o processador não impede o cálculo e podemos sustentar um cálculo de janela em movimento através dos dados nos 40 MB completos. Permite também assumir que os dados foram previamente classificados e que só tivemos que realizar uma varredura seqüencial, o que maximiza a taxa de transferência de dados do disco e pode fornecer 40MBs consistentemente para a tubulação de processamento. Com base em Jeff Deans 12 números que cada engenheiro deve saber, esta é uma configuração plausível. Nessa taxa, nosso cálculo de média móvel simples de 1 petabyte de dados demoraria cerca de 310 dias para ser concluído. Para a maioria das situações, esse custo operacional, em termos de tempo, não é razoável considerar. Felizmente, a mecânica de HDFS e MapReduce atenuam esses fatores, de modo que possamos fazer deste problema um tempo linear e uma função de capital para nos ajudar a decidir o número de máquinas que queremos implementar para efetuar eficientemente essa varredura média móvel simples. No exemplo de média móvel simples acima, negligenciamos considerar as restrições de: Armazenamento do petabyte de dados em hardware não mítico. Classificando o petabyte de dados. Considerando falha no hardware durante os 310 dias do tempo de processamento. Normalmente, as aplicações da série temporal precisam digitalizar os dados em algum ponto, o que cria grandes montanhas para escalar, se quisermos abordar grandes volumes de dados da série temporal em sistemas atuais. Vimos fontes de dados multi-terabyte e multi-petabyte no domínio da série temporal todos os dias, incluindo e em cada um desses domínios, o cenário acima é um desafio muito real a enfrentar. HDFS resolve os problemas de armazenamento e falha acima, mas o que diz respeito às questões de triagem e processamento. Ordenar grandes quantidades de dados em si é um problema não trivial, mas é acessível com alguns truques no MapReduce. Vamos dar uma olhada no código MapReduce real que podemos baixar para compilar e produzir nossa própria média móvel simples escalável, para resolver alguns desses pontos de dor. Média móvel simples no MapReduce Normalmente, um aplicativo MapReduce é composto de duas funções: (você adivinhou) uma função de mapa e uma função de redução. No mundo da programação java, criamos uma classe de mapa e uma classe de redução, cada uma com métodos herdados úteis para seus propósitos respeitosos. Nós usamos o modelo de programação MapReduce porque ele é construído para mitigar problemas de concorrência em nossos algoritmos e nós conseguimos nosso paralelismo escalável relativamente sem dor. A função de mapa pode envolver um código que executa uma operação de par-chave-valor, mas a principal operação lógica é agrupar dados por chaves. Uma maneira muito fácil de pensar sobre uma função de mapa é pensar nela como uma projeção lógica dos dados ou uma cláusula grupal. A função de redução é usada para levar esses grupos (individualmente) e executar um processo em todos os valores que foram agrupados. As operações comuns em reduzir as funções incluem: Em nosso exemplo de média móvel simples, no entanto, não operamos especificamente, nem produzimos um agregado em todos os valores. Nossa operação no sentido agregado envolve uma janela deslizante, que executa suas operações em um subconjunto dos dados em cada etapa. Também temos que considerar que os pontos em nossos dados da série temporal não estão garantidos para chegar à ordem de redução e precisam ser classificados em seções anteriores. Isso ocorre porque, com várias funções de mapa, lendo várias seções dos dados de origem, o MapReduce não impõe qualquer ordem nos pares de valores-chave agrupados nos esquemas de partição e classificação padrão. Existe o cenário em que ordenamos os dados particionados, mas, por essa causa, lidamos com os dados de séries temporais não triados de variedade jardim. Vamos dar uma primeira passagem sobre como poderíamos projetar este trabalho médio móvel de MapReduce. Queremos agrupar todos os valores ajustados ajustados de uma unidade para que possamos aplicar a operação de média móvel simples nos dados da série temporária ordenada. Queremos emitir cada par de valores de chave da série de tempos digitados em um símbolo de estoque para agrupar esses valores juntos. Na fase de redução, podemos executar uma operação, aqui a média móvel simples, sobre os dados. Uma vez que os dados mais do que prováveis ​​não chegarão ao redutor em ordem ordenada, é necessário classificar os dados antes que possamos calcular a média móvel simples. Uma maneira comum de ordenar dados é carregar os dados na memória em uma estrutura de dados, como uma pilha, bem como como isso é feito em um programa Java normal. Neste caso, use a classe de fila de prioridade Javas para classificar nossos dados. Também precisamos considerar a quantidade de memória utilizada pelos dados da série de tempo de entrada durante a classificação, pois isso é um fator limitante sobre a quantidade de dados que podemos classificar. Neste projeto, devemos carregar todos os dados da série temporal antes que possamos começar o processamento e se a quantidade de dados a serem ordenados exceda o tamanho do heap disponível, temos um problema. Um exemplo dessa implementação é hospedado no github: Para executar este código em seu próprio cluster Hadoop, baixe CDH da Cloudera e configure um cluster pseudo-distribuído 8211 que é um único nó do Hadoop. O modo pseudo-distribuído é uma ótima maneira de testar o código com o Hadoop. Faça o próximo download e compile o código da média móvel em um jar. Para baixar o código diretamente do github (no shell no MacOSX, janela do terminal ssh no linux ou MINGW32 para win32) we8217ll use o comando: nossa primeira passagem é uma solução decente, mas foi limitada pelo nosso filho Java Machine (JVM) Tamanho da pilha e estamos levando tempo para classificar os dados manualmente. Com algumas mudanças de design, podemos resolver essas duas questões aproveitando algumas propriedades inerentes do MapReduce. Primeiro, queremos olhar para o caso de classificar os dados na memória em cada redutor. Atualmente, temos que garantir que nunca enviamos mais dados para um único redutor do que pode caber na memória. A maneira como podemos controlar atualmente isso é dar a cada redutora JVM infantil mais heap e para dividir ainda mais nossos dados da série temporal na fase do mapa. Nesse caso, partiremos ainda mais por tempo, rompendo nossos dados em janelas de tempo menores. Em oposição a uma maior partição dos dados, outra abordagem a esta questão é permitir que o Hadoop classifique os dados para nós no que se chama fase de baralhamento do MapReduce. Se os dados chegam a um redutor já em ordem ordenada, podemos reduzir nossa pegada de memória e reduzir o número de loops através dos dados, observando apenas as próximas N amostras para cada cálculo da média móvel simples. Isso nos leva ao aspecto crucial deste artigo, que é chamado de mecânica de classificação secundária. A classificação é algo que podemos deixar o Hadoop fazer para nós e o Hadoop provou ser bastante bom para classificar grandes quantidades de dados, ganhando a competição Gray Sort em 2008. Ao usar o mecânico de classificação secundário, podemos resolver nossos problemas de amontoar e classificar de forma bastante simples E de forma eficiente. Para empregar um tipo secundário em nosso código, precisamos fazer da chave um composto da chave natural e do valor natural. Abaixo, na Figura 1, vemos um diagrama de como isso ficaria visualmente. Figura 1: Diagrama de chave compósita A chave compósita dá a Hadoop as informações necessárias durante o shuffle para executar um tipo não apenas no símbolo 8220stock8221, mas também no carimbo de data / hora. A classe que classifica essas chaves compostas é chamada de comparador de chaves ou aqui 8220CompositeKeyComparator8221. O comparador de chaves deve ordenar pela chave compósita, que é a combinação da chave natural e do valor natural. Podemos ver abaixo na Figura 2 onde uma versão abstrata da classificação secundária está sendo executada em uma chave composta de 2 inteiros. Figura 2: CompositeKeyComparator classificando chaves compostas (as chaves são inteiras). Na Figura 3 abaixo, vemos um exemplo mais realista em que we8217ve mudou a Chave Compacta para ter uma string de símbolo de estoque (K1) e um carimbo de data / hora (K2, exibido como uma data, mas no código é longo em ms). O diagrama ordenou os pares de KV ambos 8220K1: símbolo de estoque8221 (chave natural) e 8220K2: marca de horário8221 (chave secundária). Figura 3: CompositeKeyComparator no trabalho em nossas chaves compostas. Chave composta agora representada com um símbolo de estoque de string (K1) e uma data (K2). Uma vez que nós classificamos nossos dados na chave compósita, agora precisamos particionar os dados para a fase de redução. Na Figura 4 abaixo, vemos como os dados da Figura 3 acima foram particionados com o NaturalKeyPartitioner. Figura 4: Particionamento pela chave natural com o NaturalKeyPartitioner. Uma vez que we8217ve particionado nossos dados, os redutores agora podem começar a baixar os arquivos de partição e começar a fase de mesclagem. Inf Figure-5 abaixo vemos como o comparador de agrupamento, ou NaturalKeyGroupingComparator, é usado para garantir que uma chamada reduzida () apenas veja os dados agrupados logicamente para essa chave composta. Figura 5: Agrupando Comparador mesclando arquivos de partição. O comparador e o comparador de agrupamento para a chave compósita devem considerar apenas a chave natural para particionamento e agrupamento. Abaixo está uma breve descrição do código Simple Moving Average que é alterado para usar o tipo secundário e está hospedado no github. Se você notar, os nomes das classes coincidem com a terminologia usada nos diagramas acima e no Tom Whites Hadoop: o Guia definitivo (capítulo 8 Recursos MapReduce) para tornar o código mais fácil de entender. NaturalKey 8211 o que você normalmente usaria como chave ou grupo por operador. Nesse caso, a Chave Natural é o símbolo de grupo ou estoque, pois precisamos agrupar dados de estoque potencialmente não triados antes de classificá-lo e calcular a média móvel simples. Chave composta 8211 Uma chave que é uma combinação da chave natural e do valor natural que queremos classificar. 5 respostas em ldquo Simple Moving Average, Secondary Sort, e MapReduce (Parte 3) rdquo Cool trick com o sorterpartitioner dividido. Tanto quanto eu posso dizer, isso funciona muito bem até que a série se torne extremamente longa (pense 30 anos de dados de nível de tiquetaque) 8211 parece que o compartilhamento pelo tempo pode ser muito complicado. Você conhece algo incorporado no hadoop como um particionador de partição 8220 que pode cuspir os mesmos dados para várias partições. Experimentei mapeadores que duplicam valores em várias chaves, mas eu me pergunto se existe uma maneira mais convencional de fazer isso. Evan, você está morto com o tamanho dos dados em um único espaço de chaves. Eu atingi o mesmo problema ao trabalhar no projeto OpenPDC para o NERC: um sensor poderia ter literalmente bilhões de pontos em um período de tempo muito curto, então, para os trabalhos de protótipo, abrimos as coisas para um único dia (3,600,000ms): em um mais Versão complexa, eu usaria intervalos de tempo sobrepostos para que o mapeador obtenha dados suficientes de espaços de teclado adjacentes para cobrir um único comprimento de janela. Por enquanto, eu digo que você está no caminho certo com os valores duplicados. Eu sei que isso não está relacionado às médias móveis, mas a precisão da correspondência da série de tempo SAX usada no PDC implementou algo assim (exceto usando o MapReduce API 2) e no loop da função reduza (), sempre que o. O próximo () método é chamado no Iterator, nós obtemos um novo valor, mas a chave também milagrosamente muda. Em vez disso, a parte da chave compósita que não foi usada como uma chave natural (o timestamp neste exemplo) muda. Isso foi bastante surpreendente. Como isso acontece Post navigation Adoptando Apache Hadoop no governo federal

No comments:

Post a Comment