exercice : niveau avancé¶
En guise d’application de ce qu’on a vu jusqu’ici, je vous invite à réaliser une visualisation du théorème de Taylor; je vous renvoie à votre cours d’analyse, ou à wikipedia pour une présentation détaillée de ce théorème, mais ce que nous en retenons se résume à ceci.
On peut approximer une fonction “suffisamment régulière” - disons pour fixer les idées - par un polynôme d’ordre , dont les coefficients dépendent uniquement des dérivées successives au voisinage d’un point :
Sans perte de généralité nous avons ici fixé le point de référence comme étant égal à 0, il suffit de translater par changement de variable pour se ramener à ce cas-là.
Le théorème de Taylor nous dit que la suite de fonctions converge vers .
On pourrait penser - c’était mon cas la première fois que j’ai entendu parler de ce théorème - que l’approximation est valable au voisinage de 0 seulement; si on pense en particulier à sinus, on peut accepter l’idée que ça va nous donner une période autour de 0 peut-être.
En fait, c’est réellement bluffant de voir que ça marche vraiment incroyablement bien et loin.
mon implémentation¶
Je commence par vous montrer seulement le résultat de l’implémentation que j’ai faite.
Pour calculer les dérivées successives j’utilise la librairie autograd.
Ce code est relativement générique, vous pouvez visualiser l’approximation de Taylor avec une fonction que vous passez en paramètre - qui doit avoir tout de même la bonne propriété d’être vectorisée, et d’utiliser la couche numpy exposée par autograd :
# to compute derivatives
import autograd
import autograd.numpy as npSinon pour les autres dépendances, j’ai utilisé les ipywidgets et bokeh
from math import factorial
from ipywidgets import interact, IntSlider, Layoutfrom bokeh.plotting import figure, show
from bokeh.io import push_notebook, output_notebook
output_notebook()la classe Taylor¶
J’ai défini une classe Taylor, je ne vous montre pas encore le code, je vais vous inviter à en écrire une vous même; nous allons voir tout de suite comment l’utiliser, mais pour la voir fonctionner il vous faut l’évaluer :
↓↓↓↓↓ ↓↓↓↓↓ assurez-vous de bien évaluer la cellule cachée ici ↓↓↓↓↓ ↓↓↓↓↓
↑↑↑↑↑ ↑↑↑↑↑ assurez-vous de bien évaluer la cellule cachée ici ↑↑↑↑↑ ↑↑↑↑↑
# check the code was properly loaded
help(Taylor)Help on class Taylor in module __main__:
class Taylor(builtins.object)
| Taylor(function, domain)
|
| provides an animated view of Taylor approximation
| where one can change the degree interactively
|
| Taylor is applied on X=0, translate as needed
|
| Methods defined here:
|
| __init__(self, function, domain)
| Initialize self. See help(type(self)) for accurate signature.
|
| display(self, y_range)
| create initial drawing with degree=0
|
| Parameters:
| y_range: a (ymin, ymax) tuple
| for the animation to run smoothly, we need to display
| all Taylor degrees with a fixed y-axis range
|
| interact(self, degree_widget)
| Parameters:
| degree_widget: a ipywidget, typically an IntSlider
| styled at your convenience
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables
|
| __weakref__
| list of weak references to the object
sinus¶
Ma classe Taylor s’utilise comme ceci : d’abord on crée une instance à partir d’une fonction
et d’un domaine, i.e. l’intervalle des X qui nous intéresse.
# between -4π and 4π
DOMAIN = np.linspace(-4*np.pi, 4*np.pi, 250)
# an instance
sinus_animator = Taylor(np.sin, DOMAIN)Remarquez bien qu’ici la fonction que je passe au constructeur est en réalité autograd.numpy.sin et non pas numpy.sin, vu la façon dont on a défini notre symbole np lors des imports (et ça ne marcherait pas du tout avec numpy.sin).
Ensuite on crée un ipywidget qui va nous permettre de choisir le degré ; dans le cas de sinus, qui est impaire, les degrés intéressants sont impairs (les coefficients de Taylor pairs sont trivialement nuls lorsque est impaire).
# the widget to select a degree
sinus_widget = IntSlider(
min=1, max=33, step=2, # sinus being odd we skip even degrees
layout=Layout(width='100%')) # more convenient with the whole page widthPour lancer l’interaction, on n’a plus qu’à :
afficher le diagramme avec la méthode
display(); on a besoin pour cela de préciser les bornes en Y, qui resteront constantes au cours de l’animation (sinon la visualisation est vilaine)
puis lancer l’interaction en passant en paramètre le widget qui choisit le degré, ce qui donne :
# fixed limits in Y
sinus_animator.display((-1.5, 1.5))
sinus_animator.interact(sinus_widget)cosinus¶
La même chose avec cosinus nous donnerait ceci :
# allows to select a degree
sinus_widget = IntSlider(
min=0, max=34, step=2, # only even degrees
layout=Layout(width='100%'))
### ready to go
sinus_animator = Taylor(np.cos, DOMAIN)
sinus_animator.display((-1.5, 1.5))
sinus_animator.interact(sinus_widget)exponentielle¶
# allows to select a degree
exp_widget = IntSlider(min=0, max=17,
layout=Layout(width='100%'))
### ready to go
exp_animator = Taylor(np.exp, np.linspace(-2, 10, 200))
exp_animator.display((-15_000, 25000))
exp_animator.interact(exp_widget)quelques indices¶
affichage¶
Ici j’ai utilisé bokeh, mais on peut tout à fait arriver à quelque chose de similaire avec matplotlib sans aucun doute
conception¶
Ma classe Taylor s’inspire très exactement de la technique décrite dans le Complément #6 “Autres bibliothèques de visualisation”, et notamment la classe Animation, modulo quelques renommages.
calcul de dérivées avec autograd¶
La seule fonction que j’ai utilisée de la bibliothèque autograd est grad :
from autograd import grad# dans le cas de sinus par exemple
# les dérivées successives en 0 se retrouvent comme ceci
f = np.sin # à nouveau cette fonction est autograd.numpy.sin
f(0.)np.float64(0.0)# ordre 1
f1 = grad(f)
f1(0.)np.float64(1.0)# ordre 2
f2 = grad(f1)
f2(0.)np.float64(-0.0)votre implémentation¶
Je vous invite à écrire votre propre implémentation, qui se comporte en gros comme notre classe Taylor.
Vous pouvez naturellement simplifier autant que vous le souhaitez, ou modifier la signature comme vous le sentez (pensez alors à modifier aussi la cellule de test).
À titre indicatif ma classe Taylor fait environ 30 lignes de code utile, i.e. sans compter les lignes blanches, les docstrings et les commentaires.
# à vous de jouer
class MyTaylor:
def __init__(self, function, domain):
...
def display(self, y_range):
# là on veut créer le dessin original, c'est à dire
# la figure, la courbe de f qui ne chagera plus,
# et la courbe approchée avec disons n=0 (donc y=f(0))
...
def _update(self, n):
# modifier la courbe approximative avec Taylor à l'ordre n
# je vous recommande de créer cette méthode privée
# pour pouvoir l'appeler dans interact()
...
def interact(self, widget):
# là clairement il va y avoir un appel à
# interact() de ipywidgets
print("inactive for now")# testing MyTaylor on cosinus
sinus_widget = IntSlider(
min=0, max=34, step=2, # only even degrees
layout=Layout(width='100%'))
### ready to go
sinus_animator = MyTaylor(np.cos, DOMAIN)
sinus_animator.display((-1.5, 1.5))
sinus_animator.interact(sinus_widget)inactive for now