Peut-on remplacer un tableau de pixels par une fonction ? Dans ce projet,
vous entraînez un réseau qui reçoit les coordonnées (x, y) d’un pixel et
prédit son intensité. On redessine ensuite l’image en interrogeant cette
fonction. Le souci intéressant sera de représenter ses détails.
Ce TP long est un sujet au choix d’AP9, commencé avec l’enseignant puis poursuivi à la maison. Il prolonge Nx en AP4 et les réseaux d’AP5. Les modalités de notation, la charge attendue et l’échéance seront précisées avant le lancement en janvier ; les étapes ne sont pas un barème.
Téléchargez le squelette image-coordonnees. Son README contient le sujet autonome, les contrats, les indications Nx, les commandes et le dépannage. Trois images originales sont produites localement ; rien n’est à télécharger après les dépendances. L’entraînement, Adam, les sauvegardes et les exports SVG sont fournis. Le socle utilise le CPU et des niveaux de gris ; aucune connaissance HTML, CSS ou JavaScript n’est nécessaire.
Observer une image avant de construire le réseau
Avec Elixir 1.17 ou plus récent, ouvrez un terminal dans le dossier extrait :
mix deps.get
mix picture.preview
mix test --only fourni
Ouvrez results/preview/ondes.svg dans votre éditeur. Le dessin de droite
montre les pixels d’apprentissage, de validation et de test. Les sept tests
des briques fournies passent dès le départ ; ceux des quatre fonctions élèves
signalent « À compléter » jusqu’à leur implémentation.
La fonction apprend une seule image par expérience. Chaque pixel est un exemple, avec deux coordonnées en entrée et une intensité en cible. Les 256 pixels d’une image 16 × 16 sont séparés en 153 pixels d’apprentissage, 51 de validation et 52 de test. Le mélange est fixe et indépendant des intensités ; un pixel n’appartient qu’à une partition.
Relier les coordonnées à une intensité
Le schéma se lit de gauche à droite : un pixel donne deux coordonnées,
ramenées entre 0 et 1, qui traversent deux couches cachées puis une sortie
qui produit son intensité. Vous écrivez normalize/3, predict/2 et mse/2
dans lib/coordinate_image/picture.ex. La première ramène chaque coordonnée
dans [0, 1]. La deuxième applique deux couches denses ReLU puis une
sigmoïde ; rappelons qu’une couche dense calcule entrées × poids + biais,
que la ReLU remplace les valeurs négatives par zéro et que la sigmoïde
ramène toute valeur dans l’intervalle ]0, 1[, ce qui en fait une intensité.
La dernière fonction calcule l’erreur quadratique moyenne (MSE) utilisée pour
l’apprentissage.
| Calcul | Entrée | Résultat |
|---|---|---|
| Normalisation | {N, 2}, largeur et hauteur | {N, 2} ; le bas à droite devient (1, 1). |
| Réseau | {N, D} et les paramètres | {N, 1} ; une intensité par pixel. |
| Perte | Prédictions et cibles de même forme | Un scalaire, moyenne des erreurs au carré. |
Le README rappelle les produits matriciels, le broadcasting et les fonctions Nx utiles. Testez notamment une image rectangulaire : échanger largeur et hauteur serait invisible sur un carré.
mix test --only coordonnees
mix test --only reseau
mix test --only perte
mix picture.train raw --steps 25 --out results/raw-essai
mix picture.train raw --steps 200 --out results/raw-200
Les fichiers comparison.svg et curve.svg montrent la reconstruction et
les mesures pendant l’apprentissage. Les prédictions des pixels de test
restent hachurées jusqu’au choix final du modèle. Les dossiers d’expérience
ne sont pas écrasés ; donnez un nouveau nom à chaque essai.
Ajouter des sinus et des cosinus
Le réseau reçoit d’abord des coordonnées qui varient régulièrement. Pour l’aider à décrire des variations plus rapides, nous allons ajouter des fonctions périodiques à son entrée : des sinus et des cosinus des coordonnées, à plusieurs fréquences. Ce sont des caractéristiques calculées une fois pour toutes, pas des paramètres appris ; le réseau apprend ensuite à les combiner.
Complétez fourier/2. Pour chaque fréquence f, elle calcule les sinus et
cosinus de 2πfx et 2πfy, puis les réunit avec les coordonnées brutes.
Avec F fréquences, on obtient {N, 2 + 4F}. Le README précise l’ordre des
colonnes et guide la manipulation des axes.
mix test --only fourier
mix test --include integration
mix picture.train fourier --steps 200 --out results/fourier-200
Les fréquences par défaut sont 1, 2, 4, soit 14 entrées par pixel. Le réseau
possède alors 985 paramètres, contre 697 avec les coordonnées brutes. Comparez
les mêmes pixels, les mêmes mini-lots (les petits paquets de pixels
d’apprentissage traités à chaque pas) et le même nombre de pas, tout en
signalant cette différence de capacité. La graine conserve une expérience
reproductible, sans rendre identiques des matrices de formes différentes.
Sur le portable M3 de préparation, 200 pas ont pris environ 2 à 3 secondes
par modèle sur CPU, hors compilation. Pour l’image ondes, la MSE de validation
mesurée était d’environ 0,056 avec les coordonnées brutes et 0,0030 avec les
fréquences. Ces valeurs décrivent une expérience du corrigé, pas un seuil à
atteindre. Commencez avec 25 pas pour mesurer le coût sur votre poste.
Expliquer ce que l’expérience démontre
Comparez les courbes, les détails reproduits et les zones encore mal ajustées.
Changez ensuite un seul choix, par ex. les fréquences, et annoncez votre
hypothèse avant l’essai. Le tableau de COMPTE-RENDU.md, fourni dans le
projet, conserve les paramètres, les mesures et les observations. Ajoutez
également un cas de test personnel : un autre rectangle pour la
normalisation, ou un petit réseau dont vous pouvez calculer la sortie à la main.
Après avoir justifié le modèle retenu sur la validation, lancez :
mix picture.evaluate results/fourier-200
La commande recharge les poids, mesure le test et écrit final.svg avec tous
les pixels. Retenez bien que ce sont des pixels laissés de côté dans la même
image. Leur corrélation spatiale et le fait de connaître l’image originale
limitent ce qu’on peut conclure sur une autre image.
Un prolongement permet d’interroger le réseau sur une grille plus fine. Il faudra alors distinguer une interpolation visuellement agréable de la récupération de détails exacts. D’autres prolongements comparent à une image constante, équilibrent les nombres de paramètres ou passent à une image RGB. Le socle reste sur une grille fixe en niveau de gris.
Le dossier results/ est ignoré par Git : copiez les expériences retenues
dans rendu/ et indiquez leurs chemins dans le compte rendu.
Le projet s’inspire des Fourier features de Tancik et al., avec des fréquences fixes sur les deux axes au lieu des projections aléatoires étudiées dans l’article. La lecture de cette référence est facultative. Pour toute question, vous pouvez me contacter par email avec la commande, l’erreur et le plus petit exemple qui reproduit le souci.
Pour les curieux : le fascicule
Un petit fascicule d’approfondissement accompagne ce sujet : les idées derrière le projet, leur histoire, ce qu’elles deviennent dans les systèmes réels et quoi lire ensuite. C’est un cadeau de fin de cours ; rien n’y est à rendre.
