René's URL Explorer Experiment


Title: Double Backward with Custom Functions — 파이토치 한국어 튜토리얼 (PyTorch tutorials in Korean)

Open Graph Title: Double Backward with Custom Functions

Description: It is sometimes useful to run backwards twice through backward graph, for example to compute higher-order gradients. It takes an understanding of autograd and some care to support double backwards, however. Functions that support performing backward a single time are not necessarily equipped to s...

Open Graph Description: It is sometimes useful to run backwards twice through backward graph, for example to compute higher-order gradients. It takes an understanding of autograd and some care to support double backwards, however. Functions that support performing backward a single time are not necessarily equipped to s...

Opengraph URL: https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html

direct link

Domain: tutorials.pytorch.kr


Hey, it has json ld scripts:
    {
       "@context": "https://schema.org",
       "@type": "Article",
       "name": "Double Backward with Custom Functions",
       "headline": "Double Backward with Custom Functions",
       "description": "PyTorch Documentation. Explore PyTorch, an open-source machine learning library that accelerates the path from research prototyping to production deployment. Discover tutorials, API references, and guides to help you build and deploy deep learning models efficiently.",
       "url": "/intermediate/custom_function_double_backward_tutorial.html",
       "articleBody": "Double Backward with Custom Functions# It is sometimes useful to run backwards twice through backward graph, for example to compute higher-order gradients. It takes an understanding of autograd and some care to support double backwards, however. Functions that support performing backward a single time are not necessarily equipped to support double backward. In this tutorial we show how to write a custom autograd function that supports double backward, and point out some things to look out for. When writing a custom autograd function to backward through twice, it is important to know when operations performed in a custom function are recorded by autograd, when they aren\u2019t, and most importantly, how save_for_backward works with all of this. Custom functions implicitly affects grad mode in two ways: During forward, autograd does not record any the graph for any operations performed within the forward function. When forward completes, the backward function of the custom function becomes the grad_fn of each of the forward\u2019s outputs During backward, autograd records the computation graph used to compute the backward pass if create_graph is specified Next, to understand how save_for_backward interacts with the above, we can explore a couple examples: Saving the Inputs# Consider this simple squaring function. It saves an input tensor for backward. Double backward works automatically when autograd is able to record operations in the backward pass, so there is usually nothing to worry about when we save an input for backward as the input should have grad_fn if it is a function of any tensor that requires grad. This allows the gradients to be properly propagated. import torch class Square(torch.autograd.Function): @staticmethod def forward(ctx, x): # Because we are saving one of the inputs use `save_for_backward` # Save non-tensors and non-inputs/non-outputs directly on ctx ctx.save_for_backward(x) return x**2 @staticmethod def backward(ctx, grad_out): # A function support double backward automatically if autograd # is able to record the computations performed in backward x, = ctx.saved_tensors return grad_out * 2 * x # Use double precision because finite differencing method magnifies errors x = torch.rand(3, 3, requires_grad=True, dtype=torch.double) torch.autograd.gradcheck(Square.apply, x) # Use gradcheck to verify second-order derivatives torch.autograd.gradgradcheck(Square.apply, x) We can use torchviz to visualize the graph to see why this works import torchviz x = torch.tensor(1., requires_grad=True).clone() out = Square.apply(x) grad_x, = torch.autograd.grad(out, x, create_graph=True) torchviz.make_dot((grad_x, x, out), {\"grad_x\": grad_x, \"x\": x, \"out\": out}) We can see that the gradient wrt to x, is itself a function of x (dout/dx = 2x) And the graph of this function has been properly constructed Saving the Outputs# A slight variation on the previous example is to save an output instead of input. The mechanics are similar because outputs are also associated with a grad_fn. class Exp(torch.autograd.Function): # Simple case where everything goes well @staticmethod def forward(ctx, x): # This time we save the output result = torch.exp(x) # Note that we should use `save_for_backward` here when # the tensor saved is an ouptut (or an input). ctx.save_for_backward(result) return result @staticmethod def backward(ctx, grad_out): result, = ctx.saved_tensors return result * grad_out x = torch.tensor(1., requires_grad=True, dtype=torch.double).clone() # Validate our gradients using gradcheck torch.autograd.gradcheck(Exp.apply, x) torch.autograd.gradgradcheck(Exp.apply, x) Use torchviz to visualize the graph: out = Exp.apply(x) grad_x, = torch.autograd.grad(out, x, create_graph=True) torchviz.make_dot((grad_x, x, out), {\"grad_x\": grad_x, \"x\": x, \"out\": out}) Saving Intermediate Results# A more tricky case is when we need to save an intermediate result. We demonstrate this case by implementing: \\[sinh(x) := \\frac{e^x - e^{-x}}{2} \\] Since the derivative of sinh is cosh, it might be useful to reuse exp(x) and exp(-x), the two intermediate results in forward in the backward computation. Intermediate results should not be directly saved and used in backward though. Because forward is performed in no-grad mode, if an intermediate result of the forward pass is used to compute gradients in the backward pass the backward graph of the gradients would not include the operations that computed the intermediate result. This leads to incorrect gradients. class Sinh(torch.autograd.Function): @staticmethod def forward(ctx, x): expx = torch.exp(x) expnegx = torch.exp(-x) ctx.save_for_backward(expx, expnegx) # In order to be able to save the intermediate results, a trick is to # include them as our outputs, so that the backward graph is constructed return (expx - expnegx) / 2, expx, expnegx @staticmethod def backward(ctx, grad_out, _grad_out_exp, _grad_out_negexp): expx, expnegx = ctx.saved_tensors grad_input = grad_out * (expx + expnegx) / 2 # We cannot skip accumulating these even though we won\u0027t use the outputs # directly. They will be used later in the second backward. grad_input += _grad_out_exp * expx grad_input -= _grad_out_negexp * expnegx return grad_input def sinh(x): # Create a wrapper that only returns the first output return Sinh.apply(x)[0] x = torch.rand(3, 3, requires_grad=True, dtype=torch.double) torch.autograd.gradcheck(sinh, x) torch.autograd.gradgradcheck(sinh, x) Use torchviz to visualize the graph: out = sinh(x) grad_x, = torch.autograd.grad(out.sum(), x, create_graph=True) torchviz.make_dot((grad_x, x, out), params={\"grad_x\": grad_x, \"x\": x, \"out\": out}) Saving Intermediate Results: What not to do# Now we show what happens when we don\u2019t also return our intermediate results as outputs: grad_x would not even have a backward graph because it is purely a function exp and expnegx, which don\u2019t require grad. class SinhBad(torch.autograd.Function): # This is an example of what NOT to do! @staticmethod def forward(ctx, x): expx = torch.exp(x) expnegx = torch.exp(-x) ctx.expx = expx ctx.expnegx = expnegx return (expx - expnegx) / 2 @staticmethod def backward(ctx, grad_out): expx = ctx.expx expnegx = ctx.expnegx grad_input = grad_out * (expx + expnegx) / 2 return grad_input Use torchviz to visualize the graph. Notice that grad_x is not part of the graph! out = SinhBad.apply(x) grad_x, = torch.autograd.grad(out.sum(), x, create_graph=True) torchviz.make_dot((grad_x, x, out), params={\"grad_x\": grad_x, \"x\": x, \"out\": out}) When Backward is not Tracked# Finally, let\u2019s consider an example when it may not be possible for autograd to track gradients for a functions backward at all. We can imagine cube_backward to be a function that may require a non-PyTorch library like SciPy or NumPy, or written as a C++ extension. The workaround demonstrated here is to create another custom function CubeBackward where you also manually specify the backward of cube_backward! def cube_forward(x): return x**3 def cube_backward(grad_out, x): return grad_out * 3 * x**2 def cube_backward_backward(grad_out, sav_grad_out, x): return grad_out * sav_grad_out * 6 * x def cube_backward_backward_grad_out(grad_out, x): return grad_out * 3 * x**2 class Cube(torch.autograd.Function): @staticmethod def forward(ctx, x): ctx.save_for_backward(x) return cube_forward(x) @staticmethod def backward(ctx, grad_out): x, = ctx.saved_tensors return CubeBackward.apply(grad_out, x) class CubeBackward(torch.autograd.Function): @staticmethod def forward(ctx, grad_out, x): ctx.save_for_backward(x, grad_out) return cube_backward(grad_out, x) @staticmethod def backward(ctx, grad_out): x, sav_grad_out = ctx.saved_tensors dx = cube_backward_backward(grad_out, sav_grad_out, x) dgrad_out = cube_backward_backward_grad_out(grad_out, x) return dgrad_out, dx x = torch.tensor(2., requires_grad=True, dtype=torch.double) torch.autograd.gradcheck(Cube.apply, x) torch.autograd.gradgradcheck(Cube.apply, x) Use torchviz to visualize the graph: out = Cube.apply(x) grad_x, = torch.autograd.grad(out, x, create_graph=True) torchviz.make_dot((grad_x, x, out), params={\"grad_x\": grad_x, \"x\": x, \"out\": out}) To conclude, whether double backward works for your custom function simply depends on whether the backward pass can be tracked by autograd. With the first two examples we show situations where double backward works out of the box. With the third and fourth examples, we demonstrate techniques that enable a backward function to be tracked, when they otherwise would not be.",
       "author": {
         "@type": "Organization",
         "name": "PyTorch Contributors",
         "url": "https://pytorch.org"
       },
       "image": "../_static/img/pytorch_seo.png",
       "mainEntityOfPage": {
         "@type": "WebPage",
         "@id": "/intermediate/custom_function_double_backward_tutorial.html"
       },
       "datePublished": "2023-01-01T00:00:00Z",
       "dateModified": "2023-01-01T00:00:00Z"
     }
 

