Metadata-Version: 2.4
Name: aicoach
Version: 0.1.0
Summary: A framework-agnostic Python library that coaches you through model training.
License: MIT
Project-URL: Homepage, https://github.com/Rishabh55122/Aicoach
Project-URL: Repository, https://github.com/Rishabh55122/Aicoach
Keywords: machine learning,training,coach,diagnostics,AI
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Dynamic: license-file

# aicoach

> A framework-agnostic Python library that acts like a mentor watching your model training loop.

[![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Version](https://img.shields.io/badge/version-0.1.0-orange)](pyproject.toml)

`aicoach` monitors per-epoch training metrics (loss, validation loss, learning rate, accuracy) and returns **plain-English advice** based on patterns it detects — with no model training, GPU access, or ML framework integration required inside the library itself.

---

## Quick Start

```python
import aicoach

coach = aicoach.Coach()

for epoch in range(epochs):
    train_loss, val_loss = run_one_epoch(...)   # your training loop
    coach.observe(epoch=epoch, train_loss=train_loss, val_loss=val_loss, lr=current_lr)

    for tip in coach.get_advice():
        print(f"💡 {tip}")
```

For standalone class-imbalance checks (before training begins):

```python
label_counts = {"cat": 800, "dog": 750, "bird": 90}
advice = aicoach.check_class_imbalance(label_counts)
if advice:
    print(f"⚠️  {advice}")
```

---

## Installation

```bash
pip install aicoach
```

Or from source:

```bash
git clone https://github.com/Rishabh55122/Aicoach.git
cd Aicoach
pip install -e .[dev]
```

---

## Module Overview

| Module | Function | Detects | Severity |
|---|---|---|---|
| `history` | `Coach.observe()` / `Coach.get_advice()` | Observation store + advice aggregator | — |
| `overfitting` | `check_overfitting()` | Val loss rising while train loss falls | `WARNING` |
| `plateau` | `check_plateau()` | Metric stalled (relative range < threshold) | `WARNING` |
| `learning_rate` | `check_learning_rate()` | LR too high (oscillation) or too low (slow) | `WARNING` / `INFO` |
| `imbalance` | `check_class_imbalance()` | Majority/minority class ratio too large | `WARNING` |
| `divergence` | `check_divergence()` | NaN, Inf, or exponential loss explosion | `CRITICAL` |

---

## Advice Object

Every check returns either `None` (no issue) or an `Advice` object:

```python
from aicoach.data_types import Advice, AdviceLevel

advice.message   # str  — plain-English description and suggested action
advice.level     # AdviceLevel.INFO | WARNING | CRITICAL
advice.code      # str  — machine-readable identifier (e.g. "overfitting")
advice.metadata  # dict — diagnostic context (thresholds, values, indices used)

print(advice)    # [WARNING] (overfitting) Validation loss has risen for 3 consecutive epoch(s)...
```

---

## Module Details

<details>
<summary><strong>history — Observation tracking</strong></summary>

```python
coach = aicoach.Coach()

coach.observe(
    epoch=0,
    train_loss=0.85,
    val_loss=0.90,    # optional
    lr=1e-3,          # optional
    accuracy=0.72,    # optional
)

coach.get_metric("train_loss")           # all values
coach.get_metric("val_loss", window=5)   # last 5 only
coach.get_observations()                 # list[Observation]
coach.reset()                            # clear for a new run
len(coach)                               # number of recorded epochs
```

**Validation rules:**
- `epoch` must be a non-negative, strictly increasing `int`
- All metric values must be `int` or `float` (booleans rejected)
- `None` is accepted for optional fields

</details>

<details>
<summary><strong>overfitting — Early stopping advice</strong></summary>

```python
from aicoach.overfitting import check_overfitting

advice = check_overfitting(coach, patience=3)
```

**Triggers when** (both conditions must hold over the last `patience + 1` epochs):
1. `val_loss` rises on every consecutive step
2. `train_loss` shows a net decrease over the same window

**Default:** `patience=3` — sensible middle ground between sensitivity and noise-resistance. Increase for noisy validation curves.

</details>

<details>
<summary><strong>plateau — Stalled training detection</strong></summary>

```python
from aicoach.plateau import check_plateau

advice = check_plateau(coach, metric="train_loss", window=5, threshold=0.01)
```

**Triggers when:**
```
(max(window) - min(window)) / mean(abs(window)) < threshold
```

Uses **relative** range so it scales correctly across all loss magnitudes (a flat loss at 0.01 and a flat loss at 100 are both detected equally).

**Defaults:** `window=5`, `threshold=0.01` (1%)

</details>

<details>
<summary><strong>learning_rate — LR too high or too low</strong></summary>

```python
from aicoach.learning_rate import check_learning_rate

advice = check_learning_rate(coach, window=5)
```

**Three-zone design (mutually exclusive with plateau):**

| Zone | Condition | Advice |
|---|---|---|
| Stalled | net decrease < 1% | `check_plateau` owns this |
| Creeping | 1% ≤ net decrease < 5% + low oscillation | `lr_too_slow` (INFO) — raise LR |
| Healthy | net decrease ≥ 5% | `None` |
| Oscillating | ≥ 40% of steps went up | `lr_oscillation` (WARNING) — lower LR |

Oscillation is checked first and takes priority over the zone check.

**Defaults:** `window=5`, `oscillation_threshold=0.40`, `plateau_threshold=0.01`, `healthy_rate_threshold=0.05`

</details>

<details>
<summary><strong>imbalance — Class imbalance check</strong></summary>

```python
from aicoach.imbalance import check_class_imbalance

label_counts = {"cat": 800, "dog": 750, "bird": 90}
advice = check_class_imbalance(label_counts, ratio_threshold=4.0)
```

**Triggers when:** `max(counts) / min(counts) >= ratio_threshold`

Standalone — does not require a `Coach` instance. Call before or during training.

**Default:** `ratio_threshold=4.0` — flags when the dominant class has at least 4× as many samples as the rarest class.

</details>

<details>
<summary><strong>divergence — Catastrophic failure detection</strong></summary>

```python
from aicoach.divergence import check_divergence

advice = check_divergence(coach, window=5, growth_threshold=10.0)
```

**Three sub-checks, in priority order:**

| Code | Trigger | Scope |
|---|---|---|
| `divergence_nan` | Any `NaN` in `train_loss` | Full history |
| `divergence_inf` | Any `±Inf` in `train_loss` | Full history |
| `divergence_explosive` | `loss[-1] / loss[0] >= growth_threshold` | Rolling window |

Returns `CRITICAL` severity. When divergence fires via `get_advice()`, all other checks are suppressed.

**Default:** `window=5`, `growth_threshold=10.0` (10× growth within the window)

</details>

---

## Running Tests

```bash
pip install -e .[dev]
pytest -v
```

---

## All Default Thresholds (for your review before publishing)

| Check | Parameter | Default | Rationale |
|---|---|---|---|
| `check_overfitting` | `patience` | `3` | Middle ground between sensitivity and noise resistance |
| `check_plateau` | `window` | `5` | Short enough to respond quickly, wide enough to smooth noise |
| `check_plateau` | `threshold` | `0.01` (1%) | Relative range — scale-invariant across all loss magnitudes |
| `check_learning_rate` | `window` | `5` | Consistent with plateau |
| `check_learning_rate` | `oscillation_threshold` | `0.40` (40%) | ≥ 2 of 4 up-steps within window indicates bouncing |
| `check_learning_rate` | `plateau_threshold` | `0.01` (1%) | Shared lower boundary with `check_plateau` |
| `check_learning_rate` | `healthy_rate_threshold` | `0.05` (5%) | ≈ 1%/epoch net decrease — conservative minimum progress |
| `check_class_imbalance` | `ratio_threshold` | `4.0×` | Commonly cited rule of thumb for moderate imbalance |
| `check_divergence` | `window` | `5` | Rolling window for explosive-growth check |
| `check_divergence` | `growth_threshold` | `10.0×` | 10× growth over 5 epochs is unambiguous explosion |

---

## License

MIT — see [LICENSE](LICENSE).
