diff --git a/web/content/am/AE-Animation_oldTP.md b/web/content/am/AE-Animation_oldTP.md
new file mode 100644
index 0000000000000000000000000000000000000000..4ef11599bae37af86510677eaefad7c872ddaa22
--- /dev/null
+++ b/web/content/am/AE-Animation_oldTP.md
@@ -0,0 +1,191 @@
+==== Partie (III) Animation et DL ====
+
+Une vidéo courte expliquant quelques principes pour le TP :
+
+<iframe width="560" height="315" src="//www.youtube.com/embed/ZXjhquKAfVs" frameborder="0" allowfullscreen></iframe>
+
+  
+  
+
+[Fast Neural Style Transfer for Motion
+Data](http://www.ipab.inf.ed.ac.uk/cgvu/cga2017.pdf), Holden etal, 2017.
+Le papier qui propose une approche équivalente pour transférer le style
+d'une animation vers une autre. Le contenu est le geste et le style est
+l'effet donné dans le geste en relation avec l'état émotionnel, la
+personnalité ou les caractéristiques physiques particulières (ages,
+force, etc.). Ce Tp se propose de coder une version simplifiée de ce
+papier. Nous ferons, comme pour les images précédemment, une
+optimisation. Le papier original propose d'entrainer un réseau à faire
+ce travail, ce qui serait plus efficace une fois le réseau entrainé mais
+qui demanderait plusieurs heures de calculs. Pour ce TP l'optimisation
+ne prendra que quelques minutes, mais ne fournira un transfert qu'entre
+2 animations.
+
+  
+  
+
+-   [Le code de départ est à télécharger
+    ici.](https://perso.liris.cnrs.fr/alexandre.meyer/teaching/master_charanim/download/StyleTransfer.zip)
+
+<!-- -->
+
+-   Il faut installer un peu plus de lib que pour pytorch. Panda3D,
+    pyglm, etc. sont nécessaires pour la visualisation des animations.
+    Vous pouvez sûrement pouvoir installer un env avec le fichier .yml
+    fournit
+
+<!-- -->
+
+    conda env create -f environment.yml
+
+Ou alors un environnement neuf :
+
+    conda create --name py-deepan python=3.8
+    conda activate py-deepan
+
+    conda install numpy
+    conda install pillow
+    conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch    (mais allez voir la page de pytorch)
+    conda install multipledispatch
+    pip install panda3d                   (==1.10.7)
+    pip install torchsummary
+    pip install PyGLM
+
+  
+
+     * Vous devez installer le code comme un package pour que les 'import' trouve les fichiers :
+
+    cd ....StyleTransfer
+    pip install -e .
+
+  
+
+     * En cas de problème pour trouver les données=le chemin vers data (et seulement en cas de problème). Il faut modifier dans pydeepan/__init__.py la variable tout à la fin après le dernier "else":
+
+    else:
+       dir_resources = dir_pydeepan+"/data"                      # mettez le chemin absolu???
+
+  
+
+-   Le programme principal à lancer est
+    **pydeepan/demo/StyleTransferDemo.py**.
+
+<!-- -->
+
+       * 'z' (dés)active l'animation
+       * 'n' : joue la frame suivante d'une animation
+       * 'b' : joue la frame précédente d'une animation
+       * 'p' : passe aux animations suivantes (en restant dans le même dataset)
+       * 'd' : change de dataset (il y en a deux : StyleTransfer et Emilya)
+       * 'l' : lance l'optimisation sur les longueurs de membres
+       * 'e' : passe les animations dans l'auto-encodeur
+       * 't' : transfert le style d'une animation vers une autre (le code est à compléter)
+
+  
+
+-   Une animation est représentée par un tableau de 240 frames x 73
+    valeurs. Voir le fichier HPAAnimation.py pour une description
+    détaillée des 73 valeurs. Dans ce TP nous n'utilisons que les
+    valeurs de 0 à 65 qui représentent les positions 3D de chaque
+    articulation. Il n'y a pas de notion d'angles dans ce format
+    d'animations. Déplacer une articulation revient souvent à changer la
+    longueur d'un membre. Il y a une optimisation (touche 'l' et class
+    AOSkeletonConstraint.py) qui effectue une descente de gradient
+    (pytorch) pour "remettre" les longueurs de membre aux valeurs
+    initiales.
+
+  
+
+-   Remarque : l'autoencoder de ce code est très basique. Il introduit
+    des tremblements pour certaines animations. Il y a surement moyen de
+    faire mieux.
+
+  
+  
+
+##### Tester l'auto-encodeur
+
+Ajouter une action liée à la touche 'r' qui "casse" une animation pour
+une ou deux articulations (par exemple figer épaule+coude). Puis vous
+pourrez tester le passage dans l'auto-encoder avec la touche 'e'
+(e=encodeur). Testez également l'optimisation sur les longueurs de
+membres. Regardez dans le fichier "HPAAnimation.py" pour une description
+des articulations.
+
+          # 42 = coord X de l'épaule gauche. ':' signifie toutes les valeurs. np.mean calcule la moyenne.
+          self.anims[:,42] = np.mean( self.anims[:,42] )+ 2   
+
+Vous pouvez également ajouter de l'aléatoire sur certaines
+articulations. Pas sur toutes en même temps, l'auto-encodeur n'est pas
+si fort.
+
+  
+  
+
+##### Interpolation dans l'espace caché (espace latent)
+
+-   Faites l'interpolation entre l'animation 1 et l'animation 2 dans
+    l'espace 3D, ranger le résultat dans l'animation 3.
+-   Faites l'interpolation entre l'animation 1 et l'animation 2 dans
+    l'espace latent (l'espace de l'ato-encodeur), ranger le résultat
+    dans l'animation 4.
+
+<!-- -->
+
+-   Comparez les 2 résultats.
+
+  
+
+##### Transfert de style
+
+Comme pour les images, l'objectif est de produire une nouvelle animation
+par optimisation de toutes les positions pour toutes les frames. Donc
+d'optimiser les 240x73 valeurs. Le code à trou réalisant l'optimisation
+pour transférer le style est dans **pydeepan/chara/AOStyleTransfer.py**.
+Vous devez compléter les fonctions 'optimize', 'loss' et 'gram'.
+
+  
+
+-   Essayer déjà de partir d'un tableau/animation random est d'optimiser
+    pour produire une animation ayant le même code que l'animation
+    source (sans s'occuper du style). Dans la fonction 'loss', encoder
+    les deux animations et l'erreur sera la différence au carré des deux
+    codes. Il faut jouer sur le 'learning rate'. A la fin, vous obtenez
+    deux animations très différentes mais qui ont le même code. Un
+    passage dans l'auto-encodeur réduit fortement les différences.
+
+  
+
+-   Ajouter maintenant les infos de style de la 2e animation source dans
+    la fonction 'loss'.
+
+  
+  
+  
+
+## Quelques lectures
+
+  
+
+     * [[http://courty.fr/deep-learning-02-etapes-dun-projet-de-deep-learning/|
+
+Une bonne explication de toutes les étapes nécessaire à un apprentissage
+sont décrites ici.\]\]
+
+  
+Classification d'images avec PyTorch
+
+     * [[https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html|Sur CIFAR pour coder la base]]
+
+  
+Pour aller plus loin :
+
+     * [[https://medium.com/@shun.bu/a-diagrammatic-summary-of-the-deep-learning-architectures-for-computer-vision-applications-cd1ec193d8dc|A diagrammatic summary of the deep learning architectures for computer vision applications ]]
+     * Un article de recherche : [[https://arxiv.org/abs/1409.1556|Very Deep Convolutional Networks for Large-Scale Image Recognition]]
+
+  
+  
+Reconnaissance de caractères
+
+     * [[https://towardsdatascience.com/tutorial-alphabet-recognition-deeplearning-opencv-97e697b8fb86|Un tutoriel décrivant les étapes pour la reconnaissance de caractères]].
+     * [[https://github.com/gaurav0651/emnist/blob/master/train_emnist.ipynb|Un exemple de code PyTorch de reconnaissance de caractères]].
diff --git a/web/content/am/TP_Classification.md b/web/content/am/TP_Classification.md
new file mode 100644
index 0000000000000000000000000000000000000000..89d1241251cc89bed07dd1d631a8232af8d934fb
--- /dev/null
+++ b/web/content/am/TP_Classification.md
@@ -0,0 +1,404 @@
+# Partie Classification de points 2D
+
+Un réseau de neurones est un très bon 'classifier'. Dans un exemple simple, nous voudrions reconnaitre la classe d'un point à partir de ses coordonnées 2D notées (x_1, x_2). Un point peut appartenir à 2 classes : classe 1 par exemple en bleu ou classe 2 par exemple en vert. Le réseau prend en entrée 2 valeurs (x_1, x_2) et sort 2 valeurs (suis-je_bleu?, suis-je_vert?). "suis-je_bleu?" sera représenté par un nombre réel entre 0 et 1 : proche de 0 indiquant que le point n’appartient pas à la classe, proche de 1 indiquant que le point appartient à la classe. Par exemple, une sortie \[0.3, 0.7\] sera tranché en "c'est un point de la classe 2".
+
+  
+L'entrainement du réseau consistera à lui montrer toute une série de coordonnées de points avec les valeurs de classes associées. Le réseau va optimiser ses paramètres (poids) pour que le taux d'erreur devienne le plus petit possible.
+
+  
+
+## Un neurone
+
+Un neurone artificiel (ou un perceptron) reçoit des valeurs d’entrées, il les multiplie une à une par un poids, puis en fait la somme. Cette
+somme est passée à une fonction d'activation. Par exemple une fonction d'activation très simple peut-être de comparer la somme à un seuil. Si
+elle est inférieure, la valeur de sortie sera 0, 1 sinon. L’objectif de l’apprentissage/optimisation est de retrouver les poids qui ferons correspondre au mieux la sortie à partir des entrées sur une base de connaissance disponible.
+
+<img src="//neurone.png" class="align-center" width="400" />
+
+  
+
+## Un réseau
+
+Le principe du réseau de neurones est d’assembler entre-eux des neurones, pour leur faire apprendre des tâches complexes. Les neurones
+vont être regroupés en couches, une couche réalisant une tâche donnant un niveau d’abstraction supplémentaire pour la couche suivante. Par
+exemple, pour reconnaître une lettre, la couche la plus basse va repérer des morceaux de courbes et la couche supérieure estime que certaines
+courbes ensembles forme un 'A' et non un 'S'. L’utilisation de plusieurs couches (layer en anglais) est appelée apprentissage profond/Deep Learning. <img src="//dl_layer.png" class="align-center" width="400" />
+
+  
+[Voir une explication plus détaillé sur Wikipedia par exemple.](https://fr.wikipedia.org/wiki/R%C3%A9seau_de_neurones_artificiels)
+
+  
+Dans un 1er temps, allez jouer sur le web avec ["Playground classifier"](https://playground.tensorflow.org/) pour comprendre le principe de la classification de points avec un réseau de neurones profond.
+
+  
+<img src="//playground_dl.jpg" class="align-center" width="500" />
+
+  
+  
+Dans un 2e temps vous allez écrire votre classifier de points avec PyTorch.
+
+  
+  
+
+  
+  
+
+#### Les données
+
+Pour notre problème de reconnaitre la couleur d'un point, il faut des données d'apprentissage. [Le code de départ est donné ici](https://github.com/ucacaxm/DeepLearning_Vision_SimpleExamples/blob/master/src/classifier/classifier_pointcloud_empty.py).
+Ce code génère des points (les données) procéduralement, donc autant que l'on veut. La classe bleu sont les points dont les coordonnées sont inférieures à cosinus, et la classe verte sont les points au dessus de cosinus. Dans un "vrai" problème, ces données ne peuvent se générer, il faut les trouver quelque part ...
+
+<img src="//point_cloud.jpg" class="align-center" width="400" />
+
+  
+  
+** L'apprentissage **
+
+L'apprentissage se passe en différentes phases.
+     * La définition du réseau.
+     * La configuration de l'optimisation (optimizer), en général [[https://fr.wikipedia.org/wiki/Algorithme_du_gradient_stochastique Stochastic Gradient Descent]] couplé à une fonction d'erreur.
+     * La phase d'entrainement optimise les poids de chaque neurone à partir des données d'entrée couplées à leur sortie. La fonction d'erreur sert de mesure à faire descendre.
+     * Une phase d'évaluation **avec des données que le réseau n'a jamais vu** pour mesurer la qualité de l'apprentissage.
+
+Le code ci-dessous donne un réseau minimaliste. Vous devrez l'améliorer pour qu'il soit plus efficace.
+```
+      # voir le code de départ : https://github.com/ucacaxm/DeepLearning_Vision_SimpleExamples/blob/master/src/classifier/classifier_pointcloud_empty.py
+
+        ########################################################################################"
+        # Copier/coller juste avant main
+        class Net(nn.Module):
+           def __init__(self):
+               super(Net, self).__init__()
+               self.fc1 = nn.Linear(2, 64)
+               self.fc2 = nn.Linear(64, 2)
+
+           def forward(self, x):
+              x = F.relu(self.fc1(x))
+              x = self.fc2(x)
+              return x
+
+
+
+        ########################################################################################"
+        ############# NETWORK definition/configuration => à copier/coller dans le main 
+        net = Net()
+        print(net)
+
+        ############# SGD config: Stochastic Gradient Descent Config
+        criterion = nn.CrossEntropyLoss()
+        optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
+
+        ############ TRAINNING
+        for epoch in range(5):  # loop over the dataset multiple times
+            running_loss = 0.0
+            for i in range(1000):         # iterate on mini batches. mani-batch = a subset of the database
+                inputs, labels = next_batch(128)
+                inputs = torch.from_numpy(inputs)
+                labels = torch.from_numpy(labels).long()
+               
+                # zero the parameter gradients
+                optimizer.zero_grad()
+        
+                # forward + backward + optimize
+                outputs = net(inputs)
+                loss = criterion(outputs, torch.max(labels, 1)[1] )
+                loss.backward()
+                optimizer.step()
+
+                # print statistics
+                running_loss += loss.item()
+                if i % 100 == 99:    # print every 2000 mini-batches
+                    print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))
+                    running_loss = 0.0      
+
+
+        ############ EVALUATION         
+        TODO
+        
+        ############ DRAWING POINT CLOUD WITH ERROR
+        TODO
+```
+
+[Regardez la page des tutos de PyTorch](https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py).
+
+  
+  
+
+#### Le résultat
+
+Le résultat sera le taux de bonne reconnaissance de points, mesuré avec des points jamais observés pendant l'apprentissage. Par exemple après un apprentissage nous obtenons un taux de 96% de bonne classification, les points rouges sur l'image suivante sont les points mal classifiés.
+
+<img src="//point_cloud_errorclassif.jpg" class="align-center" width="400" />
+
+  
+  
+Pour rendre le problème un peu plus dur vous pouvez augmenter la plage de génération des points en changeant ceci :
+```
+    x = np.array( [ 2.0*3.141592*np.random.ranf(), 2.0*np.random.ranf()-1 ])
+    devient
+    x = np.array( [ 4.0*3.141592*np.random.ranf(), 2.0*np.random.ranf()-1 ])
+```
+
+<img src="//point_cloud_4pi.jpg" class="align-center" width="400" />  
+  
+  
+
+### Partie (I.b) Classification d'images
+
+Pour ce 2e problème un peu plus concret, nous disposons d'images et nous voudrions reconnaitre la classe à laquelle elles appartiennent. Par
+exemple, pour reconnaitre le nombre à partir de l'image du nombre écrit ou reconnaitre la figure géométrique à partir d'un dessin, ou plus largement reconnaitre une famille d'objets (chat, voiture, avion, fourchette, etc.).
+
+  
+Pour ce type de tâche , le réseau approprié est le ConvNET ou CNN : Convolution Neural Network. Vous pouvez lire des explications sur ce qu'est un CNN :
+
+     * [[https://medium.com/@CharlesCrouspeyre/comment-les-r%C3%A9seaux-de-neurones-%C3%A0-convolution-fonctionnent-b288519dbcf8|Plutôt vulgarisation]]
+     * [[https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/|Explication intuitive]]
+
+<img src="/convnet.png" class="align-center" width="600" />
+
+  
+Pour ce TP, nous vous invitons à utiliser [une base de données d'images issue d'un projet de L3 qui cherche à reconnaitre 5 formes dessinés](https://github.com/ucacaxm/DeepLearning_Vision_SimpleExamples/blob/master/data/shapes5_preprocessed.zip) : carré, cercle, triangle, sablier, étoile. Il y a que quelques centaines d'images par forme, c'est un bon challenge de voir ce que la reconnaissance donne avec finalement assez peu d'images. Il est également intéressant d'augmenter les données. Dans le cas d'images comme ici, vous pouvez faire de petites rotations aléatoires aux images pour en augmenter le nombre.
+
+  
+Il est également possible d'utiliser différentes base de données plus classiques :
+
+      * MNIST : un base de donnée de chiffre manuscrits
+      * la base de données de caractères [[https://www.nist.gov/itl/iad/image-group/emnist-dataset|EMNIST]]. Elle est disponible également [[https://s3.amazonaws.com/nist-srd/SD19/by_merge.zip|ici avec les images rangées dans un répertoire dont le nom est le code ascii en hexa]]. 
+      * Toutes les bases classiques de reconnaissance de catégorie d'images: [[https://www.cs.toronto.edu/~kriz/cifar.html|CIFAR-10 ou CIFAR-100]]
+      * Un peu plus de challenge avec "[[https://www.kaggle.com/c/quickdraw-doodle-recognition/data|quickdraw-doodle-recognition]]" : une base de dessins manuels à reconnaitre, 300 classes, 73 Go de données vectoriels et $12000 de récompense ...
+
+  
+  
+Un exemple de code qui charge une base d'images, voir également la doc de [imagefolder](https://pytorch.org/docs/stable/torchvision/datasets.html#imagefolder) et de [DataLoader](https://pytorch.org/docs/stable/data.html#) :
+```
+    from torchvision import datasets, transforms
+    from torch.autograd import Variable
+    import torchvision
+    from torchvision.datasets import ImageFolder
+    from torch.utils.data import DataLoader
+    from torchvision.transforms import ToTensor
+    from torch.utils.data.sampler import SubsetRandomSampler
+
+
+    class MyTransform(object):    # Votre propre fonction de transfo d'images utilisée en preprocessing
+        def __call__(self, x):
+            y = preprocess(x)
+            return y
+
+
+
+    def imshow(img):              # Pour afficher une image
+        plt.figure(1)
+        img = img / 2.0 + 0.5     # unnormalize
+        npimg = img.numpy()
+        plt.imshow(np.transpose(npimg, (1, 2, 0)))
+        #plt.imshow(npimg)
+        plt.show()
+
+
+            
+        TRANSFORM_IMG = transforms.Compose([
+                MyTransform(),    # Votre propre fonction de transfo d'images utilisée en preprocessing
+                transforms.Resize(16),
+                #transforms.CenterCrop(256),
+                transforms.ToTensor(),
+                transforms.Normalize(mean=[0., 0., 0.],
+                                     std=[0.5, 0.5, 0.5] )
+                ])
+        mydata = ImageFolder(root="../data/shapes5_preprocessed", transform=TRANSFORM_IMG)
+        loader = DataLoader(mydata, batch_size=32, shuffle=True, num_workers=2)
+
+```
+  
+
+* [[https://github.com/ncullen93/torchsample/blob/master/examples/Transforms%20with%20Pytorch%20and%20Torchsample.ipynb|Un très bon tutoriel sur le chargement de données avec PyTorch]]
+
+  
+  
+Il est intéressant de voir que chaque couche de convolutions devient de plus en plus spécifiques à l'objet :
+<img src="//dl_cnn_progression.png" class="align-center" width="600" />  
+  
+
+
+### Partie (II) Une application pratique des réseaux : transfert de style entre images
+
+  
+Ce TP vise à implémenter avec PyTorch le transfert de style d'une image à une autre en suivant un papier de Gatys etal présenté à CVPR 2016 :
+[Image Style Transfer Using Convolutional Neural Networks](https://www.cv-foundation.org/openaccess/content_cvpr_2016/html/Gatys_Image_Style_Transfer_CVPR_2016_paper.html). Ce n'est pas foncièrement un papier de deep learning et dispose de
+nombreux atouts pour un TP en image : utilisation d'un réseau pré-entrainé comme un outil, utilisation du framework de DL/PyTorch pour l'optimisation, code compact et résultats visuels et "rigolo".
+
+  
+[Le code vide peut se trouver ici](https://github.com/ucacaxm/DeepLearning_Vision_SimpleExamples/blob/master/src/style_transfer/StyleTransfer_empty.py).
+
+*   [une image de contenu](https://raw.githubusercontent.com/ucacaxm/DeepLearning_Vision_SimpleExamples/master/src/style_transfer/images/montagne_small.jpg)
+*   [une image de style](https://raw.githubusercontent.com/ucacaxm/DeepLearning_Vision_SimpleExamples/master/src/style_transfer/images/peinture1_small.jpg)
+
+Le programme commence par 3 fonctions pour charger et convertir une image :
+
+* //load_image// pour redimensionner et normaliser avec la moyenne/écart type de VGG19; 
+* //im_convert// de conversion d'un Tensor en une image Numpy ;
+* imshow pour visualiser une image sortant de //im_convert//.
+
+```
+    from PIL import Image
+    import matplotlib.pyplot as plt
+    import numpy as np
+
+    import torch
+    import torch.optim as optim
+    from torchvision import transforms, models
+
+
+
+    def load_image(img_path, max_size=400, shape=None):
+        ''' Load in and transform an image, making sure the image is <= 400 pixels in the x-y dims.'''
+        
+        image = Image.open(img_path).convert('RGB')
+        
+        # large images will slow down processing
+        if max(image.size) > max_size:
+            size = max_size
+        else:
+            size = max(image.size)
+        
+        if shape is not None:
+            size = shape
+            
+        in_transform = transforms.Compose([
+                            transforms.Resize(size),
+                            transforms.ToTensor(),
+                            transforms.Normalize((0.485, 0.456, 0.406), 
+                                                 (0.229, 0.224, 0.225))])
+
+        # discard the transparent, alpha channel (that's the :3) and add the batch dimension
+        image = in_transform(image)[:3,:,:].unsqueeze(0)
+        
+        return image
+
+
+
+    # helper function for un-normalizing an image and converting it from a Tensor image to a NumPy image for display
+    def im_convert(tensor):
+        image = tensor.to("cpu").clone().detach()
+        image = image.numpy().squeeze()
+        image = image.transpose(1,2,0)
+        image = image * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406))
+        image = image.clip(0, 1)
+        return image
+
+
+    def imshow(img):              # Pour afficher une image
+        plt.figure(1)
+        plt.imshow(img)
+        plt.show()
+
+
+    if __name__ == '__main__':
+        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+        #device = torch.device("cpu")
+        print(device)
+
+        ########################## DISPLAY IMAGE#########################################################""
+        content = load_image('images/mer.jpg').to(device)
+        style = load_image('images/peinture1.jpg', shape=content.shape[-2:]).to(device)
+
+        imshow(im_convert(content))
+        imshow(im_convert(style))
+```
+  
+  
+Nous allons réutiliser un réseau VGG déjà entrainé. [VGG est un réseau qui combine les convolutions afin d'être efficace pour de la reconnaissance d'images](http://www.robots.ox.ac.uk/~vgg/research/very_deep/) (ImageNet Challenge). Quand nous allons optimiser le transfert de style, nous ne voulons plus optimiser les couches du réseau VGG. Ceci se réalise en passant à False le besoin en gradient des paramètres. Vous pouvez donc charger le réseaux avec PyTorch comme ceci, neutraliser les couches et afficher toutes les couches comme ceci :  
+```
+        vgg = models.vgg19(pretrained=True).features
+
+        # freeze all VGG parameters since we're only optimizing the target image
+        for param in vgg.parameters():
+            param.requires_grad_(False)
+
+        features = list(vgg)[:23]
+        for i,layer in enumerate(features):
+            print(i,"   ",layer)
+```
+  
+  
+
+Pour récupérer les caractéristiques intermédiaires d'une image qui passe dans un réseau VGG vous pouvez le faire comme ceci :
+```
+### Run an image forward through a model and get the features for a set of layers. 'model' is supposed to be vgg19
+def get_features(image, model, layers=None):  
+    if layers is None:
+        layers = {'0': 'conv0',
+                  '5': 'conv5', 
+                  '10': 'conv10', 
+                  '19': 'conv19',   ## content representation
+                  }
+        
+    features = {}
+    x = image
+    # model._modules is a dictionary holding each module in the model
+    for name, layer in model._modules.items():
+        x = layer(x)
+        if name in layers:
+            features[layers[name]] = x
+            
+    return features
+```
+  
+  
+Nous allons maintenant créer l'image cible qui va être une copie de l'image de contenu et dont les pixels seront à optimiser :
+```
+        target = content.clone().requires_grad_(True).to(device)
+```
+  
+  
+
+Vous devez écrire la fonction *gram_matrix* qui calcule la [matrice de Gram](https://en.wikipedia.org/wiki/Gramian_matrix) à partir d'un
+tensor. Vous pouvez regarder la documentation de la fonction [torch.mm](https://pytorch.org/docs/stable/torch.html#torch.mm) qui
+multiplie deux matrices, et la fonction [torch.transpose](https://pytorch.org/docs/stable/torch.html#torch.transpose).
+La fonction [torch.Tensor.view](https://pytorch.org/docs/stable/tensors.html#torch.Tensor.view) permet de changer la "vue" pour par exemple passer d'un tenseur 2D à un tenseur 1D, ou d'un 3D vers un 2D, etc.
+```
+    def gram_matrix(tensor):
+       # tensor: Nfeatures x H x W ==> M = Nfeatures x Npixels with Npixel=HxW
+       ...
+       return gram
+```
+  
+  
+Écrivez le calcul de coût pour le contenu. Vous pouvez utiliser \[\[\|torch.mean\]\] avec les features extraits de la couche 'conv19'
+qui d'après l'article correspondent globalement au contenu. Attention, les noms de couches ne correspondent pas à l'article.
+
+  
+Écrivez le calcul du coût pour le style. Il va se calculer de la même manière mais vous allez itérer sur les features des autres couches. A tester un peu par essai/erreur (ou regardez l'article).
+
+  
+Le coût total (celui qui sera optimisé) se calcule en faisant la moyenne pondérée entre le coût de style et le coût de contenu. A tester un peu par essai/erreur (ou regardez l'article).
+
+  
+La partie optimisation va donc ressembler à ceci.
+```
+        optimizer = optim.Adam([target], lr=0.003)
+        for i in range(50):
+        
+            # get the features from your target image
+        
+            # the content loss
+        
+            # the style loss
+            
+            # calculate the *total* loss
+        
+            # update your target image
+            optimizer.zero_grad()
+            total_loss.backward()
+            optimizer.step()
+```
+  
+  
+
+#### Pour aller plus loin sur le transfert de style entre images
+
+[Un blog qui décrit bien les évolutions de la recherche après l'approche de Gatys](https://dudeperf3ct.github.io/style/transfer/2018/12/23/Magic-of-Style-Transfer/). Donne des explications également autour des approches de normalisation, AdaIN.
+
+  
+  
+  
diff --git a/web/content/am/_index.md b/web/content/am/_index.md
index f72e9fcacd6ce22f1815dc7eccb8605479faa1aa..6b5269e7add40e9c4a8c5efbc4fbd9947651b340 100644
--- a/web/content/am/_index.md
+++ b/web/content/am/_index.md
@@ -6,13 +6,32 @@ description: "Partie A. Meyer"
 
 
 
-# Partie Les base du Deep Learning pour l'image
-  * Alexandre Meyer
+**ATTENTION DRAFT**
+
+
+# Les base du Deep Learning pour l'image
+  * [Alexandre Meyer](https://perso.liris.cnrs.fr/alexandre.meyer)
   * [L'ancienne page de cette partie](https://perso.liris.cnrs.fr/alexandre.meyer/public_html/www/doku.php?id=image_deeplearning)
 
 
-## Cours
+  
+
+## Le Cours
+
+-   \*\* [Les transparents du cours](https://perso.liris.cnrs.fr/alexandre.meyer/teaching/master_charanim/aPDF_COURS_M2/M2_6_DeepLearning_Images.pdf)
+    \*\*
+
+  
+
+<!---
+-   La vidéo du CM de la 1ère partie : TODO
+-   La vidéo du CM de la 2e partie
+<iframe width="560" height="315" src="//www.youtube.com/embed/ge7V2C7eVWk" frameborder="0" allowfullscreen></iframe>
+-->
+  
+  
+  
 
-## Les vidéos des CM (2020)
+## Les TP
+* (Installation)[install.md]
 
-## Le TP
diff --git a/web/content/am/install.md b/web/content/am/install.md
new file mode 100644
index 0000000000000000000000000000000000000000..00573b20f8cd3c008fb67a022047f60c9694887c
--- /dev/null
+++ b/web/content/am/install.md
@@ -0,0 +1,26 @@
+
+# Installation
+
+
+## Installation de tous les outils de dév en local
+
+Faites les installations de [Anaconda, Numpy, MatPlotlib et PyTorch décrites ici](https://github.com/ucacaxm/DeepLearning_Vision_SimpleExamples). Anaconda est un gestionnaire d’environnements Python. Il vous permet entre autre d'avoir plusieurs installations de Python avec des packages différents sans interférence entre chaque environnement. Si vous avez
+besoin d'un turorial décrivant l'installation de chaque étape en détails, [regardez ici](https://mrmint.fr/installer-environnement-python-machine-learning-anaconda).
+
+  
+  
+Sous windwos lancez "Anaconda navigator" puis lancer une console. Sous Linux, depuis un terminal lancer ```conda activate p36```
+
+  
+Votre code va être écrit en Python. Vous pouvez utiliser par exemple [l'IDE Spyder](https://www.spyder-ide.org/) qui s'installe avec
+Anaconda, ou autre comme [PyCharm](https://www.jetbrains.com/pycharm/) qui est gratuit pour les étudiants. Éventuellement écrire votre dans un éditeur de code puis lancer votre script comme ceci :
+``` python mon_prog.py```
+
+
+
+  
+## Colab
+
+Ou vous pouvez travailler avec
+[Colab/Google](https://colab.research.google.com/). Vous trouverez [un tutoriel ici sur medium](https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d). Colab permet d'écrire et exécuter du code en ligne, possibilité de le
+faire tourner gratuitement sur une Nvidia K80.
diff --git a/web/content/am/tp.md b/web/content/am/tp.md
deleted file mode 100644
index 01928437b3bb1e40dc3abbe33af7a4c43cd5c52e..0000000000000000000000000000000000000000
--- a/web/content/am/tp.md
+++ /dev/null
@@ -1,10 +0,0 @@
-  
-
-# TP
-TODO
-
-  
-  
-
-## TP partie 1
-TODO