Neuroplastizität in künstlichen neuronalen Netzen

    Hallo Habr, wir haben uns lange nicht gesehen. In diesem Beitrag möchte ich über ein so relativ neues Konzept im maschinellen Lernen wie Transferlernen sprechen . Da ich keine fundierte Übersetzung dieses Begriffs gefunden habe, enthält der Titel des Beitrags auch einen anderen, aber ähnlichen Begriff, der eine biologische Voraussetzung für die Formalisierung der Theorie des Wissenstransfers von einem Modell zum anderen zu sein scheint. Der Plan lautet also wie folgt: Betrachten Sie zunächst den biologischen Hintergrund. Nachdem wir den Unterschied zwischen dem Transferlernen aus einer sehr ähnlichen Idee des Vortrainings eines tiefen neuronalen Netzwerks angesprochen haben ; und am Ende diskutieren wir das eigentliche Problem des semantischen Bild-Hashings. Um dies zu tun, werden wir nicht schüchtern sein und ein tiefes (19- schichtiges ) neuronales Netzwerk von Gewinnern des Wettbewerbs imagenet 2014 aufnehmenNehmen Sie im Abschnitt "Lokalisierung und Klassifizierung" ( Visual Geometry Group , Universität Oxford) eine kleine Korrektur vor, extrahieren Sie einige der Ebenen und verwenden Sie sie für unsere Zwecke. Lass uns gehen.

    Neuroplastizität


    Betrachten Sie zunächst die Definition. Neuroplastizität ist die Eigenschaft des Gehirns, sich unter dem Einfluss von Erfahrung oder nach einer Verletzung zu verändern. Änderungen umfassen sowohl die Schaffung von synaptischen Verbindungen als auch die Schaffung neuer Neuronen . Bis vor relativ kurzer Zeit, bis in die 70er Jahre des 20. Jahrhunderts, glaubte man, dass ein Teil des Gehirns, insbesondere der Neocortex (der nur alle motorischen Fähigkeiten, das Sprechen, das Denken usw. umfasst), nach einer gewissen Zeit des Erwachsenwerdens statisch blieb und nur angepasst werden konnte die Stärke der Verbindungen zwischen Neuronen. Später bestätigten jedoch detailliertere Studien das Vorhandensein einer Neuroplastizität des gesamten Gehirns. Ich schlage vor, ein kurzes Video anzuschauen:



    Um wirklich die volle Kraft unseres Gehirns zu spüren, schauen wir uns das Experiment des Neurophysiologen Paul Bach-y-Rita an, deren Arbeit die Erkennung von Neuroplastizität in der wissenschaftlichen Gemeinschaft stark beeinflusst hat. Ein wichtiger Faktor, der die Motivation des Wissenschaftlers beeinflusste, war die Tatsache, dass sein Vater gelähmt war. Zusammen mit seinem Bruder Physiker konnten sie seinen Vater im Alter von 68 Jahren auf die Beine stellen, wodurch er sogar Extremsport betreiben konnte. Ihre Geschichte hat gezeigt, dass das menschliche Gehirn bereits in einem späten Alter rehabilitiert werden kann. Aber dies ist eine ganz andere Geschichte, zurück zu den Erfahrungen von 1969. Das Ziel war ernst: Blinden (von Geburt an) die Möglichkeit zu geben, etwas zu sehen. Zu diesem Zweck wurde ein Zahnarztstuhl wie folgt eingenommen und umgerüstet: Eine Fernsehkamera wurde neben den Stuhl gestellt, und ein Manipulator wurde an den Stuhl gebracht, wodurch es möglich wurde, den Maßstab und die Position der Kamera zu ändern. 400 Stimulanzien wurden in der Rückenlehne des Stuhls angebracht, welches ein Gitter bildete: das von der Kamera empfangene Bild wurde auf eine Größe von 20 mal 20 komprimiert; Die Stimulanzien befanden sich in einem Abstand von 12 mm voneinander. An jedem Stimulator war eine kleine Millimeterspitze angebracht, die proportional zu dem Strom vibrierte, der dem im Inneren des Stimulators befindlichen Solenoid zugeführt wurde.



    Mit einem Oszilloskop konnte das durch die Vibration von Stimulanzien erzeugte Bild visualisiert werden.



    Ein Jahr später entwickelte Paul eine mobile Version seines Systems:
    Mobiles Visier der 1970er Jahre
    Der Mann ist wie Mavrodi, aber das ist nicht er.



    Statt einer taktilen Signalübertragung nutzen sie heutzutage den „kurzen“ Weg durch ein sensibleres Organ - die Sprache. Wie sie in den Artikeln sagen, genügen einige Stunden, um das Bild von den Rezeptoren der Zunge wahrzunehmen.
    moderne Option
    Denken Sie, er isst Nudeln? Aber nein, er schaut mit seiner Zunge.





    Und es ist nicht verwunderlich, dass sie versuchen, einen solchen Fund zu monetarisieren :


    Wie funktioniert es? Die Neuronen sprechen in einer einfachen Sprache (nicht von Biologen und Neurophysiologen, sondern in der Sprache der Datenanalyse), um Zeichen effizient zu extrahieren und daraus Schlussfolgerungen zu ziehen. Ersetzt unser neuronales Netzwerk das bekannte Signal durch ein anderes Signal , werden in Schichten in der Nähe des Sensors (Auge, Zunge, Ohr usw.) immer noch gute Low-Level-Merkmale (unter Verwendung der unten gezeigten Computersicht sind dies verschiedene Gradientenübergänge oder -muster) extrahiert. d.). Die tieferen Ebenen versuchen, übergeordnete Attribute (Rad, Fenster) zu extrahieren. Und wahrscheinlich, wenn Sie im Tonsignal nach dem Rad des Autos suchen, werden wir es höchstwahrscheinlich nicht finden. Leider können wir nicht sehen, welche Zeichen Neuronen extrahieren, aber dank des Artikels "Visualisieren und Verstehen von Faltungsnetzwerken "Es gibt die Möglichkeit, die von einem tiefen neuronalen Faltungsnetzwerk extrahierten Merkmale auf niedriger und hoher Ebene zu betrachten. Dies ist natürlich kein biologisches Netzwerk, und vielleicht ist alles nicht so in der Realität. Zumindest gibt es ein intuitives Verständnis der Gründe dafür Sie können sogar den Rezeptor Sprache sehen.

    in dem großen Bild in der Spoiler mehrere Anzeichen jeder Schicht und die Faltung des Originalbildes, die sie aktivieren gezeigt. Wie Sie sehen können, desto tiefer, desto weniger abstrakt wird CP - Schildern.

    Visualisierung von Features in einem vollständig geschulten Modell
    Jedes graue Quadrat entspricht der Visualisierung des Filters (der für die Faltung verwendet wird) oder der Gewichtung eines Neurons, und jedes Farbbild ist der Teil des Originalbilds, der das entsprechende Neuron aktiviert. Aus Gründen der Übersichtlichkeit werden Neuronen innerhalb einer Schicht in thematische Gruppen eingeteilt.



    Es kann davon ausgegangen werden, dass unser Gehirn beim Austausch der Sensoren nicht alle Neuronen vollständig neu trainieren muss. Es reicht aus, nur diejenigen zu trainieren, die Merkmale auf hoher Ebene extrahieren - und der Rest kann bereits Merkmale auf hoher Ebene extrahieren. Die Praxis zeigt, dass es ungefähr das gleiche ist. Es ist unwahrscheinlich, dass das Gehirn in ein paar Stunden, in denen es mit einer Platte auf der Zunge geht, neue synaptische Verbindungen aufbaut, ohne die Fähigkeit zu verlieren, den Geschmack von Lebensmitteln mit den Rezeptoren der Zunge zu fühlen.

    Und jetzt wollen wir uns daran erinnern, wie die Geschichte der künstlichen neuronalen Netze begann. Im Jahr 1949 veröffentlichte Donald Hebb das Buch The Organization of Behaviour , das die ersten Prinzipien des ANN-Trainings beschreibt . Es ist erwähnenswert, dass moderne Lernalgorithmen nicht weit von diesen Prinzipien entfernt sind.
    • Wenn benachbarte Neuronen synchron aktiviert werden , wird die Verbindung zwischen ihnen verbessert .
    • Wenn die benachbarten Neuronen asynchron aktiviert werden , schwächt sich die Verbindung zwischen ihnen (tatsächlich hatte Hebb diese Regel nicht, sie wurde später als Addition hinzugefügt).

    Neun Jahre später schafft Frank Rosenblatt das erste Modell für den Unterricht mit einem Lehrer - dem Perzeptron . Der Autor des ersten künstlichen neuronalen Netzes verfolgte nicht das Ziel, einen universellen Approximator zu schaffen. Er war Neurophysiologe und hatte die Aufgabe, ein Gerät zu entwickeln, das sich wie ein Mensch trainieren lässt. Schauen Sie sich an, was Journalisten über das Perzeptron schreiben. IMHO, das ist schön:

    New York Time, 8. Juli 1958

    ...


    Am Perceptron wurden Hebbs Lernregeln implementiert. Wie wir sehen können, wurde die synaptische Plastizität in den Regeln bereits in gewissem Maße berücksichtigt. Und das Online-Lernen verleiht uns im Prinzip eine gewisse Plastizität - ein neuronales Netzwerk kann sich ständig in einem kontinuierlichen Datenstrom fortbilden, und seine Prognosen ändern sich im Laufe der Zeit, wobei Änderungen in den Daten ständig berücksichtigt werden. Es gibt jedoch keine Empfehlungen für andere Aspekte der Neuroplastizität wie sensorische Substitution oder Neurogenese. Es ist jedoch nicht überraschend, dass vor der Einführung der Neuroplastizität noch etwas mehr als 20 Jahre verbleiben. Angesichts der späteren Geschichte des ANN waren die Wissenschaftler nicht in der Lage, die Neuroplastizität zu simulieren, und es ging um das Überleben der Theorie im Prinzip. Erst nach der nächsten Renaissance der neuronalen Netze in den 2000er Jahren dank Menschen wie Hinton, LeCun , Benggio und Schmidthuber haben andere Wissenschaftler die Möglichkeit, sich umfassend mit maschinellem Lernen zu befassen und sich mit dem Konzept des Transferlernens zu befassen.

    Übertragen Sie das Lernen


    Definieren Sie die Ziele des Transferlernens. Die Autoren der Veröffentlichung im Jahr 2009 mit dem gleichen Namen gibt es drei Hauptziele:
    • höherer Start - Verbesserung der Qualität des Trainings bereits bei den ersten Iterationen aufgrund einer gründlicheren Auswahl der Anfangsparameter des Modells oder anderer a priori-Informationen;
    • höhere Steigung - Beschleunigung der Konvergenz des Lernalgorithmus;
    • höhere Asymptote - Verbesserung der oberen erreichbaren Qualitätsgrenze.



    Wenn Sie mit der umfassenden Netzwerkvorbereitung vertraut sindMit Autoencodern oder eingeschränkten Boltzmann-Maschinen werden Sie sofort denken: „Es hat sich also herausgestellt, dass ich bereits das Transferlernen geübt habe oder zumindest weiß, wie es geht.“ Es stellt sich aber nicht heraus. Die Autoren ziehen eine klare Grenze zwischen maschinellem Standardlernen und Transferlernen. In der Standardmethode haben Sie nur ein Ziel und einen Datensatz, und die Aufgabe besteht darin, dieses Ziel mit beliebigen Methoden zu erreichen. Als Teil der Problemlösung können Sie ein tiefgreifendes Netzwerk aufbauen, es mit einem gierigen Algorithmus vorab trainieren, ein Dutzend weiterer Netzwerke aufbauen und auf irgendeine Weise ein Ensemble daraus bilden. All dies wird jedoch im Rahmen der Lösung eines einzelnen Problems geschehen, und die Zeit, die für die Lösung eines solchen Problems aufgewendet wird, ist vergleichbar mit der Gesamtzeit, die für die Schulung jedes Modells und seiner Vorschulung aufgewendet wird.

    Stellen Sie sich nun vor, dass es zwei Aufgaben gibt, die möglicherweise sogar von verschiedenen Personen gelöst wurden. Einer von ihnen verwendet einen Teil des Modells des anderen (Quellaufgabe), um den Zeitaufwand für die Erstellung eines Modells von Grund auf zu verringern und die Leistung seines Modells (Zielaufgabe) zu verbessern. Der Prozess der Wissensübertragung von einem Problem auf ein anderes ist der Lerntransfer. Und unser Gehirn tut wahrscheinlich genau das. Wie im obigen Beispiel besteht seine eigentliche Aufgabe darin, den Geschmack mit den Rezeptoren der Zunge zu fühlen und mit den Augen zu sehen. Die Herausforderung besteht darin, visuelle Informationen mit Sprachrezeptoren wahrzunehmen. Und anstatt neue Neuronen zu züchten oder alte abzunehmen und erneut zu trainieren, passt das Gehirn das vorhandene neuronale Netzwerk nur geringfügig an, um ein Ergebnis zu erzielen.



    Ein weiteres Merkmal des Transferlernens besteht darin, dass Informationen nur vom alten auf das neue Modell übertragen werden können, da das alte Problem seit langem gelöst ist. Während des Standardansatzes können verschiedene Modelle, die an der Lösung des Problems beteiligt sind, Informationen miteinander austauschen.



    Dieser Beitrag bezieht sich nur auf den Teil des Transfer-Lernens, der sich auf die Aufgabe bezieht, bei einem Lehrer zu unterrichten, aber ich empfehle den Interessenten, das Original zu lesen. Von dort aus erfahren Sie, dass beispielsweise beim Lernen mit Verstärkung oder beim Training von Bayes'schen Netzwerken das Transferlernen früher eingesetzt wurde als in neuronalen Netzwerken.

    Lernen mit einem Lehrer bedeutet Lernen mit markierten Beispielen, während der Lernprozess mit Beispielen manchmal als induktives Lernen (Übergang vom Besonderen zum Allgemeinen) und als Verallgemeinerungsfähigkeit als induktiver Bias bezeichnet wird . Daher der zweite Name Transfer Learning - induktive Übertragung . Dann können wir sagen, dass die Aufgabe des Wissenstransfers beim induktiven Lernen darin besteht, das im Lernprozess des alten Modells angesammelte Wissen die Verallgemeinerungsfähigkeit des neuen Modells beeinflussen zu lassen (auch wenn ein anderes Problem gelöst wird).

    Der Wissenstransfer kann auch als eine gewisse Regularisierung betrachtet werden, die den Suchraum auf eine bestimmte Menge akzeptabler und guter Hypothesen beschränkt.



    Übe


    Ich hoffe, dass Sie zu diesem Zeitpunkt von einem scheinbar unauffälligen Ansatz wie dem Wissenstransfer durchdrungen waren. Schließlich kann man einfach sagen, dass dies kein Wissenstransfer ist, die Neuroplastizität weit hergeholt ist und der beste Name für diese Methode Kopieren-Einfügen ist. Dann bist du nur ein Pragmatiker. Das ist natürlich auch gut so, und dann wird dir zumindest der dritte Abschnitt gefallen. Versuchen wir, etwas zu wiederholen, das dem im ersten Abschnitt beschriebenen ähnelt, jedoch in einem künstlichen neuronalen Netzwerk.

    Zunächst formulieren wir das Problem. Angenommen, Sie haben eine sehr große Anzahl von Bildern. Es ist notwendig, eine Suche nach ähnlichen Bildern zu organisieren. Hier treten zwei Probleme auf. Erstens ist das Ähnlichkeitsmaß zwischen den Bildern nicht offensichtlich, und wenn Sie nur den euklidischen Abstand vom n * m-dimensionalen Vektor nehmen, ist das Ergebnis nicht sehr zufriedenstellend. Zweitens können wir einen vollständigen Scan der Datenbank nicht vermeiden, selbst wenn es ein Qualitätsmaß gibt, und die Datenbank enthält möglicherweise Milliarden von Bildern.

    Um dieses Problem zu lösen, können Sie semantisches Hashing verwenden. Eine dieser Methoden wird von Salakhudinova und Hinton im Artikel Semantic Hashing beschrieben. Ihre Idee ist, dass der ursprüngliche Datenvektor von einem Binärvektor kleiner Dimension codiert wird (in unserem Fall ist dies ein Bild und im ursprünglichen Artikel ein Binärvektor von Wörtern ). Mit dieser Kodierung können Sie nach ähnlichen Bildern in einer linearen Zeit von der Codelänge unter Verwendung der Hamming-Distanz suchen . Eine solche Kodierung wird als semantisch bezeichnet, da Bilder, die in Bezug auf Bedeutung und Inhalt (Texte, Musik usw.) im neuen Attributraum nahe beieinander liegen. Um diese Idee umzusetzen, verwendeten sie ein tiefes Vertrauensnetzwerk , dessen Lernalgorithmus 2006 von Hinton und dem Unternehmen entwickelt wurde:
    • Das Eingangsnetzwerk nimmt im Allgemeinen reale Werte (Gauß-Bernoulli-Rbm) und codiert sie in einen langen Binärvektor. Jede nächste Schicht versucht, die Länge des Binärcodes zu verringern (Berboulli-Bernoulli-Rbm).
    • Ein solches Netzwerk wird nacheinander von unten nach oben von seiner eigenen eingeschränkten Boltzmann-Maschine vorab trainiert, wobei jede nächste die Ausgabe der vorherigen als Eingabedaten verwendet.
    • Anschließend wird das Netzwerk in umgekehrter Reihenfolge bereitgestellt und als Deep-Auto-Encoder trainiert , der am Eingang einen leicht verrauschten Vektor empfängt, und versucht, das ursprüngliche, nicht verrauschte Bild wiederherzustellen. Dieser Schritt wird als Feindrehen bezeichnet.
    • Immerhin ist das Binärbild in der Mitte des Autoencoders der gewünschte Binär-Hash aus dem Eingabebild.



    Es scheint mir, dass dies ein brillantes Modell ist, und ich entschied, dass das Problem im Prinzip dank Hinton gelöst wurde. Ich habe mit dem Vortraining für den NVIDIA Tesla K20 begonnen und ein paar Tage gewartet. Es stellte sich heraus, dass nicht alles so rosig war, wie Hinton es beschreibt. Entweder weil die Bilder groß sind oder weil ich Gauß-Bernoulli-RBM verwendet habe und der Artikel Poisson-Bernoulli-RBM verwendet hat, oder weil die Daten spezifisch sind, oder weil ich im Allgemeinen nicht viel unterrichtet habe . Aber irgendwie wollte ich nicht länger warten. Und dann erinnerte ich mich an den Rat von Maxim Milakov - benutze Faltungsnetzwerke sowie den Begriff Transferlernen aus einer seiner Präsentationen. Natürlich gab es auch andere Möglichkeiten, angefangen von der Komprimierung der Bilddimension über die Quantifizierung von Farben bis hin zu klassischen Zeichen des Computer-Sehens und deren Kombination in einer Menge visueller Wörter. Aber wenn ich erst einmal den tiefen Lernpfad betreten habe, ist es nicht so einfach, ihn zu deaktivieren, und die Prämien, die Lernversprechen übertragen (vor allem Zeitersparnis), haben mich getäuscht.

    Es stellte sich heraus, dass die eingangs erwähnte VGG-Gruppe, die den ImageNet-Wettbewerb 2014 gewonnen hatte, ihr trainiertes neuronales Netz für den freien Zugang für nichtkommerzielle Zwecke ausgelegt hatte. Deshalb habe ich es für Forschungszwecke heruntergeladen.

    Im Allgemeinen ImageNet- Dies ist nicht nur ein Wettbewerb, sondern auch eine Bilddatenbank, die etwas mehr als eine Million echte Bilder enthält. Jedes Bild ist einer von 1000 Klassen zugeordnet. Das Set ist nach Klassen aufgeteilt, dh etwas mehr als 1000 Bilder pro Klasse. Die Oxford-Jungs gewannen die Nominierung für Lokalisierung und Klassifizierung. Da die Bilder mehr als ein Objekt enthalten können, basiert die Bewertung darauf, ob die richtige Antwort in den Top 5 der wahrscheinlichsten Varianten gemäß der Modellversion enthalten ist. Im Bild unten sehen Sie ein Beispiel für eines der Modelle auf den Bildern von imagenet. Achten Sie auf einen lustigen Fehler mit dem Dalmatiner, das Modell fand dort leider keine Kirschen.



    Bei einer solchen Variabilität des Datensatzes ist es logisch anzunehmen, dass es irgendwo im Netzwerk einen effektiven Merkmalsextraktor sowie einen Klassifizierer gibt, der entscheidet, zu welcher Klasse das Bild gehört. Ich möchte diesen Extraktor haben, ihn vom Klassifikator trennen und ihn verwenden, um einen tiefen Auto-Encoder aus einem Artikel über semantisches Hashing zu trainieren.

    Das neuronale VGG-Netzwerk wird im Caffe- Format trainiert und gespeichert . Eine sehr coole Bibliothek für tiefes Lernen, und vor allem - leicht zu erlernen, empfehle ich, dass Sie sich vertraut machen. Bevor Sie das VGG-Netzwerk mit caffe bearbeiten, schlage ich einen kurzen Blick auf das Netzwerk selbst vor. Wenn die Details interessant sind, empfehle ich den Originalartikel - Very Deep Convolutional Networks für die groß angelegte Bilderkennung(Der Name deutet bereits auf die Tiefe des Netzwerks hin). Und für diejenigen, die mit Faltungsnetzwerken überhaupt nicht vertraut sind, müssen Sie mindestens die russische Wikipedia lesen, bevor Sie fortfahren. Es dauert nicht länger als 5-10 Minuten (oder es gibt eine kleine Beschreibung zu Habré ).

    Für den Artikel und den Wettbewerb haben die Autoren also mehrere Modelle trainiert:



    Auf ihrer Seite haben sie die Optionen D und E veröffentlicht. Für das Experiment wird die 19-lagige Version von E verwendet, bei der die ersten 16 Schichten faltungsmäßig sind und die letzten drei vollständig miteinander verbunden sind. Die letzten drei Ebenen sind abhängig von der Größe der Bilder. Für das Experiment habe ich sie ohne nachzudenken ausgeworfen und die ersten 16 Ebenen belassen, da ich die Zeichen auf hoher Ebene gelöscht habe.

    Die Kaffeebibliothek verwendet Google, um Modelle zu beschreibenProtokollpuffer und eine vollständige Beschreibung des Netzwerks lauten wie folgt.

    19-lagiges Modell
    name: "VGG_ILSVRC_19_layers"
    input: "data"
    input_dim: 10
    input_dim: 3
    input_dim: 224
    input_dim: 224
    layers {
      bottom: "data"
      top: "conv1_1"
      name: "conv1_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 64
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv1_1"
      top: "conv1_1"
      name: "relu1_1"
      type: RELU
    }
    layers {
      bottom: "conv1_1"
      top: "conv1_2"
      name: "conv1_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 64
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv1_2"
      top: "conv1_2"
      name: "relu1_2"
      type: RELU
    }
    layers {
      bottom: "conv1_2"
      top: "pool1"
      name: "pool1"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool1"
      top: "conv2_1"
      name: "conv2_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 128
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv2_1"
      top: "conv2_1"
      name: "relu2_1"
      type: RELU
    }
    layers {
      bottom: "conv2_1"
      top: "conv2_2"
      name: "conv2_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 128
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv2_2"
      top: "conv2_2"
      name: "relu2_2"
      type: RELU
    }
    layers {
      bottom: "conv2_2"
      top: "pool2"
      name: "pool2"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool2"
      top: "conv3_1"
      name: "conv3_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_1"
      top: "conv3_1"
      name: "relu3_1"
      type: RELU
    }
    layers {
      bottom: "conv3_1"
      top: "conv3_2"
      name: "conv3_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_2"
      top: "conv3_2"
      name: "relu3_2"
      type: RELU
    }
    layers {
      bottom: "conv3_2"
      top: "conv3_3"
      name: "conv3_3"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_3"
      top: "conv3_3"
      name: "relu3_3"
      type: RELU
    }
    layers {
      bottom: "conv3_3"
      top: "conv3_4"
      name: "conv3_4"
      type: CONVOLUTION
      convolution_param {
        num_output: 256
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv3_4"
      top: "conv3_4"
      name: "relu3_4"
      type: RELU
    }
    layers {
      bottom: "conv3_4"
      top: "pool3"
      name: "pool3"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool3"
      top: "conv4_1"
      name: "conv4_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_1"
      top: "conv4_1"
      name: "relu4_1"
      type: RELU
    }
    layers {
      bottom: "conv4_1"
      top: "conv4_2"
      name: "conv4_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_2"
      top: "conv4_2"
      name: "relu4_2"
      type: RELU
    }
    layers {
      bottom: "conv4_2"
      top: "conv4_3"
      name: "conv4_3"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_3"
      top: "conv4_3"
      name: "relu4_3"
      type: RELU
    }
    layers {
      bottom: "conv4_3"
      top: "conv4_4"
      name: "conv4_4"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv4_4"
      top: "conv4_4"
      name: "relu4_4"
      type: RELU
    }
    layers {
      bottom: "conv4_4"
      top: "pool4"
      name: "pool4"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool4"
      top: "conv5_1"
      name: "conv5_1"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_1"
      top: "conv5_1"
      name: "relu5_1"
      type: RELU
    }
    layers {
      bottom: "conv5_1"
      top: "conv5_2"
      name: "conv5_2"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_2"
      top: "conv5_2"
      name: "relu5_2"
      type: RELU
    }
    layers {
      bottom: "conv5_2"
      top: "conv5_3"
      name: "conv5_3"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_3"
      top: "conv5_3"
      name: "relu5_3"
      type: RELU
    }
    layers {
      bottom: "conv5_3"
      top: "conv5_4"
      name: "conv5_4"
      type: CONVOLUTION
      convolution_param {
        num_output: 512
        pad: 1
        kernel_size: 3
      }
    }
    layers {
      bottom: "conv5_4"
      top: "conv5_4"
      name: "relu5_4"
      type: RELU
    }
    layers {
      bottom: "conv5_4"
      top: "pool5"
      name: "pool5"
      type: POOLING
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layers {
      bottom: "pool5"
      top: "fc6"
      name: "fc6"
      type: INNER_PRODUCT
      inner_product_param {
        num_output: 4096
      }
    }
    layers {
      bottom: "fc6"
      top: "fc6"
      name: "relu6"
      type: RELU
    }
    layers {
      bottom: "fc6"
      top: "fc6"
      name: "drop6"
      type: DROPOUT
      dropout_param {
        dropout_ratio: 0.5
      }
    }
    layers {
      bottom: "fc6"
      top: "fc7"
      name: "fc7"
      type: INNER_PRODUCT
      inner_product_param {
        num_output: 4096
      }
    }
    layers {
      bottom: "fc7"
      top: "fc7"
      name: "relu7"
      type: RELU
    }
    layers {
      bottom: "fc7"
      top: "fc7"
      name: "drop7"
      type: DROPOUT
      dropout_param {
        dropout_ratio: 0.5
      }
    }
    layers {
      bottom: "fc7"
      top: "fc8"
      name: "fc8"
      type: INNER_PRODUCT
      inner_product_param {
        num_output: 1000
      }
    }
    layers {
      bottom: "fc8"
      top: "prob"
      name: "prob"
      type: SOFTMAX
    }
    



    Um die beschriebene Reparatur durchzuführen , genügt es, alle Ebenen in der Modellbeschreibung zu entfernen, beginnend mit fc6 (vollständig verbundene Ebene). Aber es ist erwähnenswert, dass dann die Netzwerkleistung von oben unbegrenzt sein wird, weil Die Aktivierungsfunktion ist eine gleichgerichtete Lineareinheit :



    Diese Frage wird bequem mit einem Sigmoid gelöstvon der Netzwerksteckdose. Wir können hoffen, dass viele Neuronen entweder 0 oder eine große Anzahl sein werden. Dann, nachdem wir das Sigmoid genommen haben, erhalten wir viele Einheiten und 0,5 (das Sigmoid von 0 ist 0,5). Wenn wir die erhaltenen Werte im Bereich von 0 bis 1 normalisieren, können sie als Wahrscheinlichkeiten für die Aktivierung von Neuronen interpretiert werden, und fast alle liegen im Bereich von Null oder Eins. Die Wahrscheinlichkeit der Aktivierung eines Neurons wird als die Wahrscheinlichkeit des Vorhandenseins eines Zeichens im Bild interpretiert (zum Beispiel, ob ein menschliches Auge darauf ist).



    Hier ist eine typische Antwort von einem solchen Netzwerk in meinem Fall:

    normalisiertes Sigma der letzten Faltungsschicht
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    1,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,994934
    0,0
    0,0
    0,999047
    0,829219
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,997255
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    1,0
    1,0
    0,0
    0,999382
    0,0
    0,0
    0,0
    0,0
    0,988762
    0,0
    0,0
    1,0
    1,0
    0,0
    1,0
    1,0
    0,0
    1,0
    1,0
    1,0
    1,0
    1,0
    0,0
    1,0
    1,0
    0,0
    0,0
    1,0
    1,0
    0,0
    1,0
    1,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,847886
    0,0
    0,0
    0,0
    0,0
    0,957379
    0,0
    0,0
    0,0
    0,0
    0,0
    1,0
    0,999998
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    1,0
    0,999999
    0,0
    0,54814
    0,739735
    0,0
    0,0
    0,0
    0,912179
    0,0
    0,0
    0,78984
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,681776
    0,0
    0,0
    0,991501
    0,0
    0,999999
    0,999152
    0,0
    0,0
    1,0
    0,0
    0,0
    0,0
    0,0
    0,999996
    1,0
    0,0
    1,0
    1,0
    0,0
    0,880588
    0,0
    0,0
    0,0
    0,0
    0,0
    0,0
    0,836756
    0,995515
    0,0
    0,999354
    0,0
    1,0
    1,0
    0,0
    1,0
    1,0
    0,0
    0,999897
    0,0
    0,953126
    0,0
    0,0
    0,999857
    0,0
    0,0
    0,937695
    0.999983
    1,0
    0,0
    0,0
    0,0
    0,0
    0,0
    1,0
    0,0
    0,0
    0,0


    In caffe wird dieses Problem wie folgt behoben:

     layers {
       bottom: "pool5"
       top: "sigmoid1"
       name: "sigmoid1"
       type: SIGMOID
    }
    


    Caffe implementiert einen Python-Wrapper und der folgende Code initialisiert das Netzwerk und normalisiert es:

    caffe.set_mode_gpu()
    net = caffe.Classifier('deploy.prototxt', 'VGG_ILSVRC_19_layers.caffemodel',
                           channel_swap=(2,1,0),
                           raw_scale=255,
                           image_dims=(options.width, options.height))
    #..................
    out = net.forward_all(**{net.inputs[0]: caffe_in})
    out = out['sigmoid1'].reshape(out['sigmoid1'].shape[0], np.prod(out['sigmoid1'].shape[1:]))
    out = (out - 0.5)/0.5
    


    Im Moment haben wir also eine binäre (oder fast) Darstellung von Bildern mit hochdimensionalen Vektoren in der Hand, in meinem Fall 4608 muss das Deep Befief Network noch trainiert werden, um diese Darstellungen zu komprimieren. Das daraus resultierende Modell ist zu einem noch tieferen Netzwerk geworden. Lassen Sie uns ein Suchexperiment durchführen, ohne mehrere Tage auf das Lernen von DBN zu warten: Wir wählen ein zufälliges Bild aus und suchen nach mehreren nächstgelegenen Bildern in Bezug auf die Hamming-Entfernung. Beachten Sie, dass dies alles auf rohen Features auf einem Vektor hoher Dimension ohne Gewichtung von Zeichen beruht.

    Erläuterungen: Das erste Bild ist ein Bild einer Anfrage, ein zufälliges Bild aus der Datenbank; der Rest ist ihr am nächsten.



    andere Beispiele im Spoiler

































    Fazit und Referenzen


    Ich denke, Sie können leicht ein Beispiel finden, in dem Sie statische Schichten nicht nur übertragen, sondern auch auf Ihre eigene Weise trainieren. Angenommen, Sie können einen Teil Ihres Netzwerks mithilfe eines anderen Netzwerks initialisieren und anschließend Ihre Klassen neu trainieren.



    Und wenn Sie etwas versuchen, das dem im ersten Teil beschriebenen Experiment näher kommt? Bitte: Hier ist ein Beispielartikel , der Faltungs-Deep-Believe-Netzwerke verwendet, um Merkmale aus Audiosignalen zu extrahieren. Warum nicht trainierte Windungen verwenden, um die cDBN-Gewichte zu initialisieren? Warum ist ein solches Spektrogramm kein Bild und warum werden keine Low-Level-Funktionen verwendet:



    Wenn Sie mit der Verarbeitung natürlicher Sprache experimentieren und versuchen möchten, das Lernen zu übertragen, finden Sie hier einen geeigneten Artikel von LeKunzu beginnen. Und ja, auch hier wird der Text als Bild dargestellt.

    Transferlernen ist im Allgemeinen eine großartige Sache, und caffe ist eine coole Bibliothek für tiefes Lernen.

    Der Text enthält viele Links, von denen ich hier einige nennen werde:

    Jetzt auch beliebt: