[PYTHON] Comment utiliser la bibliothèque "torchdiffeq" qui implémente le bloc ODE de Neural ODE

1.Tout d'abord

C'est très nouveau, mais je vais vous montrer comment utiliser la bibliothèque d'implémentation Neural ODE. À propos, Neural ODE est le meilleur article de NeuroIPS 2018.

Les auteurs officiels de Neural ODE ont publié une bibliothèque de dépôts officiels appelée torchdiffeq.

Bien que Neural ODE ait de nombreux articles expliquant la théorie et l'interprétation, je pensais qu'il y avait peu d'articles japonais décrivant l'utilisation réelle de cette bibliothèque, j'ai donc résumé l'utilisation de base dans cet article. À propos, torchdiffeq est une bibliothèque pour PyTorch.

En lisant cet article, vous pourrez:

--Torchdiffeq peut résoudre le problème de la valeur initiale de l'équation différentielle ordinaire du premier ordre --Torchdiffeq peut résoudre le problème de la valeur initiale de l'équation différentielle ordinaire du second ordre

2. Connaissances préalables

Je passerai en revue les connaissances préalables à l'utilisation de torchdiffeq.

2.1 Qu'est-ce qu'une équation différentielle normale?

Parmi les équations différentielles, celle avec essentiellement une seule variable inconnue est appelée équation différentielle normale. Par exemple, les équations différentielles telles que $ \ frac {dz} {dt} = f (z (t), t) $ et $ m \ ddot {x} = -kx $ ont plusieurs variables, mais $ Puisque z $ et $ x $ sont des fonctions de $ t $, il n'y a essentiellement qu'une seule variable inconnue, $ t $, et on peut dire que c'est une équation différentielle normale.

2.2 Qu'est-ce que Neural ODE?

Il existe de nombreux autres articles faciles à comprendre sur Neural ODE, veuillez donc les consulter.

Pour expliquer brièvement les grandes lignes, on peut dire que Neural ODE est un "réseau de neurones à couches continues".

Il existe une théorie selon laquelle il est difficile de saisir le concept car il existe un mot «équation différentielle normale» qui ne peut pas être entendu dans la zone du réseau neuronal, mais je pense que le point important est que «les couches sont continues». .. Cela permet par exemple de "retirer la sortie de la 0,5 ème couche", ce qui n'était pas possible avec le modèle classique.

Lien de référence ci-dessous:

3. Comment utiliser torchdiffeq

Voyons maintenant comment utiliser torchdiffeq.

3.1 Installation

Pour installer, exécutez la commande suivante.

pip install torchdiffeq

3.2 Exemple: équation différentielle du premier ordre

Avant d'entrer dans l'implémentation de Neural ODE, prenons une simple équation différentielle ordinaire du premier ordre comme exemple pour voir comment utiliser facilement torchdiffeq.

Considérez l'équation différentielle d'équation suivante. $ z(0) = 0, \\\ \frac{dz(t)}{dt} = f(t) = t $

Cette solution utilise $ C $ comme constante d'intégration

\int dz = \int tdt+C \\\ z(t) = \frac{t^2}{2} + C

Puisque $ z (0) = 0 , nous pouvons voir que la solution de cette équation différentielle est la suivante. $ z(t) = \frac{t^2}{2} $$

Implémentation par torchdiffeq

La mise en œuvre la plus simple pour résoudre ce problème avec torchdiffeq est ci-dessous.

first_order.py


from torchdiffeq import odeint

def func(t, z):
    return t

z0 = torch.Tensor([0])
t = torch.linspace(0,2,100)
out = odeint(func, z0, t)

Ci-dessous, les points sont listés.

――Il faut noter que l'élément de t doit être une colonne qui augmente (diminue) au sens étroit. Une erreur se produira même si la même valeur est incluse, telle que t = tenseur ([0, 0, 1]).

Tracez les résultats ci-dessus.

from matplotlib.pyplot as plt

plt.plot(t, out)
plt.axes().set_aspect('equal', 'datalim')  #Rapport hauteur / largeur 1:Définir sur 1
plt.grid()
plt.xlim(0,2)
plt.show()

first_order.png

