Warum Functorch? | Installieren Sie Anleitung | Transformationen | Dokumentation | Zukünftige Pläne
Diese Bibliothek befindet sich derzeit unter starker Entwicklung. Wenn Sie Vorschläge zu den API oder Anwendungsfällen haben, die Sie abgedeckt werden möchten, öffnen Sie bitte ein Github -Problem oder greifen Sie zu. Wir würden gerne hören, wie Sie die Bibliothek verwenden.
functorch ist JAX-ähnliche komponierbare Funktionstransformationen für Pytorch.
Ziel ist es, komponierbare vmap und grad -Transformationen bereitzustellen, die mit Pytorch-Modulen und Pytorch-Autograd mit einer guten Eager-Mode-Leistung funktionieren.
Darüber hinaus besteht experimentelle Funktionen, um diese Transformationen mit FX durchzuverfolgen, um die Ergebnisse dieser Transformationen im Voraus zu erfassen. Dies würde es uns ermöglichen, die Ergebnisse von VMAP oder Abschluss zu erstellen, um die Leistung zu verbessern.
Es gibt eine Reihe von Anwendungsfällen, die heute in Pytorch schwierig zu tun sind:
Durch das Komponieren von vmap , grad , vjp und jvp -Transformationen können wir das oben genannte ausdrücken, ohne ein separates Subsystem für jeden zu entwerfen. Diese Idee von komponierbaren Funktionen transformiert aus dem JAX -Framework.
Es gibt zwei Möglichkeiten, Functorch zu installieren:
Wir empfehlen, zuerst die Functorch Beta auszuprobieren.
Befolgen Sie die Anweisungen in diesem Colab -Notizbuch
Zum 21.09.2022 wird functorch neben einer nächtlichen Pytorch -Binärdatei installiert. Bitte installieren Sie eine Vorschau (nächtliche) Pytorch -Binärin; Anweisungen finden Sie unter https://pytorch.org/.
Sobald Sie das getan haben, führen Sie einen schnellen Überblick über die Vernunft in Python:
import torch
from functorch import vmap
x = torch . randn ( 3 )
y = vmap ( torch . sin )( x )
assert torch . allclose ( y , x . sin ()) Zum 21.09.2022 wird functorch neben Pytorch installiert und befindet sich im Pytorch -Quellbaum. Bitte installieren Sie PyTorch von Source, und können Sie import functorch .
Versuchen Sie, einige Tests durchzuführen, um sicherzustellen, dass alles in Ordnung ist:
pytest test/test_vmap.py -v
pytest test/test_eager_transforms.py -vAOTAUTOGRAD hat einige zusätzliche optionale Anforderungen. Sie können sie über:
pip install networkx Um Funkorch -Tests auszuführen, installieren Sie bitte unsere Testabhängigkeiten ( expecttest , pyyaml ).
Befolgen Sie die Anweisungen hier
Voraussetzung: Pytorch installieren
pip install functorchFühren Sie schließlich einen schnellen Überblick über die Gesundheit in Python:
import torch
from functorch import vmap
x = torch . randn ( 3 )
y = vmap ( torch . sin )( x )
assert torch . allclose ( y , x . sin ())Im Moment unterstützen wir die folgenden Transformationen:
grad , vjp , jvp ,jacrev , jacfwd , hessianvmapDarüber hinaus haben wir einige Dienstprogramme für die Arbeit mit Pytorch -Modulen.
make_functional(model)make_functional_with_buffers(model) HINWEIS: vmap legt den Code, für den er verwendet werden kann, Einschränkungen auf. Weitere Informationen finden Sie in der Dokumentation.
vmap(func)(*inputs) ist eine Transformation, die allen Tensoroperationen in func eine Dimension verleiht. vmap(func) gibt eine neue Funktion zurück, die func über eine Dimension (Standardeinstellung: 0) jedes Tensors in inputs ordnet.
vmap ist nützlich, um die Batch -Dimensionen zu verbergen: Man kann einen func schreiben, der auf Beispielen ausgeführt wird, und sie dann zu einer Funktion heben, die Beispiele mit vmap(func) aufnehmen kann, was zu einer einfacheren Modellierungserfahrung führt:
from functorch import vmap
batch_size , feature_size = 3 , 5
weights = torch . randn ( feature_size , requires_grad = True )
def model ( feature_vec ):
# Very simple linear model with activation
assert feature_vec . dim () == 1
return feature_vec . dot ( weights ). relu ()
examples = torch . randn ( batch_size , feature_size )
result = vmap ( model )( examples ) grad(func)(*inputs) geht davon aus, dass func einen Tensor mit einem Element zurückgibt. Es berechnet die Gradienten der Ausgabe von Func WRT in inputs[0] .
from functorch import grad
x = torch . randn ([])
cos_x = grad ( lambda x : torch . sin ( x ))( x )
assert torch . allclose ( cos_x , x . cos ())
# Second-order gradients
neg_sin_x = grad ( grad ( lambda x : torch . sin ( x )))( x )
assert torch . allclose ( neg_sin_x , - x . sin ()) Wenn Sie mit vmap komponiert werden, kann grad verwendet werden, um die Probenprobengradienten zu berechnen:
from functorch import vmap
batch_size , feature_size = 3 , 5
def model ( weights , feature_vec ):
# Very simple linear model with activation
assert feature_vec . dim () == 1
return feature_vec . dot ( weights ). relu ()
def compute_loss ( weights , example , target ):
y = model ( weights , example )
return (( y - target ) ** 2 ). mean () # MSELoss
weights = torch . randn ( feature_size , requires_grad = True )
examples = torch . randn ( batch_size , feature_size )
targets = torch . randn ( batch_size )
inputs = ( weights , examples , targets )
grad_weight_per_example = vmap ( grad ( compute_loss ), in_dims = ( None , 0 , 0 ))( * inputs ) Die vjp -Transformation wendet func für inputs an und gibt eine neue Funktion zurück, die VJPs mit einigen Tensoren cotangents berechnet.
from functorch import vjp
outputs , vjp_fn = vjp ( func , inputs ); vjps = vjp_fn ( * cotangents ) Die jvp Transformationen berechnen jacobian-vektorprodukte und gilt auch als "Forward-Mode AD". Im Gegensatz zu den meisten anderen Transformationen ist es keine Funktion höherer Ordnung, aber es gibt die Ausgänge von func(inputs) sowie die jvp s zurück.
from functorch import jvp
x = torch . randn ( 5 )
y = torch . randn ( 5 )
f = lambda x , y : ( x * y )
_ , output = jvp ( f , ( x , y ), ( torch . ones ( 5 ), torch . ones ( 5 )))
assert torch . allclose ( output , x + y ) Die jacrev -Transformation gibt eine neue Funktion zurück, die x übernimmt und den Jacobian of torch.sin in Bezug auf x unter Verwendung der Reverse-Mode-Anzeige zurückgibt.
from functorch import jacrev
x = torch . randn ( 5 )
jacobian = jacrev ( torch . sin )( x )
expected = torch . diag ( torch . cos ( x ))
assert torch . allclose ( jacobian , expected ) Verwenden Sie jacrev , um den Jakobier zu berechnen. Dies kann mit VMAP komponiert werden, um gegründete Jakobier zu produzieren:
x = torch . randn ( 64 , 5 )
jacobian = vmap ( jacrev ( torch . sin ))( x )
assert jacobian . shape == ( 64 , 5 , 5 ) jacfwd ist ein Drop-In-Ersatz für jacrev , der Jacobianer mithilfe der Vorwärtsmodus-Anzeige berechnet:
from functorch import jacfwd
x = torch . randn ( 5 )
jacobian = jacfwd ( torch . sin )( x )
expected = torch . diag ( torch . cos ( x ))
assert torch . allclose ( jacobian , expected ) Das Komponieren jacrev mit sich selbst oder jacfwd kann Hessianer produzieren:
def f ( x ):
return x . sin (). sum ()
x = torch . randn ( 5 )
hessian0 = jacrev ( jacrev ( f ))( x )
hessian1 = jacfwd ( jacrev ( f ))( x ) Der hessian ist eine Komfortfunktion, die jacfwd und jacrev kombiniert:
from functorch import hessian
def f ( x ):
return x . sin (). sum ()
x = torch . randn ( 5 )
hess = hessian ( f )( x ) Wir können diese Transformationen auch durchverfolgen, um die Ergebnisse als neuer Code mit make_fx zu erfassen. Es gibt auch eine experimentelle Integration in den NNC -Compiler (funktioniert nur vorerst auf CPU!).
from functorch import make_fx , grad
def f ( x ):
return torch . sin ( x ). sum ()
x = torch . randn ( 100 )
grad_f = make_fx ( grad ( f ))( x )
print ( grad_f . code )
def forward ( self , x_1 ):
sin = torch . ops . aten . sin ( x_1 )
sum_1 = torch . ops . aten . sum ( sin , None ); sin = None
cos = torch . ops . aten . cos ( x_1 ); x_1 = None
_tensor_constant0 = self . _tensor_constant0
mul = torch . ops . aten . mul ( _tensor_constant0 , cos ); _tensor_constant0 = cos = None
return mulManchmal möchten Sie möglicherweise eine Transformation in Bezug auf die Parameter und/oder Puffer eines nn.modules durchführen. Dies kann zum Beispiel passieren in:
Unsere Lösung für dies ist im Moment eine API, die bei einem nn.module eine zudenkliche Version davon erstellt, die wie eine Funktion bezeichnet werden kann.
make_functional(model) gibt eine funktionale Version des model und das model.parameters() zurückmake_functional_with_buffers(model) gibt eine funktionale Version des model und das model.parameters() und model.buffers() zurück.Hier ist ein Beispiel, bei dem wir die Probenstichgradienten mit einer Nn.Linar-Schicht berechnen:
import torch
from functorch import make_functional , vmap , grad
model = torch . nn . Linear ( 3 , 3 )
data = torch . randn ( 64 , 3 )
targets = torch . randn ( 64 , 3 )
func_model , params = make_functional ( model )
def compute_loss ( params , data , targets ):
preds = func_model ( params , data )
return torch . mean (( preds - targets ) ** 2 )
per_sample_grads = vmap ( grad ( compute_loss ), ( None , 0 , 0 ))( params , data , targets ) Wenn Sie ein Ensemble von Modellen erstellen, finden Sie möglicherweise combine_state_for_ensemble nützlich.
Weitere Unterlagen finden Sie auf unserer DOCS -Website.
torch._C._functorch.dump_tensor : Dumps Dispatch -Tasten auf Stack torch._C._functorch._set_vmap_fallback_warning_enabled(False) Wenn der VMAP -Warnungspam Sie stört.
Am Ende möchten wir dies in Pytorch verbreiten, sobald wir die Designdetails ausbügeln. Um die Details herauszufinden, benötigen wir Ihre Hilfe. Bitte senden Sie uns Ihre Anwendungsfälle, indem Sie ein Gespräch im Problem Tracker beginnen oder unser Projekt ausprobieren.
Functorch verfügt über eine Lizenz im BSD-Stil, wie in der Lizenzdatei zu finden ist.
Wenn Sie Functorch in Ihrer Veröffentlichung verwenden, zitieren Sie ihn bitte mit dem folgenden Bibtex -Eintrag.
@Misc { functorch2021 ,
author = { Horace He, Richard Zou } ,
title = { functorch: JAX-like composable function transforms for PyTorch } ,
howpublished = { url{https://github.com/pytorch/functorch} } ,
year = { 2021 }
}