Hmmm, parece que este quoteasy para implementar a função é realmente muito fácil de errar e tem promovido uma boa discussão sobre a eficiência da memória. I39m feliz por ter bloat se isso significa saber que something39s sido feito direito. Ndash Richard Sep 20 14 at 19:23 NumPys falta de uma determinada função específica de domínio é talvez devido à disciplina Core Teams e fidelidade à diretiva NumPys principal: fornecer um tipo de matriz N-dimensional. Bem como funções para criar e indexar essas matrizes. Como muitos objetivos fundacionais, este não é pequeno, e NumPy faz isso brilhantemente. O SciPy (muito maior) contém uma coleção muito maior de bibliotecas específicas de domínio (chamadas subpacotes por SciPy devs) - por exemplo, otimização numérica, processamento de sinal (sinal) e cálculo integral (integrar). Minha suposição é que a função que você está depois está em pelo menos um dos subpáginas SciPy (scipy. signal talvez) no entanto, eu iria olhar primeiro na coleção SciPy scikits. Identificar o (s) scikit (s) relevante (s) e procurar a função de interesse lá. Scikits são desenvolvidos independentemente pacotes baseados em NumPy / SciPy e dirigidos a uma determinada disciplina técnica (por exemplo, scikits-image. Scikits-learn, etc.) Vários destes foram (em particular, o incrível OpenOpt para otimização numérica) foram altamente considerado, maduro Projetos muito antes de escolher para residir sob a rubrica relativamente nova scikits. A página inicial do Scikits gostava de listar cerca de 30 scikits como esse. Embora pelo menos alguns deles já não estejam em desenvolvimento. Seguindo este conselho o levaria a scikits-timeseries no entanto, que o pacote não está mais em desenvolvimento ativo Em efeito, Pandas tornou-se, AFAIK, a biblioteca de série de facto NumPy tempo. Pandas tem várias funções que podem ser usadas para calcular uma média móvel o mais simples destes é provavelmente rollingmean. Que você usa assim: Agora, basta chamar a função rollingmean passando no objeto Series e um tamanho de janela. Que no meu exemplo abaixo é de 10 dias. Verificar que funcionou - por exemplo. Os valores comparados 10-15 na série original versus a nova série alisada com média de rolamento A função rollingmean, juntamente com cerca de uma dúzia de outras funções são agrupadas informalmente na documentação Pandas sob a rubrica move janela funciona um segundo grupo relacionado de funções Em Pandas é referido como funções exponencialmente ponderadas (eg ewma., Que calcula a média ponderada exponencialmente em movimento). O fato de que este segundo grupo não está incluído na primeira (funções de janela em movimento) é talvez porque as transformações exponencialmente ponderadas não dependem de um eixo de comprimento fixo de windownumpy. average ao longo do qual a média a. Se Nenhum. A média é feita sobre o arranjo achatado. Pesos. Arraylike, optional Uma matriz de pesos associados com os valores em a. Cada valor em a contribui para a média de acordo com seu peso associado. A matriz de pesos pode ser 1-D (caso em que seu comprimento deve ser o tamanho de um ao longo do eixo dado) ou da mesma forma como a. Se weightsNone. Então todos os dados em um são assumidos para ter um peso igual a um. devolvida . Bool, opcional O padrão é False. Se for verdade . A tupla (média de sumofweights) é retornada, caso contrário apenas a média é retornada. Se weightsNone. Sumofweights é equivalente ao número de elementos sobre os quais a média é tomada. Média, sumofweights. Arraytype ou double Retorna a média ao longo do eixo especificado. Quando retornado é True. Retorna uma tupla com a média como o primeiro elemento ea soma dos pesos como o segundo elemento. O tipo de retorno é Float se a for de tipo inteiro, caso contrário ele é do mesmo tipo que a. Sumofweights é do mesmo tipo que a média. Aprendi recentemente sobre avanços na resposta a este post. E estava me perguntando como eu poderia usá-los para calcular um filtro de média móvel de forma mais eficiente do que o que eu propus neste post (usando filtros de convolução). Isso é o que eu tenho até agora. Faz exame de uma vista da disposição original rola-a então pela quantidade necessária e somam os valores do kernel para computar 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 scipy. ndimage. filters. convolve é bastante lenta. Observe que eu estou procurando a conectividade de 8 vizinhos, que é um filtro 3x3 leva a média de 9 pixels (8 ao redor do pixel focal) e atribui esse valor ao pixel na nova imagem. EDIT Esclarecimento sobre como eu vejo este trabalho: use stridetricks para gerar um array como 0,1,2,1,2,3,2,3,4. Que corresponde à linha superior do kernel do filtro. Rolo ao longo do eixo vertical para obter a fila do meio do kernel 10,11,12,11,12,13,13,14,15. E adicioná-lo à matriz que eu tenho em 1) Repita para obter a linha inferior do kernel 20,21,22,21,22,23,22,23,24. . Neste ponto, eu pego a soma de cada linha e dividi-la pelo número de elementos no filtro, dando-me a média de cada pixel, (deslocado por 1 linha e 1 col, e com algumas rarezas em torno de arestas, 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 me convencer de outro método mais eficiente. Perguntou Feb 8 11 at 18:05 Para o que vale a pena, heres como youd fazê-lo usando truques fantasia striding. Eu estava indo para postar isso ontem, mas se distraiu com o trabalho real. ) Paul amp come ambos têm implementações agradável usando várias outras maneiras de fazer isso. Apenas para continuar as coisas a partir da pergunta anterior, eu imaginei Id post o equivalente N-dimensional. Você não vai ser capaz de bater significativamente scipy. ndimage funções para arrays 1D, no entanto. (Scipy. ndimage. uniformfilter deve bater scipy. ndimage. convolve.) Além disso, se você está tentando obter uma janela de 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 exibição na memória de sua matriz original, quaisquer etapas intermediárias que copiar a matriz fará uma cópia que é ordens de magnitude maior do que sua matriz original (ou seja, vamos dizer que você está trabalhando com uma matriz original 100x100 (Para um tamanho de filtro de (3,3)) será 98x98x3x3 mas usar a mesma memória que o original. No entanto, quaisquer cópias usará a quantidade de memória que uma matriz 98x98x3x3 completa) Basicamente, usando louco Striding truques é ótimo para quando você quiser vectorize operações de janela em movimento em um único eixo de um ndarray. Isso torna muito fácil calcular coisas como um desvio padrão em movimento, etc, com muito pouca 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. (Como, por exemplo, scipy. ndimage etc) De qualquer forma, heres como você fazê-lo: Então o que temos quando fazemos b rollingwindow (a, filtsize) é uma matriz 8x8x3x3, thats realmente uma visão para a mesma memória que o original 10x10 Matriz. Poderíamos ter tão facilmente usado diferentes tamanhos de filtro 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 que nos daria uma visão 6 dimensional ). Podemos então aplicar uma função arbitrária ao último eixo repetidamente para efetivamente calcular as coisas em uma janela em movimento. No entanto, porque estavam 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 é eficiente em toda a sua memória também não vai ser terrivelmente rápido, também. O equivalente para ndimage é apenas: Isto irá lidar com uma variedade de condições de fronteira, fazer o borrão no local, sem exigir uma cópia temporária da matriz, e ser muito rápido. Striding truques são uma boa maneira de aplicar uma função a uma janela em movimento ao longo de um eixo, mas theyre não uma boa maneira de fazê-lo ao longo de vários eixos, normalmente. Apenas o meu 0,02, de qualquer forma. Muito bem colocado: os truques de striding 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, normalmente. E, claro, a sua explicação da memória 39blow up39 é importante. O tipo de resumo de sua resposta (pelo menos para mim) é: "Não vá pescar muito longe, a captura quarentária está pronta em scipy39". Obrigado ndash comer Feb 9 11 at 16:37 Obrigado, Joe, para esta resposta. Em rollingwindow deve se não hasattr (.): Estar retornando rollingwindowlastaxis (.) Ao invés de rollingwindow. Ndash unutbu Feb 12 11 at 16:47 Eu não sou familiar o suficiente com Python para escrever o código para isso, mas as duas melhores maneiras de acelerar as convoluções é separar o filtro ou usar a transformada de Fourier. Filtro separado. Convolução é O (MN), 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 kernel 3-by-3 é equivalente a filtrar primeiro com um kernel 3 por 1 e depois um kernel 1-por-3, você pode obter (33) / (33) 30 melhoria de velocidade por convolução consecutiva Com dois kernels 1-d (obviamente, fica melhor à medida que o kernel fica maior). Você pode ainda ser capaz de usar truques stride aqui, é claro. Transformada de Fourier . Conv (A, B) é equivalente a ifft (fft (A) fft (B)). Isto é, uma 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 filtro. Uma vez que a multiplicação de Fourier (elemento-sábio) requer que A e B são do mesmo tamanho, B é uma matriz de tamanho (A) com o kernel no centro da imagem e zeros em qualquer outro lugar. Para colocar um kernel 3-by-3 no centro de um array, você pode ter que pad A para o tamanho ímpar. Dependendo de 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), economizando mais 30 de tempo de computação). Respondeu Feb 9 11 at 15:27 Para o que vale a pena, em python, estes são implementados em scipy. ndimage. uniformfilter e scipy. signal. fftconvolve. respectivamente. Ndash Joe Kington Feb 9 11 at 15:44 Jonas: Cool A abordagem de filtragem separada funciona bem, como você diz que economiza mais tempo à medida que o tamanho do kernel aumenta. Para uma matriz 5000x5000, em um tamanho de kernel 11x11, eu estou obtendo 7.7s para convolução 2d usando ndimage. convolve e 2.0s para dois convolutions 1d usando ndimage. convolve1d. Para sua segunda solução, o que é B ndash Benjamin Feb 9 11 at 16:02 Uma coisa que eu estou confiante precisa ser corrigido é a sua matriz de visão b. Ele tem alguns itens de memória não alocada, assim você obterá falhas. Dada a sua nova descrição do seu algoritmo, a primeira coisa que precisa de fixação é o fato de que você está striding fora da alocação de um: Porque Im ainda não bastante agarrar o método e não parece ser maneiras mais simples para resolver o problema, Im apenas vai Para colocar isso aqui: que parece apenas 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 de ser feito independentemente. Se você estiver fazendo 16 bandas, você ainda só precisa alocar B uma vez se sua intenção é salvar uma imagem. Mesmo que isso não ajude, ele pode esclarecer porque eu não entendo o problema, ou pelo menos servir como um ponto de referência para o tempo de aceleração de outros métodos. Isso é executado em 2,6 segundos no meu laptop em uma matriz de 5k x 5k de float64s, 0,5 do que é a criação de B respondeu 8 fevereiro às 19:31 Sua forma não tão clara a sua pergunta, mas Im assumindo agora que você gostaria de melhorar Significativamente esse tipo de média. Agora, que tipo de melhorias de desempenho que você realmente esperaria Update: Primeiro de tudo, um aviso: o código em seu estado atual não se adapta adequadamente à forma do kernel. No entanto isso não é minha principal preocupação agora (de qualquer maneira a idéia é lá allready como se adaptar adequadamente). 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 A. Mas esse 4D moldar não pode realmente ser o melhor. Acho que o verdadeiro problema aqui é o desempenho do somatório. Um deve ser capaz de encontrar a melhor ordem (do 4D A) inorder para utilizar plenamente a sua arquitetura cache de máquinas. No entanto, essa ordem pode não ser a mesma para pequenas matrizes que tipo de cooperação com o cache de máquinas e aquelas maiores, que não (pelo menos não maneira tão simples). Atualização 2: Aqui está uma versão ligeiramente modificada do mf. Claramente é melhor para remodelar a uma matriz 3D em primeiro lugar e, em seguida, em vez de somar apenas fazer produto ponto (isso tem a vantagem de tudo isso, que o kernel pode ser arbitrário). No entanto a sua ainda alguns 3x mais lento (na minha máquina) do Pauls atualizado função. Respondeu 8 de fevereiro às 19: 33Os exemplos a seguir produzem uma média móvel dos valores WINDOW precedentes. Nós truncar o primeiro (WINDOW -1) valores desde que can8217t encontrar a média antes deles. (O comportamento padrão para convolução é assumir que os valores antes do início de nossa seqüência são 0). (Mais formalmente, construímos a seqüência y para a seqüência x onde yi (xi x (i1) 8230. x (in)) / n) Isso faz uso da função de convolução numpy8217s. Esta é uma operação de média móvel de propósito geral. A alteração de ponderações torna alguns valores mais importantes a compensação apropriadamente permite que você visualize a média em torno do ponto em vez de antes do ponto. Em vez de truncar os valores, podemos corrigir os valores iniciais no lugar, como ilustrado neste exemplo: Como este: Related Post navigation Deixe uma resposta Cancelar resposta Obrigado pela dica, achei útil Você tem um pequeno erro no seu exemplo de valor fixo inicial : 8220extendeddata8221 deve ser o que está sendo convolvido, não 8220data8221. Obrigado por descobrir que o I8217ve alterou o exemplo. Boa gorjeta, obrigado. Eu sabia que tinha que haver uma maneira otimizada para numpy calcular médias de rolamento. Dos docs (docs. scipy. org/doc/numpy/reference/generated/numpy. convolve), parece que sua receita pode ser ainda mais concisa usando a palavra-chave mode8221valid8221 em vez de cortar: gtgtgt WINDOW 10 gtgtgt data 1,2 , 3,4,5,5,5,5,5,5,5,5,5,5,5 gtgtgt ponderações numpy. repeat (1.0, WINDOW) / WINDOW gtgtgt numpy. convolve (dados, ponderações) WINDOW-1 (4. 4.4, 4.7, 4.9, 5. 5.) gtgtgt numpy. convolve (data, weightings, 8216valid8217) array (4. 4.4, 4.7, 4.9, 5. 5.) Eu tenho Ler em muitos lugares que a mediana em movimento é um pouco melhor do que a média móvel para algumas aplicações, porque é menos sensível a outliers. Eu queria testar essa afirmação em dados reais, mas não consigo ver esse efeito (verde: mediana, vermelho: média). Veja aqui: Eu tentei com vários valores para a largura da janela (aqui no código 1000), e era sempre o mesmo: a mediana móvel não é melhor do que a média móvel (ou seja, não menos sensível a outliers). O mesmo com Janela largura 10000 (10000 a largura do pico). Pergunta: Você pode fornecer um exemplo mostrando que a mediana móvel é menos sensível a outliers do que a média móvel E, se possível, usando o arquivo de dados de amostra. WAV (link de download). I. e. é possível fazer uma mediana móvel sobre estes dados de modo que o resultado seja como esta curva amarela (ou seja, não mais espiga) Esta não é realmente uma resposta, mas eu pensei Id relatório que estou vendo e pedir mais informações. Ive carregado o seu arquivo test. wav e eu posso ver o sinal traçado abaixo. Então o que você está recebendo nas parcelas que você mostra não é tanto o valor mediano, mas é mais como um envelope do sinal. A segunda questão é que o sinal realmente parece ser parte do sinal. Se eu ampliar o blip, então isso é o que eu vejo: O que você está realmente tentando alcançar Obrigado pelo feedback. Abaixo está um código R que faz o seguinte: Carrega o arquivo wav. Toma o valor absoluto do sinal (seu carregado no canal esquerdo pela biblioteca waveR). Executa um filtro de 100 metros de média móvel nos dados para obter algo mais próximo do envelope (sinal vermelho). Em seguida, aplica um filtro mediano de comprimentos 201, 2001 e 4001 ao resultado (sinal azul). A partir da trama abaixo, o melhor desempenho é o 4001 de comprimento. Caso contrário, o efeito da falha ainda está presente. A única coisa que eu posso ver errado agora é que o envelope não corresponde ao envelope verdadeiro, bem como Id como. Um detector de envelope melhor pode melhorar este (por exemplo, o sinal analítico ou tal). Abaixo está um gráfico do envelope mediano filtrado calculado sobreposto ao sinal original. Obrigado pelo tempo que você gastou com esta questão. Na verdade, tracei a mediana e a média do valor absoluto do sinal. E sim, isso dá uma idéia do envelope, isso é o que eu quero. O que eu estava esperando (graças à mediana em vez de média) foi algo como isto. Captura de tela. Infelizmente, qualquer que seja a largura da janela para a mediana. O pico está sempre aqui. Considerando que muitos documentos dizer quotthe mediana tem a vantagem de diminuir o efeito de valores outliersquot. Ndash Basj Nov 30 15 at 14:01 Certo, então a pergunta que eu estou fazendo é: quotoutlier de whatquot. -) Tomando mediana direta ou média dos dados que você tem vai produzir resultados sem sentido. A filtragem mediana só funciona bem quando algumas amostras (em relação ao comprimento da janela) estão fora do intervalo esperado. Porque os dados que você tem estão balançando positivo e negativo, a mediana não é realmente apropriado para ele. Tomando a mediana do envelope deve funcionar melhor. Você pode até querer colocar um filtro passa-baixa simples no valor absoluto para obter um valor de envelope mais estável. Ndash Peter K. 9830 Nov 30 15 em 14:05
Comments
Post a Comment