Le tensorboard est assez pratique à utiliser. Des graphiques, des histogrammes, des images, etc. peuvent être dessinés, et l'interface est également bonne. J'utilise beaucoup chainer ces jours-ci, mais je voulais utiliser ce tensorboard pratique comme outil de visualisation, alors j'ai créé un package qui utilise tensorboard avec chainer.
https://github.com/neka-nat/tensorboard-chainer
Il y avait une personne qui fait la même chose avec pytorch, donc je le fais sur cette base.
En gros, vous pouvez voir à quoi il ressemble en exécutant demp.py
ou demo_graph.py
. Il prend en charge le dessin de graphiques, d'histogrammes, d'images, etc.
python demo.py
tensorboard --logdir runs
** SCARA **
** histogramme **
image
J'étais un peu ennuyé par la génération de graphes.
Fondamentalement, le computational_graph
du chainer est utilisé pour calculer les nœuds et les arêtes, et le type de protobuf utilisé dans le journal du tensorboard est changé. Pour le moment, comme le graphe de chaînage est adopté tel quel, le "VariableNode" entre les fonctions qui ne sont pas affichées dans tensorflow est également dessiné.
name_scope
Le reste est de savoir comment nommer les nœuds, mais nous avons préparé une version chainer de name_scope
utilisée dans tensorflow pour rendre le graphique plus facile à voir.
Il peut être utilisé sous les formes suivantes.
import chainer
import chainer.functions as F
import chainer.links as L
from tb_chainer import name_scope
class MLP(chainer.Chain):
def __init__(self, n_units, n_out):
super(MLP, self).__init__()
with self.init_scope():
self.l1 = L.Linear(None, n_units) # n_in -> n_units
self.l2 = L.Linear(None, n_units) # n_units -> n_units
self.l3 = L.Linear(None, n_out) # n_units -> n_out
def __call__(self, x):
with name_scope('linear1', self.l1.params()):
h1 = F.relu(self.l1(x))
with name_scope('linear2', self.l2.params()):
h2 = F.relu(self.l2(h1))
with name_scope('linear3', self.l3.params()):
o = self.l3(h2)
return o
L'endroit où with name_scope ...
définit l'espace de noms.
Dans ce cas, si vous ne définissez pas l'espace de noms, tous les nœuds seront dessinés comme indiqué ci-dessous, mais si vous définissez l'espace de noms, ils seront dessinés comme indiqué ci-dessous.
** Pas d'espace de noms **
** Avec espace de noms **
Bien sûr, il peut être développé dans l'espace de noms.
C'est une méthode assez agressive, mais c'est fait avec syntaxe + patch monkey. Je réécris le constructeur de VariableNode et Function pour le changer en constructeur qui peut contenir la pile d'espaces de noms.
from chainer import function
from chainer import variable
import functools
from types import MethodType
def copy_method(c):
g = MethodType(c.__init__, None, c)
return g
def _init_with_name_scope(self, *args, **kargs):
self.name_scope = kargs['name_scope']
org_init = kargs['org_init']
del kargs['name_scope']
del kargs['org_init']
org_init(self, *args, **kargs)
#Augmentez la classe de fonctions selon vos besoins.
_org_classes = [function.Function,
variable.VariableNode]
_copy_org_inits = [copy_method(c) for c in _org_classes]
class name_scope(object):
stack = []
def __init__(self, name, values=[]):
self.stack.append(name)
self._org_inits = []
for v in values:
v.node.name_scope = '/'.join(self.stack)
def __enter__(self):
for idx, c in enumerate(_org_classes):
self._org_inits.append(c.__init__)
c.__init__ = MethodType(functools.partial(_init_with_name_scope,
name_scope='/'.join(self.stack),
org_init=_copy_org_inits[idx]),
None, c)
return self
def __exit__(self, exec_type, exec_value, traceback):
for idx, c in enumerate(_org_classes):
c.__init__ = self._org_inits[idx]
self.stack.pop(-1)
Le _init_with_name_scope
ci-dessus appelle normalement le constructeur et préserve l'espace de noms, et ne bascule vers ce constructeur que dans la syntaxe with.
Il semble que la taille du tenseur puisse être indiquée sur le bord lors du dessin du réseau sur le tensorboard, mais je ne peux pas le faire car je ne sais pas comment le faire. Vous devrez peut-être regarder le contenu de la source tensorflow pour savoir ...
Magie noire avec Python Metaprogramming Python
Recommended Posts