Vous pouvez voir qu'il correspond à la solution $ z = \ frac {t ^ 2} {2} $ de l'équation différentielle obtenue par calcul manuel.

3.3 (Référence) Exemple 2: Résolution de l'équation différentielle du second ordre

Si vous utilisez torchdiffeq, vous pouvez également résoudre l'équation différentielle du second ordre. À titre d'exemple, nous résolvons l'équation différentielle de vibration simple (?) Familière à la science avec torchdiffeq. L'équation différentielle de la vibration simple est la suivante. $ m\ddot{x} = -kx $ Dans l'état initial, quand $ t = 0 $, $ x = 1 $, $ \ dot {x} = \ frac {dx} {dt} = 0 $. L'astuce pour résoudre l'équation différentielle du second ordre consiste à décomposer l'équation différentielle du second ordre en deux équations différentielles du premier ordre. Plus précisément, procédez comme suit.

\left[ \begin{array}{c} \dot{x} \\\ \ddot{x} \\\ \end{array} \right] = \left[ \begin{array}{cc} 0 & 1\\\ -\frac{k}{m} & 0\\\ \end{array} \right] \left[ \begin{array}{c} x \\\ \dot{x} \\\ \end{array} \right]

Ici, $ \ boldsymbol {y} = \ left [ \begin{array}{c} x \
\dot{x} \
\end{array} Si vous mettez \ right] $, cette équation différentielle du second ordre se traduira par l'équation différentielle du premier ordre suivante.

\frac{d\boldsymbol{y}}{dt} = f(\boldsymbol{y})

La mise en œuvre est la suivante. $ k = 1, m = 1 $.

oscillation.py


class Oscillation:
    def __init__(self, km):
        self.mat = torch.Tensor([[0, 1],
                                 [-km, 0]])

    def solve(self, t, x0, dx0):
        y0 = torch.cat([x0, dx0])
        out = odeint(self.func, y0, t)
        return out

    def func(self, t, y):
        # print(t)
        out = y @ self.mat  # @Est-ce que le produit de la matrice
        return out

if __name__=="__main__":
    x0 = torch.Tensor([1])
    dx0 = torch.Tensor([0])

    import numpy as np
    t = torch.linspace(0, 4 * np.pi, 1000)
    solver = Oscillation(1)
    out = solver.solve(t, x0, dx0)

Si vous le dessinez, vous pouvez voir que la solution de la vibration simple est correctement obtenue. osillation.png

4. Mise en œuvre du bloc ODE

Maintenant que vous êtes habitué à utiliser torchdiffeq, voyons comment implémenter réellement ODE Block. Le bloc ODE est un module qui forme la dynamique de $ \ frac {dz} {dt} = f (t, z) $. Le Neural ODE réel est construit en utilisant le bloc ODE avec la couche Full-Connect normale et la couche de convolution.

L'implémentation suivante met l'accent sur la simplicité et n'est qu'un exemple.

from torchdiffeq import odeint_adjoint as odeint

class ODEfunc(nn.Module):
    def __init__(self, dim):
        super(ODEfunc, self).__init__()
        self.seq = nn.Sequential(nn.Linear(dim, 124),
                                 nn.ReLU(),
                                 nn.Linear(124, 124),
                                 nn.ReLU(),
                                 nn.Linear(124, dim),
                                 nn.Tanh())

    def forward(self, t, x):
        out = self.seq(x)
        return out


class ODEBlock(nn.Module):
    def __init__(self, odefunc):
        super(ODEBlock, self).__init__()
        self.odefunc = odefunc
        self.integration_time = torch.tensor([0, 1]).float()

    def forward(self, x):
        self.integration_time = self.integration_time.type_as(x)
        out = odeint(self.odefunc, x, self.integration_time)
        return out[1]  # out[0]Parce que la valeur initiale est incluse dans.

Pour expliquer brièvement,

