Vamos supor que temos um conjunto de dados que pode ser fornecido aproximadamente por
import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
Portanto, temos uma variação de 20% do conjunto de dados. Minha primeira ideia foi usar a função UnivariateSpline do scipy, mas o problema é que isso não considera o pequeno ruído de uma maneira boa. Se você considerar as frequências, o fundo é muito menor que o sinal, portanto, uma spline apenas do ponto de corte pode ser uma ideia, mas isso envolveria uma transformação de quatro para a frente e para trás, o que poderia resultar em mau comportamento. Outra maneira seria uma média móvel, mas isso também precisaria da escolha certa do atraso.
Alguma dica / livros ou links sobre como lidar com esse problema?
python
numpy
scipy
signal-processing
data-processing
varantir
fonte
fonte
Respostas:
Eu prefiro um filtro Savitzky-Golay . Ele usa mínimos quadrados para regredir uma pequena janela dos seus dados em um polinômio e, em seguida, usa o polinômio para estimar o ponto no centro da janela. Finalmente, a janela é deslocada para frente em um ponto de dados e o processo se repete. Isso continua até que cada ponto seja ajustado de maneira ideal em relação aos seus vizinhos. Funciona muito bem mesmo com amostras barulhentas de fontes não periódicas e não lineares.
Aqui está um exemplo completo do livro de receitas . Veja meu código abaixo para ter uma idéia de como é fácil usar. Nota: Eu deixei de fora o código para definir a
savitzky_golay()
função porque você pode literalmente copiá-lo / colá-lo do exemplo do livro de receitas que eu vinculei acima.ATUALIZAÇÃO: Chegou ao meu conhecimento que o exemplo do livro de receitas ao qual vinculei foi retirado. Felizmente, o filtro Savitzky-Golay foi incorporado à biblioteca SciPy , como apontado por @dodohjk . Para adaptar o código acima usando a fonte SciPy, digite:
fonte
savgol_filter((x, y), ...)
.Uma maneira rápida e suja de suavizar os dados que eu uso, com base em uma caixa de média móvel (por convolução):
fonte
scipy.ndimage.filters.convolve1d()
permite especificar um eixo de um nd-array para fazer a filtragem. Mas acho que ambos sofrem de alguns problemas nos valores mascarados.Se você estiver interessado em uma versão "suave" de um sinal periódico (como o seu exemplo), uma FFT é o caminho certo a seguir. Faça a transformação de Fourier e subtraia as frequências de baixa contribuição:
Mesmo que seu sinal não seja completamente periódico, isso fará um ótimo trabalho em subtrair o ruído branco. Existem muitos tipos de filtros a serem usados (passa-alto, passa-baixo, etc ...), o apropriado depende do que você está procurando.
fonte
Ajustar uma média móvel aos seus dados reduziria o ruído; veja esta resposta para saber como fazer isso.
Se você deseja usar o LOWESS para ajustar seus dados (é semelhante a uma média móvel, mas mais sofisticada), você pode fazer isso usando a biblioteca statsmodels :
Por fim, se você conhece a forma funcional do seu sinal, pode ajustar uma curva aos seus dados, o que provavelmente seria a melhor coisa a fazer.
fonte
loess
implementado.Outra opção é usar o KernelReg no statsmodels :
fonte
Veja isso! Há uma definição clara de suavização de um sinal 1D.
http://scipy-cookbook.readthedocs.io/items/SignalSmooth.html
Atalho:
fonte
Se você estiver plotando um gráfico de séries temporais e se tiver usado o mtplotlib para desenhar gráficos, use o método mediano para suavizar o gráfico
onde
timeseries
seu conjunto de dados é passado, você pode alterarwindowsize
para obter mais suavização.fonte