[PYTHON] Versuchen Sie, RBM mit Chainer zu implementieren.

0. Einleitung

RBM ist eine Methode, die als Vorlernen verwendet wird, wenn beim Deep Learning mehrere Ebenen verwendet werden. Der Quellcode wird auf theano veröffentlicht. http://deeplearning.net/tutorial/rbm.html Diesmal habe ich diesen Code auf Chainer portiert.

Im Fall von RBM ist die Fehlerfunktion eine Funktion der freien Energie und ist kompliziert (?). Aufgrund der inversen Fehlerausbreitung erhalten Sie eine schöne Berechnungsformel, wenn Sie mit der Gewichtsmatrix und den Bias-Variablen unterscheiden. Sie kann aus dem Wert der CD-Verarbeitung (Contrastive Divergence) berechnet werden. Bei der Implementierung mit Chainer, anstatt eine Fehlerfunktion zu erstellen (Verlust) und eine inverse Fehlerausbreitung durchzuführen (Verlust.rückwärts) Es wäre einfacher, es einfach mit cupy (numpy + GPU) zu implementieren, aber ich habe es gewagt, es mit der Fehlerfunktion zu implementieren. Der Quellcode für cupy (numpy + GPU) wird nur veröffentlicht, wenn sich die Gelegenheit ergibt. Der folgende Quellcode verwendet jedoch auch cupy, um die CD-Verarbeitung zu beschleunigen. .. ..

# -*- coding: utf-8 -*-

import os,sys
import argparse
import time

import numpy as np

import chainer
from chainer import computational_graph
from chainer import cuda, Variable

import chainer.functions as F
import chainer.links as L
import chainer.optimizers as O


import pickle
import gzip

parser = argparse.ArgumentParser()
parser.add_argument('--gpu', '-g', default=-1, type=int,
                    help='GPU ID (negative value indicates CPU)')
parser.add_argument('--pcd', '-p', default=1, type=int,
                    help='pcd_flag')
parser.add_argument('--kcd', '-k', default=1, type=int,
                    help='cd-k')


'''Bei der Berechnung mit GPU Cupy= numpy +Prozess mit GPU.'''
args = parser.parse_args()
if args.gpu >= 0:
    cuda.check_cuda_available()
xp = cuda.cupy if args.gpu >= 0 else np

def sigmoid(x):
    return 1. / (1 + xp.exp(-x))

