[PYTHON] Dimensionskomprimierung durch Selbstcodierer- und Hauptkomponentenanalyse

Einführung

Wir haben eine Selbstcodierer- und Hauptkomponentenanalyse als Dimensionskomprimierungsmethode implementiert. Als Lehrbücher ["Deep Learning"](https://www.amazon.co.jp/ Deep Learning - Maschinelles Lernen Professional Series-Okaya-Takayuki / dp / 4061529021) und ["First Pattern Recognition"](https: / /www.amazon.co.jp/ Erste Mustererkennung (Hirai-Yuzo / dp / 4627849710) wurde verwendet.

Struktur dieses Artikels

Selbstcodierer

** Auto Encoder ** ist ein neuronales Netzwerk, das Eingaben als Trainingsdaten verwendet und Funktionen erfasst, die die Daten gut darstellen. Es wird als unbeaufsichtigtes Lernen klassifiziert, bei dem keine Lehrerdaten verwendet werden. Es wird zum Vorlernen neuronaler Netze und zum Ermitteln von Anfangswerten verwendet. Kommen wir nun zur Erklärung des Selbstcodierers. Stellen Sie sich ein dreischichtiges Netzwerk vor, wie in der folgenden Abbildung dargestellt. Die Aktivierungsfunktion ist die konstante Zuordnungsfunktion $ g (a) = a $.

network.png

Der Wert der Einheit in der mittleren Schicht $ z_j $ und der Wert der Einheit in der Ausgangsschicht $ y_k $ werden erhalten, indem die Eingabe vorwärts weitergegeben wird.

\begin{align}
& z_j = \sum_i w_{ji} x_i \\
& \\
& y_k = \sum_j \tilde w_{kj} z_j
\end{align}

Der Vektor mit den Werten der Einheiten in der mittleren Ebene ist $ \ boldsymbol z $, und der Vektor mit den Werten der Einheiten in der Ausgabeschicht ist $ \ boldsymbol y $. Wenn die Matrix mit $ w_ {ji} $ als $ (\ j, i ) $ -Komponente $ \ boldsymbol W $ ist, kann sie wie folgt ausgedrückt werden.

\begin{align}
& \boldsymbol z = \boldsymbol W \boldsymbol x \\
& \\
& \boldsymbol y = \boldsymbol{\tilde W} \boldsymbol z
\end{align}

Die Konvertierung in die mittlere Schicht $ \ boldsymbol z $ wird als ** Codierung ** bezeichnet, und die Konvertierung in die Ausgabeschicht $ \ boldsymbol y $ wird als ** Entschlüsselung ** bezeichnet. Der Selbstcodierer trainiert das entschlüsselte $ \ boldsymbol y $ so, dass es nahe am Eingang $ \ boldsymbol x $ liegt. Wenn die Anzahl der Einheiten in der mittleren Ebene kleiner als die Eingabedimension ist und die Eingabe reproduziert werden kann, kann die Dimension komprimiert werden. Ausführliche Informationen zur Lernmethode finden Sie unter "Implementieren eines neuronalen Netzwerks mit Python". Da die Aktivierungsfunktion eine konstante Zuordnungsfunktion ist, beträgt der Differenzwert immer $ 1 $, was einfach zu berechnen ist.

Hauptkomponentenanalyse

** Hauptkomponentenanalyse (PCA) ** ist eine lineare Transformation von Trainingsdaten $ \ boldsymbol x_i = (x_ {i1}, ..., x_ {id}) ^ T $ in Richtung maximaler Streuung. Dies ist die Methode zu finden. $ N $ Datenmatrix bestehend aus $ \ boldsymbol X = (\ boldsymbol x_1, ..., \ boldsymbol x_N) ^ T $, durchschnittlicher Vektor $ \ boldsymbol {\ bar x} = (\ bar x_1, ..., \ bar x_d) ^ T $. Die Datenmatrix $ \ boldsymbol {\ bar X} $, die die Datenmatrix minus dem mittleren Vektor ist, und die Kovarianzmatrix $ \ boldsymbol \ Sigma $ sind wie folgt.

\begin{align}
& \boldsymbol{\bar X} = (\boldsymbol x_1 - \boldsymbol{\bar x}, ..., \boldsymbol x_N - \boldsymbol{\bar x})^T \\
& \\
& \boldsymbol \Sigma = Var\bigl\{\boldsymbol{\bar X}\bigr\} = \frac{1}{N} \boldsymbol{\bar X}^T \boldsymbol{\bar X}
\end{align}

Wenn die Datenmatrix $ \ boldsymbol {\ bar X} $ linear durch einen bestimmten Koeffizientenvektor $ \ boldsymbol a_j $ konvertiert wird und $ \ boldsymbol s_j $ verwendet wird, ist die Verteilung der konvertierten Daten wie folgt.

\begin{align}
& \boldsymbol s_j = (s_{1j}, ..., s_{Nj})^T \\
& \\
& Var\bigl\{\boldsymbol s_j \bigr\} \varpropto \boldsymbol s_j^T \boldsymbol s_j = \bigl(\boldsymbol{\bar X} \boldsymbol a_j \bigr)^T \boldsymbol{\bar X} \boldsymbol a_j =  \boldsymbol a_j^T \boldsymbol{\bar X}^T \boldsymbol{\bar X} \boldsymbol a_j \varpropto \boldsymbol a_j^T Var\bigl\{\boldsymbol{\bar X}\bigr\} \boldsymbol a_j
\end{align}

Der Projektionsvektor $ \ boldsymbol a_j $, der diese Varianz maximiert, wird durch Maximieren der Lagrange-Funktion mit der auf $ 1 $ beschränkten Norm erhalten.

\begin{align}
& E(\boldsymbol a_j) = \boldsymbol a_j^T Var\bigl\{\boldsymbol{\bar X}\bigr\} \boldsymbol a_j - \lambda (\boldsymbol a_j^T \boldsymbol a_j - 1) \\
& \\
& \frac{\partial E(\boldsymbol a_j)}{\partial \boldsymbol a_j} = 2 Var\bigl\{\boldsymbol{\bar X}\bigr\} \boldsymbol a_j - 2 \lambda \boldsymbol a_j = 0 \\
& \\
& Var\bigl\{\boldsymbol{\bar X}\bigr\} \boldsymbol a_j = \lambda \boldsymbol a_j \tag{*}
\end{align}

Die Gleichung ($ \ ast $) zeigt, dass durch Lösen des Eigenwertproblems für die Kovarianzmatrix der Originaldaten ein Projektionsvektor $ \ boldsymbol a_j $ erhalten werden kann, der die Varianz maximiert. Der durch Lösen der Gleichung ($ \ ast $) erhaltene Eigenwert sei $ \ lambda_1 \ geq ... \ geq \ lambda_d $, und der entsprechende Eigenvektor sei $ \ boldsymbol a_1, ..., \ boldsymbol a_d $. Da die Kovarianzmatrix eine reelle symmetrische Matrix ist, sind die Eigenvektoren orthogonal zueinander.

\boldsymbol a_i^T \boldsymbol a_j = \delta_{ij} = \begin{cases}
1 \ ( \ i = j \ ) \\
\\
0 \ ( \ i \ne j \ )
\end{cases}

Die Merkmalsgröße, die vom Eigenvektor entsprechend dem maximalen Eigenwert linear transformiert wird, ist die Hauptkomponente $ 1 $. Die Merkmalsgröße, die vom Eigenvektor entsprechend dem $ k $ -ten Eigenwert linear transformiert wird, wird als $ k $ Hauptkomponente bezeichnet. Der Gesamtstreuungsbetrag $ V_ {total} $, der Beitragssatz der Hauptkomponente $ k $ c_k $ und der kumulative Beitragssatz $ r_k $ bis zur Hauptkomponente $ k $ sind wie folgt.

\begin{align}
& V_{total} = \sum_{i = 1}^d \lambda_i \\
& \\
& c_k = \frac{\lambda_k}{V_{total}} \\
& \\
& r_k = \frac{\sum_{i = 1}^k \lambda_i}{V_{total}}
\end{align}

Beziehung zwischen den beiden Methoden

Wählen Sie $ D_y $ Eigenvektoren von $ \ boldsymbol \ Sigma $ in absteigender Reihenfolge der Eigenwerte aus und lassen Sie die Matrix, die dies als Zeilenvektor speichert, $ \ boldsymbol U_ {D_y} $ sein. Wenn die Anzahl der Dimensionen der Eingabedaten $ D_x $ ist, werden die Dimensionen komprimiert, wenn $ D_y <D_x $. $ \ Boldsymbol U _ {D_y} $ und $ \ boldsymbol {\ bar x} $ sind die Lösungen für das folgende Minimierungsproblem $ (\ boldsymbol \ Gamma, \ boldsymbol \ xi) = (\ boldsymbol U_ {D_y}, \ boldsymbol Es ist {\ bar x}) $.

\min_{\boldsymbol \Gamma, \boldsymbol \xi} \sum_{n = 1}^N \bigl\| \ (\boldsymbol x_n - \boldsymbol \xi) - \boldsymbol \Gamma^T \boldsymbol \Gamma(\boldsymbol x_n - \boldsymbol \xi) \ \bigr\|^2 \tag{**}

In der Hauptkomponentenanalyse können alle Daten im $ D_x $ -Dimensionsraum so interpretiert werden, dass sie den $ D_y $ -Dimensionsunterraum ergeben, der am besten in dem Sinne darstellt, dass der quadratische Abstand minimiert wird. $ \ Boldsymbol W = \ Boldsymbol \ Gamma, \ Boldsymbol b = - \ Boldsymbol \ Gamma \ Boldsymbol \ xi, \ Boldsymbol {\ Tilde W} = \ Boldsymbol \ Gamma ^ T, \ Wenn boldsymbol {\ tilte b} = \ boldsymbol \ xi , stimmt die Fehlerfunktion des Selbstcodierers mit dem Ausdruck ( \ ast \ ast $) überein. Das heißt, in einem Selbstcodierer ist $ (\ boldsymbol \ Gamma, \ boldsymbol \ xi) = (\ boldsymbol U_ {D_y}, \ boldsymbol {\ bar x}) $ der Netzwerkparameter, der die Fehlerfunktion minimiert. ..

Implementierung in Python

Ich habe es wie folgt implementiert. Der Selbstcodierer und die Hauptkomponentenanalyse werden separat aufgeführt.

auto encoder

Die Komprimierungsdimension wird als $ 50 $ verarbeitet. Mit einer Lernrate von $ \ varepsilon = 0,00001 $ drehen wir die Epoche von $ 10000 $.

auto_encoder.py


import numpy

class AutoEncoder:

    def __init__(self, n_input, n_hidden):
        self.hidden_weight = numpy.random.randn(n_hidden, n_input + 1)
        self.output_weight = numpy.random.randn(n_input, n_hidden + 1)

    def fit(self, X, epsilon, epoch):
        self.error = numpy.zeros(epoch)
        N = X.shape[0]
        for epo in range(epoch):
            print u'epoch: %d' % epo
            for x in X:
                self.__update_weight(x, epsilon)

            self.error[epo] = self.__calc_error(X)

    def encode(self, X):
        Z = numpy.zeros((X.shape[0], self.hidden_weight.shape[0]))
        Y = numpy.zeros(X.shape)
        for (i, x) in enumerate(X):
            z, y = self.__forward(x)
            Z[i, :] = z
            Y[i, :] = y

        return (Z, Y)

    def __forward(self, x):
        z = self.hidden_weight.dot(numpy.hstack((1, x)))
        y = self.output_weight.dot(numpy.hstack((1, z)))

        return (z, y)

    def __update_weight(self, x, epsilon):
        z, y = self.__forward(x)

        # update output_weight
        output_delta = y - x
        self.output_weight -= epsilon * output_delta.reshape(-1, 1) * numpy.hstack((1, z))

        # update hidden_weight
        hidden_delta = self.output_weight[:, 1:].T.dot(output_delta)
        self.hidden_weight -= epsilon * hidden_delta.reshape(-1, 1) * numpy.hstack((1, x))

    def __calc_error(self, X):
        N = X.shape[0]
        err = 0.0
        for x in X:
            _, y = self.__forward(x)
            err += (y - x).dot(y - x) / 2.0

        return err

main.py


import numpy
import cv2
from sklearn.datasets import fetch_mldata
from auto_encoder import AutoEncoder

if __name__ == '__main__':

    print 'read data...'
    mnist = fetch_mldata('MNIST original', data_home = '.')
    _max = mnist.data[:, :-1].max()
    X = mnist.data[:, :-1] * 1.0 / _max
    input_size = X.shape[1]
    hidden_size = 50
    epsilon = 0.00001
    epoch = 10000
    stride = 50

    print 'auto encoder init...'
    auto = AutoEncoder(input_size, hidden_size)

    print 'train...'
    auto.fit(X[::stride], epsilon, epoch)

    print 'encode...'
    Z, Y = auto.encode(X[::stride])
    for (i, y) in enumerate(Y * _max):
        cv2.imwrite('result/%04d.png' % i, y.reshape(28, 28))

PCA

Die Komprimierungsdimension wird als $ 50 $ verarbeitet. Der Projektionsvektor und das decodierte Bild werden gespeichert.

pca.py


import numpy

class PCA:

    def __init__(self, n_components):
        self.n_components = n_components

    def fit(self, X):
        self.bar = self.__bar(X)
        self.cov = self.__cov()
        self.lamda, self.A, self.ccr = self.__solve_eigen_porblem()
        self.S = self.__transformation()

    def decode(self):
        return self.S.dot(self.A.T)

    def __bar(self, X):
        return X - X.mean(axis = 0)

    def __cov(self):
        return numpy.cov(self.bar, rowvar = 0)

    def __solve_eigen_porblem(self):
        _lamda, _A = numpy.linalg.eig(self.cov)
        lamda = _lamda[:self.n_components]
        A = _A[:, :self.n_components]
        ccr = lamda.sum() / _lamda.sum()

        return (lamda, A, ccr)

    def __transformation(self):
        return self.bar.dot(self.A)

main.py


import cv2
from matplotlib import pyplot
from sklearn.datasets import fetch_mldata
import os
from pca import PCA

if __name__ == '__main__':

    print 'read data...'
    mnist = fetch_mldata('MNIST original', data_home = '.')
    X = mnist.data
    n_components = 50
    p_dir = 'projection/'
    d_dir = 'decoded/'

    print 'train...'
    pca = PCA(n_components)
    pca.fit(X)
    print 'cumulative contribution ratio: %f' % pca.ccr

    print 'decode...'
    Xhat = pca.decode()

    print 'save projection vector...'
    if not os.path.exists(p_dir):
        os.mkdir(p_dir)
    for (i, a) in enumerate(pca.A.T):
        fig, ax = pyplot.subplots()
        heatmap = ax.pcolor(a.reshape(28, 28)[:, ::-1], cmap = pyplot.cm.RdYlBu)
        pyplot.savefig(p_dir + '%04d.png' % i, dpi = 25)
        pyplot.clf()

    print 'save decoded images...'
    if not os.path.exists(d_dir):
        os.mkdir(d_dir)
    for (i, xhat) in enumerate(Xhat[::50]):
        cv2.imwrite(d_dir + '%04d.png' % i, xhat.reshape(28, 28))

    n_components = 30
    pca = PCA(n_components)
    pca.fit(X)

    Xhat = pca.A.dot(pca.S.T)
    for (i, xhat) in enumerate(Xhat.T):
        cv2.imwrite('result/%04d.png' % i, xhat.reshape(28, 28))

Ergebnis

Die folgenden Ergebnisse wurden erhalten.

auto encoder

Entschlüsseltes Bild

decode_auto_encoder.png

Error

error_log.png

Ich habe ein gut aussehendes Bild für das dekodierte Bild ausgewählt. Die auf die Dimension $ 50 $ komprimierte Feature-Menge kann in die Dimension $ 784 $ dekodiert werden. Im Fehlerdiagramm ist die horizontale Achse die Anzahl der Epochen und die vertikale Achse der Fehlerwert. Die Differenz zwischen den Ziffern des Fehlers ist zu groß, daher wird der Logarithmus verwendet. Es ist kein exakter Fehler, aber Sie können sehen, dass er monoton abnimmt. ..

PCA

Visualisierter Projektionsvektor

projection_vector.png

Entschlüsseltes Bild

decode_pca.png

Für den Projektionsvektor wurden 10 entsprechende Vektoren in absteigender Reihenfolge des Eigenwerts ausgewählt. Der Projektionsvektor oben links projiziert zur ersten Hauptkomponente mit der größten Streuung. Das decodierte Bild liefert gute Ergebnisse sowie den Selbstcodierer.

abschließend

Wir konnten die Abmessungen durch Selbstcodierer- und Hauptkomponentenanalyse komprimieren.

Recommended Posts

Dimensionskomprimierung durch Selbstcodierer- und Hauptkomponentenanalyse
Koordinierte Filterung mit Hauptkomponentenanalyse und K-Mittel-Clustering
Hauptkomponentenanalyse mit Spark ML
Dies und das der Hauptkomponentenanalyse
Sprachverarbeitung 100 knock-85 (abgeschnittene SVD): Dimensionskomprimierung durch Hauptkomponentenanalyse
Hauptkomponentenanalyse mit Livedoor News Corpus - Vorbereitung--
Ich habe versucht, die Hauptkomponenten mit Titanic-Daten zu analysieren!
Hauptkomponentenanalyse (Hauptkomponentenanalyse: PCA)
Beginnen wir mit der multivariaten Analyse und der Hauptkomponentenanalyse mit Pokemon! Zusammenarbeit zwischen R und Tableau
Clustering und Hauptkomponentenanalyse nach der K-Means-Methode (Anfänger)
Fordern Sie die Hauptkomponentenanalyse von Textdaten mit Python heraus
Hauptkomponentenanalyse mit Python von nim mit nimpy
Hauptkomponentenanalyse (PCA) und unabhängige Komponentenanalyse (ICA) mit Python
Lernen ohne Lehrer 3 Hauptkomponentenanalyse
Hauptkomponentenanalyse zum Anfassen mit PyCaret [Normalisierung + Visualisierung (grafisch)] Memo
Gesichtserkennung mit Hauptkomponentenanalyse
Erkennen Sie die Kontur und Richtung eines geformten Objekts mit OpenCV3 und Python3 (Hauptkomponentenanalyse: PCA, Eigenvektor)
Tweet-Analyse mit Python, Mecab und CaboCha
<Kurs> Maschinelles Lernen Kapitel 4: Hauptkomponentenanalyse
[Python] Vergleich der Theorie und Implementierung der Hauptkomponentenanalyse durch Python (PCA, Kernel PCA, 2DPCA)
Versuchen Sie eine 1,5-dimensionale instationäre Wärmeübertragungsanalyse mit Heatrapy
PRML Kapitel 12 Bayesianische Hauptanalyse Python-Implementierung
Komprimieren Sie Vektoren mithilfe der Hauptkomponentenanalyse in zwei Dimensionen und visualisieren Sie sie mit matplotlib.
2. Multivariate Analyse in Python 3-2. Hauptkomponentenanalyse (Algorithmus)
Deep Learning Bildanalyse beginnend mit Kaggle und Keras
Mathematisches Verständnis der Hauptkomponentenanalyse von Anfang an
Hauptkomponentenanalyse Analysieren Sie handschriftliche Zahlen mit PCA. Teil 2
Hauptkomponentenanalyse Analysieren Sie handschriftliche Zahlen mit PCA. Teil 1
2. Multivariate Analyse in Python 3-1. Hauptkomponentenanalyse (Scikit-Learn)