Cet article est un mémo pour ma propre étude. Si vous avez des questions, je vous serais reconnaissant de bien vouloir les signaler.
Cet apprentissage est le suivant: Est-il possible de prendre une couche d'un modèle créé et formé avec des keras et de la réutiliser pour un modèle nouvellement créé?
Utilisez le modèle de cette page (https://qiita.com/yoho/items/e9a65b10ca510ab50a36). Le nom de la variable est 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
_________________________________________________________________
Utilisez vars () pour découvrir les variables du modèle.
002.py
vars(model)
Bien que cela ne soit pas illustré ici, vous pouvez voir les variables du modèle. Parmi eux, la variable _layers semble contenir une liste d'objets de calque.
J'essaierai d'y accéder.
003.py
model._layers
#La sortie est séparée par des sauts de ligne pour une visualisation facile.
#[<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>]
Vous pouvez également y accéder en tant que model.layers. La méthode getter est-elle définie? Dans ce cas, il semble qu'il n'y ait pas de input_Layer au début par rapport au cas de model._layers.
004.py
model.layers
#La sortie est séparée par des sauts de ligne pour une visualisation facile.
#[<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>]
Qu'en est-il de la dernière couche avec le moins de paramètres? Utilisez pprint pour la lisibilité.
005.py
import pprint
pprint.pprint(vars(model.layers[4]))
#Ce qui suit est la sortie.
"""
{'_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, #######Important ici#######
'units': 2,
'use_bias': True}
"""
La dernière couche reçoit 20 sorties de la couche précédente et produit 2 sorties, donc le nombre de paramètres de poids est de 20 x 2 = 40 et les paramètres de polarisation sont de 2.
Je ne suis pas sûr, mais il semble avoir deux des mêmes paramètres de poids (_trainable_weights [0] et kernel).
Quel est le paramètre de poids réel? Vérifions _trainable_weights [0] avec type ().
006.py
type( model.layers[4]._trainable_weights[0] )
#<class 'tensorflow.python.ops.resource_variable_ops.ResourceVariable'>
Cela ressemble à un objet ResourceVariable dans tensorflow, mais je ne vais pas chercher plus loin ici.
Il semble que get_weights () puisse être utilisé pour récupérer une liste de poids et de biais. La liste comporte 2 éléments.
007.py
type(model.layers[4].get_weights())
#<class 'list'>
len(model.layers[4].get_weights())
#2
Le contenu de cette liste est ndarray. Je vais regarder le contenu.
008.py
type(model.layers[4].get_weights()[0])#0ème confirmation dans la liste
#<class 'numpy.ndarray'>
model.layers[4].get_weights()[0]#0e dans la 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])#Première confirmation sur la liste
#<class 'numpy.ndarray'>
model.layers[4].get_weights()[1]#Premier dans la liste
#array([0.05854932, 0.07379959], dtype=float32)
Je ne sais pas quand les paramètres seront initialisés lorsque je construis le modèle, je vais donc vérifier s'ils sont initialisés lorsque je les incorpore dans le modèle.
Ici, nous utiliserons la dernière couche des cinq couches du modèle comme deuxième couche du nouveau modèle.
Puisque la couche de diversion est une couche qui reçoit 20 entrées, la couche d'entrée du nouveau modèle doit accepter 20 entrées.
009.py
inputs = keras.layers.Input(shape=(20,))
x = model.layers[4](inputs)
model_new = keras.Model(inputs=inputs, outputs=x)
J'étais connecté.
Si le calque est le même que le 5ème calque du modèle précédent, Vérifiez si les paramètres ont changé.
010.py
model_new.layers[1]
<keras.layers.core.Dense object at 0x1381741d0>#L'adresse de l'objet est la même.
model_new.layers[1].get_weights()[0]#Vérifiez si les paramètres ont changé-->Inchangé.
"""
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)
"""
Quand j'ai examiné cette couche avec vars (), Seule la valeur de la liste avec \ _inbound_nodes comme clé était différente.
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>]#Cela augmente.
keras.engine.base_layer.Node est un peu en attente.
Pour que les paramètres de ce calque ne changent pas pendant l'entraînement (geler le calque) Définissez la propriété entraînable sur False.
012.py
model_new.layers[1].trainable=False
Le modèle doit être compilé.
Recommended Posts