| 14 | |
| 15 | |
| 16 | class DynamicNet(torch.nn.Module): |
| 17 | def __init__(self): |
| 18 | """ |
| 19 | In the constructor we instantiate five parameters and assign them as members. |
| 20 | """ |
| 21 | super().__init__() |
| 22 | self.a = torch.nn.Parameter(torch.randn(())) |
| 23 | self.b = torch.nn.Parameter(torch.randn(())) |
| 24 | self.c = torch.nn.Parameter(torch.randn(())) |
| 25 | self.d = torch.nn.Parameter(torch.randn(())) |
| 26 | self.e = torch.nn.Parameter(torch.randn(())) |
| 27 | |
| 28 | def forward(self, x): |
| 29 | """ |
| 30 | For the forward pass of the model, we randomly choose either 4, 5 |
| 31 | and reuse the e parameter to compute the contribution of these orders. |
| 32 | |
| 33 | Since each forward pass builds a dynamic computation graph, we can use normal |
| 34 | Python control-flow operators like loops or conditional statements when |
| 35 | defining the forward pass of the model. |
| 36 | |
| 37 | Here we also see that it is perfectly safe to reuse the same parameter many |
| 38 | times when defining a computational graph. |
| 39 | """ |
| 40 | y = self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3 |
| 41 | for exp in range(4, random.randint(4, 6)): |
| 42 | y = y + self.e * x ** exp |
| 43 | return y |
| 44 | |
| 45 | def string(self): |
| 46 | """ |
| 47 | Just like any class in Python, you can also define custom method on PyTorch modules |
| 48 | """ |
| 49 | return f'y = {self.a.item()} + {self.b.item()} x + {self.c.item()} x^2 + {self.d.item()} x^3 + {self.e.item()} x^4 ? + {self.e.item()} x^5 ?' |
| 50 | |
| 51 | |
| 52 | # Create Tensors to hold input and outputs. |