[PYTHON] Umleitung trainierter Keras-Modellschichten

Einführung

Dieser Artikel ist ein Memo für meine eigene Studie. Wenn Sie Fragen haben, würde ich mich freuen, wenn Sie darauf hinweisen könnten.

Dieses Lernen ist folgendes: Ist es möglich, eine Ebene aus einem mit Keras erstellten und trainierten Modell zu nehmen und für ein neu erstelltes Modell wiederzuverwenden?

Geschultes Modell

Verwenden Sie das Modell auf dieser Seite (https://qiita.com/yoho/items/e9a65b10ca510ab50a36). Der Variablenname ist model.

001.py


model.summary()

#Layer (type)                 Output Shape              Param #   
#=================================================================
#dense_1 (Dense)              (None, 100)               1100      
#_________________________________________________________________
#dense_2 (Dense)              (None, 100)               10100     
#_________________________________________________________________
#dense_3 (Dense)              (None, 40)                4040      
#_________________________________________________________________
#dense_4 (Dense)              (None, 20)                820       
#_________________________________________________________________
#dense_5 (Dense)              (None, 2)                 42        
#=================================================================
#Total params: 16,102
#Trainable params: 16,102
#Non-trainable params: 0
_________________________________________________________________

Verwenden Sie vars (), um herauszufinden, welche Variablen das Modell hat.

002.py


vars(model)

Obwohl hier nicht gezeigt, können Sie die Variablen sehen, die das Modell hat. Unter diesen scheint die Variable _layers eine Liste von Ebenenobjekten zu enthalten.

Ich werde versuchen, darauf zuzugreifen.

003.py


model._layers
#Die Ausgabe ist zur einfachen Anzeige durch Zeilenumbrüche getrennt.
#[<keras.engine.input_layer.InputLayer object at 0x138144208>, 
#<keras.layers.core.Dense object at 0x13811af98>, 
#<keras.layers.core.Dense object at 0x138144320>, 
#<keras.layers.core.Dense object at 0x1381443c8>, 
#<keras.layers.core.Dense object at 0x138144518>, 
#<keras.layers.core.Dense object at 0x1381741d0>]

Sie können auch als model.layers darauf zugreifen. Ist die Getter-Methode definiert? In diesem Fall scheint es am Anfang keine input_Layer zu geben, verglichen mit dem Fall von model._layers.

004.py


model.layers
#Die Ausgabe ist zur einfachen Anzeige durch Zeilenumbrüche getrennt.
#[<keras.layers.core.Dense object at 0x13811af98>, 
#<keras.layers.core.Dense object at 0x138144320>, 
#<keras.layers.core.Dense object at 0x1381443c8>, 
#<keras.layers.core.Dense object at 0x138144518>, 
#keras.layers.core.Dense object at 0x1381741d0>]

Untersuche die letzte Schicht

Was ist mit der letzten Schicht mit den wenigsten Parametern? Verwenden Sie pprint zur besseren Lesbarkeit.

005.py



import pprint
pprint.pprint(vars(model.layers[4]))
#Das Folgende ist die Ausgabe.
"""
{'_built': True,
 '_inbound_nodes': [<keras.engine.base_layer.Node object at 0x138174e10>],
 '_initial_weights': None,
 '_losses': [],
 '_metrics': [],
 '_non_trainable_weights': [],
 '_outbound_nodes': [],
 '_per_input_losses': {},
 '_per_input_updates': {},
 '_trainable_weights': [<tf.Variable 'dense_5/kernel:0' shape=(20, 2) dtype=float32, numpy=
array([[-0.07533632,  0.20118327],
       [-0.17458896, -0.44313124],
       [ 0.4008763 ,  0.3295961 ],
       [-0.40597808, -0.02159814],
       [ 0.59269255, -0.15129048],
       [-0.14078082, -0.44002545],
       [ 0.18300773,  0.17778364],
       [ 0.3685053 , -0.36274177],
       [-0.28516215, -0.0659026 ],
       [ 0.45126018, -0.2892398 ],
       [ 0.19851999, -0.39362603],
       [ 0.2631754 ,  0.40239784],
       [ 0.08184562, -0.08194606],
       [-0.43493706,  0.18896711],
       [ 0.36158973,  0.20016526],
       [-0.05036243, -0.20633343],
       [-0.41589907,  0.57210416],
       [-0.10199612, -0.37373352],
       [ 0.30416492, -0.19923651],
       [ 0.02667725, -0.5090254 ]], dtype=float32)>,
                        <tf.Variable 'dense_5/bias:0' shape=(2,) dtype=float32, numpy=array([0.05854932, 0.07379959], dtype=float32)>],
 '_updates': [],
 'activation': <function linear at 0x1380400d0>,
 'activity_regularizer': None,
 'bias': <tf.Variable 'dense_5/bias:0' shape=(2,) dtype=float32, numpy=array([0.05854932, 0.07379959], dtype=float32)>,
 'bias_constraint': None,
 'bias_initializer': <keras.initializers.Zeros object at 0x138180400>,
 'bias_regularizer': None,
 'dtype': 'float32',
 'input_spec': InputSpec(min_ndim=2, axes={-1: 20}),
 'kernel': <tf.Variable 'dense_5/kernel:0' shape=(20, 2) dtype=float32, numpy=
array([[-0.07533632,  0.20118327],
       [-0.17458896, -0.44313124],
       [ 0.4008763 ,  0.3295961 ],
       [-0.40597808, -0.02159814],
       [ 0.59269255, -0.15129048],
       [-0.14078082, -0.44002545],
       [ 0.18300773,  0.17778364],
       [ 0.3685053 , -0.36274177],
       [-0.28516215, -0.0659026 ],
       [ 0.45126018, -0.2892398 ],
       [ 0.19851999, -0.39362603],
       [ 0.2631754 ,  0.40239784],
       [ 0.08184562, -0.08194606],
       [-0.43493706,  0.18896711],
       [ 0.36158973,  0.20016526],
       [-0.05036243, -0.20633343],
       [-0.41589907,  0.57210416],
       [-0.10199612, -0.37373352],
       [ 0.30416492, -0.19923651],
       [ 0.02667725, -0.5090254 ]], dtype=float32)>,
 'kernel_constraint': None,
 'kernel_initializer': <keras.initializers.VarianceScaling object at 0x138174b70>,
 'kernel_regularizer': None,
 'name': 'dense_5',
 'stateful': False,
 'supports_masking': True,
 'trainable': True,                  #######Wichtig hier#######
 'units': 2,
 'use_bias': True}
"""

Die letzte Schicht empfängt 20 Ausgaben von der vorherigen Schicht und erzeugt 2 Ausgaben, so dass die Anzahl der Gewichtsparameter 20 x 2 = 40 und die Vorspannungsparameter 2 sind.

Ich bin nicht sicher, aber es scheint zwei der gleichen Gewichtungsparameter zu haben (trainierbare Gewichte [0] und Kernel).

Was ist der tatsächliche Gewichtsparameter? Lassen Sie uns _trainable_weights [0] mit type () überprüfen.

006.py


type( model.layers[4]._trainable_weights[0] )
#<class 'tensorflow.python.ops.resource_variable_ops.ResourceVariable'>

Es sieht aus wie ein ResourceVariable-Objekt im Tensorflow, aber ich werde hier nicht weiter suchen.

Es scheint, dass get_weights () verwendet werden kann, um eine Liste von Gewichten und Verzerrungen abzurufen. Die Liste enthält 2 Elemente.

007.py


type(model.layers[4].get_weights())
#<class 'list'>
len(model.layers[4].get_weights())
#2

Der Inhalt dieser Liste ist ndarray. Ich werde mir den Inhalt ansehen.

008.py


type(model.layers[4].get_weights()[0])#0. Bestätigung in der Liste
#<class 'numpy.ndarray'>
model.layers[4].get_weights()[0]#0. in der Liste
"""
array([[-0.07533632,  0.20118327],
       [-0.17458896, -0.44313124],
       [ 0.4008763 ,  0.3295961 ],
       [-0.40597808, -0.02159814],
       [ 0.59269255, -0.15129048],
       [-0.14078082, -0.44002545],
       [ 0.18300773,  0.17778364],
       [ 0.3685053 , -0.36274177],
       [-0.28516215, -0.0659026 ],
       [ 0.45126018, -0.2892398 ],
       [ 0.19851999, -0.39362603],
       [ 0.2631754 ,  0.40239784],
       [ 0.08184562, -0.08194606],
       [-0.43493706,  0.18896711],
       [ 0.36158973,  0.20016526],
       [-0.05036243, -0.20633343],
       [-0.41589907,  0.57210416],
       [-0.10199612, -0.37373352],
       [ 0.30416492, -0.19923651],
       [ 0.02667725, -0.5090254 ]], dtype=float32)
"""

type(model.layers[4].get_weights()[1])#Erste Bestätigung auf der Liste
#<class 'numpy.ndarray'>
model.layers[4].get_weights()[1]#Erster in der Liste
#array([0.05854932, 0.07379959], dtype=float32)

Nehmen Sie die Ebene heraus und versuchen Sie, ein neues Modell zu erstellen.

Ich bin mir nicht sicher, wann die Parameter beim Erstellen des Modells initialisiert werden. Daher werde ich prüfen, ob sie beim Einbetten in das Modell initialisiert werden.

Hier verwenden wir die letzte Ebene der fünf Ebenen des Modells als zweite Ebene des neuen Modells.

Da die Umleitungsschicht eine Schicht ist, die 20 Eingaben empfängt, sollte die Eingangsschicht des neuen Modells 20 Eingaben akzeptieren.

009.py


inputs = keras.layers.Input(shape=(20,))
x = model.layers[4](inputs)
model_new = keras.Model(inputs=inputs, outputs=x)

Ich war verbunden.

Ob die Ebene dieselbe Ebene wie die 5. Ebene des vorherigen Modells ist, Überprüfen Sie, ob sich die Parameter geändert haben.

010.py


model_new.layers[1]
<keras.layers.core.Dense object at 0x1381741d0>#Die Objektadresse ist dieselbe.
model_new.layers[1].get_weights()[0]#Überprüfen Sie, ob sich die Parameter geändert haben-->Nicht geändert.
"""
array([[-0.07533632,  0.20118327],
       [-0.17458896, -0.44313124],
       [ 0.4008763 ,  0.3295961 ],
       [-0.40597808, -0.02159814],
       [ 0.59269255, -0.15129048],
       [-0.14078082, -0.44002545],
       [ 0.18300773,  0.17778364],
       [ 0.3685053 , -0.36274177],
       [-0.28516215, -0.0659026 ],
       [ 0.45126018, -0.2892398 ],
       [ 0.19851999, -0.39362603],
       [ 0.2631754 ,  0.40239784],
       [ 0.08184562, -0.08194606],
       [-0.43493706,  0.18896711],
       [ 0.36158973,  0.20016526],
       [-0.05036243, -0.20633343],
       [-0.41589907,  0.57210416],
       [-0.10199612, -0.37373352],
       [ 0.30416492, -0.19923651],
       [ 0.02667725, -0.5090254 ]], dtype=float32)
"""

Als ich diese Ebene mit vars () untersuchte, Nur der Wert der Liste mit \ _inbound_nodes als Schlüssel war unterschiedlich.

011.py


pprint.pprint(model.layers[1]._inbound_nodes)
#[<keras.engine.base_layer.Node object at 0x138144be0>]
pprint.pprint(model_new.layers[1]._inbound_nodes)
#[<keras.engine.base_layer.Node object at 0x138174e10>,
# <keras.engine.base_layer.Node object at 0x110cfe198>]#Das nimmt zu.

keras.engine.base_layer.Node steht noch aus.

So stellen Sie die Parameter dieser Ebene so ein, dass sie sich während des Trainings nicht ändern (frieren Sie die Ebene ein) Setzen Sie die trainierbare Eigenschaft auf False.

012.py


model_new.layers[1].trainable=False

Das Modell muss kompiliert werden.

Zusammenfassung

  1. Sie können Ihre Lieblingsebene aus dem trainierten Keras NN-Modell extrahieren und für andere Modelle verwenden.
  2. Sie können die Ebenenparameter einfrieren, damit sie sich nicht ändern.

Recommended Posts

Umleitung trainierter Keras-Modellschichten
Implementierung von VGG16 mit Keras, die ohne Verwendung eines trainierten Modells erstellt wurden
Veröffentlichung eines geschulten Modells von fastText
Tensorflow / Keras-Zusammenfassung
Zweidimensionale Visualisierung von Dokumentvektoren mit einem von Word2Vec trainierten Modell
Visualisieren Sie das Keras-Modell mit Python 3.5
Vorteile der Verfeinerung des Django-Modells
[Keras] Batch-Inferenz der Bogenfläche
Fordern Sie die Bildklassifizierung mit TensorFlow2 + Keras 4 heraus. ~ Lassen Sie uns mit dem trainierten Modell ~ vorhersagen