ML Functions
npcpy.ml_funcs provides a NumPy-like interface for traditional machine learning operations. Where npcpy.llm_funcs handles LLM calls, ml_funcs handles sklearn models, PyTorch training, time series forecasting, ensembles, and serialization. The API follows the same patterns -- a single call does a single operation, a matrix parameter enables grid search, and n_samples enables repeated training with different seeds.
fit_model
fit_model is the primary entry point for training sklearn-compatible models. Pass the model name as a string and any hyperparameters as keyword arguments.
from npcpy.ml_funcs import fit_model
from sklearn.datasets import make_classification
# Generate sample data
X_train, y_train = make_classification(n_samples=200, n_features=10, random_state=42)
# Fit a single model
result = fit_model(X_train, y_train, model="RandomForestClassifier", n_estimators=100)
print(result["model"]) # The fitted RandomForestClassifier
print(result["scores"]) # Training score
print(len(result["models"])) # 1
The returned dict always contains:
model-- the first (or only) fitted modelmodels-- list of all fitted modelsscores-- training scores (when available)results-- detailed results for grid search / multi-sample runs
Passing a Model Instance
You can also pass an already-constructed sklearn estimator:
from sklearn.svm import SVC
svc = SVC(kernel="rbf", C=1.0)
result = fit_model(X_train, y_train, model=svc)
print(result["model"])
Grid Search with the matrix Parameter
The matrix parameter accepts a dict mapping hyperparameter names to lists of values. fit_model trains one model for every combination in the Cartesian product.
result = fit_model(
X_train, y_train,
model="RandomForestClassifier",
matrix={
"n_estimators": [10, 50, 100],
"max_depth": [3, 5, 10],
},
)
print(f"Fitted {len(result['models'])} configurations") # 9
# Find the best model by training score
best_idx = result["scores"].index(max(result["scores"]))
best_model = result["models"][best_idx]
best_params = result["results"][best_idx]["params"]
print(f"Best params: {best_params}")
print(f"Best score: {result['scores'][best_idx]:.4f}")
Grid search runs in parallel by default. Set parallel=False to disable threading.
Multi-Sample Training
Use n_samples to train multiple models with different random seeds:
result = fit_model(
X_train, y_train,
model="RandomForestClassifier",
n_estimators=100,
n_samples=5,
)
print(f"Trained {len(result['models'])} models with different seeds")
print(f"Score range: {min(result['scores']):.4f} - {max(result['scores']):.4f}")
You can combine matrix and n_samples -- each grid combination is trained n_samples times.
Supported Models
ml_funcs ships with 27 registered sklearn models plus XGBoost.
Classification (9 models)
| Name | sklearn Class |
|---|---|
LogisticRegression |
sklearn.linear_model.LogisticRegression |
RandomForestClassifier |
sklearn.ensemble.RandomForestClassifier |
GradientBoostingClassifier |
sklearn.ensemble.GradientBoostingClassifier |
SVC |
sklearn.svm.SVC |
KNeighborsClassifier |
sklearn.neighbors.KNeighborsClassifier |
DecisionTreeClassifier |
sklearn.tree.DecisionTreeClassifier |
AdaBoostClassifier |
sklearn.ensemble.AdaBoostClassifier |
GaussianNB |
sklearn.naive_bayes.GaussianNB |
MLPClassifier |
sklearn.neural_network.MLPClassifier |
Regression (10 models)
| Name | sklearn Class |
|---|---|
LinearRegression |
sklearn.linear_model.LinearRegression |
Ridge |
sklearn.linear_model.Ridge |
Lasso |
sklearn.linear_model.Lasso |
ElasticNet |
sklearn.linear_model.ElasticNet |
RandomForestRegressor |
sklearn.ensemble.RandomForestRegressor |
GradientBoostingRegressor |
sklearn.ensemble.GradientBoostingRegressor |
SVR |
sklearn.svm.SVR |
KNeighborsRegressor |
sklearn.neighbors.KNeighborsRegressor |
DecisionTreeRegressor |
sklearn.tree.DecisionTreeRegressor |
MLPRegressor |
sklearn.neural_network.MLPRegressor |
Clustering (3 models)
| Name | sklearn Class |
|---|---|
KMeans |
sklearn.cluster.KMeans |
DBSCAN |
sklearn.cluster.DBSCAN |
AgglomerativeClustering |
sklearn.cluster.AgglomerativeClustering |
Dimensionality Reduction (3 models)
| Name | Library |
|---|---|
PCA |
sklearn.decomposition.PCA |
TSNE |
sklearn.manifold.TSNE |
UMAP |
umap.UMAP |
XGBoost
Model names starting with xgb are routed to XGBoost:
Use xgb_classifier for classification and xgb_regressor (or any name starting with xgb that does not contain classifier) for regression.
score_model
score_model evaluates fitted models against test data using named metrics.
from npcpy.ml_funcs import score_model
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
X, y = make_classification(n_samples=300, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
result = fit_model(X_train, y_train, model="RandomForestClassifier", n_estimators=100)
scores = score_model(
X_test, y_test,
model=result["model"],
metrics=["accuracy", "f1", "precision", "recall"],
)
print(scores["scores"])
# {'accuracy': 0.92, 'f1': 0.91, 'precision': 0.93, 'recall': 0.90}
Available Metrics
| Metric | Use Case |
|---|---|
accuracy |
Classification overall correctness |
f1 |
Classification F1 (weighted average) |
precision |
Classification precision (weighted average) |
recall |
Classification recall (weighted average) |
mse |
Regression mean squared error |
mae |
Regression mean absolute error |
r2 |
Regression R-squared |
Scoring Multiple Models
Pass a list of models to score them all at once:
scores = score_model(
X_test, y_test,
model=result["models"], # list from grid search
metrics=["accuracy", "f1"],
)
# scores["all_scores"] is a list of dicts, one per model
for i, s in enumerate(scores["all_scores"]):
print(f"Model {i}: accuracy={s['accuracy']:.4f} f1={s['f1']:.4f}")
ensemble_predict
ensemble_predict combines predictions from multiple models using voting, averaging, or weighted averaging.
from npcpy.ml_funcs import ensemble_predict
# Train multiple models via grid search
result = fit_model(
X_train, y_train,
model="RandomForestClassifier",
matrix={"n_estimators": [10, 50, 100]},
)
# Majority voting (classification)
predictions = ensemble_predict(X_test, result["models"], method="vote")
print(predictions["predictions"]) # array of predicted classes
print(predictions["method"]) # "vote"
# Simple averaging (regression or probabilities)
predictions = ensemble_predict(X_test, result["models"], method="average")
# Weighted averaging
predictions = ensemble_predict(
X_test,
result["models"],
method="weighted",
weights=[0.2, 0.3, 0.5],
)
The returned dict contains:
predictions-- the ensemble predictionsindividual_predictions-- a 2D array of each model's predictionsmethod-- the method used
Ensemble Methods
| Method | Description |
|---|---|
vote |
Majority voting across models (classification). Uses scipy.stats.mode. |
average |
Simple mean of all model predictions (regression). |
weighted |
Weighted sum of predictions. Pass weights as a list of floats. |
cross_validate
cross_validate runs k-fold cross-validation and returns per-fold scores.
from npcpy.ml_funcs import cross_validate
X, y = make_classification(n_samples=300, n_features=10, random_state=42)
cv_result = cross_validate(
X, y,
model="RandomForestClassifier",
cv=5,
metrics=["accuracy", "f1"],
n_estimators=100,
)
for metric, stats in cv_result.items():
print(f"{metric}: mean={stats['mean']:.4f} +/- {stats['std']:.4f}")
print(f" Per-fold: {stats['scores']}")
You can pass model hyperparameters as keyword arguments -- they are forwarded to the model constructor.
predict_model
predict_model runs inference on one or more fitted models.
from npcpy.ml_funcs import predict_model
result = predict_model(X_test, model=fitted_model)
print(result["predictions"]) # predictions from the model
# Predict probabilities
result = predict_model(X_test, model=fitted_model, method="predict_proba")
print(result["predictions"]) # probability matrix
# Transform (for PCA, TSNE, etc.)
result = predict_model(X_new, model=pca_model, method="transform")
print(result["predictions"]) # transformed features
PyTorch Functions
fit_torch
fit_torch trains a PyTorch nn.Module with a standard training loop.
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
from npcpy.ml_funcs import fit_torch
# Define a simple model
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10, 64)
self.fc2 = nn.Linear(64, 2)
def forward(self, x):
x = torch.relu(self.fc1(x))
return self.fc2(x)
model = SimpleNet()
# Create data loaders
X_tensor = torch.randn(200, 10)
y_tensor = torch.randint(0, 2, (200,))
train_loader = DataLoader(TensorDataset(X_tensor, y_tensor), batch_size=32)
# Train
result = fit_torch(
model,
train_loader,
epochs=10,
optimizer="Adam",
lr=0.001,
criterion="CrossEntropyLoss",
device="cpu",
)
print(f"Final train loss: {result['final_train_loss']:.4f}")
print(f"Loss history: {result['history']['train_loss']}")
trained_model = result["model"]
fit_torch Parameters
| Parameter | Default | Description |
|---|---|---|
model |
required | nn.Module instance |
train_loader |
required | PyTorch DataLoader |
epochs |
10 |
Number of training epochs |
optimizer |
"Adam" |
Optimizer class name from torch.optim |
lr |
0.001 |
Learning rate |
criterion |
"CrossEntropyLoss" |
Loss class name from torch.nn |
device |
"cpu" |
Device to train on ("cpu" or "cuda") |
val_loader |
None |
Optional validation DataLoader |
forward_torch
forward_torch runs a forward pass without the training loop.
from npcpy.ml_funcs import forward_torch
inputs = torch.randn(5, 10)
result = forward_torch(trained_model, inputs, device="cpu")
print(result["outputs"]) # raw tensor output
print(result["output_numpy"]) # numpy array
Set grad=True to compute gradients (for analysis or custom training):
Time Series Functions
fit_timeseries
fit_timeseries fits ARIMA, SARIMA, or exponential smoothing models using statsmodels.
import numpy as np
from npcpy.ml_funcs import fit_timeseries
# Generate sample time series
np.random.seed(42)
series = np.cumsum(np.random.randn(200)) + 100
# Fit ARIMA
result = fit_timeseries(series, method="arima", order=(1, 1, 1))
print(f"AIC: {result['aic']:.2f}")
print(f"BIC: {result['bic']:.2f}")
# Fit SARIMA with seasonal component
result = fit_timeseries(
series,
method="sarima",
order=(1, 1, 1),
seasonal_order=(1, 1, 1, 12),
)
# Fit exponential smoothing
result = fit_timeseries(series, method="exp_smoothing")
print(f"SSE: {result['sse']:.2f}")
forecast_timeseries
forecast_timeseries generates predictions from a fitted time series model.
from npcpy.ml_funcs import forecast_timeseries
model = result["model"]
# Forecast 30 periods ahead
forecast = forecast_timeseries(model, horizon=30)
print(forecast["forecast"]) # point forecasts
if "conf_int" in forecast:
print(forecast["conf_int"]) # confidence intervals
Supported Time Series Methods
| Method | Model | Requirements |
|---|---|---|
arima |
ARIMA(p,d,q) | statsmodels |
sarima |
SARIMAX with seasonal order | statsmodels |
exp_smoothing |
Holt-Winters exponential smoothing | statsmodels |
Serialization
serialize_model and deserialize_model save and load models using safe formats (no pickle).
from npcpy.ml_funcs import serialize_model, deserialize_model
# Save with joblib (default, works with sklearn models)
serialize_model(result["model"], "model.joblib")
# Load it back
loaded_model = deserialize_model("model.joblib")
# Save PyTorch models with safetensors
serialize_model(torch_model, "model.safetensors", format="safetensors")
# Load safetensors (returns state dict)
state_dict = deserialize_model("model.safetensors")
Supported Formats
| Format | Extension | Use Case |
|---|---|---|
joblib |
.joblib |
sklearn models, XGBoost, general Python objects |
safetensors |
.safetensors |
PyTorch models (saves/loads state_dict) |
Auto-detection works based on file extension. To be explicit, pass format="joblib" or format="safetensors".
Utility Functions
get_model_params
from npcpy.ml_funcs import get_model_params
params = get_model_params(result["model"])
print(params) # {'n_estimators': 100, 'max_depth': None, ...}
set_model_params
from npcpy.ml_funcs import set_model_params
updated_model = set_model_params(result["model"], {"n_estimators": 200})
Full Workflow Example
Here is a complete example that trains, evaluates, ensembles, and serializes models:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from npcpy.ml_funcs import (
fit_model, score_model, ensemble_predict,
cross_validate, serialize_model,
)
# Data
X, y = make_classification(n_samples=500, n_features=15, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# Grid search
result = fit_model(
X_train, y_train,
model="RandomForestClassifier",
matrix={
"n_estimators": [50, 100, 200],
"max_depth": [5, 10, None],
},
)
print(f"Trained {len(result['models'])} configurations")
# Score all models
scores = score_model(X_test, y_test, model=result["models"], metrics=["accuracy", "f1"])
for i, s in enumerate(scores["all_scores"]):
print(f" Config {i}: accuracy={s['accuracy']:.4f} f1={s['f1']:.4f}")
# Ensemble the top 3
top_indices = sorted(range(len(scores["all_scores"])),
key=lambda i: scores["all_scores"][i]["accuracy"],
reverse=True)[:3]
top_models = [result["models"][i] for i in top_indices]
ensemble = ensemble_predict(X_test, top_models, method="vote")
ensemble_scores = score_model(X_test, y_test, model=top_models[0], metrics=["accuracy"])
print(f"Ensemble (vote): {len(top_models)} models")
# Cross-validate the best model
cv = cross_validate(X, y, model="RandomForestClassifier",
cv=5, metrics=["accuracy", "f1"], n_estimators=200)
for metric, stats in cv.items():
print(f" CV {metric}: {stats['mean']:.4f} +/- {stats['std']:.4f}")
# Save the best model
serialize_model(top_models[0], "best_model.joblib")
print("Model saved to best_model.joblib")