Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

logistic_regression_torch.py

01_classical_ml/logistic_regression_torch.py  ·  85 lines  ·  view on GitHub

"""
Logistic Regression using PyTorch
Simple PyTorch implementation
"""
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

class LogisticRegressionTorch(nn.Module):
    """
    Logistic Regression using PyTorch
    """
    
    def __init__(self, input_size: int = 2):
        super(LogisticRegressionTorch, self).__init__()
        self.linear = nn.Linear(input_size, 1)
        self.sigmoid = nn.Sigmoid()
    
    def forward(self, x):
        return self.sigmoid(self.linear(x))


# Usage Example
if __name__ == "__main__":
    # Generate sample data
    np.random.seed(42)
    n_samples = 100
    
    # Class 0
    X0 = np.random.randn(n_samples//2, 2).astype(np.float32) + np.array([-2, -2])
    y0 = np.zeros(n_samples//2, dtype=np.float32)
    
    # Class 1
    X1 = np.random.randn(n_samples//2, 2).astype(np.float32) + np.array([2, 2])
    y1 = np.ones(n_samples//2, dtype=np.float32)
    
    #explain vstack and hstack with same example
    # X0 = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
    # X1 = [[11, 12], [13, 14], [15, 16], [17, 18], [19, 20]]
    #y0 = [0, 0, 0, 0, 0]
    #y1 = [1, 1, 1, 1, 1]
    # np.vstack([X0, X1]) = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16], [17, 18], [19, 20]]
    # np.hstack([X0, X1]) = [[1, 2, 11, 12], [3, 4, 13, 14], [5, 6, 15, 16], [7, 8, 17, 18], [9, 10, 19, 20]]
    # np.vstack is used to stack the arrays vertically
    # np.hstack is used to stack the arrays horizontally
    X = np.vstack([X0, X1])
    y = np.hstack([y0, y1])
    
    # Convert to PyTorch tensors
    X_tensor = torch.from_numpy(X)
    #explain unsqueeze with same example
    # X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
    # y = [0, 0, 0, 0, 0]
    # torch.from_numpy(y).unsqueeze(1) = [[0], [0], [0], [0], [0]]
    # torch.from_numpy(y).unsqueeze(1) is used to add a dimension to the array to make it a column vector
    y_tensor = torch.from_numpy(y).unsqueeze(1)
    
    # Create model
    model = LogisticRegressionTorch(input_size=2)
    criterion = nn.BCELoss()
    optimizer = optim.SGD(model.parameters(), lr=0.1)
    
    # Training
    n_epochs = 1000
    for epoch in range(n_epochs):
        # Forward pass
        predictions = model(X_tensor)
        loss = criterion(predictions, y_tensor)
        
        # Backward pass
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if (epoch + 1) % 200 == 0:
            print(f'Epoch [{epoch+1}/{n_epochs}], Loss: {loss.item():.4f}')
    
    # Evaluate
    with torch.no_grad():
        predictions = model(X_tensor)
        predicted_classes = (predictions >= 0.5).float()
        accuracy = (predicted_classes == y_tensor).float().mean()
        print(f"\nAccuracy: {accuracy.item():.4f}")