46 votes

Lissage des valeurs au fil du temps: moyenne mobile ou meilleure?

Je code quelque chose au moment où je prends un tas de valeurs au cours du temps à partir d'un matériel d'une boussole. Cette boussole est très précis et des mises à jour très souvent, avec le résultat que si elle bouge légèrement, je me retrouve avec la valeur impaire qui est très incompatible avec ses voisins. Je veux lisser ces valeurs.

Ayant déjà lu un peu partout, il semblerait que ce que je veux, c'est un filtre passe-haut, filtre passe-bas ou d'une moyenne mobile. La moyenne mobile je peux descendre avec, il suffit de garder un historique des 5 dernières valeurs ou que ce soit, et l'utilisation de la moyenne de ces valeurs en aval dans mon code où j'ai été une fois juste à l'aide de la valeur la plus récente.

Qui devrait, je pense, de lisser ces remue bien, mais il me semble que c'est probablement tout à fait inefficace, et c'est probablement l'un de ces Problèmes Connus le Bon Programmeurs pour qui il y a de vraiment bien Malin solution Mathématique.

Je suis, cependant, une de ces terribles autodidacte programmeurs sans l'ombre d'une éducation formelle en rien, même vaguement liées à la fac d'informatique ou de Mathématiques. Lecture un peu autour de lui suggère que ce pourrait être un haut ou passe-bas, filtre, mais je ne trouve rien qui explique, en des termes compréhensibles pour un hack comme moi que l'effet de ces algorithmes ne seront pas sur un tableau de valeurs, et encore moins comment les mathématiques œuvres. La réponse donnée ici, par exemple, techniquement n'répondre à ma question, mais seulement en termes compréhensibles pour ceux qui savez probablement déjà comment résoudre le problème.

Ce serait une très belle et intelligente personne en effet qui pourrait expliquer le genre de problème que cela est, et comment les solutions de travail, dans des termes compréhensibles à un Arts d'études supérieures.

58voto

e.James Points 51680

Si vous tentez de supprimer le occasionnel valeur impaire, un filtre passe-bas est le meilleur des trois options que vous avez identifié. Filtres passe-bas de permettre à basse vitesse des changements tels que ceux causés par la rotation d'une boussole à la main, tout en rejetant à haute vitesse des changements tels que ceux causés par des bosses sur la route, par exemple.

Une moyenne mobile ne sera probablement pas suffisant, étant donné que les effets d'un "blip" dans vos données affecter plusieurs valeurs, en fonction de la taille de votre moyenne mobile de la fenêtre.

Si les valeurs bizarres sont facilement détectés, vous pourriez être mieux avec un glitch-algorithme de retrait qui ignore complètement entre eux:

if (abs(thisValue - averageOfLast10Values) > someThreshold)
{
    thisValue = averageOfLast10Values;
}

Voici une guick graphique pour illustrer:

graph comparison

Le premier graphique est le signal d'entrée, avec une désagréable glitch. Le deuxième graphique montre l'effet d'une 10-exemple de la moyenne mobile. Le graphique final est une combinaison de la 10-moyenne d'échantillon et le simple problème de la détection de l'algorithme présenté ci-dessus. Lorsque le problème est détecté, le 10-moyenne des échantillons est utilisée au lieu de la valeur réelle.

38voto

Rex Kerr Points 94401

Si votre moyenne mobile doit être long pour atteindre le lissage, et vous n'avez pas vraiment besoin d'une forme particulière de noyau, alors vous êtes mieux si vous utilisez une façon exponentielle en décomposition moyenne mobile:

a(i+1) = tiny*data(i+1) + (1.0-tiny)*a(i)

lorsque vous choisissez tiny à être une constante appropriée (par exemple, si vous choisissez de minuscules = 1 - 1/N, il aura la même quantité de calcul de la moyenne comme une fenêtre de taille N, mais réparties différemment par rapport aux anciens points).

De toute façon, puisque la prochaine valeur de la moyenne mobile ne dépend que de la précédente et de vos données, vous n'avez pas à garder une file d'attente ou quoi que ce soit. Et vous pouvez penser ce que le fait de faire quelque chose comme, "eh Bien, j'ai un nouveau point, mais je n'ai pas vraiment confiance en elle, donc je vais garder 80% de mon ancien estimation de la mesure, et seulement faire confiance à ce nouveau point de données de 20%". C'est à peu près la même chose que de dire, "eh Bien, je n'ai confiance en ce nouveau point 20%, et je vais utiliser les 4 autres points que j'ai confiance en la même quantité", sauf qu'au lieu de explicitement de prendre les 4 autres points, vous êtes en supposant que le calcul de la moyenne que vous avez fait la dernière fois était raisonnable de sorte que vous pouvez utiliser votre travail précédent.

6voto

Dan Tao Points 60518

La moyenne mobile je peux descendre avec ... mais il me semble que c'est probablement tout à fait inefficace.

Il n'y a vraiment aucune raison d'une moyenne mobile devrait être inefficace. Maintenir le nombre de points de données que vous voulez dans la mémoire tampon (comme une file d'attente circulaire). Sur chaque point de données, vous pop la plus ancienne de la valeur et de la soustraire une somme, et de pousser le plus récent et l'ajouter à la somme. Ainsi, chaque nouveau point de données est vraiment n'entraîne qu'une pop/push, une addition et une soustraction. Votre moyenne mobile est toujours ce décalage somme divisée par le nombre de valeurs dans votre tampon.

Il devient un peu plus compliqué si vous êtes à recevoir des données simultanément à partir de plusieurs threads, mais puisque vos données sont à venir à partir d'un périphérique matériel qui semble très douteux pour moi.

Ah et aussi: terrible autodidacte programmeurs, unissons-nous! ;)

2voto

Daren Thomas Points 26812

D'une manière exponentielle en décomposition moyenne mobile peut être calculé "à la main" avec seulement la tendance si vous utilisez les bonnes valeurs. Voir http://www.fourmilab.ch/hackdiet/e4/ pour avoir une idée sur la manière de le faire rapidement avec un stylo et du papier si vous êtes à la recherche pour "de façon exponentielle lissés en moyenne mobile à 10% de lissage". Mais puisque vous avez un ordinateur, vous voulez probablement faire binaires décalage par opposition à la virgule en train de changer ;)

De cette façon, vous avez besoin d'une variable pour votre valeur actuelle et l'autre pour la moyenne. Le prochain moyen peut être calculé à partir de cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X