Skip to main content

numl — ML-алгоритмы с нуля на NumPy

Учебная реализация трёх фундаментальных алгоритмов машинного обучения без использования sklearn, PyTorch или TensorFlow. Написана с целью закрепить теорию на практике.

LinearRegression · LogisticRegression · MNISTNeuralNetwork

Установка

pip install numl

Или клонировать репозиторий для разработки:

git clone https://github.com/KarIes-ss/numl.git
cd numl
pip install -r requirements.txt

Структура проекта

numl/
├── numl/
│   ├── base.py        # BaseModel: цикл SGD, ранняя остановка
│   ├── linear.py      # LinearRegression (SGD / GD / normal equation)
│   ├── logistic.py    # LogisticRegression (SGD / GD)
│   ├── neural.py      # MNISTNeuralNetwork 784→128→64→10 (backprop)
│   └── __init__.py
├── tests/
│   ├── test_linear.py    # 22 теста
│   ├── test_logistic.py  # 21 тест
│   └── test_neural.py    # 34 теста
├── examples/
│   ├── california_housing.ipynb   # LinearRegression на реальных данных
│   ├── breast_cancer.ipynb        # LogisticRegression + анализ порога
│   └── mnist_neural.ipynb         # NeuralNetwork на MNIST
└── requirements.txt

Математика

Ниже — формулы, которые реализованы в коде. Каждый раздел содержит ссылку на соответствующий файл.

Линейная регрессия linear.py

Модель: $\hat{y} = \mathbf{w}^\top \mathbf{x} + b$

Функция потерь (MSE):

$$L = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2$$

Градиент и шаг обновления:

$$\frac{\partial L}{\partial \mathbf{w}} = \frac{1}{m} \mathbf{X}^\top (\hat{\mathbf{y}} - \mathbf{y}), \qquad \mathbf{w} \leftarrow \mathbf{w} - \alpha \cdot \frac{\partial L}{\partial \mathbf{w}}$$

В итеративных режимах обучения можно добавлять штрафы L1/L2 к функции потерь; в библиотеке они доступны через параметры l1 и l2 для LinearRegression и LogisticRegression.

Аналитическое решение (нормальное уравнение):

$$\boldsymbol{\theta} = (\mathbf{X}^\top \mathbf{X})^{-1} \mathbf{X}^\top \mathbf{y}$$

Реализовано через np.linalg.lstsq для численной устойчивости при вырожденных матрицах.


Логистическая регрессия logistic.py

Функция активации — сигмоид:

$$\hat{y} = \sigma(z) = \frac{1}{1 + e^{-z}}, \quad z = \mathbf{w}^\top \mathbf{x} + b$$

Функция потерь (Binary Cross-Entropy):

$$L = -\frac{1}{n} \sum_{i=1}^{n} \left[ y_i \log \hat{y}_i + (1 - y_i) \log (1 - \hat{y}_i) \right]$$

После упрощения через цепное правило градиент принимает ту же форму, что и в линейной регрессии:

$$\frac{\partial L}{\partial \mathbf{w}} = \frac{1}{m} \mathbf{X}^\top (\hat{\mathbf{y}} - \mathbf{y})$$

Благодаря этому LogisticRegression и LinearRegression используют один и тот же цикл обучения в BaseModel, переопределяя только _activation() и _compute_loss().

Почему norm_eq запрещён: BCE не имеет простого аналитического решения в замкнутой форме, поэтому для логистической регрессии используется только итеративная оптимизация.


Нейронная сеть neural.py

Архитектура:

Вход (784) → Dense(128, ReLU) → Dense(64, ReLU) → Dense(10, Softmax)

Прямой проход для слоя $l$:

$$\mathbf{z}^{[l]} = \mathbf{W}^{[l]} \mathbf{a}^{[l-1]} + \mathbf{b}^{[l]}, \qquad \mathbf{a}^{[l]} = g^{[l]}(\mathbf{z}^{[l]})$$

Функция потерь (Categorical Cross-Entropy):

$$L = -\frac{1}{m} \sum_{i=1}^{m} \sum_{k=1}^{K} y_{ik} \log \hat{y}_{ik}$$

Обратный проход (цепное правило):

$$\boldsymbol{\delta}^{[3]} = \hat{\mathbf{Y}} - \mathbf{Y}$$

$$\boldsymbol{\delta}^{[l]} = \left(\mathbf{W}^{[l+1]\top} \boldsymbol{\delta}^{[l+1]}\right) \odot \text{ReLU}'(\mathbf{z}^{[l]})$$

$$\frac{\partial L}{\partial \mathbf{W}^{[l]}} = \frac{1}{m} \boldsymbol{\delta}^{[l]} \mathbf{a}^{[l-1]\top}, \qquad \frac{\partial L}{\partial \mathbf{b}^{[l]}} = \frac{1}{m} \sum \boldsymbol{\delta}^{[l]}$$


Быстрый старт

from numl import LinearRegression, LogisticRegression, MNISTNeuralNetwork

LinearRegression

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from numl import LinearRegression

X, y = fetch_california_housing(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test  = scaler.transform(X_test)

model = LinearRegression(method="norm_eq").fit(X_train, y_train)
print(f"R² = {model.score(X_test, y_test):.4f}")

LogisticRegression

from sklearn.datasets import load_breast_cancer
from numl import LogisticRegression

X, y = load_breast_cancer(return_X_y=True)
# ... предобработка ...

model = LogisticRegression(lr=0.1, epochs=500, threshold=0.5)
model.fit(X_train, y_train)

proba  = model.predict(X_test)
labels = model.predict_class(X_test)
print(f"Accuracy = {model.score(X_test, y_test):.4f}")

Запуск тестов

pip install -r requirements.txt
python -m pytest tests/ -v

Архитектурные решения

  • BaseModel содержит общий цикл обучения, раннюю остановку и историю потерь.
  • Подклассы переопределяют только _activation() и _compute_loss().
  • Для линейной регрессии norm_eq реализован через np.linalg.lstsq.
  • Для логистической регрессии нормальное уравнение не используется.

Metadata

Release files for numl 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for numl 0.2.0
File Size Uploaded
numl-0.2.0.tar.gz 24.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for numl 0.2.0
File Interpreter ABI Platform
numl-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 42.6 kB

Release files / numl-0.2.0.tar.gz

Download URL numl-0.2.0.tar.gz
Size 24.4 kB
Tags Source
SHA-256 checksum
How to use checksums
09b9a293f2478d565a7725ac44e1aa496fdf6e6dded9d2f40af0f8d7408ca8e8
BLAKE2b-256 checksum
How to use checksums
22d2eabfe397fee2a711221cb6d378f0d6333949794d962d41ea7b718270e5a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release files / numl-0.2.0-py3-none-any.whl

Download URL numl-0.2.0-py3-none-any.whl
Size 18.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
16abfe87d20b11ccd5e9d66b65487c54689a72a90da37b4ed3655bc59cb33993
BLAKE2b-256 checksum
How to use checksums
b371ffa5d75c7101ea877d1ea0f558e3533570b405c94101f680cc2036012b87
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page