Skip to main content

A clean implementation of linear regression algorithms from scratch

Project description

Linear Regression from Scratch

A production-quality, educational implementation of linear regression algorithms built from scratch using NumPy. This library provides clean, well-documented implementations for learning the mathematical foundations of linear regression while maintaining professional-grade code quality.

🎯 Project Overview

This project implements linear regression algorithms from first principles without using high-level ML libraries like scikit-learn. It's designed as both an educational tool and a functional library that demonstrates professional Python package development practices.

🌟 What Makes This Special

  • 📚 Educational Focus: Understand the mathematics behind linear regression
  • 🏗️ Production Quality: Professional package structure ready for PyPI
  • 🔬 From Scratch: Only NumPy used for mathematical operations
  • 🧪 Fully Tested: Comprehensive test suite with edge case handling
  • 📦 Complete Package: Installable via pip with proper dependency management

📁 Project Architecture

See the full project architecture in DEVELOPMENT.md.

📐 Mathematical Background

For a detailed explanation of the mathematical foundations behind linear regression, see mathematical_background.md.

🚀 Quick Start

Prerequisites

  • Python 3.8+
  • pip package manager

Installation

Option 1: Install from PyPI (recommended)

pip install linreg-from-scratch

Option 2: Clone & Setup for development

git clone https://github.com/illoonego/linear-regression-from-scratch.git
cd linear-regression-from-scratch

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install all dependencies using pyproject.toml (PEP 621)
pip install -e .[dev]
# For optional dependencies (notebooks, docs):
pip install -e ".[notebooks,docs]"

Note: All dependencies are managed via pyproject.toml. The legacy requirements.txt file has been removed for clarity and modern Python packaging best practices.

Running Examples

# Run all examples
python examples/basic_linear_regression.py

# Run specific examples
python examples/basic_linear_regression.py 1d    # Simple regression
python examples/basic_linear_regression.py 2d    # Multiple regression

Basic Usage

Simple Linear Regression

import numpy as np
from linear_regression import LinearRegression, StandardScaler, r2_score

# Create sample data
X = np.array([[1], [2], [3], [4], [5]])
y = np.array([2.1, 3.9, 6.1, 8.0, 9.9])  # y ≈ 2x with noise

# Option 1: Direct usage
model = LinearRegression(learning_rate=0.01, n_iterations=1000)
model.fit(X, y, method='gradient_descent')
predictions = model.predict(X)
print(f"Weights: {model.weights_}")
print(f"R² Score: {r2_score(y, predictions):.4f}")

# Option 2: With preprocessing
scaler = StandardScaler()
X_scaled = scaler.fit(X).transform(X)
model.fit(X_scaled, y)
predictions_scaled = model.predict(X_scaled)
print(f"Weights (scaled): {model.weights_}")
print(f"R² Score (scaled): {r2_score(y, predictions_scaled):.4f}")

Multiple Linear Regression

import numpy as np
from linear_regression import LinearRegression, r2_score

# House price prediction example
np.random.seed(42)
size_sqft = np.random.uniform(800, 2500, 100)
bedrooms = np.random.randint(1, 5, 100)
X = np.column_stack((size_sqft, bedrooms))

# True relationship: price = 150*size + 10000*bedrooms + 20000 + noise
price = 150 * size_sqft + 10000 * bedrooms + 20000 + np.random.randn(100) * 10000

model = LinearRegression(learning_rate=1e-7, n_iterations=5000)
model.fit(X, price)
predictions = model.predict(X)

print(f"Learned coefficients: {model.weights_[1:]}")  # [size_coef, bedroom_coef]
print(f"Intercept: {model.weights_[0]}")
print(f"R² Score: {r2_score(price, predictions):.4f}")

Polynomial Regression Example

import numpy as np
from linear_regression import PolynomialRegression, r2_score

X = np.array([[1], [2], [3], [4], [5]])
y = np.array([1, 4, 9, 16, 25])  # y = x^2
model = PolynomialRegression(degree=2)
model.fit(X, y)
predictions = model.predict(X)
print(f"Predictions: {predictions}")
print(f"R² Score: {r2_score(y, predictions):.4f}")

📊 Current Features

✅ Implemented & Tested

  • LinearRegression: Complete implementation with both gradient descent and normal equation (closed-form solution)
  • PolynomialRegression: Full implementation with feature expansion, robust input validation, and edge case handling
  • StandardScaler: Feature standardization with robust validation
  • Metrics: r2_score, mean_squared_error, mean_absolute_error (100% coverage)
  • Examples: Working 1D, 2D, and polynomial regression demonstrations
  • Error Handling: Comprehensive input validation and edge case management
  • Verbose Training Output: Control progress printing with the verbose flag
  • Professional Structure: PyPI-ready package with proper metadata

🚧 Planned Features

