3. Examples#

Complete examples are listed below which show the library in action.

3.1. Example 1: Linear Regression#

Fits a line to noisy data using a single weight matrix and bias, trained with SGD.

from clumsygrad.loss import mse_loss
from clumsygrad.optimizer import SGD
from clumsygrad.random import randn
from clumsygrad.tensor import Tensor, TensorType

# Data following y = 3*x1 - 2*x2 + 5, with a little noise
X = randn((100, 2), tensor_type=TensorType.INPUT)
true_W = Tensor([[3.0], [-2.0]])
true_b = Tensor([5.0])
y = X @ true_W + true_b + randn((100, 1)) * 0.1

# The model to train
W = Tensor([[0.0], [0.0]], tensor_type=TensorType.PARAMETER)
b = Tensor([0.0], tensor_type=TensorType.PARAMETER)
optimizer = SGD([W, b], lr=0.1)

for epoch in range(100):
    optimizer.zero_grad()
    prediction = X @ W + b
    loss = mse_loss(prediction, y)
    loss.backward()
    optimizer.step()

print(f"Loss: {loss.data:.4f}")
print(f"Learned W: {W.data.flatten()}, b: {b.data.flatten()}")

3.2. Example 2: Logistic Regression#

Passing a linear model through sigmoid() turns it into a binary classifier. This example also swaps in Adam, which can be used anywhere SGD is used.

from clumsygrad import activation as act
from clumsygrad.loss import mse_loss
from clumsygrad.optimizer import Adam
from clumsygrad.random import randn
from clumsygrad.tensor import Tensor, TensorType

# Points labeled by which side of a line they fall on
X = randn((100, 2), tensor_type=TensorType.INPUT) * 2
true_W = Tensor([[4.0], [4.0]])
target = act.sigmoid(X @ true_W)

W = Tensor([[0.0], [0.0]], tensor_type=TensorType.PARAMETER)
b = Tensor([0.0], tensor_type=TensorType.PARAMETER)
optimizer = Adam([W, b], lr=0.1)

for epoch in range(150):
    optimizer.zero_grad()
    prediction = act.sigmoid(X @ W + b)
    loss = mse_loss(prediction, target)
    loss.backward()
    optimizer.step()

print(f"Loss: {loss.data:.4f}")

3.3. Example 3: A Small Neural Network#

A single hidden layer with a relu() activation can fit curves a straight line cannot, such as y = x^2.

from clumsygrad import activation as act
from clumsygrad.loss import mse_loss
from clumsygrad.optimizer import Adam
from clumsygrad.random import rand, randn
from clumsygrad.tensor import Tensor, TensorType

X = rand((100, 1), tensor_type=TensorType.INPUT) * 4 - 2  # range: -2 to 2
y = X**2

w1 = randn((1, 10), tensor_type=TensorType.PARAMETER)
b1 = Tensor([[0.0] * 10], tensor_type=TensorType.PARAMETER)
w2 = randn((10, 1), tensor_type=TensorType.PARAMETER)
b2 = Tensor([0.0], tensor_type=TensorType.PARAMETER)
optimizer = Adam([w1, b1, w2, b2], lr=0.05)

for epoch in range(300):
    optimizer.zero_grad()
    hidden = act.relu(X @ w1 + b1)
    prediction = hidden @ w2 + b2
    loss = mse_loss(prediction, y)
    loss.backward()
    optimizer.step()

print(f"Loss: {loss.data:.4f}")

3.4. Example 4: Inference with no_grad()#

Making predictions with a trained model doesn’t require building a computational graph. Wrapping the forward pass in no_grad() skips graph tracking, so the result comes back as a plain tensor with no gradient bookkeeping attached.

from clumsygrad.tensor import no_grad

# Continuing from the model trained in Example 3
with no_grad():
    hidden = act.relu(X @ w1 + b1)
    prediction = hidden @ w2 + b2

print(prediction.requires_grad)  # False
print(prediction.data[:3].flatten())
print(y.data[:3].flatten())

3.5. Carry On#

  • Read the Tutorial for a step-by-step introduction to tensors and gradients.

  • Browse the API Reference for full function documentation.