class RBM(chainer.Chain):
    '''
    n_visbile:Sichtbare Schichtdimension
    n_hidden:Versteckte Ebenendimension
    l.W:Gewichtsmatrix
    l.b:hbias
    l.a:vbaias
    real:Die sichtbare Schicht ist 0,Die Fälle werden danach unterteilt, ob es sich um 1 oder eine reelle Zahl handelt. Die erste Schicht nimmt eine reelle Zahl an, die mittlere Schicht ist jedoch 0,Ich denke nur an einen.
h in chainer= l(v)Die Gewichtsmatrix, die im Allgemeinen RBM erscheint, wird transponiert, um sich zu multiplizieren.
    '''
    def __init__(self,n_visible,n_hidden,real=0,k=1,pcd_flag=0):
        super(RBM,self).__init__(
            l=L.Linear(n_visible,n_hidden),
            # chainer 1.Diese Verwendung wurde in 5 Handbuch veraltet, also hinzufügen_Verwenden Sie param.
#            a=L.Parameter(xp.zeros(n_visible,dtype=xp.float32)),
        )
        self.l.add_param("a",(n_visible),dtype=xp.float32)

        ''' l.Lernt es nicht, wenn a nicht mit Hilfe von Chainer initialisiert und initialisiert wird?'''
        self.l.a.data.fill(0)

        self.n_visible = n_visible
        self.n_hidden = n_hidden
        self.real = real
        self.k = k
        self.pcd_flag = pcd_flag

    def __call__(self,v_data,v_prev_data=None):

        batch_size = v_data.shape[0]

        if self.pcd_flag == 0:
            v_prev_data = v_data
        elif self.pcd_flag ==1 and v_prev_data is None:
            v_prev_data = v_data
        vh_data = self.constrastive_divergence(v_prev_data,self.k)
        v = Variable(v_data)
        vh = Variable(vh_data.astype(np.float32))

        '''
        http://deeplearning.net/tutorial/rbm.HTML-Ausdruck(5)Von
Fehlerfunktion(loss)Ist(Freie Energie sichtbarer Schichtdaten)Wann(Sichtbare Schichtdaten-CD-k freie Energie)の差Wannなる。
        loss = (self.free_energy(v) - self.free_energy(vh)) / batch_size
        v->Die Zuordnung zu vh ist nicht im Lernen enthalten, also die CD-Die Variableisierung nach Abschluss der k-Verarbeitung ist abgeschlossen
        '''

        loss = (self.free_energy(v) - self.free_energy(vh)) / batch_size
        return loss

    def free_energy(self,v):
        ''' Function to compute the free energy '''
        '''
Der Eingabewert v muss variabel sein
Ursprünglich nach der Aufnahme von SUM in Zeileneinheiten, Spalteneinheiten(Anzahl der Chargen)Es ist ein Prozess, der SUM dauern sollte
Immerhin werde ich SUM nehmen, also SUM auf einmal
        '''
        batch_size = v.data.shape[0]
        n_visible = self.n_visible
        real = self.real
        if real == 0:
            '''
Die sichtbare Schicht[0,1]Wann
            vbias_term = -1 * SUM((a(i) * v(i))
            '''
            vbias_term = F.sum(F.matmul(v,self.l.a))
        else:
            '''
Wenn die sichtbare Ebene eine reelle Zahl ist
            vbias_term = -0.5 * SUM((v(i)-a(i)) * (v(i)-a(i)))
Anzahl der Chargen in Chainer*In der Eingabeebene zu handhaben, die Vorspannung von jeder Zeile zu subtrahieren
Verwenden Sie zwangsweise m * n
            '''
            m = Variable(xp.ones((batch_size,1),dtype=xp.float32))
            n = F.reshape(self.l.a,(1,n_visible))
            v_ = v - F.matmul(m,n)
            vbias_term = -F.sum(0.5 * v_ * v_)

        wx_b = self.l(v)
        hidden_term = F.sum(F.log(1+F.exp(wx_b)))
        return -vbias_term-hidden_term

    def propup(self,vis):
        '''
Berechnen Sie die Wahrscheinlichkeitsverteilung versteckter Ebenen aus sichtbaren Ebenendaten
Die versteckte Schicht[0,1]Es gibt also die Wahrscheinlichkeit zurück, 1 zu sein.
Der Eingabewert vis ist immer xp(np)
        '''
        pre_sigmoid_activation = xp.dot(vis,self.l.W.data.T) + self.l.b.data
        return sigmoid(pre_sigmoid_activation)

    def propdown(self,hid):
        '''
Berechnen Sie die Wahrscheinlichkeitsverteilung der sichtbaren Ebene aus den Daten der verborgenen Ebene
Die sichtbare Schicht[0,1]Wann ist die Wahrscheinlichkeit, 1 zu werden, zurückgegeben.
Wenn die sichtbare Ebene eine reelle Zahl ist, gibt sie den Durchschnitt der Normalverteilung zurück. Die Verteilung ist auf 1 festgelegt.
Der versteckte Eingabewert ist immer xp(np)
        '''
        real = self.real
        if real == 0:
            pre_sigmoid_activation = xp.dot(hid,self.l.W.data) + self.l.a.data
            v_mean = sigmoid(pre_sigmoid_activation)
        else:
            v_mean = xp.dot(hid,self.l.W.data) + self.l.a.data
        return v_mean

    def sample_h_given_v(self,v0_sample):
        '''
        v0_sample → h1_Gibbs-Probenahme
        [0,1]Erstellen Sie einen zufälligen Wert von und vergleichen Sie ihn mit der Wahrscheinlichkeit von 1, die durch Popup berechnet wird
        h1_mean[i] >  p[i]Dann h1_sample[i] = 1
        h1_mean[i] <= p[i]Dann h1_sample[i] = 0
        '''
        h1_mean = self.propup(v0_sample)
        h1_sample = xp.random.binomial(size=h1_mean.shape,n=1,p=h1_mean)
        return h1_mean,h1_sample

    def sample_v_given_h(self,h0_sample):
        '''
        h0_sample → v1_Gibbs-Probenahme
Die sichtbare Schicht[0,1]Im Falle von
        [0,1]Der Wert von ist der Zufallswert p[i]Und vergleichen Sie es mit der Wahrscheinlichkeit von 1, die durch Popdown berechnet wird
        v1_mean[i] >  p[i]Dann v1_sample[i] = 1
        v1_mean[i] <= p[i]Dann v1_sample[i] = 0
Wenn die sichtbare Ebene eine reelle Zahl ist
        v1_sample[i]Ist durchschnittlich v1_mean[i]Weil es sich um eine Normalverteilung mit Varianz 1 handelt
Zufallswert u aus Normalverteilung mit Mittelwert 0 und Varianz 1[i]Und addieren Sie den durch Popdown berechneten Wert
        v1_sample[i] = v1_mean[i] + u[i]
        '''
        v1_mean = self.propdown(h0_sample)
        if self.real == 0:
            v1_sample = xp.random.binomial(size=v1_mean.shape,n=1,p=v1_mean)
        else:
            batch_number = h0_sample.shape[0]
            v1_sample = v1_mean + xp.random.randn(batch_number,self.n_visible)
        return v1_mean,v1_sample

    def gibbs_hvh(self,h0_sample):
        ''' h->v->Gibbs Sampling h'''
        v1_mean,v1_sample = self.sample_v_given_h(h0_sample)
        h1_mean,h1_sample = self.sample_h_given_v(v1_sample)
        return v1_mean,v1_sample,h1_mean,h1_sample

    def gibbs_vhv(self,v0_sample):
        ''' v->h->v Gibbs Sampling'''
        h1_mean,h1_sample = self.sample_h_given_v(v0_sample)
        v1_mean,v1_sample = self.sample_v_given_h(h1_sample)
        return h1_mean,h1_sample,v1_mean,v1_sample

    def constrastive_divergence(self,v0_sample,k=1):
        ''' CD-Verarbeitung von k, cupy ist erforderlich, um es GPU zu machen'''
        vh_sample = v0_sample
        for step in range(k):
            ph_mean,ph_sample,vh_mean,vh_sample = self.gibbs_vhv(vh_sample)
        return vh_sample

    def reconstruct(self, v):
        h = sigmoid(xp.dot(v,self.l.W.data.T) + self.l.b.data)
        reconstructed_v = sigmoid(xp.dot(h,self.l.W.data) + self.l.a.data)
        return reconstructed_v

