TL;DR
est appliqué lors de la construction du graphe avant, pas quand
backward () est exécuté. Cependant, comme le mouvement n'est pas très intuitif, il vaut mieux ne pas changer plusieurs fois ʻenable_backprop
dans le graphe.train
n'inclut pas ʻenable_backprop dans
chainer.configuration`.chainer.extensions.Evaluator
les définira de manière appropriée, vous pouvez donc être rassuré.chainer.extensions.Evaluator
, changez les deux configurations
Quand j'ai finalement soulevé mon poids et essayé d'élever la bibliothèque d'aide Chainer et Oreore à la v2, j'ai remarqué que ʻenable_backprop` se comportait de manière erratique. En particulier, considérez les questions suivantes.
change au milieu du graphique? Est-il possible de faire quelque chose comme
.unchain_backward ()`?train
est défini sur False, est-ce que ʻenable_backprop` sera automatiquement défini sur False?chainer.extensions.Evaluator
?Au fait, ce post est à partir de la v2.0.0.
Avec l'implémentation utilisant contextmanager, je suis très curieux de savoir ce qui se passe si ʻenable_backpropchange au milieu du graphique. Si
no_backprop_mode a un effet lors de l'exécution de
backward (), et que j'ai utilisé
no_backprop_modeau moment du calcul avant, mais j'ai oublié de placer le calcul arrière avec
no_backprop_mode`, la précision est donc anormalement bonne. J'ai des ennuis [^ 1].
[^ 1]: Bien sûr, les données ne changent pas réellement à moins que vous n'appeliez l'optimiseur, donc vous pouvez faire cette erreur en pratique.
La réponse se trouve à l'adresse function_node.py. Comme décrit ici, l'effet de no_backprop_mode
est que le parent n'est pas enregistré lors de la construction du graphe de calcul, donc il a l'effet ** dans la plage spécifiée pendant ** le calcul avant.
Exécution normale
a = chainer.Variable(np.array([0.1], dtype=np.float32))
with chainer.configuration.using_config('enable_backprop', True):
chainer.config.show()
b = a * 2.0
b.backward()
print a.grad
production
cudnn_deterministic False
debug False
enable_backprop True
keep_graph_on_report False
train True
type_check True
use_cudnn auto
[ 2.]
Vous pouvez voir qu'il est efficace même si l'arrière est hors de portée.
a = chainer.Variable(np.array([0.1], dtype=np.float32))
with chainer.configuration.using_config('enable_backprop', False):
chainer.config.show()
b = a * 2.0
b.backward()
print a.grad
production
cudnn_deterministic False
debug False
enable_backprop False
keep_graph_on_report False
train True
type_check True
use_cudnn auto
None
De plus, comme mentionné ci-dessus, ʻenable_backprop` se déconnecte du ** parent **. Par conséquent, le gradient de son parent est 0, pas la variable nouvellement créée dans contextmanager.
a = chainer.Variable(np.array([0.1], dtype=np.float32))
with chainer.configuration.using_config('enable_backprop', False):
b = a * 2.0
c = b + 0.5
c.backward()
print a.grad # None
print b.grad # [ 1.]
De plus, ** n'est pas complètement dépendant de la configuration lors de l'appel vers l'arrière? Non **. Par conséquent, il semble préférable d'utiliser ʻunchain_backward () docilement au lieu d'implémenter ʻenable_backprop
plusieurs fois dans un graphe de calcul.
train
est défini sur False, est-ce que ʻenable_backprop` sera automatiquement défini sur False?** Non. ** **
a = chainer.Variable(np.array([0.1], dtype=np.float32))
with chainer.configuration.using_config('train', False):
chainer.config.show()
b = a * 2.0
b.backward()
print a.grad
production
cudnn_deterministic False
debug False
enable_backprop True
keep_graph_on_report False
train False
type_check True
use_cudnn auto
[ 2.]
Donc, si vous écrivez votre propre code comme ʻextensions.Evaluator, vous devez définir ʻenable_backprop
et train
sur False
.
chainer.extensions.Evaluator
?** Ça a l'air bien. ** ʻenable_backprop et
trainsont tous les deux
False`.
import chainer
import chainer.functions as F
import chainer.links as L
from chainer import training
from chainer.training import extensions
# Network definition
class MLP(chainer.Chain):
def __init__(self, n_out):
super(MLP, self).__init__()
with self.init_scope():
self.l1 = L.Linear(None, n_out)
def __call__(self, x):
chainer.config.show()
print ""
return self.l1(x)
model = L.Classifier(MLP(10))
optimizer = chainer.optimizers.Adam()
optimizer.setup(model)
# Load the MNIST dataset
train, test = chainer.datasets.get_mnist()
test = chainer.datasets.split_dataset(test, 1)[0]
train_iter = chainer.iterators.SerialIterator(train, 32)
test_iter = chainer.iterators.SerialIterator(test, 1,
repeat=False, shuffle=False)
# Set up a trainer
updater = training.StandardUpdater(train_iter, optimizer)
trainer = training.Trainer(updater, (1, 'iteration'))
trainer.extend(extensions.Evaluator(test_iter, model), trigger=(1, 'iteration'))
# Run the training
trainer.run()
production
cudnn_deterministic False
debug False
enable_backprop True
keep_graph_on_report False
train True
type_check True
use_cudnn auto
cudnn_deterministic False
debug False
enable_backprop False
keep_graph_on_report False
train False
type_check True
use_cudnn auto
Comme vous pouvez le voir, ʻenable_backprop et
train` sont tous les deux "False". En termes de code, cette zone est applicable.
Recommended Posts