Le cerveau de l'intérieur (visualisation du passage du motif à travers le modèle de réseau de neurones artificiels)

Présentation


L'article est destiné à ceux qui se sont déjà intéressés à la question de ce qui se passe à l'intérieur du réseau de neurones artificiels ( ANN) . Maintenant, presque tout le monde peut développer son propre ANN en utilisant les bibliothèques prêtes à l'emploi disponibles dans la plupart des langages de programmation. Dans cet article, je vais essayer de montrer à quoi ressemble exactement l'objet ( Pattern ), en passant par les couches de l'ANN, développé et compilé à l'aide de la bibliothèque d' apprentissage en profondeur Tensorflow avec le complément Keras .

Logiciels utilisés


Les composants suivants sont requis (les versions que j'ai spécifiées pour mon boîtier):

  • tensorflow 1.10.0
  • keras 2.2.4
  • matplotlib 2.2.0
  • modul-os
  • numpy1.14.3

Il est également possible de dessiner l'architecture du réseau, mais pour cela il est nécessaire d'installer des outils de visualisation, dans mon cas des keras ont été utilisés, et dans la méthode

PLOT_PATTERN_PROCCESS(...) 

établir

PLOT_MODEL = True


 def PLOT_PATTERN_PROCCESS(model, pattern, FOLDER_TO_SAVE, grid_size=(3, 3), limit_size_layer=(15, 15), PLOT_MODEL=True): 

image

Idée principale


Il faut choisir un motif (le passage que nous allons observer), après l'avoir choisi, le réseau est divisé en couches tensorielles . Dans le cycle de la deuxième à la dernière couche, un nouveau réseau est créé, où la sortie est le numéro de la couche dans le cycle, et en sautant le motif, le résultat à la sortie du réseau est un tableau à n dimensions.

Implémentation


Connexion des bibliothèques

 from keras.models import * from keras.layers import * import matplotlib.pyplot as plt import os import numpy as np 

Méthodes utilisées:

  • def PLOT_PATTERN_PROCCESS (modèle, motif, FOLDER_TO_SAVE, grid_size = (3, 3), limit_size_layer = (15, 15), PLOT_MODEL = True):
     def PLOT_PATTERN_PROCCESS(model, pattern, FOLDER_TO_SAVE, grid_size=(3, 3), limit_size_layer=(15, 15), PLOT_MODEL=True): """ :param model:   keras :type model: Sequential :param pattern:  ,       :type pattern: np.array :param FOLDER_TO_SAVE:       :type FOLDER_TO_SAVE: str :param grid_size:     :type grid_size: tuple :param limit_size_layer:      :type limit_size_layer: tuple :param PLOT_MODEL:    :type PLOT_MODEL: PLOT_MODEL """ SAVE_AR_LIST = [] for num_layer in range(1, len(model.layers)): LO = model.layers[num_layer].output _model = Model(inputs=model.input, outputs=LO) if ( len(_model.output_shape) == 3 and _model.output_shape[1] > limit_size_layer[0] and _model.output_shape[2] > limit_size_layer[1] ): _output = _model.predict(pattern)[0] SAVE_AR_LIST.append( [ num_layer, model.layers[num_layer].name, _output.tolist() ] ) ### PIC_NUM = 0 while len(SAVE_AR_LIST) > 0: fig, axs = plt.subplots(nrows=grid_size[0], ncols=grid_size[1], figsize=(10, 10), tight_layout=True) xmin, xmax = plt.xlim() ymin, ymax = plt.ylim() for ax in axs.flat: [num_layer, layer_name, ar] = SAVE_AR_LIST.pop(0) ax.imshow(np.array(ar), cmap='viridis', extent=(xmin, xmax, ymin, ymax)) ax.set_title(layer_name + " " + str(np.array(ar).shape)) if len(SAVE_AR_LIST) == 0: break # plt.show() plt.savefig(os.path.join(FOLDER_TO_SAVE, str(PIC_NUM) + '.png'), fmt='png') plt.close(fig) PIC_NUM += 1 ### if PLOT_MODEL: from keras.utils.vis_utils import plot_model plot_model( model=model, to_file=os.path.join(FOLDER_TO_SAVE, model.name + " neural network architecture.png"), show_shapes=True, show_layer_names=True ) ### 

  • def build_model (IN_SHAPE = 50, CLASSES = 5) -> Séquentiel:
     def build_model(IN_SHAPE=50,CLASSES=5) -> Sequential: inputs_LAYER0 = Input(shape=(IN_SHAPE,IN_SHAPE)) Dense_2_2 = Dense(75, activation='relu')(inputs_LAYER0) Dense_2_3 = Dense(50, activation='relu', name="my_dense")(Dense_2_2) Dense_2_4 = Dense(25, activation='relu')(Dense_2_3) Dense_2_5 = Dense(10, activation='relu')(Dense_2_4) flat_f_0 = Flatten()(Dense_2_5) final_layer= Dense(CLASSES, activation='softmax')(flat_f_0) # model = Model(input=inputs_LAYER0, output=final_layer, name="simple model") model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) model.summary() return model 


Code de programme

 model_ = build_model() pattern = np.random.sample((1,50,50)) os.makedirs("PLOT_PATTERN_PROCCESS") PLOT_PATTERN_PROCCESS( model = model_, pattern = pattern, FOLDER_TO_SAVE = "PLOT_PATTERN_PROCCESS", PLOT_MODEL=False, grid_size=(2, 2) ) 

Description du programme


La méthode

 build_model() 

renvoie un modèle ANN au format séquentiel , conçu pour classer quelque chose en 5 classes.

model.summary ()
 _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) (None, 50, 50) 0 _________________________________________________________________ dense_1 (Dense) (None, 50, 75) 3825 _________________________________________________________________ my_dense (Dense) (None, 50, 50) 3800 _________________________________________________________________ dense_2 (Dense) (None, 50, 25) 1275 _________________________________________________________________ dense_3 (Dense) (None, 50, 10) 260 _________________________________________________________________ flatten_1 (Flatten) (None, 500) 0 _________________________________________________________________ dense_4 (Dense) (None, 5) 2505 ================================================================= Total params: 11,665 Trainable params: 11,665 Non-trainable params: 0 _________________________________________________________________ 


