Section courante

A propos

Section administrative du site

Gestion du graphe de calcul

Theano construit des graphes de calcul d'expressions mathématiques. Les bricks vous aident à construire ces graphes <bricks_overview>, mais elles font bien plus que cela. Lorsqu'une brick est appliquée à une variable Theano, elle l'annote automatiquement de deux manières :

Utilisation des annotations

La classe .ComputationGraph fournit une interface vers ce graphe annoté. Par exemple, imaginons que nous souhaitions entraîner un auto-encodeur en utilisant la décroissance pondérale sur certaines couches.

>>> from theano import tensor
>>> x = tensor.matrix('features')
>>> from blocks.bricks import MLP, Logistic, Rectifier
>>> from blocks.initialization import IsotropicGaussian, Constant
>>> mlp = MLP(activations=[Rectifier()] * 2 + [Logistic()],
...           dims=[784, 256, 128, 784],
...           weights_init=IsotropicGaussian(), biases_init=Constant(0.01))
>>> y_hat = mlp.apply(x)
>>> from blocks.bricks.cost import BinaryCrossEntropy
>>> cost = BinaryCrossEntropy().apply(x, y_hat)

Notre graphe de calcul Theano est maintenant défini par nos pertes et nos coûts. Nous initialisons le graphe géré.

>>> from blocks.graph import ComputationGraph
>>> cg = ComputationGraph(cost)

Nous constaterons qu'il y a de nombreuses variables dans ce graphique.

>>> print(cg.variables) # doctest: +SKIP
[TensorConstant{0}, b, W_norm, b_norm, features, TensorConstant{1.0}, ...]

Pour appliquer la décomposition de poids, nous avons uniquement besoin des matrices de pondération. Celles-ci sont étiquetées avec le rôle :const:`~blocks.roles.WEIGHT`. Créons donc un filtre qui les trouve pour nous.

>>> from blocks.filter import VariableFilter
>>> from blocks.roles import WEIGHT
>>> print(VariableFilter(roles=[WEIGHT])(cg.variables))
[W, W, W]

Notez que les variables dans :attr:`cg.variables <.ComputationGraph.variables>` sont ordonnées selon l'ordre topologique de leurs noeuds d'application. Cela signifie que pour un réseau à propagation directe, les paramètres seront renvoyés dans l'ordre de nos couches.

Imaginons un instant que nous ayons affaire à un réseau beaucoup plus complexe et que nous souhaitions appliquer une pondération aux paramètres d'une couche en particulier. Pour ce faire, nous pouvons filtrer les variables selon les bricks les ayant créées.

>>> second_layer = mlp.linear_transformations[1]
>>> from blocks.roles import PARAMETER
>>> var_filter = VariableFilter(roles=[PARAMETER], bricks=[second_layer])
>>> print(var_filter(cg.variables))
[b, W]

Remarque

Il existe différents rôles que vous pouvez filtrer. Vous avez peut-être déjà remarqué qu'il existe une hiérarchie entre nombre d'entre eux : filtrer par :const:`~blocks.roles.PARAMETER` renverra également les variables des rôles enfants :const:`~blocks.roles.WEIGHT` et :const:`~blocks.roles.BIAS`.

Nous pouvons également voir les variables auxiliaires créées par nos bricks. Celles-ci peuvent être intéressantes à surveiller pendant l'entraînement, par exemple :

>>> print(cg.auxiliary_variables)
[W_norm, b_norm, W_norm, b_norm, W_norm, b_norm]


Dernière mise à jour : Vendredi, le 6 juin 2025