olszewskip:

Do I understand correctly that it doesn’t matter for the training loop in this section that the P3 function is defined as LegendrePolynomial3.apply rather than simply as
def P3(x):
    return 0.5 * (5 * x ** 3 - 3 * x)

?


Yes, you are right, that in this example, it doesn’t matter for the training loop if the function is defined as  LegendrePolynomial3.apply or just a subroutine P3. This is a simple example to show how to define a custom instantiation of autograd.Function. Note that, the elementary operators involved in this subroutine are *, **, -. Under the hood, Pytorch has already implemented with backward (or) gradient calculators for these operations.



 olszewskip:

what is the advantage here of the approach with inheriting from torch.autograd.Function?


In certain scenarios, when there is a need for some complicated custom operations to be performed (that is not defined in pytorch), typically we write those operations (both forward and backward) as a Cuda C++ op and connect python & Cuda C++ via autograd.Function.