[PYTHON] Informationen zum Verhalten von enable_backprop von Chainer v2

TL;DR

Zweck

Als ich endlich mein Gewicht hob und versuchte, die Chainer- und Oreore-Hilfsbibliothek auf v2 zu erhöhen, bemerkte ich, dass das Verhalten von "enable_backprop" spürbar wurde. Berücksichtigen Sie insbesondere die folgenden Fragen.

Dieser Beitrag ist übrigens ab v2.0.0.

Umfrage

Was ist, wenn sich das "enable_backprop" in der Mitte des Diagramms ändert?

Bei der Implementierung mit dem Kontextmanager bin ich sehr gespannt, was passiert, wenn sich "enable_backprop" in der Mitte des Diagramms ändert. Wenn "no_backprop_mode" einen Effekt hat, wenn "backward ()" ausgeführt wird und "no_backprop_mode" zum Zeitpunkt der Vorwärtsberechnung verwendet wird, die Rückwärtsberechnung jedoch vergessen wird, in "no_backprop_mode" eingeschlossen zu sein, ist die Genauigkeit ungewöhnlich gut. Ich bin in Schwierigkeiten [^ 1].

[^ 1]: Natürlich ändern sich die Daten nur, wenn Sie den Optimierer aufrufen. Daher ist es in Ordnung, diesen Fehler in der Praxis zu machen.

Die Antwort finden Sie unter function_node.py. Wie hier beschrieben, bewirkt no_backprop_mode, dass das übergeordnete Element beim Erstellen des Berechnungsdiagramms nicht registriert wird, sodass der ** Effekt innerhalb des Bereichs liegt, der während der ** Vorwärtsberechnung angegeben wurde.

Normale Ausführung

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

Ausgabe


cudnn_deterministic  False
debug                False
enable_backprop      True
keep_graph_on_report False
train                True
type_check           True
use_cudnn            auto
[ 2.]

Sie können sehen, dass es auch dann wirksam ist, wenn der Rückwärtsbereich außerhalb der Reichweite liegt.

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

Ausgabe


cudnn_deterministic  False
debug                False
enable_backprop      False
keep_graph_on_report False
train                True
type_check           True
use_cudnn            auto
None

Wie oben erwähnt, wird enable_backprop auch vom ** übergeordneten ** getrennt. Daher ist der Gradient des übergeordneten Elements 0 und nicht die neu erstellte Variable im Kontextmanager.

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.]

Außerdem ist ** nicht vollständig von der Konfiguration abhängig, wenn Rückwärts aufgerufen wird? Nicht **. Daher scheint es besser, "unchain_backward ()" gehorsam zu verwenden, als es so zu implementieren, dass "enable_backprop" in einem Berechnungsgraphen mehrmals verwendet wird.

Wenn train auf False gesetzt ist, wird enable_backprop dann automatisch auch auf False gesetzt?

** Nein. ** ** **

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

Ausgabe


cudnn_deterministic  False
debug                False
enable_backprop      True
keep_graph_on_report False
train                False
type_check           True
use_cudnn            auto
[ 2.]

Wenn Sie also Ihren eigenen Code wie "extensions.Evaluator" schreiben, müssen Sie sowohl "enable_backprop" als auch "train" auf "False" setzen.

Ist es in Ordnung, der Standardbibliothek "chainer.extensions.Evaluator" zu vertrauen und sie zu verwenden?

** Es sieht okay aus. ** Sowohl enable_backprop als auch train sind auf False gesetzt.

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()

Ausgabe


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

Wie Sie sehen können, sind sowohl "enable_backprop" als auch "train" "False". In Bezug auf Code ist hier anwendbar.

Recommended Posts

Informationen zum Verhalten von enable_backprop von Chainer v2
Über das Verhalten von Yield_per von SqlAlchemy
Über Variable von Chainer
Über das Verhalten von copy, deepcopy und numpy.copy
Informationen zum Verhalten der Warteschlange während der Parallelverarbeitung
Über die Komponenten von Luigi
Über die Funktionen von Python
Ein Hinweis zum Verhalten von bowtie2 bei mehreren Treffern
Über den Rückgabewert von pthread_mutex_init ()
Über den Rückgabewert des Histogramms.
Über den Grundtyp von Go
Über die Obergrenze von Threads-max
Über die Größe der Punkte in Matplotlib
Informationen zur Grundlagenliste der Python-Grundlagen
Überprüfen Sie das Verhalten des Zerstörers in Python
Informationen zur virtuellen Umgebung von Python Version 3.7
Über die Argumente der Setup-Funktion von PyCaret
Über die Normalgleichung der linearen Regression
Ich wollte vorsichtig mit dem Verhalten der Standardargumente von Python sein
Informationen zur Genauigkeit der Berechnungsmethode für das Umfangsverhältnis von Archimedes
Über den Test
Informationen zur X-Achsen-Notation des Balkendiagramms von Matplotlib
Über die Verarbeitungsgeschwindigkeit von SVM (SVC) von Scikit-Learn
Verhalten von multiprocessing.pool.Pool.map
Das Verhalten von signal () hängt von der Kompilierungsoption ab
Schreiben Sie eine Notiz über die Python-Version von Python Virtualenv
Über die Entwicklungsinhalte des maschinellen Lernens (Beispiel)
[Hinweis] Über die Rolle des Unterstrichs "_" in Python
Visualisieren Sie das Verhalten des Sortieralgorithmus mit matplotlib
Über die Warteschlange
Denken Sie an das Rack und WSGI der nächsten Generation
Über das Testen bei der Implementierung von Modellen für maschinelles Lernen
Über die Ineffizienz der Datenübertragung im luigi on-memory
Über die übersichtliche Anordnung in der Importreihenfolge von Flake8
Lassen Sie uns die Emotionen von Tweet mit Chainer (2.) analysieren.
Eine Geschichte über die Änderung des Master-Namens von BlueZ
Persönliche Hinweise zur Integration von vscode und anaconda
Ein Memorandum über die Umsetzung von Empfehlungen in Python
Lassen Sie uns die Emotionen von Tweet mit Chainer (1.) analysieren.
Der Beginn von cif2cell
Über alles von numpy
Über die Zuweisung von numpy.ndarray
[Python] Verhalten von Argmax
der Zen von Python
Die Geschichte von sys.path.append ()
Informationen zur Entfaltungsfunktion
Über den Servicebefehl
Über die Verwirrungsmatrix
Über das Besuchermuster
Rache der Typen: Rache der Typen
Hinweis zum Standardverhalten von collate_fn in PyTorch
Denken Sie an die Analyseumgebung (Teil 1: Übersicht) * Stand Januar 2017
Informationen zum Kamerawechselereignis der Google Maps Android API