See the DEVELOPMENT.md for the full roadmap and planned features.

🧪 Testing & Development

Run Tests & Coverage

# Run all tests and coverage
pytest --cov=src/linear_regression tests/ -v
# Coverage: LinearRegression 99%, PolynomialRegression & metrics 100%

Continuous Integration & Delivery (CI/CD)

This project uses GitHub Actions for:

  • CI: Automatic tests, linting (ruff), formatting checks (black), and coverage reporting on every push and pull request. See .github/workflows/python-ci.yml.
  • CD: Automated publishing to PyPI on new version tags. See .github/workflows/python-cd.yml.

How releases work:

  • When a new version tag (e.g., v1.0.0) is pushed, the CD workflow builds and publishes the package to PyPI using secure repository secrets.
  • See DEVELOPMENT.md for more on the release workflow.

Code Quality

# Format code
black src/ tests/ examples/

# Sort imports  
isort src/ tests/ examples/

# Lint code
flake8 src/ tests/ examples/

Development Installation

# Install with development dependencies
pip install -e ".[dev,notebooks,docs]"

🎯 Example Output

$ python examples/basic_linear_regression.py 2d

2D Multiple Linear Regression Example
----------------------------------------

Generating synthetic data...
Data points: 100
True weights: size coefficient=150, bedroom coefficient=10000, intercept=20000

Training model with Gradient Descent...
Iteration 0: Cost = 1250000000.0000
Iteration 500: Cost = 125678923.4567  
Iteration 1000: Cost = 89234567.1234

Training completed!

Results:
Learned weights: size coefficient=149.87, bedroom coefficient=9989.23, intercept=20145.67
R² Score:        0.9234
MSE:             89234567.12

Comparison with True Values:
model_gd = LinearRegression(learning_rate=0.01, n_iterations=1000, verbose=True)
model_gd.fit(X, y, method='gradient_descent')
predictions_gd = model_gd.predict(X)
print(f"GD Weights: {model_gd.weights_}")
print(f"GD R² Score: {r2_score(y, predictions_gd):.4f}")

# Option 2: Normal Equation (closed-form)
model_ne = LinearRegression(verbose=False)
model_ne.fit(X, y, method='normal_equation')
predictions_ne = model_ne.predict(X)
print(f"NE Weights: {model_ne.weights_}")
print(f"NE R² Score: {r2_score(y, predictions_ne):.4f}")
True:    size=150.00, bedroom=10000.00, intercept=20000.00  
Learned: size=149.87, bedroom=9989.23, intercept=20145.67
Error:   size=0.13, bedroom=10.77, intercept=145.67

🎓 Educational Value

This project demonstrates:

  • Mathematical Understanding: Implement algorithms from equations, including polynomial feature expansion
  • Software Engineering: Professional Python package development
  • Machine Learning: Core concepts without library abstractions
  • Numerical Computing: Efficient NumPy vectorized operations
  • Testing: Comprehensive test coverage with edge cases and fixtures
  • Documentation: Clear code documentation and user guides

📏 Metrics Usage Example

from linear_regression import r2_score, mean_squared_error, mean_absolute_error
print(r2_score(y, predictions))
print(mean_squared_error(y, predictions))
print(mean_absolute_error(y, predictions))

🤝 Contributing

We welcome contributions! Please see:

🙏 Acknowledgments

  • Built for educational purposes to understand ML fundamentals
  • Mathematical foundations from "The Elements of Statistical Learning"
  • Inspired by the need for transparent, understandable ML implementations

Note: This is primarily an educational project. For production ML workflows, consider using established libraries like scikit-learn, though this implementation is production-quality and could be used in real applications.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linreg_from_scratch-0.2.0.tar.gz (20.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linreg_from_scratch-0.2.0-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file linreg_from_scratch-0.2.0.tar.gz.

File metadata

  • Download URL: linreg_from_scratch-0.2.0.tar.gz
  • Upload date:
  • Size: 20.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for linreg_from_scratch-0.2.0.tar.gz
Algorithm Hash digest
SHA256 25eb0f52a4e85e3d7872067c542cb4a1959ffcd57cf9ee12363e42e5f099f6ce
MD5 9a5170566f2d8a4bbe2717eefbdd3004
BLAKE2b-256 6a4f1b7e825b7b6815d624cf71141bc634d941972f631e571b9213170e3dc361

See more details on using hashes here.

File details

Details for the file linreg_from_scratch-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for linreg_from_scratch-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7efe8844e579271227dc0380b0daaf63072fbef78a862701c1c03d2ac187cdd3
MD5 e58e0c5b4efb19293f96dc6e2f5fc2de
BLAKE2b-256 ad10fcfd6d7bc2bb78a98d224faeea9a9af5dbe71fa2d30eecf132eb3c823bac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page