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).
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')
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')
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))
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')
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.
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).
https://pyro.ai/examples/gplvm.html GPLVM ist unbeaufsichtigtes Lernen und kann Dimensionen reduzieren, indem Eingaben von Ausgaben gefunden werden.
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