Saturday, February 11, 2017

Algorithme De La Moyenne Mobile Récursive

Je travaille encore sur groaking la chose de F - essayant de travailler dehors comment penser en F plutôt que juste traduire d'autres langues que je connais. Ive récemment pensé aux cas où vous n'avez pas une carte 1: 1 entre avant et après. Cas où List. map tombe en panne. Un exemple de cela est le déplacement des moyennes, où généralement vous aurez len-n1 résultats pour une liste de longueur len lors de la moyenne sur n éléments. Pour les gourous là-bas, est-ce un bon moyen de le faire (en utilisant la queue pincée de Jomo Fisher) (Peut-être une meilleure façon serait d'implémenter un MovingAverageQueue en héritant de Fifo) a demandé Nov 17 08 at 11:12 J'ai dû déclarer Il comme laisser MovingAverage n (seqltfloatgt s) afin de mettre cela dans un module d'utilité, loin du site d'appel, pour apaiser le système de type. Autant que je peux dire, cela ne fonctionne qu'avec des flotteurs, en raison d'une limitation de Array. average. MSDN prétend que je peux remplacer cela par Array. averageBy pour utiliser ce sur une séquence int, mais qui donne une erreur différente. Brian, pouvez-vous reformuler cette réponse pour travailler dans des contextes génériques, de sorte qu'il fonctionne avec seq-of-any-arithmetic-type, sans type d'inférence ndash Warren Young Jun 27 13 at 19:04 Je dois souligner que mon besoin de Cette fonction de moyenne mobile est d'obtenir une fenêtre courte (30ish) sur une séquence d'entiers qui sont presque tous dans les millions, donc je don39t besoin de virgule flottante. Même un seul chiffre à la droite de la virgule décimale est d'aucune utilité pratique dans ma demande. Conversion de mes entiers à FP et le résultat retour à int juste pour apaiser la bibliothèque standard F doesn39t appel. Ndash Warren Young Jun 27 13 à 19:30 Si vous vous souciez de la performance, alors vous pouvez calculer une moyenne mobile en utilisant efficacement quelque chose comme ceci (en supposant étaient de calculer une moyenne mobile sur une fenêtre de 3 jours) La partie difficile à ce sujet est la tenue Sur votre total d'exécution précédente et la fenêtre N °. Je suis venu avec le code suivant: Cette version n'est pas aussi jolie que le code Haskell, mais il devrait éviter les problèmes de performance associés à recalculer votre fenêtre sur chaque exécution. Il conserve un total courant et tient les numéros précédemment utilisés dans une file d'attente, il devrait donc être très rapide. Juste pour le plaisir, j'ai écrit une référence simple: Si vous vous souciez de la performance et comme le code élégant, puis essayez Utiliser FSUnit, nous pouvons le tester Le tour de l'algorithme est la première somme les n premiers numéros et ensuite maintenir un total en cours en ajoutant la tête De la fenêtre et en soustrayant la queue de la fenêtre. La fenêtre coulissante est obtenue en faisant un zip auto sur la séquence, mais avec le deuxième argument à zip avancé par la taille de la fenêtre. À la fin du pipeline, il suffit de diviser le total en cours par la taille de la fenêtre. Le balayage de note est comme un pli, mais donne chaque version de l'état dans une séquence. Une solution encore plus élégante though possibley avec le coup de la performance est de faire l'observation que si nous zéro pad la séquence nous ne devons pas calculer la somme initiale. Il pourrait y avoir un coup de performance dû à la deuxième indirection liée à l'enveloppement des deux séquences mais peut-être n'est pas significatif selon la taille de la fenêtre a répondu Août 31 12 à 8: 06Le défaut principal dans votre programme est que le calcul récursif est incorrect. Pour calculer la moyenne, vous devez obtenir la somme de la valeur courante et des valeurs restantes. Puis divisez cette somme par le nombre de valeurs. Le nombre de valeurs est num. La valeur courante est tout calculatenumber () renvoie. La somme des valeurs restantes est num-1 multipliée par la moyenne des valeurs restantes. La moyenne des valeurs restantes est calculée en faisant un appel récursif à average (). Ainsi, nous écrivons ce qui suit: Un programme complet utilisant cette fonction pourrait ressembler à ceci: Notez que ce n'est pas un très bon moyen de calculer la moyenne parce que vous perdez la précision chaque fois que vous divisez la somme courante par num. Lorsque cette moyenne est multipliée à nouveau lorsque l'appel récursif revient, les chiffres significatifs que vous avez perdus dans la division ne sont pas restaurés. Vous détruisez l'information en divisant puis en multipliant la somme. Pour une plus grande précision, vous voulez garder la trace de la somme que vous passez par les éléments, puis diviser à la fin. Un autre point à considérer est ce que signifie une moyenne mobile. Ce que nous avons mis en œuvre ci-dessus n'est pas une moyenne mobile, mais une moyenne fixe. C'est la moyenne d'une fenêtre fixe d'éléments. Si vous déplacez la fenêtre d'une position, vous devez tout recommencer et calculer la somme à nouveau. La bonne façon de mettre en œuvre une fenêtre en mouvement est de garder une trace de tous les éléments de la fenêtre. Lorsque vous décalez la fenêtre d'une position vers la droite, vous retirez l'élément le plus à gauche de la fenêtre et soustrayez sa valeur de la somme, puis ajoutez le nouvel élément à droite à la fenêtre et ajoutez sa valeur à la somme. C'est ce qui en fait une somme mobile. Diviser la somme mobile par le nombre d'éléments vous donne la moyenne mobile. Le moyen naturel d'implémenter une fenêtre en mouvement est avec une file d'attente, car vous pouvez ajouter de nouveaux éléments à la tête et pop éléments anciens de la queue. Réponse Nov 22 14 at 17: 44The Scientist and Engineers Guide sur le traitement du signal numérique Par Steven W. Smith, Ph. D. Un avantage énorme du filtre de la moyenne mobile est qu'il peut être implémenté avec un algorithme qui est très rapide. Pour comprendre cet algorithme, imaginez passer un signal d'entrée, x, à travers un filtre de moyenne mobile à sept points pour former un signal de sortie, y. Maintenant, regardez comment sont calculés deux points de sortie adjacents, y 50 et y 51. Ce sont presque les mêmes points de calcul x 48 à x 53 doivent être ajoutés pour y 50 et encore pour y 51. Si y 50 a déjà été calculé , Le moyen le plus efficace de calculer y 51 est: Une fois que y 51 a été trouvé en utilisant y 50, alors y 52 peut être calculé à partir de l'échantillon y 51, et ainsi de suite. Après le premier point est calculé en y, tous les autres points peuvent être trouvés avec seulement une seule addition et soustraction par point. Cela peut être exprimé dans l'équation: Notez que cette équation utilise deux sources de données pour calculer chaque point dans la sortie: points de l'entrée et les points précédemment calculés de la sortie. C'est ce qu'on appelle une équation récursive, ce qui signifie que le résultat d'un calcul est utilisé dans les calculs futurs. (Le terme récursif a aussi d'autres significations, surtout en informatique). Le chapitre 19 traite plus en détail d'une variété de filtres récursifs. Soyez conscient que le filtre récursif à moyenne mobile est très différent des filtres récursifs typiques. En particulier, la plupart des filtres récursifs ont une réponse impulsionnelle infiniment longue (IIR), composée de sinusoïdes et exponentielles. La réponse impulsionnelle de la moyenne mobile est une impulsion rectangulaire (réponse impulsionnelle finie, ou FIR). Cet algorithme est plus rapide que les autres filtres numériques pour plusieurs raisons. Tout d'abord, il n'y a que deux calculs par point, indépendamment de la longueur du noyau du filtre. Deuxièmement, l'addition et la soustraction sont les seules opérations mathématiques nécessaires, alors que la plupart des filtres numériques nécessitent une multiplication longue. Troisièmement, le schéma d'indexation est très simple. Chaque indice de l'équation 15-3 se trouve en ajoutant ou en soustrayant des constantes entières qui peuvent être calculées avant le début du filtrage (c'est-à-dire p et q). Tout l'algorithme peut être réalisé avec une représentation entière. Selon le matériel utilisé, les entiers peuvent être plus d'un ordre de grandeur plus rapide que le point flottant. Étonnamment, la représentation entière fonctionne mieux que le point flottant avec cet algorithme, en plus d'être plus rapide. L'erreur arrondi de l'arithmétique à virgule flottante peut produire des résultats inattendus si vous ne faites pas attention. Par exemple, imaginez un 10 000 échantillons de signal filtrés par cette méthode. Le dernier échantillon dans le signal filtré contient l'erreur accumulée de 10 000 additions et 10 000 soustractions. Cela apparaît dans le signal de sortie comme un décalage de dérive. Les nombres entiers n'ont pas ce problème parce qu'il n'y a pas d'erreur arrondi dans l'arithmétique. Si vous devez utiliser un point flottant avec cet algorithme, le programme du Tableau 15-2 montre comment utiliser un accumulateur à double précision pour éliminer cette dérive.


No comments:

Post a Comment