Row 9145

Row ID: 9145 | Dataset Entry | Axioma AXP Content Repository

Content Data

This page contains data entry 9145 from the Axioma AXP content repository. The structured data below represents the complete record for this entry.

Hi, my intention is to prepare myself for the upcoming academic year on September.

I want to have the ability to write my own PyTorch's Module, Loss, and Optimizer. I intend to start easy with Module (Linear), Loss (Least Squares) and Optimizer (Gradient Descent).

My goal is to implement: 1. `LeastSquares` loss which subclass the `torch.nn.modules.loss._Loss` class. 2. `GradientDescent` optimizer which subclass the `torch.optim.optimizer.Optimizer` class. 2. `Cubic Polynomial` module which subclass the `torch.nn.Module` class.

What I've tried: 1. Read [Learning PyTorch with Examples](https://pytorch.org/tutorials/beginner/pytorch_with_examples.html)

The Learning PyTorch with Examples teach how to define autograd functions. This became [a dedicated StackOverflow question](https://stackoverflow.com/questions/78504721/why-torch-autograd-function-backward-pass-a-grad-output)

The rest of the examples teach how to use existing Loss function (such as `torch.nn.MSELoss`), Optimizer (such as `torch.optim.SGD`) and Module (such as `torch.nn.Linear`).

After spending a day. I am confused on how `torch.nn.modules.loss._Loss`, `torch.optim.optimizer.Optimizer`, and `torch.nn.Module` works. Is there a tutorial how to create your own PyTorch Loss, Optimizer, and Module?

The code below is trying to mimic `PyTorch`. But, I don't know how `optimizer.zero_grad()`, `loss.backward()`, and `optimizer.step()` can update the `model.parameters()`. So, I put everything in 1 class.

**I am open to learn the design pattern and so on. Please point me to the right direction.**

``` import numpy as np import math import matplotlib.pyplot as plt

class Module: pass

class CubicPolynomial(Module): a: np.float64 b: np.float64 c: np.float64 d: np.float64

learning_rate: np.float64

def __init__(self, learning_rate=1e-6) -> None: self.a = np.random.randn() self.b = np.random.randn() self.c = np.random.randn() self.d = np.random.randn()

self.learning_rate = learning_rate

def __call__(self, x: np.ndarray): return self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3 def loss_ln(self, y_pred: np.ndarray, y: np.ndarray) -> np.float64: return ((y_pred - y) ** 2).sum() def zero_grad(self) -> None: # Manually zero the gradients after updating weights self.grad_a = None self.grad_b = None self.grad_c = None self.grad_d = None def backward(self, y_pred: np.ndarray) -> None: # Backprop to compute gradients of a, b, c, d with respect to loss grad_y_pred = 2.0 * (y_pred - y) # d/da (y_pred - y)² # 2 * (y_pred - y) self.grad_a = grad_y_pred.sum() # d/db (a + (b * x) + (c * x²) + (d * x³) - y)² # 2 * (y_pred - y) * x self.grad_b = (grad_y_pred * x).sum()

# d/dc (a + (b * x) + (c * x²) + (d * x³) - y)² # 2 * (y_pred - y) * x² self.grad_c = (grad_y_pred * x ** 2).sum()

# d/dd (a + (b * x) + (c * x²) + (d * x³) - y)² # 2 * (y_pred - y) * x³ self.grad_d = (grad_y_pred * x ** 3).sum()

def step(self) -> None: # Update weights using gradient descent self.a -= self.learning_rate * self.grad_a self.b -= self.learning_rate * self.grad_b self.c -= self.learning_rate * self.grad_c self.d -= self.learning_rate * self.grad_d

dtype = np.float64

# Create random input and output data x = np.linspace(-math.pi, math.pi, 2000, dtype=dtype) y = np.sin(x)

plt.plot(x, y, 'blue')

learning_rate = 1e-6 model = CubicPolynomial(learning_rate=learning_rate)

for t in range(2000): # Forward pass: compute predicted y y_pred = model(x)

# Compute and print loss loss = model.loss_ln(y_pred, y) if t % 100 == 99: print(t, loss)

# Before the backward pass, use the optimizer object to zero all of the # gradients for the variables it will update (which are the learnable # weights of the model). This is because by default, gradients are # accumulated in buffers( i.e, not overwritten) whenever .backward() # is called. Checkout docs of torch.autograd.backward for more details. model.zero_grad()

# Backward pass: compute gradient of the loss with respect to model # parameters model.backward(y_pred)

# Calling the step function on an Optimizer makes an update to its # parameters model.step()

print(f'Result: y = {model.a} + {model.b} x + {model.c} x^2 + {model.d} x^3')

plt.plot(x, y_pred, 'orange')

%reset -f ```

FieldValue
text Hi, my intention is to prepare myself for the upcoming academic year on September. I want to have the ability to write my own PyTorch's Module, Loss, and Optimizer. I intend to start easy with Module (Linear), Loss (Least Squares) and Optimizer (Gradient Descent). My goal is to implement: 1. `LeastSquares` loss which subclass the `torch.nn.modules.loss._Loss` class. 2. `GradientDescent` optimizer which subclass the `torch.optim.optimizer.Optimizer` class. 2. `Cubic Polynomial` module which sub…
label r/datascience
dataType post
communityName r/datascience
datetime 2024-05-20
username_encoded Z0FBQUFBQm5Lakw0NzI3RFdEWlNfQXZVaXRxZHpSV3B2b2RlcFdrYUhKaFRQMnctRkQ0T25vZzFwdGhTUHVFN1Z2YXRSMUJIQ2JfRXRlaUVhSjBMVEVON19NRDMxenh0YUE9PQ==
url_encoded Z0FBQUFBQm5Lak9JLTlDSnpGOVdSaFR1WDFRb1VhWkxhXzVUU1I0bGZQdXc2SHNZdGhDd280a29uSlBXcE8yaldnWWdRZE1ESWxFSFRveHpRUmJOTkNCT3JsSklhWW10cGRSQ2RDdWdOWmU2b2JhU2FOcFQzc3c0Y05VQWJtRWJ2d2UyZ3R3NXI2c1ZBdmxvdEY5alZaYkxabmh3MV9OWGVWZWtfeTFjcEdja0tjMFExQVpNcUpiQ19GU3otS1NWa2x3aUQ3N2hKQWI5bENKTUpYN3RCLWNkd1o4bU5XZ05Ydz09

Raw Record

{
  "text": "Hi, my intention is to prepare myself for the upcoming academic year on September.\n\nI want to have the ability to write my own PyTorch's Module, Loss, and Optimizer. I intend to start easy with Module (Linear), Loss (Least Squares) and Optimizer (Gradient Descent).\n\nMy goal is to implement:\n1. `LeastSquares` loss which subclass the `torch.nn.modules.loss._Loss` class.\n2. `GradientDescent` optimizer which subclass the `torch.optim.optimizer.Optimizer` class.\n2. `Cubic Polynomial` module which subclass the `torch.nn.Module` class.\n\nWhat I've tried:\n1. Read [Learning PyTorch with Examples](https://pytorch.org/tutorials/beginner/pytorch_with_examples.html)\n\n   The Learning PyTorch with Examples teach how to define autograd functions. This became [a dedicated StackOverflow question](https://stackoverflow.com/questions/78504721/why-torch-autograd-function-backward-pass-a-grad-output)\n\n   The rest of the examples teach how to use existing Loss function (such as `torch.nn.MSELoss`), Optimizer (such as `torch.optim.SGD`) and Module (such as `torch.nn.Linear`).\n\n\nAfter spending a day. I am confused on how `torch.nn.modules.loss._Loss`, `torch.optim.optimizer.Optimizer`, and `torch.nn.Module` works. Is there a tutorial how to create your own PyTorch Loss, Optimizer, and Module?\n\nThe code below is trying to mimic `PyTorch`. But, I don't know how `optimizer.zero_grad()`, `loss.backward()`, and `optimizer.step()` can update the `model.parameters()`. So, I put everything in 1 class.\n\n**I am open to learn the design pattern and so on. Please point me to the right direction.**\n\n```\nimport numpy as np\nimport math\nimport matplotlib.pyplot as plt\n\nclass Module: pass\n\nclass CubicPolynomial(Module):\n  a: np.float64\n  b: np.float64\n  c: np.float64\n  d: np.float64\n\n  learning_rate: np.float64\n\n  def __init__(self, learning_rate=1e-6) -> None:\n    self.a = np.random.randn()\n    self.b = np.random.randn()\n    self.c = np.random.randn()\n    self.d = np.random.randn()\n\n    self.learning_rate = learning_rate\n\n  def __call__(self, x: np.ndarray):\n    return self.a + self.b * x + self.c * x ** 2 + self.d * x ** 3\n  \n  def loss_ln(self, y_pred: np.ndarray, y: np.ndarray) -> np.float64:\n    return ((y_pred - y) ** 2).sum()\n  \n  def zero_grad(self) -> None:\n    # Manually zero the gradients after updating weights\n    self.grad_a = None\n    self.grad_b = None\n    self.grad_c = None\n    self.grad_d = None\n  \n  def backward(self, y_pred: np.ndarray) -> None:\n    # Backprop to compute gradients of a, b, c, d with respect to loss\n    grad_y_pred = 2.0 * (y_pred - y)\n    # d/da (y_pred - y)²\n    #      2 * (y_pred - y)\n    self.grad_a = grad_y_pred.sum()\n    \n    # d/db (a + (b * x) + (c * x²) + (d * x³) - y)²\n    #      2 * (y_pred - y) * x\n    self.grad_b = (grad_y_pred * x).sum()\n\n    # d/dc (a + (b * x) + (c * x²) + (d * x³) - y)²\n    #      2 * (y_pred - y) * x²\n    self.grad_c = (grad_y_pred * x ** 2).sum()\n\n    # d/dd (a + (b * x) + (c * x²) + (d * x³) - y)²\n    #      2 * (y_pred - y) * x³\n    self.grad_d = (grad_y_pred * x ** 3).sum()\n\n  def step(self) -> None:\n    # Update weights using gradient descent\n    self.a -= self.learning_rate * self.grad_a\n    self.b -= self.learning_rate * self.grad_b\n    self.c -= self.learning_rate * self.grad_c\n    self.d -= self.learning_rate * self.grad_d\n\ndtype = np.float64\n\n# Create random input and output data\nx = np.linspace(-math.pi, math.pi, 2000, dtype=dtype)\ny = np.sin(x)\n\nplt.plot(x, y, 'blue')\n\nlearning_rate = 1e-6\nmodel = CubicPolynomial(learning_rate=learning_rate)\n\nfor t in range(2000):\n  # Forward pass: compute predicted y\n  y_pred = model(x)\n\n  # Compute and print loss\n  loss = model.loss_ln(y_pred, y)\n  if t % 100 == 99:\n    print(t, loss)\n\n  # Before the backward pass, use the optimizer object to zero all of the\n  # gradients for the variables it will update (which are the learnable\n  # weights of the model). This is because by default, gradients are\n  # accumulated in buffers( i.e, not overwritten) whenever .backward()\n  # is called. Checkout docs of torch.autograd.backward for more details.\n  model.zero_grad()\n\n  # Backward pass: compute gradient of the loss with respect to model\n  # parameters\n  model.backward(y_pred)\n\n  # Calling the step function on an Optimizer makes an update to its\n  # parameters\n  model.step()\n\n\nprint(f'Result: y = {model.a} + {model.b} x + {model.c} x^2 + {model.d} x^3')\n\nplt.plot(x, y_pred, 'orange')\n\n%reset -f\n```",
  "label": "r/datascience",
  "dataType": "post",
  "communityName": "r/datascience",
  "datetime": "2024-05-20",
  "username_encoded": "Z0FBQUFBQm5Lakw0NzI3RFdEWlNfQXZVaXRxZHpSV3B2b2RlcFdrYUhKaFRQMnctRkQ0T25vZzFwdGhTUHVFN1Z2YXRSMUJIQ2JfRXRlaUVhSjBMVEVON19NRDMxenh0YUE9PQ==",
  "url_encoded": "Z0FBQUFBQm5Lak9JLTlDSnpGOVdSaFR1WDFRb1VhWkxhXzVUU1I0bGZQdXc2SHNZdGhDd280a29uSlBXcE8yaldnWWdRZE1ESWxFSFRveHpRUmJOTkNCT3JsSklhWW10cGRSQ2RDdWdOWmU2b2JhU2FOcFQzc3c0Y05VQWJtRWJ2d2UyZ3R3NXI2c1ZBdmxvdEY5alZaYkxabmh3MV9OWGVWZWtfeTFjcEdja0tjMFExQVpNcUpiQ19GU3otS1NWa2x3aUQ3N2hKQWI5bENKTUpYN3RCLWNkd1o4bU5XZ05Ydz09"
}

Entry Information