statsnb 0.2.0
Flexible Naive Bayes classifiers using scipy.stats distributions
License: MIT
Requires Python: >=3.8
Keywords: machine-learning, naive-bayes, classification, scipy, scikit-learn

# StatsNB - Flexible Naive Bayes Classifiers

[![PyPI version](https://badge.fury.io/py/statsnb.svg)](https://badge.fury.io/py/statsnb)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Naive Bayes classifiers using **any** scipy.stats continuous distribution, fully compatible with scikit-learn.

## What is StatsNB?

`GaussianNB` from scikit-learn assumes Gaussian (normal) distributions. But what if your data follows a different distribution?

**StatsNB** lets you use **all continuous distributions** from `scipy.stats`, see [scipy.stats documentation](https://docs.scipy.org/doc/scipy/reference/stats.html).

## When to Use StatsNB?

**Use StatsNB when:**
- Your data is heavy-tailed (try `t` or `cauchy` distributions)
- Your data is bounded (try `beta` distribution)
- Your data is strictly positive and skewed (try `gamma` or `lognorm`)
- You want to experiment with different distributions


## Installation
```bash
pip install statsnb
```

## Quick Start
```python
from statsnb import StatsNB
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# Load data
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

# Use t-distribution (more robust than Gaussian)
clf = StatsNB(dist='t')
clf.fit(X_train, y_train)
print(f"Accuracy: {clf.score(X_test, y_test):.3f}")

# Try different distributions
for dist in ['norm', 't', 'laplace', 'cauchy']:
    clf = StatsNB(dist=dist)
    clf.fit(X_train, y_train)
    print(f"{dist:10s}: {clf.score(X_test, y_test):.3f}")
```

## Advanced Features

### Fix Parameters During Fitting
```python
# Fix degrees of freedom for t-distribution
clf = StatsNB(dist='t', fit_args={'fdf': 5})
clf.fit(X_train, y_train)

# Fix location for exponential distribution
clf = StatsNB(dist='expon', fit_args={'floc': 0})
clf.fit(X_train, y_train)
```

### Custom Priors
```python
# Specify class prior probabilities
clf = StatsNB(dist='gamma', priors=[0.2, 0.3, 0.5])
clf.fit(X_train, y_train)
```

### Use Method of Moments (Faster)
```python
# MM is much faster than MLE for some distributions
clf = StatsNB(dist='norm', fit_args={'method': 'MM'})
clf.fit(X_train, y_train)
```


## API Compatibility

StatsNB is fully compatible with scikit-learn:
```python
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV

# Use in pipelines
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', StatsNB())
])
pipe.fit(X_train, y_train)

# Use in grid search
param_grid = {'clf__dist': ['norm', 't', 'laplace']}
grid = GridSearchCV(pipe, param_grid, cv=5)
grid.fit(X_train, y_train)
print(f"Best distribution: {grid.best_params_}")
```
## Performance Note

Unlike `GaussianNB` which uses analytical solutions, `StatsNB` uses numerical optimization (MLE) to fit distributions. This makes it:

- **~5-10x slower** than `GaussianNB`

-  **No incremental learning** (`partial_fit` not supported)
   - Numerical optimization doesn't support online updates

-  **No sample weights**
   - `scipy.stats.fit()` doesn't support weighted MLE

- **More flexible** - supports any distribution
- **Still efficient** for most real-world datasets

However, for `norm`,`expon`,`gamma`,`laplace`, parameter inference can be done with Methods of Momentum, thus support all features of `GaussianNB`.

Therefore, We provide `MomentNB`, which supports all GaussianMB features
- **Incremental learning**
- **Sample weights**
- **Variance Smoothing**
- **And much faster!**

However,`MomentNB` only supports  `norm`,`expon`,`gamma`,`laplace`, setting `dist=` other distributions will result in an error.

## Examples

See the [`examples/`](examples/) directory for more.

## Requirements

- Python ≥ 3.8
- numpy ≥ 1.20.0
- scipy ≥ 1.7.0
- scikit-learn ≥ 1.0.0

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Citation

If you use StatsNB in your research, please cite:
```bibtex
@software{statsnb2025,
  author = {Your Name},
  title = {StatsNB: Flexible Naive Bayes Classifiers},
  year = {2025},
  url = {https://github.com/yourusername/statsnb}
}
```

## Acknowledgments

- Built on top of [scikit-learn](https://scikit-learn.org/) and [scipy](https://scipy.org/)
- Inspired by the flexibility needs of real-world data science