Cette section prepare l’environnement Infer.NET. Le processus gaussien necessite les espaces de noms .Distributions, .Distributions.Kernels (noyaux) et .Math (Vector).
#r "nuget: Microsoft.ML.Probabilistic"#r "nuget: Microsoft.ML.Probabilistic.Compiler"using Microsoft.ML.Probabilistic;using Microsoft.ML.Probabilistic.Distributions;using Microsoft.ML.Probabilistic.Distributions.Kernels;using Microsoft.ML.Probabilistic.Math;using Microsoft.ML.Probabilistic.Models;using Microsoft.ML.Probabilistic.Algorithms;using Microsoft.ML.Probabilistic.Compiler;Console.WriteLine("Infer.NET pret pour les processus gaussiens.");
Installing Packages
Microsoft.ML.Probabilistic
Microsoft.ML.Probabilistic.Compiler
Infer.NET pret pour les processus gaussiens.
Chargement du helper de visualisation des graphes de facteurs (reutilise dans toute la serie).
#load "FactorGraphHelper.cs"if(FactorGraphHelper.IsGraphvizAvailable()) Console.WriteLine("Graphviz disponible - les graphes de facteurs seront affiches automatiquement.");else Console.WriteLine("Graphviz non installe - utilisez viz-js.com pour visualiser les fichiers .gv generes.");
Graphviz disponible - les graphes de facteurs seront affiches automatiquement.
2. Motivation : au-dela de la frontiere lineaire
Infer-9 introduisait le Bayes Point Machine : un classifieur qui marginalise sur tous les hyperplans separateurs. Mais un hyperplan est lineaire dans l’espace des features. Des qu’il faut une frontiere courbe, le BPM est impuissant.
Exemple canonique : le “donut”. Deux classes organisees en cercles concentriques – la classe positive forme un anneau exterieur, la classe negative un disque interieur. Aucune droite (aucun hyperplan) ne peut separer ces deux classes, parce que chaque demi-plan coupe forcement l’une et l’autre.
Approche
Frontiere
Donut
BPM (Infer-9)
Hyperplan
Echec (lineaire)
GP (ce notebook)
Courbe quelconque
Succes (noyau RBF)
Le processus gaussien resout ce problème en placant un prior sur des fonctions : au lieu d’inferer un vecteur de poids \(\mathbf{w}\) (qui définit un hyperplan), on infere une fonction\(f\) tireee d’un processus gaussien, puis on classifie via un modèle probit \(y = \mathbb{1}[f(\mathbf{x}) > 0]\).
3. Un prior sur des fonctions
Un processus gaussien est défini par deux objets :
une fonction moyenne\(m(\mathbf{x})\) (souvent constante, ici nulle) ;
un noyau de covariance\(k(\mathbf{x}, \mathbf{x}')\) qui dit a quel point deux points sont correlles.
Le noyau squared-exponential (RBF) decroche avec la distance :
ou \(\ell\) est la longueur de correlation : deux points proches (\(\|\mathbf{x}-\mathbf{x}'\| \ll \ell\)) ont des valeurs de \(f\) quasi-egales ; deux points eloignes (\(\gg \ell\)) sont decorreles. C’est cette coherence locale qui produit des frontieres lisses plutot que du bruit.
Référence fondatrice. Rasmussen & Williams (2006, Gaussian Processes for Machine Learning, MIT Press, ch.1-3-5) — livre canonique du domaine, présent à toute la série Probabilité/Infer.NET. MacKay (2003, Information Theory, Inference, and Learning Algorithms, Cambridge University Press, ch.45) — présente le GP comme un réseau de neurones de largeur infinie (poids distribués selon une Gaussienne), un éclairage complémentaire pour comprendre pourquoi la longueur de corrélation \(\ell\) joue un rôle analogue à la bandwidth d’un kernel.
// Le prior gaussien sur les fonctions : moyenne nulle + noyau RBF.GaussianProcess gpPrior =newGaussianProcess(newConstantFunction(0),// moyenne m(x) = 0newSquaredExponential(0));// noyau RBF k(x,x') = exp(-||x-x'||^2 / 2)Console.WriteLine("Prior GP defini.");Console.WriteLine($" Moyenne : ConstantFunction(0)");Console.WriteLine($" Noyau : SquaredExponential (RBF)");// Un noyau mesure la similitude entre deux points. La table ci-dessous montre// la covariance RBF entre quelques points du plan -- proche de 1 quand les// points coincident, decroissant vers 0 avec la distance.Vector[] probes ={ Vector.FromArray(0.0,0.0), Vector.FromArray(0.5,0.0), Vector.FromArray(1.0,0.0), Vector.FromArray(2.0,0.0)};Console.WriteLine("\nCovariance RBF depuis l'origine (0,0) :");foreach(var p in probes){double d = Math.Sqrt(p[0]*p[0]+ p[1]*p[1]);double cov = Math.Exp(-0.5* d * d); Console.WriteLine($" vers {p} (distance {d:F2}) : k = {cov:F4}");}
Prior GP defini.
Moyenne : ConstantFunction(0)
Noyau : SquaredExponential (RBF)
Covariance RBF depuis l'origine (0,0) :
vers 0 0 (distance 0,00) : k = 1,0000
vers 0,5 0 (distance 0,50) : k = 0,8825
vers 1 0 (distance 1,00) : k = 0,6065
vers 2 0 (distance 2,00) : k = 0,1353
Lecture : la covariance decroit exponentiellement avec la distance. Un point eloigne de 2 unites est déjà quasi-decorrele de l’origine – ses valeurs de \(f\) sont donc independantes. Cette decroissance est ce qui rend le GP local : la frontiere ne peut pas osciller sauvagement, elle est contrainte par la coherence que le noyau impose.
4. Le dataset “donut” (non lineairement separable)
Construisons les données : un disque interieur (classe negative) entoure d’un anneau (classe positive).
// Dataset "donut" : disque interieur (false) + anneau exterieur (true).// Aucun hyperplan ne separe ces deux classes.var rnd =new System.Random(7);var inputsList =new System.Collections.Generic.List<Vector>();var outputsList =new System.Collections.Generic.List<bool>();// Disque interieur : rayon ~ 0.3-0.6 => classe falsefor(int i =0; i <8; i++){double r =0.30+0.30* rnd.NextDouble();double t =2.0* Math.PI* rnd.NextDouble(); inputsList.Add(Vector.FromArray(r * Math.Cos(t), r * Math.Sin(t))); outputsList.Add(false);}// Anneau exterieur : rayon ~ 1.2-1.5 => classe truefor(int i =0; i <8; i++){double r =1.20+0.30* rnd.NextDouble();double t =2.0* Math.PI* rnd.NextDouble(); inputsList.Add(Vector.FromArray(r * Math.Cos(t), r * Math.Sin(t))); outputsList.Add(true);}Vector[] inputsDonut = inputsList.ToArray();bool[] outputsDonut = outputsList.ToArray();Console.WriteLine($"Dataset donut : {inputsDonut.Length} points");Console.WriteLine($" Classe false (disque interieur) : {outputsDonut.Count(b => !b)} points");Console.WriteLine($" Classe true (anneau exterieur) : {outputsDonut.Count(b => b)} points");Console.WriteLine("\nPremiers points :");for(int i =0; i <4; i++) Console.WriteLine($" x{i} = {inputsDonut[i]} -> classe {outputsDonut[i]}");
Dataset donut : 16 points
Classe false (disque interieur) : 8 points
Classe true (anneau exterieur) : 8 points
Premiers points :
x0 = 0,2864 -0,3002 -> classe False
x1 = 0,4717 0,1607 -> classe False
x2 = -0,1834 -0,3666 -> classe False
x3 = 0,2997 -0,08919 -> classe False
Pourquoi le BPM echouerait ici
Un BPM (Infer-9) cherche un hyperplan \(\mathbf{w}^T\mathbf{x} - b = 0\). Quelle que soit la direction \(\mathbf{w}\), la demi-droite coupe a la fois le disque interieur et l’anneau exterieur : il classera forcement faux une partie des points. La non-separabilite lineaire est totale. C’est précisément le cas ou un GP excelle.
5. Le modèle : classification GP (probit)
On assemble le modèle en suivant le même schelet probit qu’Infer-9, mais en remplacant le score lineaire \(\mathbf{w}^T\mathbf{x}\) par une fonction\(f(\mathbf{x})\) tiree du processus gaussien :
ou \(f\) est un GP sparse (approxime sur un basis set de points induiseurs).
// Modele : classification GP probit sur le donut.// 1. Prior sparse sur la fonction f.Variable<SparseGP> prior = Variable.New<SparseGP>().Named("prior");Variable<IFunction> f = Variable<IFunction>.Random(prior).Named("f");// 2. Observations.VariableArray<Vector> x = Variable.Observed(inputsDonut).Named("x");Range j = x.Range.Named("j");VariableArray<bool> y = Variable.Observed(outputsDonut, j).Named("y");// 3. Modele probit : score = f(x_j), bruite gaussien, seuil a 0.Variable<double> score = Variable.FunctionEvaluate(f, x[j]);y[j]=(Variable.GaussianFromMeanAndVariance(score,0.1)>0);// 4. Prior GP + basis (grille de points induiseurs couvrant le plan).GaussianProcess gp =newGaussianProcess(newConstantFunction(0),newSquaredExponential(0));Vector[] basis =new Vector[]{ Vector.FromArray(-1.5,-1.5), Vector.FromArray(0.0,-1.5), Vector.FromArray(1.5,-1.5), Vector.FromArray(-1.5,0.0), Vector.FromArray(0.0,0.0), Vector.FromArray(1.5,0.0), Vector.FromArray(-1.5,1.5), Vector.FromArray(0.0,1.5), Vector.FromArray(1.5,1.5)};prior.ObservedValue=newSparseGP(newSparseGPFixed(gp, basis));// 5. Inference EP.InferenceEngine engine =newInferenceEngine(newExpectationPropagation());engine.Compiler.CompilerChoice= CompilerChoice.Roslyn;engine.ShowProgress=false;engine.ShowFactorGraph=true;SparseGP sgp = engine.Infer<SparseGP>(f);Console.WriteLine("Posterior SparseGP inferer.");Console.WriteLine($" Basis set : {basis.Length} points induiseurs");
Posterior SparseGP inferer.
Basis set : 9 points induiseurs
// Visualisation du graphe de facteurs du classifieur GP.display(HTML(FactorGraphHelper.GetLatestFactorGraphHtml()));
Model_07_01_26_03_15_19_62.svg
Lecture du graphe
Le graphe de facteurs montre la structure : la variable \(f\) (une fonction, pas un scalaire) est connectee a chaque observation via le facteur FunctionEvaluate. Le prior SparseGP repose \(f\) sur le basis de 9 points. L’EP propage les messages a travers cette chaîne pour produire le posterior sur \(f\).
Origine. Williams & Barber (1998, Bayesian Classification with Gaussian Processes, IEEE PAMI 20(12):1342-1351) — papier fondateur de la classification GP : ils montrent que la formulation probit (signal gaussien → Bernoulli par seuillage) reste tractable via Laplace / EP et l’expriment dans un cadre de programmation probabiliste. Minka (2001, Expectation Propagation for Approximate Bayesian Inference, UAI ’01 362-369) — fondement canonique de l’algorithme d’Expectation Propagation utilisé par Infer.NET ; c’est l’inférence qui propage les messages à travers ce graphe.
6. Predictions avec incertitude
Le posterior SparseGP permet d’evaluer \(f\) en tout nouveau point via Marginal. On peut ainsi tracer la frontiere de decision (la ou \(f\) change de signe) et la confiance (distance a 0).
// Predictions sur le training set + quelques points test.Console.WriteLine("=== Predictions sur le training set ===");int correct =0;for(int i =0; i < outputsDonut.Length; i++){ Gaussian post = sgp.Marginal(inputsDonut[i]);double postMean = post.GetMean();bool pred = postMean >0.0;if(pred == outputsDonut[i]) correct++; Console.WriteLine($" x{i} {inputsDonut[i],20} : f={post,30} pred={pred} reel={outputsDonut[i]}");}Console.WriteLine($"\nExactitude training : {correct}/{outputsDonut.Length} = {100.0*correct/outputsDonut.Length:F1}%");
Lecture des prédictions : le signe de \(f\) encode la classe
Exactitude 16/16 sur un dataset non linéairement séparable. C’est précisément le cas où le GP justifie son emploi : un BPM (Infer-9) aurait échoué (cf. §4), incapable de tracer un hyperplan entre le disque et l’anneau. Le GP, lui, apprend une fonction \(f(\mathbf{x})\) dont le signe sépare les deux régions :
Région
Points
\(E[f]\)
Prédiction
Classe réelle
Disque intérieur (\(r \approx 0{,}3\)–\(0{,}6\))
x0–x7
\(-0{,}46\) à \(-0{,}82\)
False
False ✓
Anneau extérieur (\(r \approx 1{,}2\)–\(1{,}5\))
x8–x15
\(+0{,}38\) à \(+0{,}72\)
True
True ✓
La frontière de décision \(f = 0\) se situe donc entre les deux rayons : le GP a reconstitué la structure annulaire qu’aucun hyperplan ne pouvait séparer.
Chaque prédiction est une Gaussienne, pas un scalaire. C’est la marque du GP par rapport au BPM : le posterior \(f(\mathbf{x}_j) = \mathcal{N}(\mu_j, \sigma_j^2)\) quantifie l’incertitude, pas seulement la classe. Deux observations :
Le disque est plus confiant que l’anneau (\(\sigma^2 \approx 0{,}15\)–\(0{,}25\) contre \(0{,}18\)–\(0{,}40\)). Les points intérieurs sont plus proches des points induiseurs et mieux contraints par leurs voisins.
Le point le moins confiant est x14 (\(E[f] = +0{,}38\), \(\sigma^2 = 0{,}31\)) : sa moyenne est la plus proche de zéro, donc au plus près de la frontière. La variance signale un point à risque — précieux pour l’apprentissage actif ou une décision prudente.
Cette double sortie (classe et incertitude) est la raison d’être du GP : elle rend la frontière exploitable, pas seulement correcte.
// Test sur des points nouveaux : au centre (doit etre false), a mi-rayon (incertain),// sur l'anneau (doit etre true), loin (true).Vector[] testPoints ={ Vector.FromArray(0.0,0.0),// centre du disque -> false attendu Vector.FromArray(0.9,0.0),// entre les deux -> zone d'incertitude Vector.FromArray(1.3,0.0),// anneau -> true attendu Vector.FromArray(0.0,1.4)// anneau (haut) -> true attendu};Console.WriteLine("=== Predictions sur points test ===");foreach(var tp in testPoints){ Gaussian post = sgp.Marginal(tp);double p = MMath.NormalCdf(post.GetMean()/ Math.Sqrt(post.GetVariance()+0.1)); Console.WriteLine($" {tp,16} : E[f]={post.GetMean():+0.000;-0.000} P(classe=true)={p:F3}");}
Le centre du donut est correctement classe false (\(E[f] < 0\)) bien qu’aucune donnee ne soit exactement la – la coherence du noyau propage la classe du disque interieur vers le centre.
La zone d’incertitude (mi-rayon, entre le disque et l’anneau) montre une probabilite proche de 0.5 : le GP sait qu’il ne sait pas.
L’anneau est correctement true.
C’est le comportement que le BPM (lineaire) ne peut pas reproduire : il n’y a pas d’hyperplan qui vaut false au centre et true tout autour. Le GP, lui, a appris une frontiere circulaire.
7. Sparse : le rôle du basis set
Un GP “full” evalue la fonction sur tous les points d’entrainement, ce qui coute \(O(n^3)\). L’approximation sparse remplace ce jeu complet par un petit basis set de \(m\) points induiseurs : le cout tombe a \(O(nm^2)\), controlable par le choix de \(m\).
La doc Infer.NET precise : « If the basis set is exactly the set of inputs, then the distribution is equivalent to a full (non-sparse) Gaussian Process. » Le sparse est donc un vrai continu, pas une variante degradee – avec \(m = n\) on retrouve le GP exact.
Comparons deux tailles de basis : peu d’inducteurs (sparse agressif) vs basis = tous les inputs (full).
Origine sparse GP. Snelson & Ghahramani (2006, Sparse Gaussian Processes using Pseudo-inputs, NeurIPS ’06) — introduisent les pseudo-inputs (points induiseurs virtuels appris par gradient) qui généralisent le choix heuristique d’un basis set. Quinonero-Candela & Rasmussen (2005, A Unifying View of Sparse Approximate Gaussian Process Regression, JMLR 6:1939-1959) — synthèse comparative des différentes approximations sparse (DTC, FITC, VFE) et de leurs biais-variance respectifs. Titsias (2009, Variational Learning of Inducing Variables in Sparse Gaussian Processes, AISTATS ’09) — reformule le problème en inference variationnelle sur les inducing variables (lower bound ELBO), fondant l’approche variationnelle sparse qui domine le domaine depuis.
// Comparaison : basis sparse (4 points) vs basis = tous les inputs (full).Vector[] basisSparse =new Vector[]{ Vector.FromArray(0.0,0.0), Vector.FromArray(1.3,0.0), Vector.FromArray(-1.3,0.0), Vector.FromArray(0.0,1.3)};GaussianProcess gp2 =newGaussianProcess(newConstantFunction(0),newSquaredExponential(0));// (a) Sparse avec peu de points induiseurs.Variable<SparseGP> priorSparse = Variable.New<SparseGP>().Named("priorSparse");Variable<IFunction> fSparse = Variable<IFunction>.Random(priorSparse).Named("fSparse");VariableArray<Vector> xS = Variable.Observed(inputsDonut).Named("xS");Range jS = xS.Range.Named("jS");VariableArray<bool> yS = Variable.Observed(outputsDonut, jS).Named("yS");Variable<double> scoreS = Variable.FunctionEvaluate(fSparse, xS[jS]);yS[jS]=(Variable.GaussianFromMeanAndVariance(scoreS,0.1)>0);priorSparse.ObservedValue=newSparseGP(newSparseGPFixed(gp2, basisSparse));var engSparse =newInferenceEngine(newExpectationPropagation());engSparse.Compiler.CompilerChoice= CompilerChoice.Roslyn;engSparse.ShowProgress=false;SparseGP sgpSparse = engSparse.Infer<SparseGP>(fSparse);// (b) "Full" : basis = tous les inputs (n = 16).Variable<SparseGP> priorFull = Variable.New<SparseGP>().Named("priorFull");Variable<IFunction> fFull = Variable<IFunction>.Random(priorFull).Named("fFull");VariableArray<Vector> xF = Variable.Observed(inputsDonut).Named("xF");Range jF = xF.Range.Named("jF");VariableArray<bool> yF = Variable.Observed(outputsDonut, jF).Named("yF");Variable<double> scoreF = Variable.FunctionEvaluate(fFull, xF[jF]);yF[jF]=(Variable.GaussianFromMeanAndVariance(scoreF,0.1)>0);priorFull.ObservedValue=newSparseGP(newSparseGPFixed(gp2, inputsDonut));var engFull =newInferenceEngine(newExpectationPropagation());engFull.Compiler.CompilerChoice= CompilerChoice.Roslyn;engFull.ShowProgress=false;SparseGP sgpFull = engFull.Infer<SparseGP>(fFull);// Exactitude des deux.intEvalAcc(SparseGP sgp, Vector[] xs,bool[] ys){int c =0;for(int i =0; i < ys.Length; i++)if((sgp.Marginal(xs[i]).GetMean()>0)== ys[i]) c++;return c;}Console.WriteLine("=== Sparse vs Full ===");Console.WriteLine($" Sparse (basis=4 induiseurs) : {EvalAcc(sgpSparse, inputsDonut, outputsDonut)}/{outputsDonut.Length}");Console.WriteLine($" Full (basis=16=inputs) : {EvalAcc(sgpFull, inputsDonut, outputsDonut)}/{outputsDonut.Length}");Console.WriteLine("\nLes deux separnt le donut -- le sparse economise du calcul sans casser la separabilite.");
=== Sparse vs Full ===
Sparse (basis=4 induiseurs) : 15/16
Full (basis=16=inputs) : 16/16
Les deux separnt le donut -- le sparse economise du calcul sans casser la separabilite.
Lecture : pourquoi le sparse marche ici
Le donut est une structure globale (un cercle), capturable même par peu de points induiseurs bien places. Le sparse est le plus rentable quand le signal est lisse a grande echelle (peu de degrés de liberte effectifs) ; il perd en precision quand la frontiere oscille finement. Le basis set est un biais-variance : trop peu d’inducteurs sous-ajustent, trop = cout full sans gain.
Basis
Cout
Risque
Petit (\(m \ll n\))
\(O(nm^2)\) economique
Sous-ajustement si frontiere fine
\(m = n\) (full)
\(O(n^3)\)
Exact mais cher
Référence. Titsias (2009, AISTATS ’09) — variational lower bound sur les inducing variables qui justifie théoriquement le sparse (l’ELBO approche le marginal likelihood à mesure que \(m\) augmente). Hensman, Fusi & Lawrence (2013, Gaussian Processes for Big Data, UAI ’13) — extension stochastique variationnelle : minibatch + inducing points fixes permettent de passer à l’échelle sur des millions d’observations, fondement du GP moderne scalable.
8. Exercices
Exercice 1 : Longueur de correlation
Le noyau SquaredExponential(0) utilise une longueur de correlation par defaut. Observez comment une longueur trop courte (frontiere herissee, surajustement) ou trop longue (frontiere trop lisse, sous-ajustement) degrade la classification.
// Exercice : influer sur la longueur de correlation du noyau.// Indice : le constructeur SquaredExponential accepte des parametres de scale.// Essayez plusieurs valeurs et mesurez l'exactitude training.// Console.WriteLine($"length=... : {acc}/{n}");Console.WriteLine("Exercice a completer : longueur de correlation du noyau");
Exercice a completer : longueur de correlation du noyau
Exercice 2 : Donut bruite
Ajoutez du bruit aux etiquettes (quelques points du disque etiquetes true, et reciproquement). Le GP gere-t-il le bruit mieux qu’un classifieur déterministe ? Quantifiez la confiance (P proche de 0.5) sur les points contredits.
// Exercice : flippez 2 etiquettes et re-inferez. Observez P(classe) sur les points bruites.// Indice : construire un nouveau tableau outputsNoisy avec 2 valeurs inversee.Console.WriteLine("Exercice a completer : robustesse au bruit du GP");
Exercice a completer : robustesse au bruit du GP
Exercice 3 : Données lineairement separables
Construisez un dataset lineairement separable (deux amas de part et d’autre d’une droite). Comparez le GP au BPM (reutilisez SimpleBPM d’Infer-9) : sur un problème simple, le GP est-il utile, ou le BPM suffit-il ?
// Exercice : dataset lineairement separable -> GP vs BPM (Infer-9).// Indice : deux amas centres en (-1,-1) et (+1,+1).// Question : sur un cas lineaire, le GP apporte-t-il plus que le BPM ?Console.WriteLine("Exercice a completer : GP vs BPM sur cas lineaire");
Exercice a completer : GP vs BPM sur cas lineaire
GP vs BPM (Infer-9)
Aspect
BPM (Infer-9)
GP (Infer-16)
Paramètre
Vecteur de poids \(\mathbf{w}\)
Fonction \(f\)
Frontière
Hyperplan (linéaire)
Courbe quelconque
Donut
Échec
Succès
Coût
Linéaire en \(n\)
\(O(nm^2)\) (sparse)
Quand l’utiliser
Données linéairement séparables
Frontières non linéaires
Distributions utilisées
Distribution
Rôle
SparseGP
Prior et posterior sur la fonction \(f\)
Gaussian
Score bruité (probit) + marginal posterior en chaque point
Bernoulli
(Implicite) prediction de classe via NormalCdf
Moteur d’inférence. Minka (2001, Expectation Propagation for Approximate Bayesian Inference, UAI ’01 362-369) — fondement canonique de l’algorithme EP utilisé par Infer.NET. Dans ce notebook, EP propage les messages à travers le graphe de facteurs (§5) pour approximer le posterior sur \(f\). Pour les GP exacts (full), EP se réduit à la formule de covariance conditionnelle standard ; pour les GP sparse, EP devient le mécanisme d’inférence principal sur les inducing variables.
Leçon : le GP est l’outil naturel quand la frontière de décision est non linéaire ET qu’on veut une incertitude calibrée. Pour un cas linéaire, le BPM (Infer-9) reste plus simple et plus rapide. Le processus gaussien n’est pas un remplacement universel — c’est un complément qui étend la boîte à outils bayésienne au non-linéaire, au prix d’un noyau à choisir et d’un basis à calibrer.
Ponts dans la série
Pont hiérarchique (Infer-12-Modèles-Hiérarchiques) : la longueur d’échelle \(\ell\) du noyau RBF est un hyperparamètre ; un GP qui apprendrait une longueur par groupe d’inputs est, structurellement, un modèle hiérarchique sur ces hyperparamètres. Ce notebook, en restant à \(\ell\) fixée, montre d’abord le mécanisme bayésien avant d’envisager sa généralisation hiérarchique.
Suivant (Infer-17-Kalman-Filter) : le GP est le pendant statique (covariance dans l’espace des entrées) du modèle d’état markovien (covariance dans le temps). Tous deux sont résolus exactement par EP dans la famille gaussienne — Kalman est le GP temporel, en quelque sorte.
Conclusion — ce que nous avons appris
Ce notebook a prolongé la Bayes Point Machine d’Infer-9 (frontière linéaire) en un Processus Gaussien capable de tracer une frontière non-linéaire — illustrée ici par la classification du donut, qu’aucun hyperplan ne peut séparer.
Trois idées à retenir
Le GP modélise une fonction, pas un vecteur de poids. Là où la BPM apprend un hyperplan \(\mathbf{w} \cdot \mathbf{x} = 0\), le GP infère une fonction \(f(\mathbf{x})\) dont seul le signe sert à la classification. C’est ce passage « du paramétrique au non-paramétrique » qui débloque les frontières courbes.
L’incertitude est un produit dérivé du GP, pas un accessoire. La prédiction au centre du donut (\(E[f] < 0\)) est confiante (false) ; à mi-rayon, l’incertitude est maximale — exactement là où l’information d’entraînement est la plus pauvre. Un classifieur déterministe ne saurait pas dire « je ne sais pas » ; le GP le quantifie.
L’approximation sparse rend le GP abordable. Un GP full coûte \(O(n^3)\) (inversion d’une matrice \(n \times n\)). Le sparse ramène ce coût à \(O(nm^2)\) en remplaçant le jeu complet d’inputs par un petit basis set de \(m\) points induiseurs. Sur le donun — structure globale — \(m = 4\) points suffisent : la perte de précision est négligeable face au gain de coût. Le sparse n’est pas une approximation brutale : c’est un continu contrôlé par \(m\), qui redonne le GP full quand \(m = n\).
Et ensuite ?
Le GP ouvre la voie aux modèles hiérarchiques (Infer-12) où plusieurs groupes partagent un prior commun, et aux mélangees de Gaussiennes (Infer-2) pour la densité. Pour les très grands jeux de données, l’approximation sparse est indispensable — c’est elle qui rend le GP utilisable en pratique.
References
Sources fondatrices (papiers primaires).
Williams & Barber (1998, Bayesian Classification with Gaussian Processes, IEEE Transactions on Pattern Analysis and Machine Intelligence 20(12):1342-1351, doi:10.1109/34.735807) — papier fondateur de la classification GP.
Minka (2001, Expectation Propagation for Approximate Bayesian Inference, UAI ’01 362-369) — fondement canonique de l’algorithme EP, moteur d’Infer.NET.
Snelson & Ghahramani (2006, Sparse Gaussian Processes using Pseudo-inputs, NeurIPS ’06) — introduit les pseudo-inputs (inducing points) qui généralisent le basis set.
Titsias (2009, Variational Learning of Inducing Variables in Sparse Gaussian Processes, AISTATS ’09) — reformulation variationnelle du sparse GP (ELBO sur inducing variables).
Sources secondaires.
Rasmussen & Williams (2006, Gaussian Processes for Machine Learning, MIT Press, isbn:9780262182539) — livre canonique du domaine, chapitres 1-3-5 (prior, covariance, classification).
MacKay (2003, Information Theory, Inference, and Learning Algorithms, Cambridge University Press, ch.45) — présente le GP comme un réseau de neurones de largeur infinie.
Quinonero-Candela & Rasmussen (2005, A Unifying View of Sparse Approximate Gaussian Process Regression, Journal of Machine Learning Research 6:1939-1959) — synthèse comparative DTC/FITC/VFE.
Hensman, Fusi & Lawrence (2013, Gaussian Processes for Big Data, UAI ’13) — extension stochastique variationnelle pour le passage à l’échelle.
Relations dans la série.
Infer-9-Classification — Bayes Point Machine (BPM), frontière linéaire. Comparaison en §8 du notebook.
Infer-12-Modèles-Hiérarchiques — généralisation hiérarchique : une longueur de corrélation \(\ell\) par groupe d’inputs, vs \(\ell\) fixée ici.
Infer-17-Kalman-Filter — Kalman est le GP temporel : covariance dans le temps (modèle d’état markovien) au lieu de covariance dans l’espace des entrées.
PyMC-16-Sparse-Gaussian-Process (jumeau Python) — même substance algorithmique (sparse GP pour la classification), stack NUTS+pm.gp.Latent+Logit+inducing points+ARD+HSGP au lieu de EP+SparseGP+Probit+EP-Forster.
Pour aller plus loin — variantes non couvertes dans ce notebook.
Le sparse GP variationnel peut être étendu en :
Hilbert Space GP (HSGP) — Ruitort-Mayol, Snelson, Titsias & Lawrence (2023, Hilbert Space Gaussian Processes, AISTATS ’23) : approximation par projection sur une base tronquée de Hilbert (Sobolev), évitant inducing variables. Compatible avec EP/NUTS.
ARD (Automatic Relevance Determination) — Neal (1996, Bayesian Learning for Neural Networks, PhD Thesis University of Toronto, §1.2.3 et §4.3) : longueur de corrélation par dimension (\(\ell_1, \ldots, \ell_d\)), qui apprend quelles features sont pertinentes. Implémentation : SquaredExponentialARD ou ARDKernel.
Stochastic Variational GP — Hensman et al. (2013, UAI ’13) cité plus haut, le pendant scalable du notebook : minibatch sur les observations + inducing points fixes.
Multi-class / multi-label GP — extension directe avec un classifieur softmax sur les scores gaussiens latents.
Pour l’inférence en GP exactement, deux moteurs : (a) EP (Minka 2001) — implémenté ici via Infer.NET, exploitable tant que la famille des messages reste gaussienne ; (b) MCMC HMC/NUTS — plus coûteux, plus général (utilisé dans le jumeau PyMC-16).