PyTorch:控制流 + 权重共享

原文:https://pytorch.org/tutorials/beginner/examples_nn/dynamic_net.html#sphx-glr-beginner-examples-nn-dynamic-net-py

为了展示 PyTorch 动态图的强大功能,我们将实现一个非常奇怪的模型:一个从三到五阶(动态变化)的多项式,在每次正向传递中选择一个 3 到 5 之间的一个随机数,并将这个随机数作为阶数,第四和第五阶共用同一个权重来多次重复计算。

  1. import random
  2. import torch
  3. import math
  4. class DynamicNet(torch.nn.Module):
  5. def __init__(self):
  6. """
  7. In the constructor we instantiate five parameters and assign them as members.
  8. """
  9. super().__init__()
  10. self.a = torch.nn.Parameter(torch.randn(()))
  11. self.b = torch.nn.Parameter(torch.randn(()))
  12. self.c = torch.nn.Parameter(torch.randn(()))
  13. self.d = torch.nn.Parameter(torch.randn(()))
  14. self.e = torch.nn.Parameter(torch.randn(()))
  15. def forward(self, x):
  16. """
  17. For the forward pass of the model, we randomly choose either 4, 5
  18. and reuse the e parameter to compute the contribution of these orders.
  19. Since each forward pass builds a dynamic computation graph, we can use normal
  20. Python control-flow operators like loops or conditional statements when
  21. defining the forward pass of the model.
  22. Here we also see that it is perfectly safe to reuse the same parameter many
  23. times when defining a computational graph.
  24. """
  25. y = self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3
  26. for exp in range(4, random.randint(4, 6)):
  27. y = y + self.e * x ** exp
  28. return y
  29. def string(self):
  30. """
  31. Just like any class in Python, you can also define custom method on PyTorch modules
  32. """
  33. 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 ?'
  34. # Create Tensors to hold input and outputs.
  35. x = torch.linspace(-math.pi, math.pi, 2000)
  36. y = torch.sin(x)
  37. # Construct our model by instantiating the class defined above
  38. model = DynamicNet()
  39. # Construct our loss function and an Optimizer. Training this strange model with
  40. # vanilla stochastic gradient descent is tough, so we use momentum
  41. criterion = torch.nn.MSELoss(reduction='sum')
  42. optimizer = torch.optim.SGD(model.parameters(), lr=1e-8, momentum=0.9)
  43. for t in range(30000):
  44. # Forward pass: Compute predicted y by passing x to the model
  45. y_pred = model(x)
  46. # Compute and print loss
  47. loss = criterion(y_pred, y)
  48. if t % 2000 == 1999:
  49. print(t, loss.item())
  50. # Zero gradients, perform a backward pass, and update the weights.
  51. optimizer.zero_grad()
  52. loss.backward()
  53. optimizer.step()
  54. print(f'Result: {model.string()}')

脚本的总运行时间:(0 分钟 0.000 秒)

下载 Python 源码:dynamic_net.py

下载 Jupyter 笔记本:dynamic_net.ipynb

由 Sphinx 画廊生成的画廊