Conseils pour algorithme de lissage de courbe

Conseils pour algorithme de lissage de courbe - Divers - Programmation

Marsh Posté le 10-10-2017 à 17:39:06    

Bonjour,
J'ai un système qui fait des relevés de température, dont je trace la courbe.
Les points de la série sont de la forme Temps en X, float en Y, tout simplement.

 

Malheureusement d'une valeur à l'autre, j'ai des sauts de valeurs, dus à l'imprécision. Ce qui donne un graphique assez chaotique (vignette cliquable) :
https://img15.hostingpics.net/pics/813953Nofilter.png
Sachant que je suis une buse en maths pures, j'aimerais bien une proposition d'algo pour lisser ces cahots, tout en préservant les valeurs extrêmes.

 

Sachant que j'aimerais éviter l'algo naïf du genre "si la variation est de moins de 0.5, tu reprends la valeur d'avant" ), j'ai fait une tentative avec Kalman (via cette implémentation : https://github.com/prozoroff/UKFSharp/ ) mais le résultat n'est pas satisfaisant car même si la courbe est beaucoup plus lisse, et qu'on retrouve la forme générale, les valeurs extrêmes sont également considérablement compressées (ce qui est logique avec la définition de l'algo !) :
https://img15.hostingpics.net/pics/448767Kalman.png

 

Auriez vous une suggestion d'algo (dont l'implémentation est facilement trouvable en C# si possible) pour améliorer ça ?

 

Merci :jap:


Message édité par TotalRecall le 10-10-2017 à 17:39:59

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 10-10-2017 à 17:39:06   

Reply

Marsh Posté le 10-10-2017 à 17:53:39    

A partir de ton ex, tu pourrais nous poster le genre de graphique résultat que tu voudrais obtenir, svp ?
Parce que vu ton ex, on pourrait très biens e dire qu'on ne veut pas des valeurs aberrantes ou, au contraire, qu'on veut les conserver car pertinentes. A contrario, les baisses ou augmentations en escalier, on pourrait vouloir les lisser en une unique pente moyenne.
 
Tu pourrais aussi sous-échantillonner ton signal (nb de valeurs par période moindre) et donc faire une moyenne des x valeurs de la période.
 
Après, tu peux partir de Kalman mais de bidouiller l'algo pour qu'il conserve les valeurs qui ont une grosse variation. Pourquoi ne pas établir le seuil non pas en valeur absolue mais en % ?
 
Edit :  tu peux aussi approximer ton graph avec une spline...


Message édité par rufo le 10-10-2017 à 17:54:51

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 10-10-2017 à 18:03:33    

Hello,  
Je n'ai pas d'exemple tout fait. J'espérais que les deux illustrations suffiraient à mettre en évidence le souci actuel tout en suggérant ce que je vise.
 
L'approximation avec une spline donnerait toujours autant de sauts non pertinents, donc pas grand intérêt même si visuellement ça serait moins "carré".
 
Concernant l'idée de tweaker l'algo pour qu'il conserve les grosses variations tout en absorbant les petites, j'y ai songé également. Mais même si j'ai une idée théorique du principe général de Kalman, pour moi c'est incompréhensible, toutes les variables ont des noms abscons et je n'ai pas le niveau en maths pour attaquer ça :
https://github.com/prozoroff/UKFSha [...] nFilter.cs
Après il y a peut être d'autres implémentations qui permettent de paramétrer quelques trucs.
 
Je me disais simplement que quelqu'un de moins ignorant que moi en maths aurait pu me citer un algo que je ne connais pas (c'est facile, le seul que je connais c'est Kalman [:twixy]) pour lisser des graphes comme le mien, etc. C'est toujours une bonne occasion d'apprendre !


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 10-10-2017 à 21:58:28    

C'est très spécial comme demande, la question sous jacente est "jusqu'où" tu veux lisser...
 
Tu as bien sur spline et bezier:
https://fr.wikipedia.org/wiki/Courbe_de_B%C3%A9zier
 
Mais c'est "aggressif" on va dire.
 
Le mieux serait quelque chose de plus simple je pense:
Tu fais la moyenne et l'écart type de ta série de nombres, et tu enlèves les extrêmes de ces valeurs:
https://fr.wikipedia.org/wiki/%C3%89cart_type
 
Disons que ta moyenne c'est M: et bien tu ne gardes que tout ce qui est entre M + 25% et M - 25% (soit les 50% "au milieu" ) et dégage le reste.
Ca lissera de facto...
 
Tu peux croiser ca avec la dérivée seconde de la fonction par exemple pour un résultat similaire ;)

Reply

Marsh Posté le 10-10-2017 à 22:34:41    

Ca pourra peut-être t'aider :
http://forums.mediabox.fr/topic/12 [...] bedonnees/
https://openclassrooms.com/forum/su [...] rimentales
http://www.commentcamarche.net/for [...] -graphique
 