--ODE Block traite l'entrée reçue «x» comme la valeur initiale de l'équation différentielle. ―― ʻODEfunc` est $ f $ qui décrit la dynamique du système.

En faisant cela, vous pouvez utiliser ODE Block comme un module du réseau neuronal comme indiqué ci-dessous.

class ODEnet(nn.Module):
    def __init__(self, in_dim, mid_dim, out_dim):
        super(ODEnet, self).__init__()

        odefunc = ODEfunc(dim=mid_dim)
        
        self.fc1 = nn.Linear(in_dim, mid_dim)
        self.relu1 = nn.ReLU(inplace=True)
        self.norm1 = nn.BatchNorm1d(mid_dim)
        self.ode_block = ODEBlock(odefunc)  #Utiliser le bloc ODE
        self.norm2 = nn.BatchNorm1d(mid_dim)
        self.fc2 = nn.Linear(mid_dim, out_dim)

    def forward(self, x):
        batch_size = x.shape[0]
        x = x.view(batch_size, -1)

        out = self.fc1(x)
        out = self.relu1(out)
        out = self.norm1(out)
        out = self.ode_block(out)
        out = self.norm2(out)
        out = self.fc2(out)

        return out

Ce modèle a été lent à calculer. Cependant, l'utilisation de torchdiffeq ne semble pas le ralentir, et pour autant que j'ai essayé, le modèle Neural ODE dans le référentiel officiel est aussi rapide qu'un réseau neuronal normal. (Celui-ci devrait être un modèle plus petit ...)

5. Résumé

Nous avons introduit une utilisation rudimentaire de torchdiffeq qui est utile pour implémenter Neural ODE. Si vous souhaitez voir le programme qui entraîne réellement le modèle, veuillez consulter le Dépôt officiel de torchdiffeq ou [Mon référentiel d'implémentation](https: // github. com / TakadaTakumi / neuralODE_sample).

référence

torchdiffeq - GitHub Mon référentiel d'implémentation

Recommended Posts

Comment utiliser la bibliothèque "torchdiffeq" qui implémente le bloc ODE de Neural ODE
Comment utiliser la bibliothèque C en Python
Comment utiliser la bibliothèque de dessins graphiques Bokeh
[Python] Comment utiliser la bibliothèque de création de graphes Altair
Comment utiliser la bibliothèque de solveurs "kociemba" de Rubik Cube
Comment utiliser le décorateur
[python] Comment utiliser Matplotlib, une bibliothèque pour dessiner des graphiques
Remarques sur l'utilisation de la guimauve dans la bibliothèque de schémas
Comment utiliser la fonction zip
Comment utiliser le module optparse
Comment utiliser le module ConfigParser
Comment utiliser le pipeline Spark ML
[Linux] Comment utiliser la commande echo
Comment utiliser le débogueur IPython (ipdb)
Comment utiliser hmmlearn, une bibliothèque Python qui réalise des modèles de Markov cachés
python Je ne sais pas comment obtenir le nom de l'imprimante que j'utilise habituellement.
Comment utiliser MkDocs pour la première fois
Comment utiliser la bibliothèque d'images Python dans la série python3
Comment utiliser l'API Google Cloud Translation
Comment utiliser l'API du guide des programmes NHK
[Algorithm x Python] Comment utiliser la liste
Comment utiliser la bibliothèque de traitement d'image basée sur PyTorch "Kornia"
Comment utiliser une bibliothèque qui n'est pas initialement incluse dans Google App Engine
Une introduction approximative à la bibliothèque de traduction automatique neuronale
Comment résoudre la fonction récursive qui a résolu abc115-D
Comment utiliser Raspeye Relay Module Python
Je voulais utiliser la bibliothèque Python de MATLAB
Ajouter un utilisateur Linux, comment utiliser la commande useradd
Comment utiliser la commande grep et des exemples fréquents
Comment utiliser la clause exist dans l'ensemble de requêtes Django
[Introduction à Udemy Python3 + Application] 27. Comment utiliser le dictionnaire
[Introduction à Udemy Python3 + Application] 30. Comment utiliser l'ensemble
Comment utiliser argparse et la différence entre optparse
Comment utiliser le modèle appris dans Lobe en Python
(Rappelez-vous rapidement) Comment utiliser la ligne de commande LINUX
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser Pandas 2
Comment utiliser Virtualenv
Comment utiliser pytest_report_header
Comment utiliser Bio.Phylo
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser IPython
Comment utiliser virtualenv
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser le dictionnaire {}
Comment utiliser Pyenv
Comment utiliser la liste []
Comment utiliser python-kabusapi
Comment utiliser OptParse