Im Fall von Chainer können Sie chainer.links.Linear verwenden, um die Gewichtsmatrix (W) und die Vorspannung (b) der Abbildung jeder Schicht zu definieren. Im Fall von RBM ist eine zusätzliche Vorspannung erforderlich. l.add_param("a",(n_visible),dtype=xp.float32) Ich habe einen Parameter hinzugefügt. l.W: Gewichtsmatrix l.b:hbias l.a:vbaias Es wird sein. So verwalten Sie die Zuordnung von der sichtbaren Ebene zur verborgenen Ebene mit chainer.links.Linear Dies ist eine Umsetzung der in einem allgemeinen RBM-Buch beschriebenen Gewichtsmatrix. (Wij → Wji)

1. Experimentieren Sie mit MNIST

Ich habe mit dem folgenden Quellcode mit MNIST-Daten experimentiert. Da es keinen GPU-Server gab, wurde dieser von der CPU trainiert, sodass die Anzahl der Schulungen 50-mal beträgt. Dieses Mal wird die verborgene Schicht auf 500 Dimensionen eingestellt und die Ergebnisse mit einem Lernkoeffizienten von 0,01, einem Impuls von 0,5 und PCD-10 werden verwendet.

Das Folgende sind die Originaldaten. Tatsächlich gibt es 60.000 Fälle, aber nur 150 Fälle werden angezeigt mnist_original.png

Das Folgende ist ein Bild des oben rekonstruierten Bildes. Es ist fast reproduziert. mnist_reconstruct.png Es werden nur Elemente angezeigt.

