[PYTHON] Introduction à l'apprentissage profond ~ Préparation au codage ~

Personne cible

Ceci est une continuation de l'article précédent (https://qiita.com/kuroitu/items/221e8c477ffdd0774b6b). Dans cet article, nous préparerons le codage. Si vous voulez l'implémenter vous-même, mais que c'est assez ... jetez un œil. (Fondamentalement, je ne peux pas utiliser de techniques compliquées, alors ne vous inquiétez pas) ** L'environnement de codage est jupyter notebook. ** ** Si vous voulez le gérer au niveau du module ailleurs, décommentez la commande telle que ʻimport`. Si cela ne fonctionne pas, faites-le moi savoir dans les commentaires ... Le prochain article est ici

table des matières

[Implémentation de méthode spéciale](#Implémentation de méthode spéciale) - [Implémentation de la méthode `__init__`](Implémentation de la méthode #__init__) - [Implémentation des méthodes `__repr__` et` __str__`](Implémentation des méthodes #__repr__ et __str__) - [Implémentation de la méthode `__len__`](Implémentation de la méthode #__len__) - [Implémentation de la méthode `__getitem__`](Implémentation de la méthode #__getitem__) - [Implémentation de la méthode `__setitem__`](Implémentation de la méthode #__setitem__) - [Implémentation de la méthode `__delitem__`](Implémentation de la méthode #__delitem__) -
[Implémentation de la méthode définie par l'utilisateur](#Implémentation de la méthode définie par l'utilisateur) - [Implémentation de la méthode `_rename`](Implémentation de la méthode #_rename) - [Implémentation de méthode ʻAppend`](implémentation de méthode #append) - [Implémentation de la méthode ʻExtend`](implémentation de la méthode #extend) - [Méthode ʻImpact of insert`](Implémentation de la méthode #insert) - [Implémentation de la méthode ʻextend_insert`](Implémentation de la méthode #extend_insert) - [Implémentation de la méthode `remove`](Implémentation de la méthode #remove) - [Implémentation d'autres méthodes](#Implémentation d'autres méthodes) - [Implémentation des propriétés](# Implémentation des propriétés) - [Code complet](# Code complet) - [Préparation du code pour une erreur de couche](#Préparation du code pour une erreur de couche) - [Conclusion](#Conclusion) - [Liste des codes affichés](# Liste des codes affichés)

Préparation du code du module de couche

Commencez par créer un conteneur de base.

baselayer.py

baselayer.py


import numpy as np


class BaseLayer():
    """
Toutes les classes de couches sous-jacentes
Décrivez le traitement commun à la couche intermédiaire et à la couche de sortie.
    """
    
    def __init__(self):
        pass
    
    
    def forward(self):
        """
Mise en œuvre de la propagation directe
        """
        pass
    
    
    def backward(self):
        """
Mise en œuvre de la rétropropagation
        """
        pass
    
    
    def update(self):
        """
Mise en œuvre de l'apprentissage des paramètres
        """
        pass
Je n'ai encore rien implémenté, donc c'est juste un conteneur. Seuls les noms de fonctions à définir sont implémentés. Ce sont la couche intermédiaire et la couche de sortie qui héritent de ce conteneur.
middlelayer.py

middlelayer.py


import numpy as np


#import .baselayer import BaseLayer


class MiddleLayer(BaseLayer):
    """
Classe moyenne
La couche d'entrée est également traitée comme l'une des couches intermédiaires en termes de montage.
    """
    pass
outputlayer.py

outputlayer.py


import numpy as np


#from .baselayer import BaseLayer


class OutputLayer(BaseLayer):
    """
Classe de couche de sortie
    """
    pass

Préparation du code du gestionnaire de couches

Ici, nous allons préparer un gestionnaire pour gérer les modules de couche. ** Enfin, rassemblez le code. Veuillez noter que vous avez peut-être oublié de changer le code au milieu. ** ** Fondamentalement, nous le ferons en gardant à l'esprit le type List et le type Dictionary de Python.

layermanager.py

layermanager.py


import numpy as np


#from .layer import *


class _TypeManager():
    """
Classe de gestionnaire pour les types de couches
    """
    N_TYPE = 2  #Nombre de types de couches
    
    MIDDLE = 0  #Numérotation des couches intermédiaires
    OUTPUT = 1  #Numérotation des couches de sortie


class LayerManager(_TypeManager):
    """
Classe Manager pour la gestion des couches
    """
    def __init__(self):
        pass
La classe `_TypeManager` est une classe qui contient le nombre de types de calques et leur numérotation. Le premier `_` (trait de soulignement) est une classe` privée` dans d'autres langues qui restreint l'accès à partir de modules externes. Cependant, Python n'a pas d'attribut `private` complet, il est donc accessible.

La classe LayerManager connaît le type Dictionary et vous permet de conserver une liste de couches et de les ajouter / supprimer. Aussi, héritons de _TypeManager.

Au fait, le module «layer» est un module pour importer tous les modules liés à «Layer».

layer.py

layer.py


from .middlelayer import *
from .outputlayer import *
from ._layererror import *

Le module _layererror sera décrit plus tard, mais nous prévoyons d'en faire un module qui résume les erreurs qui se produisent dans la couche.

Mise en œuvre de méthodes spéciales

Tout d'abord, implémentez une méthode spéciale de la classe LayerManager. Voir Documentation officielle pour une liste de méthodes spéciales.

Implémentation de la méthode __init __

Maintenant, implémentez la méthode __init__ de la classe LayerManager. En premier lieu, la méthode __init__ est l'une des méthodes spéciales de Python et l'une des méthodes appelées lors de la création d'une instance d'une classe. En d'autres termes, décrivez l'action que vous souhaitez effectuer lorsque la classe LayerManager est générée. ici

  • Gardez une liste de couches
  • Gardez une liste de noms de couches
  • Gardez le nombre de couches par type

Je veux que vous le fassiez, alors mettez-le en œuvre de cette façon.

Implémentation de `__init__`

layermanager.py


    def __init__(self):
        self.__layer_list = []  #Liste des couches
        self.__name_list = []   #Liste de noms pour chaque couche
        self.__ntype = np.zeros(self.N_TYPE)  #Nombre de couches par type
Bien sûr, je ne veux pas être touché de l'extérieur, alors rendons-le `privé` avec` __` (deux traits de soulignement).

Implémentation des méthodes __repr__ et __str__

La méthode __repr__ est une représentation sous forme de chaîne" officielle "appelée depuis la fonction repr, une des fonctions intégrées de Python. Cela s'appelle "officiel", mais le fait est que ce sont des informations détaillées. La méthode __str__ est une représentation sous forme de chaîne" non officielle "qui est appelée depuis l'une des fonctions intégrées de Python, la fonction str et les fonctions intégrées format et print. Le sens du terme «informel» est qu'il est facile à lire.

Implémentation des méthodes `__repr__` et` __str__`

layermanager.py


    def __repr__(self):
        layerRepr= "layer_list: " + repr(self.__layer_list)
        nameRepr = "name_list: " + repr(self.__name_list)
        ntypeRepr = "ntype: " + repr(self.__ntype)
        return (layerRepr + "\n"
                + nameRepr + "\n"
                + ntypeRepr)
    
    
    def __str__(self):
        layerStr = "layer_list: " + str(self.__layer_list)
        nameStr = "name_list: " + str(self.__name_list)
        ntypeStr = "ntype: " + str(self.__ntype)
        return (layerStr + "\n"
                + nameStr + "\n"
                + ntypeStr)

Implémentation de la méthode __len__

La méthode __len__ décrit le comportement lorsqu'elle est appelée à partir de la fonction len, qui est l'une des fonctions intégrées de Python. Retournons le nombre de couches que possède la classe LayerManager.

Implémentation de `__len__`

layermanager.py


    def __len__(self):
        """
Fonctions intégrées Python`len`Décrit l'opération lorsqu'elle est appelée depuis.
Renvoie la somme du nombre de couches par type.
        """
        return np.sum(self.__ntype)

Implémentation de la méthode __getitem__

La méthode __getitem__ est une méthode appelée lors de la récupération d'un élément en spécifiant un index etc. dans une liste Python ou un tableau numpy.

Implémentation de `__getitem__`

layermanager.py


    def __getitem__(self, key):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        x = lm[3].~~
Est appelé lors de l'accès à un élément d'une liste ou d'un tableau, comme
Décrivez l'opération à ce moment-là.
tranche et str,Autoriser uniquement l'accès int.
        """
        if isinstance(key, slice):
            #Si la clé est une tranche, reportez-vous à la liste des calques avec tranche.
#Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            return self.__layer_list[key]
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Renvoie les éléments de la liste des couches applicables.
            if key in self.__name_list:
                index = self.__name_list.index(key)
                return self.__layer_list[index]
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si key est un entier, renvoie l'élément correspondant dans la liste des couches.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            return self.__layer_list[key]
        else:
            raise KeyError("{}: Not defined such key type.".format(key))
J'ai mis trop de commentaires et c'est devenu trop long ...

Implémentation de la méthode __setitem__

__setitem__ est une méthode souvent utilisée dans le type Dictionary, etc., qui est appelée lors de la définition de key et value comme lm [key] = value. Autoriser uniquement l'écrasement des éléments et donner une erreur dans le cas contraire. La raison est que nous ne voulons pas que l'utilisateur enregistre une clé égoïste car nous utiliserons la règle de dénomination plus tard.

Implémentation de `__setitem__`

layermanager.py


    def __setitem__(self, key, value):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        lm[1] = x
Est appelé lors de l'accès à un élément d'une liste ou d'un tableau, comme
Décrivez l'opération à ce moment-là.
Seul l'écrasement des éléments est autorisé et l'ajout de nouveaux éléments est interdit.
        """
        value_type = ""
        if isinstance(value, list):
            #Spécifié sur le côté droit'value'Mais'list'Si
            #Tous les éléments'BaseLayer'Erreur si classe ou ne l'hérite pas.
            if not np.all(
                np.where(isinstance(value, BaseLayer), True, False)):
                self.AssignError()
            value_type = "list"
        elif isinstance(value, BaseLayer):
            #Spécifié sur le côté droit'value'Mais'BaseLayer'Est-ce une classe?
            #Erreur s'il n'est pas hérité.
            self.AssignError(type(value))
        if value_type == "":
            value_type = "BaseLayer"
            
        if isinstance(key, slice):
            #Si la clé est une tranche, écrasez l'élément dans la liste des calques.
            #pourtant'value_type'Mais'list'Sinon, une erreur.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            if value_type != "list":
                self.AssignError(value_type)
            self.__layer_list[key] = value
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Remplacez les éléments dans la liste des calques applicables.
            #pourtant'value_type'Mais'BaseLayer'Sinon, une erreur.
            if value_type != "BaseLayer":
                raise AssignError(value_type)
            if key in self.__name_list:
                index = self.__name_list.index(key)
                self.__layer_list[index] = value
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si la clé est un entier, écrasez l'élément correspondant dans la liste des couches.
            #pourtant'value_type'Mais'BaseLayer'Sinon, une erreur.
            #Aussi, une valeur anormale(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            if value_type != "BaseLayer":
                raise AssignError(value_type)
            self.__layer_list[key] = value
        else:
            raise KeyError(key, ": Undefined such key type.")

Implémentation de la méthode __delitem__

__delitem__ est une méthode appelée pardel lm [key]etc. Cela supprime simplement l'élément spécifié. Cependant, le traitement après suppression est un peu gênant.

Implémentation de `__delitem__`

layermanager.py


    def __delitem__(self, key):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        del lm[2]
Parce qu'il est appelé lorsque l'élément de la liste ou du tableau est accédé par l'instruction del comme
Décrivez l'opération à ce moment-là.
Si l'élément spécifié existe, il sera supprimé et renommé.
        """
        if isinstance(key, slice):
            #Si la clé est une tranche, supprimez l'élément spécifié tel quel
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            del self.__layer_list[slice]
            del self.__name_list[slice]
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Supprimez l'élément concerné.
            if key in self.__name_list:
                del self.__layer_list[index]
                del self.__name_list[index]
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si la clé est un entier, supprimez l'élément correspondant dans la liste des couches.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            del self.__layer_list[key]
        else:
            raise KeyError(key, ": Undefined such key type.")
        
        #Renommer
        self._rename()
L'implémentation elle-même est similaire à `__getitem__` etc., mais pour renommer, le processus est lancé vers une autre fonction` _rename`. Vous pouvez vous attendre à ce qu'il soit utilisé à divers endroits. Ceci termine la mise en œuvre de méthodes spéciales. D'autres méthodes spéciales n'ont pas besoin d'être définies, elles seront donc transmises.

Serpentin

Au fait, «_» (trait de soulignement simple) signifie l'attribut «privé», qui est plus faible que «__» (double trait de soulignement). Ceci est accessible de l'extérieur en tant que nom de classe._rename, mais les doubles traits de soulignement ne sont accessibles qu'en utilisant, par exemple, nom de classe ._ nom de module __ nom de méthode. .. De plus, les fonctions de module qui n'appartiennent pas à une classe ne peuvent pas être importées par from module name import * si private est spécifié par _. Vous devez l'appeler "à partir du nom du module import _ nom de la méthode".

Implémentation de méthodes définies par l'utilisateur

À partir de là, nous implémenterons des fonctions définies par l'utilisateur (c'est-à-dire que nous définissons). Ici, je vais essentiellement implémenter les fameux points du type List et du type Dictionary.

Implémentation de la méthode _rename

Pour le moment, implémentez la méthode _rename qui apparaissait dans l'implémentation précédente. Quand est-ce nécessaire?

  • Les éléments sont ajoutés au milieu
  • Les éléments au milieu sont supprimés

Il y a deux manières. Si vous faites de votre mieux et réfléchissez à la logique, il semble que vous puissiez réduire le nombre de changements, mais c'est gênant, je vais donc vous raconter depuis le début. Parce qu'il est facile à mettre en œuvre. ** La maintenabilité est importante. ** ** <détails>

Implémentation de la méthode _rename </ summary>

layermanager.py


    def _rename(self):
        """
Lorsque la dénomination de la liste de noms enfreint les règles en raison de l'opération de liste
Renommez la liste de dénomination et chaque couche pour respecter à nouveau les règles.
        
La règle de dénomination est[Type de calque][Quel nombre]ça ira.
Si le type de calque est Couche intermédiaire, Milieu
Sortie pour la couche de sortie
Il est abrégé en.
Le nombre est compté par type.
        
Aussi, ici encore__Compte ntypes.
        """
        #Initialiser le nombre de couches par type
        self.__ntype = np.zeros(self.N_TYPE)
        
        #Recompter et renommer chaque couche
        for i in range(len(self)):
            if "Middle" in self.__name_list[i]:
                self.__ntype[self.MIDDLE] += 1
                self.__name_list[i] = "Middle{}".format(
                        self.__ntype[self.MIDDLE])
                self.__layer_list[i].name = "Middle{}".format(
                        self.__ntype[self.MIDDLE])
            elif "Output" in self.__name_list[i]:
                self.__ntype[self.OUTPUT] += 1
                self.__name_list[i] = "Output{}".format(
                        self.__ntype[self.OUTPUT])
                self.__layer_list[i].name = "Output{}".format(
                        self.__ntype[self.OUTPUT])
            else:
                raise UndefinedLayerType(self.__name_list[i])
Nous renommons également chaque couche, car nous envisageons de donner également à chaque couche une propriété `name`. Je pense que c'est utile pour générer des déclarations d'erreur. Si vous n'en avez pas besoin, vous pouvez l'effacer.

Implémentation de la méthode ʻAppend`

Implémentez la méthode familière ʻappend` dans la méthode d'ajout d'éléments à la liste. Puisqu'il est ajouté à la fin, il n'y a pas de traitement compliqué.

Implémentation de la méthode ʻappend`

layermanager.py


    def append(self, *, name="Middle", **kwds):
        """
Implémentation de la méthode append familière, qui est une méthode pour ajouter des éléments à une liste.
        """
        if "prev" in kwds:
            # 'prev'Est inclus dans le mot-clé
            #Cela signifie que le nombre d'éléments de la couche précédente est spécifié.
            #Fondamentalement, il est censé être le moment d'insérer la première couche, donc
            #En dehors de cela, il est essentiellement déterminé automatiquement et n'est pas spécifié.
            if len(self) != 0:
                if kwds["prev"] != self.__layer_list[-1].n:
                    #Erreur s'il ne correspond pas au nombre d'unités à la fin.
                    raise UnmatchUnitError(self.__layer_list[-1].n,
                                           kwds["prev"])
            else:
                if len(self) == 0:
                    #La première couche doit toujours spécifier le nombre d'unités d'entrée.
                    raise UnmatchUnitError("Input units", "Unspecified")
                else:
                    #Le nombre d'unités dans la dernière couche'kwds'Ajouter à
                    kwds["prev"] = self.__layer_list[-1].n
            
            #Lisez le type de couche et modifiez le nom selon la règle de dénomination
            if name == "mid" or "m":
                name = "Middle"
            elif name == "out" or "o":
                name = "Output"
            else:
                raise UndefinedLayerError(name)
            
            #Ajoutez un calque.
            if name == "Middle":
                #Incrémenter la couche par type
                self.__ntype[self.MIDDLE] += 1
                #Ajouter au nom
                name += str(self.__ntype[self.MIDDLE])
                #Ajouter à la liste de noms
                self.__name_list.append(name)
                #Enfin, créez un calque et ajoutez-le à la liste.
                self.__layer_list.append(
                        MiddleLayer(name=name, **kwds))
            elif name == "Output":
                #C'est également la même chose.
                self.__ntype[self.OUTPUT] += 1
                name += str(self.__ntype[self.OUTPUT])
                self.__name_list.append(name)
                self.__layer_list.append(
                        OutputLayer(name=name, **kwds))
            #Si vous ne dessinez pas d'instruction else ici, modifiez le nom selon la règle de dénomination
            #Déjà anormal au stade'name'Est omis.

Implémentation de la méthode ʻExend`

Ce n'est peut-être pas très familier? Implémentez la méthode ʻextend de List. <détails> <summary> Description de la méthode ʻextend </ summary>

La méthode ʻextend` est essentiellement une méthode pour joindre une liste dans une liste. Par exemple

example.py


x = [1, 2, 3]
y = [4, 5, 6]
x.append(y)
print(x)

Puis

[1, 2, 3, [4, 5, 6]]

Je pense que ce sera comme ça. ʻSi vous utilisez la méthode extend`

example.py


x = [1, 2, 3]
y = [4, 5, 6]
x.extend(y)
print(x)

Le résultat de

[1, 2, 3, 4, 5, 6]

Ce sera.

Je vais donc le mettre en œuvre.
Implémentation de la méthode ʻextend`

layermanager.py


    def extend(self, lm):
        """
Un autre gestionnaire de couches qui existe déjà dans la méthode d'extension'lm'Des éléments de
Tout ajouter.
        """
        if not isinstance(lm, LayerManager):
            # 'lm'Erreur si l'instance de n'est pas LayerManager.
            raise TypeError(type(lm), ": Unexpected type.")
        if len(self) != 0:
            if self.__layer_list[-1].n != lm[0].prev:
                #Avec le nombre d'unités dans votre dernière couche
                # 'lm'Erreur si le nombre d'entrées dans la première couche de n'est pas le même.
                raise UnmatchUnitError(self.__layer_list[-1].n,
                                       lm[0].prev)
        
        #Chaque'extend'Ajouter par méthode
        self.__layer_list.extend(lm.layer_list)
        self.__name_list.extend(lm.name_list)
        
        #Renommer
        self._rename()
Il y a `lm.layer_list` et` lm.name_list` dans le code, mais ceux-ci sont implémentés en tant que propriétés (` getter`) en utilisant le décorateur` property` décrit plus loin.

Implémentation de la méthode ʻInsert`

Cela peut ne pas être très familier non plus. Une méthode qui ajoute un élément à une position spécifiée.

Implémentation de la méthode ʻInsert`

layermanager.py


    def insert(self, prev_name, name="Middle", **kwds):
        """
Dans la méthode d'insertion, spécifiez le nom du calque précédent et combinez-le avec ce calque.
Ajoutez un élément.
        """
        # 'prev_name'Erreur si n'existe pas.
        if not prev_name in self.__name_list:
            raise KeyError(prev_name, ": No such key.")
        # 'prev'Est inclus dans le mot-clé
        # 'prev_name'Erreur s'il ne correspond pas au nombre d'unités du calque spécifié dans.
        if "prev" in kwds:
            if kwds["prev"] \
                != self.__layer_list[self.index(prev_name)].n:
                raise UnmatchUnitError(
                    kwds["prev"],
                    self.__layer_list[self.index(prev_name)].n)
        # 'n'Est inclus dans le mot-clé
        if "n" in kwds:
            # 'prev_name'Si ce n'est pas le dernier
            if prev_name != self.__name_list[-1]:
                #Erreur s'il ne correspond pas au nombre d'unités dans la couche suivante.
                if kwds["n"] != self.__layer_list[
                        self.index(prev_name)+1].prev:
                    raise UnmatchUnitError(
                        kwds["n"],
                        self.__layer_list[self.index(prev_name)].prev)
        #S'il n'y a pas encore d'éléments'append'Donnez une erreur pour utiliser la méthode.
        if len(self) == 0:
            raise RuntimeError(
                "You have to use 'append' method instead.")
        
        #Obtenir l'index de l'emplacement d'insertion
        index = self.index(prev_name) + 1
        
        #Lisez le type de couche et modifiez le nom selon la règle de dénomination
        if name == "mid" or "m":
            name = "Middle"
        elif name == "out" or "o":
            name = "Output"
        else:
            raise UndefinedLayerError(name)
        
        #Insérer un élément
        #En ce moment,'name'Ne respecte pas encore les règles de dénomination,
        #Je le renommerai plus tard alors ne vous inquiétez pas.
        if "Middle" in name:
            self.__layer_list.insert(index,
                                     MiddleLayer(name=name, **kwds))
            self.__name_list.insert(index, name)
        elif "Output" in name:
            self.__layer_list.insert(index,
                                     OutputLayer(name=name, **kwds))
            self.__name_list.insert(index, name)
        
        #Renommer
        self._rename()

Implémentation de la méthode ʻExtend_insert`

Ceci est l'original. Il se comporte comme une combinaison de la méthode ʻextend et de la méthode ʻinsert.

Implémentation de la méthode ʻExend_insert`

layermanager.py


    def extend_insert(self, prev_name, lm):
        """
C'est la fonction d'origine.
Il se comporte comme une combinaison de la méthode extend et de la méthode insert.
En termes simples, c'est comme insérer un autre gestionnaire de calques.
        """
        if not isinstance(lm, LayerManager):
            # 'lm'Erreur si l'instance de n'est pas LayerManager.
            raise TypeError(type(lm), ": Unexpected type.")
        # 'prev_name'Erreur si n'existe pas.
        if not prev_name in self.__name_list:
            raise KeyError(prev_name, ": No such key.")
        #Le nombre d'unités des couches avant et après l'emplacement spécifié et les première et dernière couches de lm
        #S'ils ne correspondent pas, une erreur se produit.
        if len(self) != 0:
            if self.__layer_list[self.index(prev_name)].n \
                    != lm.layer_list[0].prev:
                #Avec le nombre d'unités dans votre emplacement désigné'lm'Le premier nombre d'unités dans
                #S'ils ne correspondent pas, une erreur se produit.
                raise UnmatchUnitError(
                    self.__layer_list[self.index(prev_name)].n,
                    lm.layer_list[0].prev)
            if prev_name != self.__name_list[-1]:
                # 'prev_name'N'est-ce pas ma dernière couche
                if lm.layer_list[-1].n \
                    != self.__layer_list[self.index(prev_name)+1].prev:
                    # 'lm'Le nombre d'unités à la fin et au niveau suivant de votre emplacement désigné
                    # 'prev'Erreur s'il ne correspond pas au nombre d'unités.
                    raise UnmatchUnitError(
                        lm.layer_list[-1].n,
                        self.__layer_list[self.index(prev_name)+1].prev)
        else:
            #Si vous n'avez aucun élément'extend'J'obtiens une erreur lors de l'utilisation de la méthode.
            raise RuntimeError(
                "You have to use 'extend' method instead.")
        
        #Obtenir l'index de l'emplacement d'insertion
        index = self.index(prev_name) + 1
        
        #Éléments après l'emplacement d'insertion'buf'Après avoir évacué vers, retirez-le une fois
        #Ajouter un élément à l'aide de la méthode extend
        layer_buf = self.__layer_list[index:]
        name_buf = self.__name_list[index:]
        del self.__layer_list[index:]
        del self.__name_list[index:]
        self.extend(lm)
        
        #Ajouter l'élément qui a été évacué
        self.__layer_list.extend(layer_buf)
        self.__name_list.extend(name_buf)
        
        #Renommer
        self._rename()
Cela peut sembler un peu compliqué, mais c'est simple à faire. Peut-être existe-t-il un moyen plus simple de l'écrire ...

Implémentation de la méthode remove

La méthode remove supprime l'élément spécifié, n'est-ce pas? Cela a déjà été fait avec [Implémentation de l'instruction del](implémentation de la méthode #delitem), alors appelez-la simplement.

Implémentation de la méthode `remove`

layermanager.py


    def remove(self, key):
        """
La méthode remove supprime l'élément avec le nom spécifié.
Il est également autorisé à être spécifié par index.
        """
        #Déjà implémenté'del'La phrase est OK.
        del self[key]

Mise en œuvre d'autres méthodes

Autre que ce qui précède, c'est une liste de méthodes qui est utile.

Implémentation pratique de la méthode

layermanager.py


    def index(self, target):
        return self.__name_list.index(target)
    
    
    def name(self, indices):
        return self.__name_list[indices]

Mise en œuvre de la propriété

Nous allons implémenter les propriétés ici. En gros, seul getter est nécessaire, alors décorez-le avec @ property et implémentez-le. Si vous voulez ajouter setter, vous pouvez utiliser le décorateur @ property name.setter.

<détails>

Implémentation de la propriété </ summary>

layermanager.py


    @property
    def layer_list(self):
        return self.__layer_list
    
    
    @property
    def name_list(self):
        return self.__name_list
    
    
    @property
    def ntype(self):
        return self.__ntype

Code complet

Le code du gestionnaire de couches précédent est intégré et publié sous forme de texte intégral. Bien sûr, nous ajouterons des méthodes, etc. dans les prochains articles.

layermanager.py

layermanager.py


import numpy as np


#from .layer import *


class _TypeManager():
    """
Classe de gestionnaire pour les types de couches
    """
    N_TYPE = 2  #Nombre de types de couches
    
    MIDDLE = 0  #Numérotation des couches intermédiaires
    OUTPUT = 1  #Numérotation des couches de sortie


class LayerManager(_TypeManager):
    """
Classe Manager pour la gestion des couches
    """
    def __init__(self):
        self.__layer_list = []  #Liste des couches
        self.__name_list = []   #Liste de noms pour chaque couche
        self.__ntype = np.zeros(self.N_TYPE)  #Nombre de couches par type
    
    
    def __repr__(self):
        layerRepr= "layer_list: " + repr(self.__layer_list)
        nameRepr = "name_list: " + repr(self.__name_list)
        ntypeRepr = "ntype: " + repr(self.__ntype)
        return (layerRepr + "\n"
                + nameRepr + "\n"
                + ntypeRepr)
    
    
    def __str__(self):
        layerStr = "layer_list: " + str(self.__layer_list)
        nameStr = "name_list: " + str(self.__name_list)
        ntypeStr = "ntype: " + str(self.__ntype)
        return (layerStr + "\n"
                + nameStr + "\n"
                + ntypeStr)
    
    
    def __len__(self):
        """
Fonctions intégrées Python`len`Décrit l'opération lorsqu'elle est appelée depuis.
Renvoie la somme du nombre de couches par type.
        """
        return np.sum(self.__ntype)
    
    
    def __getitem__(self, key):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        x = lm[3].~~
Est appelé lors de l'accès à un élément d'une liste ou d'un tableau, comme
Décrivez l'opération à ce moment-là.
tranche et str,Autoriser uniquement l'accès int.
        """
        if isinstance(key, slice):
            #Si la clé est une tranche, reportez-vous à la liste des calques avec tranche.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            return self.__layer_list[key]
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Renvoie les éléments de la liste des couches applicables.
            if key in self.__name_list:
                index = self.__name_list.index(key)
                return self.__layer_list[index]
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si key est un entier, renvoie l'élément correspondant dans la liste des couches.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            return self.__layer_list[key]
        else:
            raise KeyError(key, ": Undefined such key type.")
    
    
    def __setitem__(self, key, value):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        lm[1] = x
Est appelé lors de l'accès à un élément d'une liste ou d'un tableau, comme
Décrivez l'opération à ce moment-là.
Seul l'écrasement des éléments est autorisé et l'ajout de nouveaux éléments est interdit.
        """
        value_type = ""
        if isinstance(value, list):
            #Spécifié sur le côté droit'value'Mais'list'Si
            #Tous les éléments'BaseLayer'Erreur si classe ou ne l'hérite pas.
            if not np.all(
                np.where(isinstance(value, BaseLayer), True, False)):
                self.AssignError()
            value_type = "list"
        elif isinstance(value, BaseLayer):
            #Spécifié sur le côté droit'value'Mais'BaseLayer'Est-ce une classe?
            #Erreur s'il n'est pas hérité.
            self.AssignError(type(value))
        if value_type == "":
            value_type = "BaseLayer"
            
        if isinstance(key, slice):
            #Si la clé est une tranche, écrasez l'élément dans la liste des calques.
            #pourtant'value_type'Mais'list'Sinon, une erreur.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            if value_type != "list":
                self.AssignError(value_type)
            self.__layer_list[key] = value
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Remplacez les éléments dans la liste des calques applicables.
            #pourtant'value_type'Mais'BaseLayer'Sinon, une erreur.
            if value_type != "BaseLayer":
                raise AssignError(value_type)
            if key in self.__name_list:
                index = self.__name_list.index(key)
                self.__layer_list[index] = value
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si la clé est un entier, écrasez l'élément correspondant dans la liste des couches.
            #pourtant'value_type'Mais'BaseLayer'Sinon, une erreur.
            #Aussi, une valeur anormale(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            if value_type != "BaseLayer":
                raise AssignError(value_type)
            self.__layer_list[key] = value
        else:
            raise KeyError(key, ": Undefined such key type.")
    
    
    def __delitem__(self, key):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        del lm[2]
Parce qu'il est appelé lorsque l'élément de la liste ou du tableau est accédé par l'instruction del comme
Décrivez l'opération à ce moment-là.
Si l'élément spécifié existe, il sera supprimé et renommé.
        """
        if isinstance(key, slice):
            #Si la clé est une tranche, supprimez l'élément spécifié tel quel
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            del self.__layer_list[slice]
            del self.__name_list[slice]
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Supprimez l'élément concerné.
            if key in self.__name_list:
                del self.__layer_list[index]
                del self.__name_list[index]
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si la clé est un entier, supprimez l'élément correspondant dans la liste des couches.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            del self.__layer_list[key]
        else:
            raise KeyError(key, ": Undefined such key type.")
        
        #Renommer
        self._rename()
    
    
    def _rename(self):
        """
Lorsque la dénomination de la liste de noms enfreint les règles en raison de l'opération de liste
Renommez la liste de dénomination et chaque couche pour respecter à nouveau les règles.
        
La règle de dénomination est[Type de calque][Quel nombre]ça ira.
Si le type de calque est Couche intermédiaire, Milieu
Sortie pour la couche de sortie
Il est abrégé en.
Le nombre est compté par type.
        
Aussi, ici encore__Compte ntypes.
        """
        #Initialiser le nombre de couches par type
        self.__ntype = np.zeros(self.N_TYPE)
        
        #Recompter et renommer chaque couche
        for i in range(len(self)):
            if "Middle" in self.__name_list[i]:
                self.__ntype[self.MIDDLE] += 1
                self.__name_list[i] = "Middle{}".format(
                        self.__ntype[self.MIDDLE])
                self.__layer_list[i].name = "Middle{}".format(
                        self.__ntype[self.MIDDLE])
            elif "Output" in self.__name_list[i]:
                self.__ntype[self.OUTPUT] += 1
                self.__name_list[i] = "Output{}".format(
                        self.__ntype[self.OUTPUT])
                self.__layer_list[i].name = "Output{}".format(
                        self.__ntype[self.OUTPUT])
            else:
                raise UndefinedLayerType(self.__name_list[i])
    
    def append(self, *, name="Middle", **kwds):
        """
Implémentation de la méthode append familière, qui est une méthode pour ajouter des éléments à une liste.
        """
        if "prev" in kwds:
            # 'prev'Est inclus dans le mot-clé
            #Cela signifie que le nombre d'éléments de la couche précédente est spécifié.
            #Fondamentalement, il est censé être le moment d'insérer la première couche, donc
            #En dehors de cela, il est essentiellement déterminé automatiquement et n'est pas spécifié.
            if len(self) != 0:
                if kwds["prev"] != self.__layer_list[-1].n:
                    #Erreur s'il ne correspond pas au nombre d'unités à la fin.
                    raise UnmatchUnitError(self.__layer_list[-1].n,
                                           kwds["prev"])
            else:
                if len(self) == 0:
                    #La première couche doit toujours spécifier le nombre d'unités d'entrée.
                    raise UnmatchUnitError("Input units", "Unspecified")
                else:
                    #Le nombre d'unités dans la dernière couche'kwds'Ajouter à
                    kwds["prev"] = self.__layer_list[-1].n
            
            #Lisez le type de couche et modifiez le nom selon la règle de dénomination
            if name == "mid" or "m":
                name = "Middle"
            elif name == "out" or "o":
                name = "Output"
            else:
                raise UndefinedLayerError(name)
            
            #Ajoutez un calque.
            if name == "Middle":
                #Incrémenter la couche par type
                self.__ntype[self.MIDDLE] += 1
                #Ajouter au nom
                name += str(self.__ntype[self.MIDDLE])
                #Ajouter à la liste de noms
                self.__name_list.append(name)
                #Enfin, créez un calque et ajoutez-le à la liste.
                self.__layer_list.append(
                        MiddleLayer(name=name, **kwds))
            elif name == "Output":
                #C'est également la même chose.
                self.__ntype[self.OUTPUT] += 1
                name += str(self.__ntype[self.OUTPUT])
                self.__name_list.append(name)
                self.__layer_list.append(
                        OutputLayer(name=name, **kwds))
            #Si vous ne dessinez pas d'instruction else ici, modifiez le nom selon la règle de dénomination
            #Déjà anormal au stade'name'Est omis.
    
    
    def extend(self, lm):
        """
Un autre gestionnaire de couches qui existe déjà dans la méthode d'extension'lm'Des éléments de
Tout ajouter.
        """
        if not isinstance(lm, LayerManager):
            # 'lm'Erreur si l'instance de n'est pas LayerManager.
            raise TypeError(type(lm), ": Unexpected type.")
        if len(self) != 0:
            if self.__layer_list[-1].n != lm[0].prev:
                #Avec le nombre d'unités dans votre dernière couche
                # 'lm'Erreur si le nombre d'entrées dans la première couche de n'est pas le même.
                raise UnmatchUnitError(self.__layer_list[-1].n,
                                       lm[0].prev)
        
        #Chaque'extend'Ajouter par méthode
        self.__layer_list.extend(lm.layer_list)
        self.__name_list.extend(lm.name_list)
        
        #Renommer
        self._rename()
    
    
    def insert(self, prev_name, name="Middle", **kwds):
        """
Dans la méthode d'insertion, spécifiez le nom du calque précédent et combinez-le avec ce calque.
Ajoutez un élément.
        """
        # 'prev_name'Erreur si n'existe pas.
        if not prev_name in self.__name_list:
            raise KeyError(prev_name, ": No such key.")
        # 'prev'Est inclus dans le mot-clé
        # 'prev_name'Erreur s'il ne correspond pas au nombre d'unités du calque spécifié dans.
        if "prev" in kwds:
            if kwds["prev"] \
                != self.__layer_list[self.index(prev_name)].n:
                raise UnmatchUnitError(
                    kwds["prev"],
                    self.__layer_list[self.index(prev_name)].n)
        # 'n'Est inclus dans le mot-clé
        if "n" in kwds:
            # 'prev_name'Si ce n'est pas le dernier
            if prev_name != self.__name_list[-1]:
                #Erreur s'il ne correspond pas au nombre d'unités dans la couche suivante.
                if kwds["n"] != self.__layer_list[
                        self.index(prev_name)+1].prev:
                    raise UnmatchUnitError(
                        kwds["n"],
                        self.__layer_list[self.index(prev_name)].prev)
        #S'il n'y a pas encore d'éléments'append'Donnez une erreur pour utiliser la méthode.
        if len(self) == 0:
            raise RuntimeError(
                "You have to use 'append' method instead.")
        
        #Obtenir l'index de l'emplacement d'insertion
        index = self.index(prev_name) + 1
        
        #Lisez le type de couche et modifiez le nom selon la règle de dénomination
        if name == "mid" or "m":
            name = "Middle"
        elif name == "out" or "o":
            name = "Output"
        else:
            raise UndefinedLayerError(name)
        
        #Insérer un élément
        #En ce moment,'name'Ne respecte pas encore les règles de dénomination,
        #Je le renommerai plus tard alors ne vous inquiétez pas.
        if "Middle" in name:
            self.__layer_list.insert(index,
                                     MiddleLayer(name=name, **kwds))
            self.__name_list.insert(index, name)
        elif "Output" in name:
            self.__layer_list.insert(index,
                                     OutputLayer(name=name, **kwds))
            self.__name_list.insert(index, name)
        
        #Renommer
        self._rename()
    
    
    def extend_insert(self, prev_name, lm):
        """
C'est la fonction d'origine.
Il se comporte comme une combinaison de la méthode extend et de la méthode insert.
En termes simples, c'est comme insérer un autre gestionnaire de calques.
        """
        if not isinstance(lm, LayerManager):
            # 'lm'Erreur si l'instance de n'est pas LayerManager.
            raise TypeError(type(lm), ": Unexpected type.")
        # 'prev_name'Erreur si n'existe pas.
        if not prev_name in self.__name_list:
            raise KeyError(prev_name, ": No such key.")
        #Le nombre d'unités des couches avant et après l'emplacement spécifié et les première et dernière couches de lm
        #S'ils ne correspondent pas, une erreur se produit.
        if len(self) != 0:
            if self.__layer_list[self.index(prev_name)].n \
                    != lm.layer_list[0].prev:
                #Avec le nombre d'unités dans votre emplacement désigné'lm'Le premier nombre d'unités dans
                #S'ils ne correspondent pas, une erreur se produit.
                raise UnmatchUnitError(
                    self.__layer_list[self.index(prev_name)].n,
                    lm.layer_list[0].prev)
            if prev_name != self.__name_list[-1]:
                # 'prev_name'N'est-ce pas ma dernière couche
                if lm.layer_list[-1].n \
                    != self.__layer_list[self.index(prev_name)+1].prev:
                    # 'lm'Le nombre d'unités à la fin et au niveau suivant de votre emplacement désigné
                    # 'prev'Erreur s'il ne correspond pas au nombre d'unités.
                    raise UnmatchUnitError(
                        lm.layer_list[-1].n,
                        self.__layer_list[self.index(prev_name)+1].prev)
        else:
            #Si vous n'avez aucun élément'extend'J'obtiens une erreur lors de l'utilisation de la méthode.
            raise RuntimeError(
                "You have to use 'extend' method instead.")
        
        #Obtenir l'index de l'emplacement d'insertion
        index = self.index(prev_name) + 1
        
        #Éléments après l'emplacement d'insertion'buf'Après avoir évacué vers, retirez-le une fois
        #Ajouter un élément à l'aide de la méthode extend
        layer_buf = self.__layer_list[index:]
        name_buf = self.__name_list[index:]
        del self.__layer_list[index:]
        del self.__name_list[index:]
        self.extend(lm)
        
        #Ajouter l'élément qui a été évacué
        self.__layer_list.extend(layer_buf)
        self.__name_list.extend(name_buf)
        
        #Renommer
        self._rename()
    
    
    def remove(self, key):
        """
La méthode remove supprime l'élément avec le nom spécifié.
Il est également autorisé à être spécifié par index.
        """
        #Déjà implémenté'del'La phrase est OK.
        del self[key]
    
    
    def index(self, target):
        return self.__name_list.index(target)
    
    
    def name(self, indices):
        return self.__name_list[indices]
    
    
    @property
    def layer_list(self):
        return self.__layer_list
    
    
    @property
    def name_list(self):
        return self.__name_list
    
    
    @property
    def ntype(self):
        return self.__ntype
Je pense que les commentaires représentent plus de la moitié ... Si cela vous gêne, supprimez-le ~

Préparation du code d'erreur de couche

Présentation du module _layererror. Pour le moment, seules les erreurs apparues jusqu'à présent dans l'implémentation sont implémentées. Cela peut également être ajouté.

_layererror.py

_layererror.py


class LayerManagerError(Exception):
    """Classe de base pour les erreurs définies par l'utilisateur dans les modules de couche"""
    pass


class AssignError(LayerManagerError):
    def __init__(self, value=None):
        if not value is None:
            self.value = value
            self.message = (str(value) 
                         + ": Assigning that value is prohibited.")
        else:
            self.value = None
            self.message = "Assigning that value is prohibited."
    
    
    def __str__(self):
        return self.message


class UnmatchUnitError(LayerManagerError):
    def __init__(self, prev, n):
        self.prev = prev
        self.n = n
        
        self.message = "Unmatch units: {} and {}.".format(prev, n)
    
    
    def __str__(self):
        return self.message


class UndefinedLayerError(LayerManagerError):
    def __init__(self, type_name):
        self.type = type_name
        self.message = str(type_name) + ": Undefined layer type."
    
    
    def __str__(self):
        return self.message
Je ne chevauche aucune exception définie par l'utilisateur, je vais donc les publier ici.

la première

_layererror.py


class LayerManagerError(Exception):
    """Classe de base pour les erreurs définies par l'utilisateur dans les modules de couche"""
    pass

Attraper des exceptions sur les calques

example.py


try:
    raise AssignError()
except LayerManagerError:
    print("catch LayerManagerError")

Il est destiné à être en mesure de détecter toutes les erreurs qui en héritent. Bien sûr, vous pouvez également détecter les erreurs individuellement. De plus, l'instruction d'erreur ne peut être sortie qu'après avoir défini la méthode __str__.

en conclusion

J'ai donc créé ici un modèle pour les objets de calque, un gestionnaire pour les gérer et un module pour le contrôle des erreurs. Nous continuerons d'ajouter le contenu de l'implémentation dans les articles suivants et suivants.

Liste des codes affichés

baselayer.py [here](#layer module code preparation)

baselayer.py


import numpy as np


class BaseLayer():
    """
Toutes les classes de couches sous-jacentes
Décrivez le traitement commun à la couche intermédiaire et à la couche de sortie.
    """
    
    def __init__(self):
        pass
    
    
    def forward(self):
        """
Mise en œuvre de la propagation directe
        """
        pass
    
    
    def backward(self):
        """
Mise en œuvre de la rétropropagation
        """
        pass
    
    
    def update(self):
        """
Mise en œuvre de l'apprentissage des paramètres
        """
        pass
middlelayer.py [here](#layer module code preparation)

middlelayer.py


import numpy as np


#import .baselayer import BaseLayer


class MiddleLayer(BaseLayer):
    """
Classe moyenne
La couche d'entrée est également traitée comme l'une des couches intermédiaires en termes de montage.
    """
    pass
outputlayer.py [here](#layer module code preparation)

outputlayer.py


import numpy as np


#from .baselayer import BaseLayer


class OutputLayer(BaseLayer):
    """
Classe de couche de sortie
    """
    pass
layermanager.py [ici](# code texte intégral)

layermanager.py


import numpy as np


#from .layer import *


class _TypeManager():
    """
Classe de gestionnaire pour les types de couches
    """
    N_TYPE = 2  #Nombre de types de couches
    
    MIDDLE = 0  #Numérotation des couches intermédiaires
    OUTPUT = 1  #Numérotation des couches de sortie


class LayerManager(_TypeManager):
    """
Classe Manager pour la gestion des couches
    """
    def __init__(self):
        self.__layer_list = []  #Liste des couches
        self.__name_list = []   #Liste de noms pour chaque couche
        self.__ntype = np.zeros(self.N_TYPE)  #Nombre de couches par type
    
    
    def __repr__(self):
        layerRepr= "layer_list: " + repr(self.__layer_list)
        nameRepr = "name_list: " + repr(self.__name_list)
        ntypeRepr = "ntype: " + repr(self.__ntype)
        return (layerRepr + "\n"
                + nameRepr + "\n"
                + ntypeRepr)
    
    
    def __str__(self):
        layerStr = "layer_list: " + str(self.__layer_list)
        nameStr = "name_list: " + str(self.__name_list)
        ntypeStr = "ntype: " + str(self.__ntype)
        return (layerStr + "\n"
                + nameStr + "\n"
                + ntypeStr)
    
    
    def __len__(self):
        """
Fonctions intégrées Python`len`Décrit l'opération lorsqu'elle est appelée depuis.
Renvoie la somme du nombre de couches par type.
        """
        return np.sum(self.__ntype)
    
    
    def __getitem__(self, key):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        x = lm[3].~~
Est appelé lors de l'accès à un élément d'une liste ou d'un tableau, comme
Décrivez l'opération à ce moment-là.
tranche et str,Autoriser uniquement l'accès int.
        """
        if isinstance(key, slice):
            #Si la clé est une tranche, reportez-vous à la liste des calques avec tranche.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            return self.__layer_list[key]
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Renvoie les éléments de la liste des couches applicables.
            if key in self.__name_list:
                index = self.__name_list.index(key)
                return self.__layer_list[index]
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si key est un entier, renvoie l'élément correspondant dans la liste des couches.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            return self.__layer_list[key]
        else:
            raise KeyError(key, ": Undefined such key type.")
    
    
    def __setitem__(self, key, value):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        lm[1] = x
Est appelé lors de l'accès à un élément d'une liste ou d'un tableau, comme
Décrivez l'opération à ce moment-là.
Seul l'écrasement des éléments est autorisé et l'ajout de nouveaux éléments est interdit.
        """
        value_type = ""
        if isinstance(value, list):
            #Spécifié sur le côté droit'value'Mais'list'Si
            #Tous les éléments'BaseLayer'Erreur si classe ou ne l'hérite pas.
            if not np.all(
                np.where(isinstance(value, BaseLayer), True, False)):
                self.AssignError()
            value_type = "list"
        elif isinstance(value, BaseLayer):
            #Spécifié sur le côté droit'value'Mais'BaseLayer'Est-ce une classe?
            #Erreur s'il n'est pas hérité.
            self.AssignError(type(value))
        if value_type == "":
            value_type = "BaseLayer"
            
        if isinstance(key, slice):
            #Si la clé est une tranche, écrasez l'élément dans la liste des calques.
            #pourtant'value_type'Mais'list'Sinon, une erreur.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            if value_type != "list":
                self.AssignError(value_type)
            self.__layer_list[key] = value
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Remplacez les éléments dans la liste des calques applicables.
            #pourtant'value_type'Mais'BaseLayer'Sinon, une erreur.
            if value_type != "BaseLayer":
                raise AssignError(value_type)
            if key in self.__name_list:
                index = self.__name_list.index(key)
                self.__layer_list[index] = value
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si la clé est un entier, écrasez l'élément correspondant dans la liste des couches.
            #pourtant'value_type'Mais'BaseLayer'Sinon, une erreur.
            #Aussi, une valeur anormale(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            if value_type != "BaseLayer":
                raise AssignError(value_type)
            self.__layer_list[key] = value
        else:
            raise KeyError(key, ": Undefined such key type.")
    
    
    def __delitem__(self, key):
        """
Par exemple
        lm = LayerManager()
        
        +----------------+
        | (Ajouter un élément à lm) |
        +----------------+
        
        del lm[2]
Parce qu'il est appelé lorsque l'élément de la liste ou du tableau est accédé par l'instruction del comme
Décrivez l'opération à ce moment-là.
Si l'élément spécifié existe, il sera supprimé et renommé.
        """
        if isinstance(key, slice):
            #Si la clé est une tranche, supprimez l'élément spécifié tel quel
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            del self.__layer_list[slice]
            del self.__name_list[slice]
        elif isinstance(key, str):
            #Si key est une chaîne, récupérez l'index dans la liste des noms de chaque couche et
            #Supprimez l'élément concerné.
            if key in self.__name_list:
                del self.__layer_list[index]
                del self.__name_list[index]
            else:
                #Si la clé n'existe pas, une KeyError est émise.
                raise KeyError("{}: No such item".format(key))
        elif isinstance(key, int):
            #Si la clé est un entier, supprimez l'élément correspondant dans la liste des couches.
            #Valeur inhabituelle(Index hors de portée, etc.)Quand est entré
            #Python me donne une erreur.
            del self.__layer_list[key]
        else:
            raise KeyError(key, ": Undefined such key type.")
        
        #Renommer
        self._rename()
    
    
    def _rename(self):
        """
Lorsque la dénomination de la liste de noms enfreint les règles en raison de l'opération de liste
Renommez la liste de dénomination et chaque couche pour respecter à nouveau les règles.
        
La règle de dénomination est[Type de calque][Quel nombre]ça ira.
Si le type de calque est Couche intermédiaire, Milieu
Sortie pour la couche de sortie
Il est abrégé en.
Le nombre est compté par type.
        
Aussi, ici encore__Compte ntypes.
        """
        #Initialiser le nombre de couches par type
        self.__ntype = np.zeros(self.N_TYPE)
        
        #Recompter et renommer chaque couche
        for i in range(len(self)):
            if "Middle" in self.__name_list[i]:
                self.__ntype[self.MIDDLE] += 1
                self.__name_list[i] = "Middle{}".format(
                        self.__ntype[self.MIDDLE])
                self.__layer_list[i].name = "Middle{}".format(
                        self.__ntype[self.MIDDLE])
            elif "Output" in self.__name_list[i]:
                self.__ntype[self.OUTPUT] += 1
                self.__name_list[i] = "Output{}".format(
                        self.__ntype[self.OUTPUT])
                self.__layer_list[i].name = "Output{}".format(
                        self.__ntype[self.OUTPUT])
            else:
                raise UndefinedLayerType(self.__name_list[i])
    
    def append(self, *, name="Middle", **kwds):
        """
Implémentation de la méthode append familière, qui est une méthode pour ajouter des éléments à une liste.
        """
        if "prev" in kwds:
            # 'prev'Est inclus dans le mot-clé
            #Cela signifie que le nombre d'éléments de la couche précédente est spécifié.
            #Fondamentalement, il est censé être le moment d'insérer la première couche, donc
            #En dehors de cela, il est essentiellement déterminé automatiquement et n'est pas spécifié.
            if len(self) != 0:
                if kwds["prev"] != self.__layer_list[-1].n:
                    #Erreur s'il ne correspond pas au nombre d'unités à la fin.
                    raise UnmatchUnitError(self.__layer_list[-1].n,
                                           kwds["prev"])
            else:
                if len(self) == 0:
                    #La première couche doit toujours spécifier le nombre d'unités d'entrée.
                    raise UnmatchUnitError("Input units", "Unspecified")
                else:
                    #Le nombre d'unités dans la dernière couche'kwds'Ajouter à
                    kwds["prev"] = self.__layer_list[-1].n
            
            #Lisez le type de couche et modifiez le nom selon la règle de dénomination
            if name == "mid" or "m":
                name = "Middle"
            elif name == "out" or "o":
                name = "Output"
            else:
                raise UndefinedLayerError(name)
            
            #Ajoutez un calque.
            if name == "Middle":
                #Incrémenter la couche par type
                self.__ntype[self.MIDDLE] += 1
                #Ajouter au nom
                name += str(self.__ntype[self.MIDDLE])
                #Ajouter à la liste de noms
                self.__name_list.append(name)
                #Enfin, créez un calque et ajoutez-le à la liste.
                self.__layer_list.append(
                        MiddleLayer(name=name, **kwds))
            elif name == "Output":
                #C'est également la même chose.
                self.__ntype[self.OUTPUT] += 1
                name += str(self.__ntype[self.OUTPUT])
                self.__name_list.append(name)
                self.__layer_list.append(
                        OutputLayer(name=name, **kwds))
            #Si vous ne dessinez pas d'instruction else ici, modifiez le nom selon la règle de dénomination
            #Déjà anormal au stade'name'Est omis.
    
    
    def extend(self, lm):
        """
Un autre gestionnaire de couches qui existe déjà dans la méthode d'extension'lm'Des éléments de
Tout ajouter.
        """
        if not isinstance(lm, LayerManager):
            # 'lm'Erreur si l'instance de n'est pas LayerManager.
            raise TypeError(type(lm), ": Unexpected type.")
        if len(self) != 0:
            if self.__layer_list[-1].n != lm[0].prev:
                #Avec le nombre d'unités dans votre dernière couche
                # 'lm'Erreur si le nombre d'entrées dans la première couche de n'est pas le même.
                raise UnmatchUnitError(self.__layer_list[-1].n,
                                       lm[0].prev)
        
        #Chaque'extend'Ajouter par méthode
        self.__layer_list.extend(lm.layer_list)
        self.__name_list.extend(lm.name_list)
        
        #Renommer
        self._rename()
    
    
    def insert(self, prev_name, name="Middle", **kwds):
        """
Dans la méthode d'insertion, spécifiez le nom du calque précédent et combinez-le avec ce calque.
Ajoutez un élément.
        """
        # 'prev_name'Erreur si n'existe pas.
        if not prev_name in self.__name_list:
            raise KeyError(prev_name, ": No such key.")
        # 'prev'Est inclus dans le mot-clé
        # 'prev_name'Erreur s'il ne correspond pas au nombre d'unités du calque spécifié dans.
        if "prev" in kwds:
            if kwds["prev"] \
                != self.__layer_list[self.index(prev_name)].n:
                raise UnmatchUnitError(
                    kwds["prev"],
                    self.__layer_list[self.index(prev_name)].n)
        # 'n'Est inclus dans le mot-clé
        if "n" in kwds:
            # 'prev_name'Si ce n'est pas le dernier
            if prev_name != self.__name_list[-1]:
                #Erreur s'il ne correspond pas au nombre d'unités dans la couche suivante.
                if kwds["n"] != self.__layer_list[
                        self.index(prev_name)+1].prev:
                    raise UnmatchUnitError(
                        kwds["n"],
                        self.__layer_list[self.index(prev_name)].prev)
        #S'il n'y a pas encore d'éléments'append'Donnez une erreur pour utiliser la méthode.
        if len(self) == 0:
            raise RuntimeError(
                "You have to use 'append' method instead.")
        
        #Obtenir l'index de l'emplacement d'insertion
        index = self.index(prev_name) + 1
        
        #Lisez le type de couche et modifiez le nom selon la règle de dénomination
        if name == "mid" or "m":
            name = "Middle"
        elif name == "out" or "o":
            name = "Output"
        else:
            raise UndefinedLayerError(name)
        
        #Insérer un élément
        #En ce moment,'name'Ne respecte pas encore les règles de dénomination,
        #Je le renommerai plus tard alors ne vous inquiétez pas.
        if "Middle" in name:
            self.__layer_list.insert(index,
                                     MiddleLayer(name=name, **kwds))
            self.__name_list.insert(index, name)
        elif "Output" in name:
            self.__layer_list.insert(index,
                                     OutputLayer(name=name, **kwds))
            self.__name_list.insert(index, name)
        
        #Renommer
        self._rename()
    
    
    def extend_insert(self, prev_name, lm):
        """
C'est la fonction d'origine.
Il se comporte comme une combinaison de la méthode extend et de la méthode insert.
En termes simples, c'est comme insérer un autre gestionnaire de calques.
        """
        if not isinstance(lm, LayerManager):
            # 'lm'Erreur si l'instance de n'est pas LayerManager.
            raise TypeError(type(lm), ": Unexpected type.")
        # 'prev_name'Erreur si n'existe pas.
        if not prev_name in self.__name_list:
            raise KeyError(prev_name, ": No such key.")
        #Le nombre d'unités des couches avant et après l'emplacement spécifié et les première et dernière couches de lm
        #S'ils ne correspondent pas, une erreur se produit.
        if len(self) != 0:
            if self.__layer_list[self.index(prev_name)].n \
                    != lm.layer_list[0].prev:
                #Avec le nombre d'unités dans votre emplacement désigné'lm'Le premier nombre d'unités dans
                #S'ils ne correspondent pas, une erreur se produit.
                raise UnmatchUnitError(
                    self.__layer_list[self.index(prev_name)].n,
                    lm.layer_list[0].prev)
            if prev_name != self.__name_list[-1]:
                # 'prev_name'N'est-ce pas ma dernière couche
                if lm.layer_list[-1].n \
                    != self.__layer_list[self.index(prev_name)+1].prev:
                    # 'lm'Le nombre d'unités à la fin et au niveau suivant de votre emplacement désigné
                    # 'prev'Erreur s'il ne correspond pas au nombre d'unités.
                    raise UnmatchUnitError(
                        lm.layer_list[-1].n,
                        self.__layer_list[self.index(prev_name)+1].prev)
        else:
            #Si vous n'avez aucun élément'extend'J'obtiens une erreur lors de l'utilisation de la méthode.
            raise RuntimeError(
                "You have to use 'extend' method instead.")
        
        #Obtenir l'index de l'emplacement d'insertion
        index = self.index(prev_name) + 1
        
        #Éléments après l'emplacement d'insertion'buf'Après avoir évacué vers, retirez-le une fois
        #Ajouter un élément à l'aide de la méthode extend
        layer_buf = self.__layer_list[index:]
        name_buf = self.__name_list[index:]
        del self.__layer_list[index:]
        del self.__name_list[index:]
        self.extend(lm)
        
        #Ajouter l'élément qui a été évacué
        self.__layer_list.extend(layer_buf)
        self.__name_list.extend(name_buf)
        
        #Renommer
        self._rename()
    
    
    def remove(self, key):
        """
La méthode remove supprime l'élément avec le nom spécifié.
Il est également autorisé à être spécifié par index.
        """
        #Déjà implémenté'del'La phrase est OK.
        del self[key]
    
    
    def index(self, target):
        return self.__name_list.index(target)
    
    
    def name(self, indices):
        return self.__name_list[indices]
    
    
    @property
    def layer_list(self):
        return self.__layer_list
    
    
    @property
    def name_list(self):
        return self.__name_list
    
    
    @property
    def ntype(self):
        return self.__ntype
_layererror.py [here](#layer error code preparation)

_layererror.py


class LayerManagerError(Exception):
    """Classe de base pour les erreurs définies par l'utilisateur dans les modules de couche"""
    pass


class AssignError(LayerManagerError):
    def __init__(self, value=None):
        if not value is None:
            self.value = value
            self.message = (str(value) 
                         + ": Assigning that value is prohibited.")
        else:
            self.value = None
            self.message = "Assigning that value is prohibited."
    
    
    def __str__(self):
        return self.message


class UnmatchUnitError(LayerManagerError):
    def __init__(self, prev, n):
        self.prev = prev
        self.n = n
        
        self.message = "Unmatch units: {} and {}.".format(prev, n)
    
    
    def __str__(self):
        return self.message


class UndefinedLayerError(LayerManagerError):
    def __init__(self, type_name):
        self.type = type_name
        self.message = str(type_name) + ": Undefined layer type."
    
    
    def __str__(self):
        return self.message

référence

  • [Maîtrisons le trait de soulignement de Python (_)! ](Https://medium.com/lsc-psd/pythonic Various-python underscore-Let's master it-3c132842eeef)

Série d'apprentissage en profondeur

Recommended Posts

Introduction à l'apprentissage profond ~ Préparation au codage ~
Introduction au Deep Learning ~ Règles d'apprentissage ~
Apprentissage par renforcement profond 1 Introduction au renforcement de l'apprentissage
Introduction au Deep Learning ~ Rétropropagation ~
Introduction à l'apprentissage en profondeur ~ Approximation des fonctions ~
Introduction au Deep Learning ~ Dropout Edition ~
Introduction au Deep Learning ~ Propagation vers l'avant ~
Introduction à l'apprentissage profond ~ Expérience CNN ~
Introduction au Deep Learning ~ Pliage et mise en commun ~
Premier apprentissage profond ~ Préparation ~
Introduction à l'apprentissage automatique
Introduction à l'apprentissage profond ~ Fonction de localisation et de perte ~
[Mémorandum d'apprentissage] Introduction à vim
Une introduction à l'apprentissage automatique
Super introduction à l'apprentissage automatique
Introduction à la rédaction de notes d'apprentissage automatique
Apprentissage profond pour démarrer sans GPU
Introduction à la préparation python-environnement (édition Mac)
Présentation de la bibliothèque d'apprentissage automatique SHOGUN
L'apprentissage en profondeur
Introduction au Deep Learning (2) - Essayez votre propre régression non linéaire avec Chainer-
Introduction à l'apprentissage automatique: fonctionnement du modèle
Une introduction à OpenCV pour l'apprentissage automatique
Comment étudier le test Deep Learning G
Introduction à discord.py (1er jour) -Préparation pour discord.py-
Alignement d'image: du SIFT au deep learning
Une introduction à Python pour l'apprentissage automatique
Introduction à TensorFlow - Explication des termes et concepts d'apprentissage automatique
Introduction à MQTT (Introduction)
Introduction à Scrapy (1)
Introduction à Scrapy (3)
[Introduction] Renforcer l'apprentissage
Premiers pas avec Supervisor
Introduction à Tkinter 1: Introduction
Mémorandum d'apprentissage profond
Introduction à PyQt
Introduction à Scrapy (2)
Commencer l'apprentissage en profondeur
[Linux] Introduction à Linux
Apprentissage en profondeur Python
Introduction à Scrapy (4)
Apprentissage profond × Python
Introduction à discord.py (2)
[Python] Introduction facile à l'apprentissage automatique avec python (SVM)
[Super introduction à l'apprentissage automatique] Découvrez les didacticiels Pytorch
Un amateur a essayé le Deep Learning avec Caffe (Introduction)
Deep Learning from scratch ① Chapitre 6 "Techniques liées à l'apprentissage"
Une introduction à Cython sans aller plus loin
[Introduction à StyleGAN2] Apprentissage indépendant avec 10 visages d'anime ♬
[Super introduction à l'apprentissage automatique] Découvrez les didacticiels Pytorch
[Pour les débutants] Introduction à la vectorisation dans l'apprentissage automatique
Introduction à Cython sans approfondir -2-
Introduction au Deep Learning (1) --Chainer est expliqué d'une manière facile à comprendre pour les débutants-
Python: pratique du Deep Learning
Fonctions d'apprentissage en profondeur / d'activation
Apprentissage profond à partir de zéro
Premiers pas avec le Web Scraping
Introduction aux baies non paramétriques
Deep learning 1 Pratique du deep learning