article:modified_time2022-11-30T07:09:41+00:00
og:typearticle
og:site_namePyTorch Tutorials KR
og:image../_static/img/pytorch_seo.png
og:image:altPyTorch Tutorials KR
og:ignore_canonicaltrue
docsearch:languageko
docbuild:last-update2022년 11월 30일
None2
pytorch_projecttutorials

Links:

https://pytorch.kr/
PyTorch 시작하기 https://pytorch.kr/get-started/locally/
기본 익히기 https://tutorials.pytorch.kr/beginner/basics/intro.html
한국어 튜토리얼 https://tutorials.pytorch.kr/
한국어 모델 허브 https://pytorch.kr/hub/
Official Tutorials https://docs.pytorch.org/tutorials/
블로그 https://pytorch.kr/blog/
PyTorch API https://docs.pytorch.org/docs/
Domain API 소개 https://pytorch.kr/domains/
한국어 튜토리얼 https://tutorials.pytorch.kr/
Official Tutorials https://docs.pytorch.org/tutorials/
한국어 커뮤니티 https://discuss.pytorch.kr/
개발자 정보 https://pytorch.kr/resources/
Landscape https://landscape.pytorch.org/
https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html
https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html
PyTorch 시작하기https://pytorch.kr/get-started/locally/
기본 익히기https://tutorials.pytorch.kr/beginner/basics/intro.html
한국어 튜토리얼https://tutorials.pytorch.kr/
한국어 모델 허브https://pytorch.kr/hub/
Official Tutorialshttps://docs.pytorch.org/tutorials/
블로그https://pytorch.kr/blog/
PyTorch APIhttps://docs.pytorch.org/docs/
Domain API 소개https://pytorch.kr/domains/
한국어 튜토리얼https://tutorials.pytorch.kr/
Official Tutorialshttps://docs.pytorch.org/tutorials/
한국어 커뮤니티https://discuss.pytorch.kr/
개발자 정보https://pytorch.kr/resources/
Landscapehttps://landscape.pytorch.org/
Skip to main contenthttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#main-content
v2.8.0+cu128https://tutorials.pytorch.kr/index.html
Intro https://tutorials.pytorch.kr/intro.html
Compilers https://tutorials.pytorch.kr/compilers_index.html
Domains https://tutorials.pytorch.kr/domains.html
Distributed https://tutorials.pytorch.kr/distributed.html
Deep Dive https://tutorials.pytorch.kr/deep-dive.html
Extension https://tutorials.pytorch.kr/extension.html
Ecosystem https://tutorials.pytorch.kr/ecosystem.html
Recipes https://tutorials.pytorch.kr/recipes_index.html
한국어 튜토리얼 GitHub 저장소https://github.com/PyTorchKorea/tutorials-kr
파이토치 한국어 커뮤니티https://discuss.pytorch.kr/
Intro https://tutorials.pytorch.kr/intro.html
Compilers https://tutorials.pytorch.kr/compilers_index.html
Domains https://tutorials.pytorch.kr/domains.html
Distributed https://tutorials.pytorch.kr/distributed.html
Deep Dive https://tutorials.pytorch.kr/deep-dive.html
Extension https://tutorials.pytorch.kr/extension.html
Ecosystem https://tutorials.pytorch.kr/ecosystem.html
Recipes https://tutorials.pytorch.kr/recipes_index.html
한국어 튜토리얼 GitHub 저장소https://github.com/PyTorchKorea/tutorials-kr
파이토치 한국어 커뮤니티https://discuss.pytorch.kr/
PyTorch Custom Operatorshttps://tutorials.pytorch.kr/advanced/custom_ops_landing_page.html
Custom Python Operatorshttps://tutorials.pytorch.kr/advanced/python_custom_ops.html
Custom C++ and CUDA Operatorshttps://tutorials.pytorch.kr/advanced/cpp_custom_ops.html
Double Backward with Custom Functionshttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html
Fusing Convolution and Batch Norm using Custom Functionhttps://tutorials.pytorch.kr/intermediate/custom_function_conv_bn_tutorial.html
Registering a Dispatched Operator in C++https://tutorials.pytorch.kr/advanced/dispatcher.html
Extending dispatcher for a new backend in C++https://tutorials.pytorch.kr/advanced/extend_dispatcher.html
Facilitating New Backend Integration by PrivateUse1https://tutorials.pytorch.kr/advanced/privateuseone.html
https://tutorials.pytorch.kr/index.html
Extensionhttps://tutorials.pytorch.kr/extension.html
#https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#double-backward-with-custom-functions
#https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-the-inputs
https://user-images.githubusercontent.com/13428986/126559699-e04f3cb1-aaf2-4a9a-a83d-b8767d04fbd9.png
#https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-the-outputs
https://user-images.githubusercontent.com/13428986/126559780-d141f2ba-1ee8-4c33-b4eb-c9877b27a954.png
#https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-intermediate-results
https://user-images.githubusercontent.com/13428986/126560494-e48eba62-be84-4b29-8c90-a7f6f40b1438.png
#https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-intermediate-results-what-not-to-do
https://user-images.githubusercontent.com/13428986/126565889-13992f01-55bc-411a-8aee-05b721fe064a.png
#https://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#when-backward-is-not-tracked
https://user-images.githubusercontent.com/13428986/126559935-74526b4d-d419-4983-b1f0-a6ee99428531.png
이전 Custom C++ and CUDA Operators https://tutorials.pytorch.kr/advanced/cpp_custom_ops.html
다음 Fusing Convolution and Batch Norm using Custom Function https://tutorials.pytorch.kr/intermediate/custom_function_conv_bn_tutorial.html
PyData Sphinx Themehttps://pydata-sphinx-theme.readthedocs.io/en/stable/index.html
이전 Custom C++ and CUDA Operators https://tutorials.pytorch.kr/advanced/cpp_custom_ops.html
다음 Fusing Convolution and Batch Norm using Custom Function https://tutorials.pytorch.kr/intermediate/custom_function_conv_bn_tutorial.html
Saving the Inputshttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-the-inputs
Saving the Outputshttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-the-outputs
Saving Intermediate Resultshttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-intermediate-results
Saving Intermediate Results: What not to dohttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#saving-intermediate-results-what-not-to-do
When Backward is not Trackedhttps://tutorials.pytorch.kr/intermediate/custom_function_double_backward_tutorial.html#when-backward-is-not-tracked
torchaohttps://docs.pytorch.org/ao
torchrechttps://docs.pytorch.org/torchrec
torchfthttps://docs.pytorch.org/torchft
TorchCodechttps://docs.pytorch.org/torchcodec
torchvisionhttps://docs.pytorch.org/vision
ExecuTorchhttps://docs.pytorch.org/executorch
PyTorch on XLA Deviceshttps://docs.pytorch.org/xla
GitHub로 이동https://github.com/PyTorchKorea
튜토리얼로 이동https://tutorials.pytorch.kr/
커뮤니티로 이동https://discuss.pytorch.kr/
https://pytorch.kr/
파이토치 한국 사용자 모임https://pytorch.kr/
사용자 모임 소개https://pytorch.kr/about
기여해주신 분들https://pytorch.kr/contributors
리소스https://pytorch.kr/resources/
행동 강령https://pytorch.kr/coc
행동 강령https://pytorch.kr/coc
Linux Foundation의 정책https://www.linuxfoundation.org/policies/
our code of conducthttps://pytorch.kr/coc
Linux Foundation's policieshttps://www.linuxfoundation.org/policies/
Cookies Policyhttps://www.facebook.com/policies/cookies/
Sphinxhttps://www.sphinx-doc.org/
PyData Sphinx Themehttps://pydata-sphinx-theme.readthedocs.io/en/stable/index.html

Viewport: width=device-width, initial-scale=1


URLs of crawlers that visited me.