Thursday, 21 February 2019

Filtro de média móvel eficiente


Atualmente, estou desenvolvendo um sistema gráfico LCD para exibir temperaturas, fluxos, tensões, energia e energia em um sistema de bomba de calor. O uso de um LCD gráfico significa que metade da minha SRAM e.75 do meu flash foram usadas por um buffer de tela E strings. I estão atualmente exibindo min max valores médios de energia À meia-noite, quando a figura diária redefine, o sistema verifica se o consumo para o dia está acima ou abaixo do mínimo ou máximo anterior, e armazena o valor A média é calculada dividindo O consumo de energia acumulada pelo número de dias. Eu gostaria de exibir a média diária na última semana e mês 4 semanas para a simplicidade IEa média móvel Atualmente, isso envolve a manutenção de uma matriz de valores para os últimos 28 dias e cálculo de uma média sobre a Array inteiro para mensal e últimos 7 dias para weekly. Initially eu estava fazendo isso usando uma matriz de carros alegóricos como a energia está na forma 12 12kWh, mas isso estava usando 28 4 bytes 112 bytes 5 4 de SRAM eu don t min D tendo apenas um único ponto decimal de resolução, então eu mudei para usar uint16t e multiplicar a figura por 100 Isso significa que 12 12 é representado como 1212, e eu dividir por 100 para fins de exibição. O tamanho da matriz é agora para baixo 56 bytes muito melhor. Não há maneira trivial de reduzir a figura para baixo para um uint8t que eu posso ver que eu poderia tolerar a perda de uma casa decimal 12 1kWh em vez de 12 12kWh, mas o consumo é freqüentemente superior a 25 5kWh 255 sendo o mais alto Valor representado por um número inteiro sem assinatura de 8 bits O consumo nunca esteve abaixo de 10 0kWh ou acima de 35 0kWh, portanto, possivelmente eu poderia subtrair 10 dos números armazenados, mas eu sei que um dia vamos exceder esses limites. Então testei código para compactar Valores de 9 bits em uma matriz Isso dá um intervalo de 0-51 2kWh e usa 32 bytes no total No entanto, acessando uma matriz como esta é muito lento, especialmente quando você tem que iterar sobre todos os valores para calcular uma média. Assim minha pergunta Existe uma maneira mais eficiente de Lculating uma média móvel com três janelas - vida útil, 28 dias e 7 dias Eficiência significa menor em termos de uso de SRAM, mas sem a penalidade de código enorme Eu posso evitar armazenar todos os valores. E você está certo Então isso tecnicamente faz a minha resposta incorreta Estou investindo mais tempo e paciência para ele Talvez algo fora da caixa Eu vou deixar você saber se eu chegar a algo Nós fazemos algo parecido com isso muito no meu local de trabalho Deixe-me Pergunte a respeito Desculpe pela confusão Aditya Somani Mar 8 14 às 17 15.Existe uma maneira mais eficiente de calcular uma média móvel com 28 dias e 7 dias precisando se lembrar de 27 dias de história. Você pode ficar perto o suficiente armazenar 11 valores em vez de 28 valores, talvez algo como. Em outras palavras, ao invés de armazenar todos os detalhes de todos os dias para os últimos 27 dias, uma loja de 7 ou mais valores de informações diárias detalhadas para os últimos 7 ou mais dias, e também armazenar 4 ou mais Valores resumidos do total ou da média Para cada uma das últimas 4 semanas, eu tenho essencialmente uma matriz de valores como este. A matriz acima é simplificada, estou coletando 1 valor por milissegundo no meu código real e eu preciso processar a saída em um algoritmo que eu 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 o meu algoritmo olharia para trás e ver o último número 0 25 como o pico, como há uma diminuição para 0 24 antes dele. O objetivo é tomar esses valores e aplicar um algoritmo para eles que irá suavizar-los um pouco para que eu tenho mais valores lineares ou seja, eu gostaria que meus resultados para ser curvy, não jaggedy. I foi-me dito para aplicar Um filtro de média móvel exponencial para os meus valores Como posso fazer isso É muito difícil para mim ler equações matemáticas, eu lidar muito melhor com o código. Como posso processar valores em minha matriz, aplicando um cálculo exponencial de média móvel para até mesmo para eles. asked Feb 8 12 at 20 27. Para calcular uma média exponencial E você precisa manter algum estado ao redor e você precisa de um parâmetro de ajuste Isso chama para uma pequena classe supondo que você está usando o Java 5 ou posterior. Instantiar com o parâmetro de decadência que você quer pode ter ajuste deve ser entre 0 e 1 e, em seguida, use a média para Ao ler uma página sobre alguma 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 matrizes e seqüências com índices Eles também algumas outras notações, o que não ajuda No entanto, O EMA é bastante simples, como você só precisa se lembrar de um valor antigo sem arranjos de estado complicado required. answered 8 de fevereiro de 12 em 20 42. TKKocheran Muito bonito Isn t it nice quando as coisas podem ser simples Se começar com uma nova seqüência, obter um novo Note que os primeiros alguns termos na seqüência média saltarão em torno de um bit devido a efeitos de limite, 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 de média móvel na ave Rager e experimentar sem perturbar o resto do seu programa muito Donal Fellows Feb 9 12 em 0 06.Eu estou tendo um tempo difícil entender suas perguntas, mas vou tentar responder anyway.1 Se o algoritmo encontrado 0 25 em vez de 0 36 , Então é errado É errado porque ele assume um aumento ou diminuição monotônica que está sempre subindo ou sempre indo para baixo A menos que você média TODOS os seus dados, seus pontos de dados --- como você apresentá-los --- são não-lineares Se você realmente Quero 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 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úmeros 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 suave Uma boa maneira de ver as médias móveis no trabalho é ir para o Google Finance, selecione uma ação tentar Tesla Motors Bastante volátil TSLA e clique em technicals na parte inferior do gráfico Selecione Média Móvel com um determinado período e média móvel exponencial para comparar as suas diferenças. A média móvel exponencial é apenas mais uma elaboração deste, mas pondera os dados mais antigos menos do que os novos dados Esta é uma maneira de polarizar a suavização em direção à parte de trás Por favor, leia a entrada de Wikipedia. Então, isso é mais um comentário do que uma resposta, mas a pequena caixa de comentário foi apenas a pequena boa sorte. Se você está tendo problemas com a matemática, Poderia ir com uma média móvel simples em vez de exponencial Assim, a saída que você obtém seria o último x termos dividido por x pseudocódigo não testado. Note que você vai precisar para lidar com o início e fim partes dos dados uma vez que claramente você pode t média a última 5 termos quando Você está no seu 2º ponto de dados Além disso, existem formas mais eficientes de calcular essa soma média móvel - a mais antiga, mas isso é para obter o conceito do que está acontecendo. Passos na resposta a este post e queria saber como eu poderia usá-los para calcular um filtro de média móvel mais eficiente do que o que eu propus neste post usando convolution filters. This é o que eu tenho até agora Ele tem uma visão da matriz original, em seguida Rola-lo pela quantidade necessária e somas os valores do kernel para calcular a média Estou ciente de que as bordas não são tratadas corretamente, mas eu posso cuidar disso depois Existe uma maneira melhor e mais rápida O objetivo é filtrar grandes matrizes de ponto flutuante Até 5000x5000 x 16 camadas de tamanho, uma tarefa que é bastante lento at. Note que estou procurando 8-vizinho conectividade, que é um filtro 3x3 leva a média de 9 pixels 8 ao redor do pixel focal e atribui esse valor para o Pixel no novo Image. EDIT Esclarecimento sobre como eu vejo este working. use stridetricks para gerar uma matriz como 0,1,2, 1,2,3, 2,3,4 que corresponde à linha superior do kernel. Roll filtro ao longo da vertical Eixo para obter a linha do meio do kernel 10,11,12, 11,12,13, 13,14,15 e adicioná-lo à matriz que eu tenho em 1.Repeat para obter a linha inferior do kernel 20,21, 22, 21, 22, 23, 22, 23, 24 Neste ponto, tomo a soma de cada linha e dividi-la pelo número de elementos no filtro, dando-me a média de cada pixel, deslocada por 1 linha e 1 Col, e com algumas rarezas em torno de bordas, mas eu posso cuidar disso mais tarde. O que eu estava esperando é um melhor uso de stridetricks para obter os 9 valores ou a soma dos elementos do kernel diretamente, para toda a matriz, ou que Alguém pode convencer-me de outro método mais eficiente. Perguntou 8 de fevereiro em 18 05.Para o que vale a pena, aqui é como você fazê-lo usando truques fantasia striding eu estava indo para postar isso ontem, mas se distraiu com o trabalho real. Paul comer ambos têm implementações agradável usando várias outras formas de fazer isso Apenas para continuar as coisas a partir da pergunta anterior, eu pensei que eu pós o equivalente N-dimensional. Você não vai ser capaz de bater significativamente funções para matrizes 1D, no entanto deve Além disso, se você está tentando obter uma janela em movimento multidimensional, você corre o risco de explodir o uso de memória sempre que você inadvertidamente fazer uma cópia de sua matriz Enquanto a matriz de rolamento inicial é apenas uma visão para a memória de sua matriz original, Etapas intermediárias que copiar a matriz fará uma cópia que é ordens de magnitude maior do que a sua matriz original ou seja, vamos dizer que você está trabalhando com uma matriz original 100x100 A visão para ele para um tamanho de filtro de 3,3 será 98x98x3x3, mas use A mesma memória que o original No entanto, todas as cópias usará a quantidade de memória que um array 98x98x3x3 completo. Basicamente, usando truques loucos truques é ótimo para quando você quiser vetorizar as operações de janela em movimento Um único eixo de um ndarray Ele torna muito fácil de calcular coisas como um desvio padrão em movimento, etc, com muito pouco sobrecarga Quando você quer começar a fazer isso ao longo de vários eixos, é possível, mas você normalmente é melhor com funções mais especializadas Tais como etc .. De qualquer forma, aqui é como você faz it. So o que temos quando fazemos b rollingwindow a, filtsize é uma matriz 8x8x3x3, que s realmente uma visão para a mesma memória que a matriz 10x10 original Poderíamos ter apenas Como facilmente usado tamanho de filtro diferente ao longo de diferentes eixos ou operado apenas ao longo de eixos selecionados de uma matriz N-dimensional ou seja, filtsize 0,3,0,3 em uma matriz de 4 dimensões daria-nos uma 6 dimensional view. We pode então aplicar um arbitrário Função para o último eixo repetidamente para efetivamente calcular as coisas em uma janela em movimento. No entanto, porque estamos armazenando matrizes temporárias que são muito maiores do que a nossa matriz original em cada etapa de média ou std ou qualquer outra coisa, isso não é de todo memória eficiente Também não vai ser te Rribly rápido, quer. O equivalente para ndimage é just. This irá lidar com uma variedade de condições de fronteira, fazer o borrão no local, sem a necessidade de uma cópia temporária da matriz, e ser muito rápido Striding truques são uma boa maneira de aplicar uma função Para uma janela em movimento ao longo de um eixo, mas eles não são uma boa maneira de fazê-lo ao longo de vários eixos, geralmente. Isso apenas o meu 0 02, de qualquer modo. Muito bem colocado Striding truques são uma boa maneira de aplicar uma função a uma janela em movimento Ao longo de um eixo, mas eles não são uma boa maneira de fazê-lo ao longo de vários eixos, geralmente E, claro, sua explicação da memória explodir é importante Um tipo de resumo da sua resposta, pelo menos para mim não é ir pescar muito longe, A captura quarenteed está allready em scipy Obrigado comem fevereiro 9 11 em 16 37.Thanks, Joe, para esta resposta Em rollingwindow deve se não hasattr devolver rollingwindowlastaxis ao invés de rollingwindow unutbu Feb 12 11 at 16 47.Não estou familiarizado o suficiente com Python para escrever o código para isso, mas os dois melhores wa Ys para acelerar as convoluções é separar o filtro ou usar a transformada de Fourier. Separado filtro Convolução é OMN, onde M e N são o número de pixels na imagem e no filtro, respectivamente. Uma vez que a filtragem média com um 3 por 3 Kernel é equivalente a primeira filtragem com um kernel 3-por-1 e, em seguida, um kernel 1-por-3, você pode obter 3 3 3 3,30 melhoria de velocidade por convolução consecutiva com dois kernels 1-d isso obviamente fica melhor como o kernel fica Maior Você ainda pode usar truques de stride aqui, é claro. Transformação de Fourier Conv A, B é equivalente a ifft fft A fft B iea convolução no espaço direto torna-se uma multiplicação no espaço de Fourier, onde A é a sua imagem e B é o seu Como a multiplicação elementar das transformações de Fourier requer que A e B sejam do mesmo tamanho, B é uma matriz de tamanho A com o kernel no centro da imagem e zeros em toda a parte Para colocar um 3-by-3 Kernel no centro de uma matriz, você pode ter que pad A para od D tamanho Dependendo da sua implementação da transformada de Fourier, isso pode ser muito mais rápido do que a convolução e se você aplicar o mesmo filtro várias vezes, você pode pré-computar fft B salvar mais 30 de computação time. answered Feb 9 11 at 15 27. Para o que vale a pena, em python, estes são implementados em e, respectivamente, Joe Kington fevereiro 9 11 em 15 44. Jonas Cool A filtragem separada funciona muito bem, como você diz que economiza mais tempo como o tamanho do kernel aumenta Para um 5000x5000 Array, em um tamanho de kernel 11x11, estou recebendo 7 7s para convolução 2d usando e 2 0s para dois convolutions 1d usando Para sua segunda solução o que é Benjamin Ben 9 fevereiro em 16 02.One coisa que eu estou confiante precisa ser corrigido é Sua matriz de visão b. It tem alguns itens de memória não alocada, então você vai ter crashes. Given sua nova descrição do seu algoritmo, a primeira coisa que precisa de fixação é o fato de que você está striding fora da atribuição de a. Because I m Ainda não entender completamente o método e parece haver O ser maneiras mais simples de resolver o problema, eu só vou colocar isso aqui. que parece apenas como a abordagem direta A única operação estranha é que ele tem alocar e preencher B apenas uma vez Toda a adição, divisão e indexação tem que ser feito Independentemente Se você está fazendo 16 bandas, você ainda só precisa alocar B uma vez se sua intenção é salvar uma imagem Mesmo que isso não ajuda, pode esclarecer porque eu não entendo o problema, ou pelo menos servir como um ponto de referência para Tempo o speedups de outros métodos Isso é executado em 2 6 seg no meu laptop em uma matriz 5k x 5k de float64 s, 0 5 do que é a criação de B. resposta fevereiro 8 11 em 19 31.It s não tão claro forma seu Pergunta, mas eu estou assumindo agora que você vai gostar de melhorar significativamente este tipo de averaging. Now, que tipo de melhorias de desempenho que você realmente espera. Update Primeiro de tudo, um aviso o código em seu estado atual não se adaptar adequadamente A forma do kernel No entanto, essa não é a minha principal preocupação agora mesmo assim A idéia é lá allready como se adaptar adequadamente. Eu acabei de escolher a nova forma de um 4D A intuitivamente, para mim, realmente faz sentido pensar em um centro do kernel 2D para ser centralizado para cada posição de grade de 2D original. 4D forma não pode realmente ser o melhor que eu acho que o verdadeiro problema aqui é o desempenho de soma Um deve ser capaz de encontrar a melhor ordem do 4D A inorder para utilizar plenamente sua arquitetura de cache de máquinas Contudo, essa ordem pode não ser a mesma para Pequenas matrizes que tipo de cooperação com o cache de suas máquinas e aqueles maiores, que don t pelo menos não maneira tão simples. Update 2 Aqui está uma versão ligeiramente modificada de mf Claramente é melhor para remodelar a uma matriz 3D em primeiro lugar e, em seguida, Em vez de somar apenas fazer produto de ponto isso tem a vantagem de tudo isso, que o kernel pode ser arbitrária No entanto, é ainda alguns 3x mais lento na minha máquina do Pauls atualizado function. answered 08 de fevereiro de 19 em 19 33.

No comments:

Post a Comment