Comme vous pouvez le voir sur l'architecture, un motif est un tableau de taille 50x50. Variable

 pattern 

et il y a un objet observable.
Ensuite, un répertoire est créé

 os.makedirs("PLOT_PATTERN_PROCCESS") 
,
où tout le résultat sera enregistré.

Description de la méthode PLOT_PATTERN_PROCCESS


J'ai décrit le sens de la méthode ci-dessus, mais il est important de dire que nous n'avons pas besoin de toutes les couches, car les sorties de certaines couches ne peuvent pas être affichées ou cela ne sera pas informatif.
L'obtention du modèle de sortie se produit ici:

 _output = _model.predict(pattern)[0] 

Dans cette implémentation, vous pouvez afficher un modèle de sortie bidimensionnel dont les dimensions ne sont pas inférieures au paramètre

 limit_size_layer 

Alternant à travers les couches du modèle ANN, la variable

 SAVE_AR_LIST 
progressivement rempli de données:

  1. Numéro de couche

     num_layer 
  2. Nom du calque

     model.layers[num_layer].name 
  3. Tableau bidimensionnel en sortie

      _output.tolist() 

Exclure progressivement un résultat de

 SAVE_AR_LIST 
,
et le mettre dans la cellule de toile

 ax.imshow(np.array(ar), cmap='viridis', extent=(xmin, xmax, ymin, ymax)) 
.
Le résultat est un fichier (0.png)

image

Recommandations


  • Définissez le nom du calque comme suit:

     Dense_2_3 = Dense(50, activation='relu', name="my_dense")(Dense_2_2) 

    Ceci est très pratique lors de l'évaluation et de la comparaison avec la neuroarchitecture.
  • En utilisant cette approche, il est intéressant de voir comment le modèle change lors du passage du réseau lors de l'apprentissage d'une époque à l'autre
  • N'installez pas la grille

     grid_size 

    grand parce que la taille des images affichées sera petite et non informative
  • Si vous observez le passage en dynamique (pendant l'entraînement ou en passant un pack de motifs), on parle déjà d'informations de grandes tailles. Pour réduire la RAM occupée par l'application, il est préférable d'enregistrer des tableaux dans des fichiers sur un PC, par exemple, au format JSON , et après avoir traité tous les modèles, parcourez les fichiers un par un et transformez-les en images

Bonne chance!

Source: https://habr.com/ru/post/fr438972/


All Articles