Als nächstes ist ein Bild, das die Gewichtsmatrix visualisiert. Die verborgene Schicht hat 500 Dimensionen in Bezug auf die Basis jedes Vektors Es wird in 28 * 28 Bilder konvertiert. mnist_weight.png

Recommended Posts

Versuchen Sie, RBM mit Chainer zu implementieren.
Versuchen Sie, XOR mit PyTorch zu implementieren
Versuchen Sie, Parfüm mit Go zu implementieren
Versuchen Sie, Pferderennen mit Chainer vorherzusagen
Versuchen Sie Common Representation Learning mit Chainer
Versuchen Sie, XOR mit der Keras Functional API zu implementieren
Versuchen Sie es mit Chainer Deep Q Learning - Launch
Seq2Seq (1) mit Chainer
Versuchen Sie es mit Python.
Verwenden Sie Tensorboard mit Chainer
Versuchen Sie SNN mit BindsNET
Versuchen Sie eine Regression mit TensorFlow
Versuchen Sie, assoziativen Speicher durch Hop-Field-Netzwerk in Python zu implementieren
Versuchen wir nun die Gesichtserkennung mit Chainer (Vorhersagephase).
Versuchen Sie, das LWMA von MetaTrader mit der FIR-Filterfunktion von scipy zu implementieren
Versuchen wir nun die Gesichtserkennung mit Chainer (Lernphase)
Versuchen Sie, den Boden durch Rekursion herauszufordern
Versuchen Sie, das strukturierte gRPC-Protokoll einfach und einfach mit grpc_zap zu implementieren
Versuchen Sie die Funktionsoptimierung mit Optuna
Versuchen Sie es mit TensorFlow
Versuchen Sie die Kantenerkennung mit OpenCV
Versuchen Sie Google Mock mit C.
Versuchen Sie es mit matplotlib mit PyCharm
Versuchen Sie, mit einer Shell zu programmieren!
Versuchen Sie die GUI-Programmierung mit Hy
Versuchen Sie Auto Encoder mit Pytorch
Probieren Sie die Python-Ausgabe mit Haxe 3.2 aus
Versuchen Sie die Matrixoperation mit NumPy
Lernen Sie mit Chainer elliptische Bahnen
Versuchen Sie, CNN mit ChainerRL auszuführen
Probieren Sie verschiedene Dinge mit PhantomJS aus
Versuchen Sie Deep Learning mit FPGA
Seq2Seq (3) ~ CopyNet Edition ~ mit Chainer
Verwendung von Chainer mit Jetson TK1
Neuronales Netz beginnend mit Chainer
Versuchen Sie, Python mit Try Jupyter auszuführen
Bedingte GAN mit Chainer implementiert
Lassen Sie uns Yuma in Python 3 implementieren
Bildunterschriftengenerierung mit Chainer
Probieren Sie Selenium Grid mit Docker aus
Versuchen Sie die Gesichtserkennung mit Python
Probieren Sie OpenCV mit Google Colaboratory aus
SmoothGrad mit Chainer v2 implementiert
Deep Embedded Clustering mit Chainer 2.0
Ein bisschen im Kettenschiff stecken
Versuchen Sie es mit Kaggle leicht maschinell
Versuchen Sie TensorFlow MNIST mit RNN
Versuchen Sie, Jupyter Hub mit Docker zu erstellen
Versuchen Sie es mit Folium mit Anakonda
Implementierung der logistischen Regression mit NumPy
Einführung in Deep Learning (2) - Versuchen Sie Ihre eigene nichtlineare Regression mit Chainer-
Vermeiden Sie die Implementierung nutzloser Funktionen mit Vererbung
Probieren Sie Deep Learning mit FPGA-Select-Gurken aus
Versuchen Sie es mit Python + Beautiful Soup
Versuchen Sie, Yuma in der Sprache Go zu implementieren
Mehrschichtiges Perzeptron mit Kette: Funktionsanpassung
Versuchen Sie, Facebook mit Python zu betreiben
Versuchen Sie die Singularwertzerlegung mit Python
Versuchen Sie es mit TensorFlow Part 2
Versuchen Sie es mit einer http-Eingabeaufforderung mit interaktivem http-Zugriff