Letztes Mal habe ich ein gewöhnliches neuronales Netzwerk implementiert, ohne Bibliotheken wie Tensorflow und Chainer zu verwenden. Es gibt jedoch bereits viele solcher Implementierungen im Netz, und das ist nicht sehr interessant. Deshalb habe ich dieses Mal ein Netzwerk mit gemischter Dichte ** implementiert, um mich auf das letzte Mal vorzubereiten. Da der Code des zuletzt implementierten neuronalen Netzwerks verwendet wird, lesen Sie bitte Vorheriger Artikel.
Bei der Lösung des Regressionsproblems ist es möglicherweise nicht möglich, mit der Fehlerfunktion der Quadratsumme gut damit umzugehen. Die folgende Abbildung (Reproduktion von PRML Abbildung 5.19) zeigt das Ergebnis, als das neuronale Netzwerk unter Verwendung der Fehlerfunktion der Quadratsumme unter Verwendung der blauen Punkte als Trainingsdaten trainiert wurde. Wenn $ x = 0,5 $ ist, sieht der Wert von $ y $ bei 0,2, 0,5 oder 0,8 gut aus. Da ich jedoch einen von ihnen auswählen muss, wird er 0,5 und ich passe nicht zu den anderen beiden. ** Ich habe das neuronale Netzwerk trainiert, passte aber nicht sehr gut, da die Kostenfunktion einer monomodalen Gaußschen Verteilung nachempfunden ist **. Die Beziehung zwischen der Eingabe $ x $ und dem Ziel $ t $ wird in einer Gaußschen Verteilung wie folgt ausgedrückt.
p(t|x) = \mathcal{N}(t|\mu(x),\sigma^2),
Basierend darauf wurden Anpassung und Schätzung der Funktion $ \ mu (x) $ durchgeführt. Und das geschätzte $ \ mu (x) $ ist in der obigen Abbildung rot, was ein schlechtes Ergebnis ist.
Das Netzwerk mit gemischter Dichte löst das obige Problem, indem eine Kostenfunktion verwendet wird, die einer multimodalen gemischten Gaußschen Verteilung nachempfunden ist. Bereiten Sie einen Mischungskoeffizienten $ \ pi \ _k $ für jede K-Gauß-Verteilung vor und ermitteln Sie die Beziehung zwischen der Eingabe $ x $ und dem Ziel $ t $.
p(t|x) = \sum_{k=1}^K\pi_k(x)\mathcal{N}(t|\mu_k(x),\sigma^2_k(x))
Modell mit. Die Summe der Mischungskoeffizienten beträgt jedoch 1 ($ \ sum_k \ pi_k = 1 $). Im obigen Beispiel für Trainingsdaten gibt es bei $ x = 0,5 $ einen Satz von 3 Datenpunkten um $ y = 0,2,0,5,0,8 $. Daher scheint es gut, $ K = 3 $ zu setzen. Durch Anpassen der drei Gaußschen Verteilungen an verschiedene Sätze von Datenpunkten können sogar multimodale Daten verarbeitet werden. Daher ist angesichts des Trainingsdatensatzes $ \ {x \ _n, t \ _n \} _ {n = 1} ^ N $ die zu optimierende Kostenfunktion
\begin{align}
E(w) &= \sum_{n=1}^N E_n\\
&= -\sum_{n=1}^N \ln p(t_n|x_n)\\
&= -\sum_{n=1}^N \ln \left\{\sum_{k=1}^K\pi_k(x_n,w)\mathcal{N}\left(t_n|\mu_k(x_n,w),\sigma^2_k(x_n,w)\right)\right\}
\end{align}
Es wird sein. Dann schätzen wir den Parameter $ w $, der die obige Gleichung minimiert. Ein neuronales Netzwerk wird für die Funktionen $ \ pi_k, \ mu_k, \ sigma_k $ verwendet. Wenn Sie die Eingabe $ x $ mit dem Parameter $ w $ in das Netzwerk einfügen, werden der Mischungskoeffizient, der Mittelwert und die Varianz ausgegeben und die Wahrscheinlichkeitsverteilung von $ t $ berechnet.
Diesmal ist die Eingabe $ {\ bf x} $ eindimensional, da die Regression für die Daten durchgeführt wird, wie in der obigen Abbildung gezeigt. Die Anzahl der Knoten in der Mitte $ {\ bf z} $ beträgt laut PRML 5, und die Anzahl der Knoten in der Ausgabe $ {\ bf y} $ beträgt 9. Die Parameter der ersten Schicht sind $ W ^ {(1)}, {\ bf b} ^ {(1)} $, die Aktivierungsfunktion ist $ f (\ cdot) $ und die Parameter der zweiten Schicht sind $ W ^ { Als (2)}, {\ bf b} ^ {(2)} $ ist die Vorwärtsausbreitung wie folgt.
\begin{align}
{\bf z} &= f(W^{(1)}{\bf x} + {\bf b}^{(1)})\\
{\bf y} &= W^{(2)}{\bf z} + {\bf b}^{(2)}
\end{align}
Diese neun Ausgaben sind die Aktivitäten der gemischten Gaußschen Verteilungsparameter $ \ pi_k, \ mu_k, \ sigma_k $. Erstens ist die Ausgabe $ {\ bf y} $ die Aktivität, die $ \ pi, \ mu, \ sigma $ drei von oben entspricht.
{\bf y} =
\begin{bmatrix}
a_{\pi_1}\\
a_{\pi_2}\\
a_{\pi_3}\\
a_{\mu_1}\\
a_{\mu_2}\\
a_{\mu_3}\\
a_{\sigma_1}\\
a_{\sigma_2}\\
a_{\sigma_3}
\end{bmatrix}
Da der Mischungskoeffizient $ \ pi_k $ eine Einschränkung von $ \ sum_k \ pi_k = 1 $ hat, wird der Mischungskoeffizient von der Softmax-Funktion ausgegeben.
\pi_k = {\exp(a_{\pi_k})\over\sum_{l=1}^K\exp(a_{\pi_l})}
Der Durchschnitt ist $ \ mu_k = a_ {\ mu_k} $ ohne die nichtlineare Transformation. Da die Standardabweichung $ \ sigma $ 0 oder mehr ist, verwenden Sie die Exponentialfunktion $ \ sigma_k = \ exp (a_ {\ sigma_k}) $. Sie haben jetzt die Funktionen $ \ pi_k, \ mu_k, \ sigma_k $, die zur Berechnung der gemischten Gaußschen Verteilung benötigt werden.
Wie ich in der vorherigen Implementierung eines neuronalen Netzwerks geschrieben habe, ist zum Trainieren eines neuronalen Netzwerks ein Gradient erforderlich, der durch Differenzieren der Kostenfunktion mit der Ausgabe des neuronalen Netzwerks erhalten wird. Damit können Sie auch die Fehler-Backpropagation verwenden, um die Differenz für den Kostenfunktionsparameter $ w $ zu berechnen. Der Gradient am Ausgang des neuronalen Netzes dieser Kostenfunktion ist
\gamma_{nk}(t_n|x_n) = {\pi_k\mathcal{N}(t_n|\mu_k(x_n,w),\sigma_k^2(x_n,w))\over\sum_l\pi_l\mathcal{N}(t_n|\mu_l(x_n,w),\sigma_l^2(x_n,w))}
Verwenden von,
\begin{align}
{\partial E_n\over\partial a_{\pi_k}} &= \pi_k - \gamma_{nk}\\
{\partial E_n\over\partial a_{\mu_k}} &= \gamma_{nk}{\mu_k - t_n\over\sigma^2_k}\\
{\partial E_n\over\partial a_{\sigma_k}} &= \gamma_{nk}\left(1 - {||t_n - \mu_k||^2\over \sigma^2_k}\right)
\end{align}
Es wird sein. Die Ableitung von Formeln ist eine Übung in PRML. Lesen Sie daher bitte die Antwort oder das Papier zum Netzwerk mit gemischter Dichte.
Der Code der oben geschriebenen Formel lautet wie folgt.
#Kostenfunktionsklasse
class GaussianMixture(object):
"""Negative Log Likelihood of Gaussian Mixture model"""
def __init__(self, n_components):
#Anzahl der Gaußschen Verteilungen, 3 in vorherigen Beispielen
self.n_components = n_components
#Methode zur Berechnung des Wertes der Kostenfunktion
def __call__(self, X, targets):
#Konvertieren Sie den Netzwerkausgang X mit Aktivierungsfunktion, um die Standardabweichung, den Mischungskoeffizienten und den Durchschnitt zu berechnen
sigma, weight, mu = self.activate(X)
#Gaußsche Funktion N.(t|mu,sigma^2)Berechnen Sie den Wert von
gauss = self.gauss(mu, sigma, targets)
#Negative Log-Wahrscheinlichkeit E für gemischte Gaußsche Verteilung(w):PRML(Gleichung 5.153)
return -np.sum(np.log(np.sum(weight * gauss, axis=1)))
#Konvertieren mit Aktivierungsfunktion
def activate(self, X):
assert np.size(X, 1) == 3 * self.n_components
#Teilen Sie X, wo es der Standardabweichung, dem Mischungskoeffizienten und dem Mittelwert entspricht
X_sigma, X_weight, X_mu = np.split(X, [self.n_components, 2 * self.n_components], axis=1)
#Standardabweichung mit Aktivierungsfunktion umrechnen
sigma = np.exp(X_sigma)
#Konvertieren Sie den Mischungskoeffizienten mit der Aktivierungsfunktion und subtrahieren Sie den Maximalwert, damit die Ziffern nicht überlaufen
weight = np.exp(X_weight - np.max(X_weight, 1, keepdims=True))
weight /= np.sum(weight, axis=1, keepdims=True)
return sigma, weight, X_mu
#Gaußsche Funktion N.(target|mu,sigma^2)Berechnung
def gauss(self, mu, sigma, targets):
return np.exp(-0.5 * (mu - targets) ** 2 / np.square(sigma)) / np.sqrt(2 * np.pi * np.square(sigma))
#Unterscheiden Sie die Kostenfunktion nach Aktivität
def delta(self, X, targets):
sigma, weight, mu = self.activate(X)
var = np.square(sigma)
gamma = weight * self.gauss(mu, sigma, targets)
gamma /= np.sum(gamma, axis=1, keepdims=True)
#Berechnen Sie jedes Differential
delta_mu = gamma * (mu - targets) / var
delta_sigma = gamma * (1 - (mu - targets) ** 2 / var)
delta_weight = weight - gamma
#Verbinden und dann zurückkehren
delta = np.hstack([delta_sigma, delta_weight, delta_mu])
return delta
#Erstellen Sie Trainingsdaten, die der Umkehrfunktion der Funktion func folgen
def create_toy_dataset(func, n=300):
t = np.random.uniform(size=(n, 1))
x = func(t) + np.random.uniform(-0.05, 0.05, size=(n, 1))
return x, t
Eine der Methoden, die ich in Eile angewendet habe, weil es Zeiten gab, in denen das Lernen nicht gut lief. Anstatt alle Trainingsdaten zur Berechnung des Gradienten zu verwenden, nehmen wir einige aus den Trainingsdaten und führen die Gradientenberechnung durch. Auf diese Weise können Sie möglicherweise die lokale Lösung verlassen.
#Trainingsdatensatz x,Wähle zufällig n Paare aus t aus
def sample(x, t, n=None):
assert len(x) == len(t)
N = len(x)
if n is None:
n = N
indices = np.random.choice(N, n, replace=False)
return x[indices], t[indices]
Dies ist die Hauptfunktion, die das Netzwerk mit gemischter Dichte lernt und das Ergebnis veranschaulicht.
def main():
def func(x):
return x + 0.3 * np.sin(2 * np.pi * x)
#Generieren Sie Datenpunkte gemäß der Umkehrfunktion der Funktion func
x, t = create_toy_dataset(func)
#Bestimmen Sie die Struktur des neuronalen Netzwerks.
layers = [TanhLayer(1, 5, std=0.1), LinearLayer(5, 9, std=0.1)]
#Bestimmen Sie die zu optimierende Kostenfunktion
cost_function = GaussianMixture(3)
#Erstellen Sie ein neuronales Netzwerk
nn = NeuralNetwork(layers, cost_function)
#Kommentieren Sie die folgende Zeile aus, um zu überprüfen, ob die Implementierung funktioniert.
# nn._gradient_check(np.array([[0.5]]), np.array([[0.5]]))
#Stellen Sie den ersten Lernkoeffizienten ein
learning_rate = 1e-4
for i in xrange(500000):
#Berechnen Sie den Wert der Kostenfunktion alle 10.000 Mal und setzen Sie den Lernkoeffizienten auf 0.9 mal
if i % 10000 == 0:
print "step %6d, cost %f" % (i, nn.cost(x, t))
learning_rate *= 0.9
#Mini-Stapelverarbeitung
batch = sample(x, t, n=100)
nn.fit(*batch, learning_rate=learning_rate)
#Testdaten erstellen
x_test = np.linspace(x.min(), x.max(), 100)
y_test = np.linspace(t.min(), t.max(), 100)
X_test, Y_test = np.meshgrid(x_test, y_test)
test = np.array([X_test, Y_test]).transpose(1, 2, 0).reshape(-1, 2)
#Berechnen Sie die Wahrscheinlichkeit von Testdaten
sigma, weight, mu = nn(test[:, 0].reshape(-1, 1))
probs = cost_function.gauss(mu, sigma, test[:, 1].reshape(-1, 1))
probs = np.sum(weight * probs, axis=1)
Probs = probs.reshape(100, 100)
#PRML Abbildung 5.21(a)Reproduktion von
plt.plot(x_test, weight[:100, 0], color="blue")
plt.plot(x_test, weight[:100, 1], color="red")
plt.plot(x_test, weight[:100, 2], color="green")
plt.title("weights")
plt.show()
#PRML Abbildung 5.21(b)Reproduktion von
plt.plot(x_test, mu[:100, 0], color="blue")
plt.plot(x_test, mu[:100, 1], color="red")
plt.plot(x_test, mu[:100, 2], color="green")
plt.title("means")
plt.show()
#PRML Abbildung 5.21(c)Reproduktion von
plt.scatter(x, t, alpha=0.5, label="observation")
levels_log = np.linspace(0, np.log(probs.max()), 21)
levels = np.exp(levels_log)
levels[0] = 0
plt.contourf(X_test, Y_test, Probs, levels, alpha=0.5)
plt.colorbar()
plt.xlim(x.min(), x.max())
plt.ylim(t.min(), t.max())
plt.show()
Das neural_network
in der dritten Zeile ist das neural_network.py
, das [letztes Mal] implementiert wurde (http://qiita.com/cutting_the_Gordian_knot/items/507f2f1531b870a973bf). Legen Sie es in das gleiche Verzeichnis wie diesen Code.
mixture_density_network.py
import matplotlib.pyplot as plt
import numpy as np
from neural_network import TanhLayer, LinearLayer, NeuralNetwork
class GaussianMixture(object):
"""Negative Log Likelihood of Gaussian Mixture model"""
def __init__(self, n_components):
self.n_components = n_components
def __call__(self, X, targets):
sigma, weight, mu = self.activate(X)
gauss = self.gauss(mu, sigma, targets)
return -np.sum(np.log(np.sum(weight * gauss, axis=1)))
def activate(self, X):
assert np.size(X, 1) == 3 * self.n_components
X_sigma, X_weight, X_mu = np.split(X, [self.n_components, 2 * self.n_components], axis=1)
sigma = np.exp(X_sigma)
weight = np.exp(X_weight - np.max(X_weight, 1, keepdims=True))
weight /= np.sum(weight, axis=1, keepdims=True)
return sigma, weight, X_mu
def gauss(self, mu, sigma, targets):
return np.exp(-0.5 * (mu - targets) ** 2 / np.square(sigma)) / np.sqrt(2 * np.pi * np.square(sigma))
def delta(self, X, targets):
sigma, weight, mu = self.activate(X)
var = np.square(sigma)
gamma = weight * self.gauss(mu, sigma, targets)
gamma /= np.sum(gamma, axis=1, keepdims=True)
delta_mu = gamma * (mu - targets) / var
delta_sigma = gamma * (1 - (mu - targets) ** 2 / var)
delta_weight = weight - gamma
delta = np.hstack([delta_sigma, delta_weight, delta_mu])
return delta
def create_toy_dataset(func, n=300):
t = np.random.uniform(size=(n, 1))
x = func(t) + np.random.uniform(-0.05, 0.05, size=(n, 1))
return x, t
def sample(x, t, n=None):
assert len(x) == len(t)
N = len(x)
if n is None:
n = N
indices = np.random.choice(N, n, replace=False)
return x[indices], t[indices]
def main():
def func(x):
return x + 0.3 * np.sin(2 * np.pi * x)
x, t = create_toy_dataset(func)
layers = [TanhLayer(1, 5, std=0.1), LinearLayer(5, 9, std=0.1)]
cost_function = GaussianMixture(3)
nn = NeuralNetwork(layers, cost_function)
# nn._gradient_check(np.array([[0.5]]), np.array([[0.5]]))
learning_rate = 1e-4
for i in xrange(500000):
if i % 10000 == 0:
print "step %6d, cost %f" % (i, nn.cost(x, t))
learning_rate *= 0.9
batch = sample(x, t, n=100)
nn.fit(*batch, learning_rate=learning_rate)
x_test = np.linspace(x.min(), x.max(), 100)
y_test = np.linspace(t.min(), t.max(), 100)
X_test, Y_test = np.meshgrid(x_test, y_test)
test = np.array([X_test, Y_test]).transpose(1, 2, 0).reshape(-1, 2)
sigma, weight, mu = nn(test[:, 0].reshape(-1, 1))
probs = cost_function.gauss(mu, sigma, test[:, 1].reshape(-1, 1))
probs = np.sum(weight * probs, axis=1)
Probs = probs.reshape(100, 100)
plt.plot(x_test, weight[:100, 0], color="blue")
plt.plot(x_test, weight[:100, 1], color="red")
plt.plot(x_test, weight[:100, 2], color="green")
plt.title("weights")
plt.show()
plt.plot(x_test, mu[:100, 0], color="blue")
plt.plot(x_test, mu[:100, 1], color="red")
plt.plot(x_test, mu[:100, 2], color="green")
plt.title("means")
plt.show()
plt.scatter(x, t, alpha=0.5, label="observation")
levels_log = np.linspace(0, np.log(probs.max()), 21)
levels = np.exp(levels_log)
levels[0] = 0
plt.contourf(X_test, Y_test, Probs, levels, alpha=0.5)
plt.colorbar()
plt.xlim(x.min(), x.max())
plt.ylim(t.min(), t.max())
plt.show()
if __name__ == '__main__':
main()
Als Ergebnis der Ausführung des obigen Codes zum Trainieren des Netzwerks mit gemischter Dichte unter Verwendung des blauen Punkts als Trainingsdatenpunkt wurde das in Abbildung 5.21 von PRML gezeigte Diagramm reproduziert. Die Linienfarbe usw. kann jedoch unterschiedlich sein. Es wird durch drei Gaußsche Verteilungen, blau, rot und grün, an die Trainingsdatenpunkte angepasst.
Wie beim letzten Mal habe ich ein Video des Lernprozesses gemacht.
Ich hatte erst von dem Mixed-Density-Netzwerk gehört, als ich es auf PRML gelesen hatte. Als ich im Internet suchte, war der Artikel des PRML-Autors CM Bishop aus dem Jahr 1994 ein Hit, also diese Person selbst Kann von befürwortet worden sein. Das Netzwerk mit gemischter Dichte scheint effektiver zu sein als das herkömmliche Modell, wenn es multimodal ist. Daher möchte ich dies auf einige tatsächliche Daten anwenden.
Recommended Posts