Edit : c'est bon, j'ai trouvé l'algo que tu cherches, je pense : https://fr.wikipedia.org/wiki/Algor [...] tzky-Golay
 
Sinon : https://fr.wikipedia.org/wiki/Lissa [...] 9matiques)


Message édité par rufo le 10-10-2017 à 22:38:47

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 11-10-2017 à 09:06:24    

Hello,

 

J'ai un peu parcouru ta littérature et le "Savitzky-Golay smoothing" m'a l'air prometteur, et on peut faire un peu de fine tuning, merci.
Je vais comparer ça avec mon Kalman dès que j'aurai trouvé une implémentation gratos et compréhensible.

 

Je suis aussi tombé sur ça : http://www.robosoup.com/2014/01/cl [...] ter-c.html
C'est basique mais ça peut être pas mal à tester, l'avantage c'est que je comprend le code (pas comme les multiplications de matrices denses et les factorisations de Cholesky  :pt1cable:), que ça ne nécessite aucune lib externe (alors que le Kalman plus haut dépend de MathNet.Numerics), et qu'on peut aussi ajuster le comportement.

 

Je ferai un feedback avec la nouvelle courbe si j'arrive à quelque chose quand j'aurai pu me repencher là dessus :D.

 

edit : un résumé des algos : https://stackoverflow.com/a/204229/461444


Message édité par TotalRecall le 11-10-2017 à 09:08:53

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 11-10-2017 à 09:26:07    

Si tu veux garder les valeurs aberrantes il te faut définir un seuil d'exclusion.
Perso je ne me prendrai pas la tête je ferai pour chaque point une moyenne glissante, chaque point devient la moyenne des 2 précédents et des 2 suivants plus la valeur en question. Le nombre de points pris en compte pour le calcul de la moyenne définie ton degré de lissage. Et comme je disais précédemment il te faut définir une valeur seuil, c'est à dire que tu ne calcules la moyenne que si la différence entre le point en question et le précédent est inférieur à ta valeur seuil définie.
Un bézier est quand même plus compliqué à mettre en place quand tu veux garder des valeurs aberrantes et est plus représentatif d'un effet inertiel.

 

EDIT : et si tu veux quelque chose de toujours assez simple mais d'un peu plus poussé tu peux "coefficiencer" tes valeurs dans ta moyenne, si tu fais une moyenne sur 5 points par exemple tu donnes moins de poids aux points les plus éloignés de ton point central, un peu à la manière d'un barycentre. Les coefficients sont calculés selon la distance entre tes points sur l'axe des abscisses.


Message édité par MaybeEijOrNot le 11-10-2017 à 09:37:31

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 11-10-2017 à 13:37:23    

En fait elles ne sont pas aberrantes : les petites variations correspondent aux imprécisions de la mesure, les fortes variations correspondent à des changements réels. D'où l'importance de lisser les petites variations sans dézinguer les grandes :p.


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Marsh Posté le 11-10-2017 à 16:30:03    

Oui j'avais bien compris, c'est pourquoi il est en effet important de garder les valeurs extrêmes, je me suis mal exprimé en effet avec le terme "aberrant".
Avec l'algo de Savitzky-Golay tu garderas plus ou moins ces valeurs extrêmes en fonction du degré du polynôme choisi. Sachant que plus le degré est élevé, plus tu vas garder fidèlement ces valeurs extrêmes mais moins tu vas lisser ta courbe. Mais pour moi tu te rapproches plus d'un bézier dans ce cas là. Tu fais en quelque sorte une analyse fonctionnelle de ta courbe ce qui me semble inutile à moins d'y trouver un sens physique.
Avec une valeur seuil tu t'assures de rendre les valeurs extrêmes avec fidélité avec un lissage que tu contrôles de manière indépendante. Tu peux toujours utiliser une valeur seuil avec n'importe quel algo mais je ne vois pas l'intérêt de partir dans quelque chose de trop complexe.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 17-10-2017 à 09:53:23    

Hello,
Avec l'algo dont j'ai donné le lien plus haut :
http://www.robosoup.com/2014/01/cl [...] ter-c.html
En jouant sur la diminution (de 0.3 à 0.8) et le nombre d'échantillons (3 à 5) les résultats sont très variés tout en respectant bien la tendance générale, donc c'est plutôt souple, et c'est rapide et simple tout en donnant un meilleur résultat qu'une moyenne mobile.

 

Du coup même si ça ne correspond à rien de formel ça convient, je vais en rester là pour le moment.

 

Je me pencherai sur Savitzky-Golay si un jour j'ai le temps de retravailler un peu tout ça mais pour l'instant ça n'est pas du tout ma priorité.

 

Merci pour vos suggestions :jap:


Message édité par TotalRecall le 17-10-2017 à 09:53:34

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed