[PYTHON] Implementieren Sie den Gaußschen Prozess in Pyro

Der Gaußsche Prozess war ursprünglich einer der kontinuierlichen zeitstochastischen Prozesse, wurde jedoch als probabilistisches Modell auf maschinelles Lernen angewendet. Der Punkt ist, dass ** Gaußsche Prozesse unendlich dimensionale multivariate Gaußsche Verteilungen ** sind. Wenn es sich um eine Funktion handelt, folgt jeder Ausgang für verschiedene Eingänge einer Gaußschen Verteilung. Der Kernel definiert die Ähnlichkeit der Eingaben. Wenn die Eingaben ähnlich sind, sind die Ausgaben ähnlich, sodass Sie glatte Kurven vorhersagen können. Unter einem anderen Gesichtspunkt können Sie es sich als ein lineares Regressionsmodell vorstellen, bei dem die Basisfunktionen unendlich auf dem Gitter angeordnet sind. Angesichts der beobachteten Daten wird die Kernelmatrix berechnet, um den Mittelwert und die Varianz an den nicht beobachteten Stellen zu bestimmen. (Die Gaußsche Verteilung ändert sich nicht.) Bei der Berechnung können Sie die Ausgabe erhalten, ohne den Merkmalsvektor mit dem Kernel-Trick zu berechnen.

Eine theoretische Erklärung des Gaußschen Prozesses finden Sie unter "Gaußscher Prozess und maschinelles Lernen (Machine Learning Professional Series)". Interessanterweise stellt sich heraus, dass der Gaußsche Prozess einem neuronalen Netzwerk mit einer unendlichen Anzahl von Einheiten entspricht (https://oumpy.github.io/blog/2020/04/neural_tangents.html).

Dieses Mal werde ich den in [Vorheriger Artikel] eingeführten Gaußschen Prozess mit Pyro implementieren (https://qiita.com/takeajioka/items/ab299d75efa184eb1432).

Gaußscher Prozess kehrt mit Pyro zurück

Beispiel für das offizielle Tutorial von Pyro wird durchgeführt. Das offizielle Dokument ist ebenfalls hilfreich.

import matplotlib.pyplot as plt
import torch
import pyro
import pyro.contrib.gp as gp
import pyro.distributions as dist
pyro.set_rng_seed(100)

Nehmen Sie 20 Punkte von y = 0,5 * sin (3x) und verwenden Sie sie als Beobachtungsdaten.

N = 20
X = dist.Uniform(0.0, 5.0).sample(sample_shape=(N,))
y = 0.5 * torch.sin(3*X) + dist.Normal(0.0, 0.2).sample(sample_shape=(N,))
plt.plot(X.numpy(), y.numpy(), 'kx')

image.png Aus diesen 20 Beobachtungsdaten sagen wir die ursprüngliche Funktion voraus (in diesem Fall y = 0,5 * sin (3x)). Entscheiden Sie sich für einen Kernel und führen Sie eine Gaußsche Prozessregression durch.

#Stellen Sie Hyperparameter ein
variance = torch.tensor(0.1)
lengthscale = torch.tensor(0.1)
noise = torch.tensor(0.01)
#Rückkehr
kernel = gp.kernels.RBF(input_dim=1, variance=variance, lengthscale=lengthscale)
gpr = gp.models.GPRegression(X, y, kernel, noise=noise)

Jetzt hast du eine Rückkehr. Zeigen Sie das Vorhersageergebnis an.

Xtest = torch.linspace(-0.5, 5.5, 500)
with torch.no_grad():
    mean, cov = gpr(Xtest, full_cov=True, noiseless=False)
sd = cov.diag().sqrt()
plt.plot(Xtest.numpy(), mean.numpy(), 'r', lw=2)
plt.fill_between(Xtest.numpy(), (mean - 2.0 * sd).numpy(), (mean + 2.0 * sd).numpy(), color='C0', alpha=0.3)
plt.plot(X.numpy(), y.numpy(), 'kx')

image.png

Bei der Gaußschen Prozessregression wird die Vorhersagefunktion als eine Funktionswolke (ein Satz von Vorhersagekurven) ausgedrückt, wie in der obigen Abbildung gezeigt. Dieser Punkt ähnelt dem Ergebnis der Bayes'schen linearen Regression. Dieses Ergebnis ist jedoch das Ergebnis, wenn Hyperparameter (Varianz, Längenskala, Rauschen) wie der Kernel angemessen bestimmt werden. Optimieren Sie mit der Gradientenabstiegsmethode der Varianteninferenz, um sie an die entsprechenden Kernel-Hyperparameter anzupassen. (MCMC ist auch akzeptabel)

optimizer = torch.optim.Adam(gpr.parameters(), lr=0.005)
loss_fn = pyro.infer.Trace_ELBO().differentiable_loss
losses = []
num_steps = 2500
for i in range(num_steps):
    optimizer.zero_grad()
    loss = loss_fn(gpr.model, gpr.guide)
    loss.backward()
    optimizer.step()
    losses.append(loss.item())
#Zeichnen Sie die Verlustkurve
plt.plot(losses)
plt.xlabel("step")
plt.ylabel("loss")
#Optimierungsergebnisse anzeigen
print('variance = {}'.format(gpr.kernel.variance))
print('lengthscale = {}'.format(gpr.kernel.lengthscale))
print('noise = {}'.format(gpr.noise))

image.png

variance = 0.15705525875091553 lengthscale = 0.4686208963394165 noise = 0.017524730414152145

Zeigen Sie das Vorhersageergebnis an.

Xtest = torch.linspace(-0.5, 5.5, 500)
with torch.no_grad():
    mean, cov = gpr(Xtest, full_cov=True, noiseless=False)
sd = cov.diag().sqrt()
plt.plot(Xtest.numpy(), mean.numpy(), 'r', lw=2)
plt.fill_between(Xtest.numpy(), (mean - 2.0 * sd).numpy(), (mean + 2.0 * sd).numpy(), color='C0', alpha=0.3)
plt.plot(X.numpy(), y.numpy(), 'kx')

image.png

Die Form der Wolke ist glatter als in der vorherigen Abbildung und liegt näher an der ursprünglichen Funktion (y = 0,5 * sin (3x)). Ich denke, dass das Vorhersageergebnis durch Anpassen der Hyperparameter verbessert wurde.

Andere Anwendungen

Bayesianische Optimierung

https://pyro.ai/examples/bo.html Sie können den Mindestwert während der Suche ermitteln, indem Sie eine Vorhersagefunktion durch Regression ausgeben (ungefähre Lösungsmethode).

Modell des latenten Gaußschen Prozesses (GPLVM)

https://pyro.ai/examples/gplvm.html GPLVM ist unbeaufsichtigtes Lernen und kann Dimensionen reduzieren, indem Eingaben von Ausgaben gefunden werden.

Am Ende

Bei der normalen Datenanalyse müssen Sie das für Ihre Situation geeignete Wahrscheinlichkeitsmodell festlegen. Beispielsweise definiert die statistische Bayes'sche Modellierung ein Modell zur Bestimmung der vorherigen Verteilung. In dieser Hinsicht muss der Gaußsche Prozess nur ** den Kernel (Ähnlichkeit zwischen Samples) ** angeben, sodass er sehr vielseitig zu sein scheint. Und selbst dieser Kernel scheint automatisch von der ARD bestimmt zu werden (automatische Relevanzbestimmung).

Darüber hinaus kann der Gaußsche Prozess Unsicherheit ausdrücken, und ich denke, dass es möglich ist, auch mit einer kleinen Anzahl von Stichproben flexibel zu lernen. Als Modell ist es jedoch kompliziert und schwer zu interpretieren.

Recommended Posts

Implementieren Sie den Gaußschen Prozess in Pyro
Gaußscher Prozess
Implementieren Sie einen Teil des Prozesses in C ++
Rückkehr nach dem Gaußschen Verfahren
Implementieren Sie XENO mit Python
Gaußscher Prozess mit pymc3
Implementieren Sie LSTM AutoEncoder mit Keras
Gaußsche Prozessregression mit GPy
Implementieren Sie die Follow-Funktion in Django
Implementiere die Timer-Funktion im Pygame
Implementieren Sie Style Transfer mit Pytorch
Implementieren Sie den rekursiven Abschluss in Go
Implementieren Sie Naive Bayes in Python 3.3
Implementieren Sie UnionFind (gleichwertig) in 10 Zeilen
Implementieren Sie Redis Mutex in Python
Implementieren Sie die Erweiterung in Python
Implementieren Sie schnelles RPC in Python
Implementieren Sie den Dijkstra-Algorithmus in Python
Implementieren Sie den Slack Chat Bot in Python
Implementieren Sie das Stacking-Lernen in Python [Kaggle]
Implementieren Sie einen tabellengesteuerten Test in Java
Implementieren Sie die Funktion power.prop.test von R in Python
Implementieren Sie einen Datumssetzer in Tkinter
Implementieren Sie das Singleton-Muster in Python
Behandeln Sie Anfragen in einem separaten Prozess
Implementieren Sie die REST-API schnell in Python