sklearn Integration
The nirs4all.sklearn module provides sklearn-compatible wrappers for trained nirs4all pipelines, enabling integration with scikit-learn tools and SHAP explainers.
Overview
import nirs4all
from nirs4all.sklearn import NIRSPipeline, NIRSPipelineClassifier
import shap
# Train with nirs4all
result = nirs4all.run(pipeline, dataset)
# Wrap for sklearn compatibility
pipe = NIRSPipeline.from_result(result)
# Use sklearn-style interface
y_pred = pipe.predict(X_test)
score = pipe.score(X_test, y_test)
# Use with SHAP
explainer = shap.Explainer(pipe.predict, X_background)
shap_values = explainer(X_test)
Key Concept
Important: NIRSPipeline is a prediction wrapper, not a training estimator. Training is always done via nirs4all.run(). The wrapper provides sklearn compatibility for:
Prediction (
predict(),score())SHAP integration (via
predict()callable)sklearn tools that only need prediction (e.g.,
cross_val_predict,permutation_importance)
# ✅ Correct workflow
result = nirs4all.run(pipeline, dataset) # Training
pipe = NIRSPipeline.from_result(result) # Wrap for sklearn
pipe.predict(X_new) # Prediction works
# ❌ NIRSPipeline does NOT train
pipe = NIRSPipeline(steps=[...])
pipe.fit(X, y) # Raises NotImplementedError
Classes
NIRSPipeline
sklearn-compatible regressor wrapper for trained nirs4all pipelines.
Class Methods
NIRSPipeline.from_result(result, fold=0)
Create wrapper from a RunResult.
import nirs4all
from nirs4all.sklearn import NIRSPipeline
result = nirs4all.run(pipeline, dataset, save_artifacts=True)
pipe = NIRSPipeline.from_result(result)
# Specify which fold to use (default: 0)
pipe = NIRSPipeline.from_result(result, fold=2)
Parameter |
Type |
Description |
|---|---|---|
|
|
Result from |
|
|
CV fold index to use (default: 0) |
Returns: NIRSPipeline instance.
NIRSPipeline.from_bundle(path)
Load wrapper from an exported .n4a bundle.
from nirs4all.sklearn import NIRSPipeline
# Load from bundle (deployment scenario)
pipe = NIRSPipeline.from_bundle("exports/model.n4a")
y_pred = pipe.predict(X_new)
Parameter |
Type |
Description |
|---|---|---|
|
|
Path to |
Returns: NIRSPipeline instance.
Instance Methods
predict(X)
Make predictions on new data.
pipe = NIRSPipeline.from_bundle("model.n4a")
y_pred = pipe.predict(X_new)
Parameter |
Type |
Description |
|---|---|---|
|
|
Input features (n_samples, n_features) |
Returns: ndarray of predictions (n_samples,) or (n_samples, n_outputs).
transform(X)
Apply preprocessing without model prediction.
pipe = NIRSPipeline.from_result(result)
X_preprocessed = pipe.transform(X)
Useful for:
Debugging preprocessing
Getting intermediate features for analysis
Base model predictions in stacking
score(X, y)
Calculate R² score (coefficient of determination).
r2 = pipe.score(X_test, y_test)
print(f"R² = {r2:.4f}")
get_transformers()
Get list of preprocessing transformers.
transformers = pipe.get_transformers()
for name, transformer in transformers:
print(f"{name}: {type(transformer).__name__}")
Properties
Property |
Type |
Description |
|---|---|---|
|
|
Underlying fitted model (for SHAP) |
|
|
Always True (wrapper wraps fitted model) |
|
|
Name of the model |
|
|
List of preprocessing step names |
|
|
Index of model step in pipeline |
|
|
Number of CV folds |
|
|
Weights for each fold |
NIRSPipelineClassifier
Classification variant with predict_proba() and accuracy scoring.
from nirs4all.sklearn import NIRSPipelineClassifier
# Classification pipeline
result = nirs4all.run(classification_pipeline, dataset)
pipe = NIRSPipelineClassifier.from_result(result)
# Classification-specific methods
y_pred = pipe.predict(X_test)
proba = pipe.predict_proba(X_test)
accuracy = pipe.score(X_test, y_test) # Uses accuracy, not R²
Additional Methods
predict_proba(X)
Get probability predictions (if model supports it).
proba = pipe.predict_proba(X_test)
# proba.shape: (n_samples, n_classes)
SHAP Integration
NIRSPipeline is designed to work seamlessly with SHAP:
Kernel SHAP (Any Model)
import shap
from nirs4all.sklearn import NIRSPipeline
# Create wrapper
pipe = NIRSPipeline.from_result(result)
# Use with Kernel SHAP (works with any model)
background = shap.kmeans(X_train, 50) # Sample background data
explainer = shap.KernelExplainer(pipe.predict, background)
shap_values = explainer.shap_values(X_test[:10], nsamples=100)
Explainer Auto-Detection
import shap
# SHAP auto-detects best explainer type
explainer = shap.Explainer(pipe.predict, X_train[:100])
shap_values = explainer(X_test)
# Visualization
shap.summary_plot(shap_values)
shap.waterfall_plot(shap_values[0])
Direct Model Access
For model-specific SHAP explainers (TreeExplainer, LinearExplainer):
import shap
pipe = NIRSPipeline.from_result(result)
# Access underlying model
model = pipe.model_
print(f"Model type: {type(model).__name__}")
# Use model-specific explainer
if hasattr(model, 'feature_importances_'):
# Tree-based model
explainer = shap.TreeExplainer(model)
shap_values = explainer(X_test)
elif hasattr(model, 'coef_'):
# Linear model
explainer = shap.LinearExplainer(model, X_train)
shap_values = explainer(X_test)
Examples
Basic Workflow
import nirs4all
from nirs4all.sklearn import NIRSPipeline
from sklearn.preprocessing import MinMaxScaler
from sklearn.cross_decomposition import PLSRegression
# 1. Train with nirs4all
result = nirs4all.run(
pipeline=[
MinMaxScaler(),
PLSRegression(n_components=10)
],
dataset="sample_data/regression",
save_artifacts=True
)
# 2. Wrap for sklearn compatibility
pipe = NIRSPipeline.from_result(result)
# 3. Use sklearn interface
from nirs4all.data import DatasetConfigs
dataset = DatasetConfigs("sample_data/regression")
for config, name in dataset.configs:
ds = dataset.get_dataset(config, name)
X_test, y_test = ds.x({})[:50], ds.y[:50]
break
y_pred = pipe.predict(X_test)
r2 = pipe.score(X_test, y_test)
print(f"R² = {r2:.4f}")
Export and Deploy
import nirs4all
from nirs4all.sklearn import NIRSPipeline
# Training environment
result = nirs4all.run(pipeline, dataset, save_artifacts=True)
result.export("exports/production_model.n4a")
# Deployment environment (different machine/script)
pipe = NIRSPipeline.from_bundle("exports/production_model.n4a")
# Production predictions
y_pred = pipe.predict(new_data)
Feature Importance with SHAP
import nirs4all
from nirs4all.sklearn import NIRSPipeline
import shap
import matplotlib.pyplot as plt
# Train and wrap
result = nirs4all.run(pipeline, dataset)
pipe = NIRSPipeline.from_result(result)
# Get data
X = ... # Your spectral data
# SHAP analysis
background = X[:100]
explainer = shap.Explainer(pipe.predict, background)
shap_values = explainer(X[100:150])
# Visualize
shap.summary_plot(shap_values, feature_names=[f"λ{i}" for i in range(X.shape[1])])
plt.title("Wavelength Importance")
plt.tight_layout()
plt.savefig("shap_summary.png")
Cross-Validation Compatibility
from nirs4all.sklearn import NIRSPipeline
from sklearn.model_selection import cross_val_predict
# Note: NIRSPipeline is for prediction only
# For CV during training, use nirs4all.run() with ShuffleSplit
# But you can use cross_val_predict for prediction validation
# (using pre-trained model)
pipe = NIRSPipeline.from_bundle("model.n4a")
# This works because it only needs predict()
# Note: cv=1 means no CV, just train-test split
from sklearn.model_selection import permutation_importance
perm_importance = permutation_importance(pipe, X_test, y_test, n_repeats=10)
Best Practices
1. Save Artifacts for Wrapping
# ✅ Enable artifacts for NIRSPipeline.from_result()
result = nirs4all.run(pipeline, dataset, save_artifacts=True)
pipe = NIRSPipeline.from_result(result)
# ❌ Without artifacts, from_result() may fail
result = nirs4all.run(pipeline, dataset, save_artifacts=False)
2. Export for Deployment
# Development: train and export
result = nirs4all.run(pipeline, dataset)
result.export("model.n4a")
# Production: load from bundle
pipe = NIRSPipeline.from_bundle("model.n4a")
# No need for training data or original pipeline
3. Choose Appropriate SHAP Explainer
import shap
# For any model (slower but universal)
explainer = shap.KernelExplainer(pipe.predict, background)
# For tree-based models (fast)
explainer = shap.TreeExplainer(pipe.model_)
# For linear models (fast)
explainer = shap.LinearExplainer(pipe.model_, background)
# For neural networks (gradient-based)
explainer = shap.DeepExplainer(pipe.model_, background)
4. Handle High-Dimensional NIRS Data
# NIRS data often has 2000+ wavelengths
# Use subsampling for SHAP efficiency
# Sample fewer background points
background = shap.kmeans(X_train, 50) # Not all samples
# Explain fewer test samples
shap_values = explainer(X_test[:20], nsamples=200)
# Or use feature groups
from nirs4all.operators.transforms import wavelength_bins
groups = wavelength_bins(n_features=X.shape[1], bin_size=50)
Limitations
No Training:
NIRSPipeline.fit()raisesNotImplementedError. Usenirs4all.run()for training.Single Fold: Default uses fold 0. For ensemble prediction across folds, use
nirs4all.predict()withall_predictions=True.Preprocessing in Wrapper: The wrapper applies preprocessing internally. SHAP values are for preprocessed features, not raw wavelengths.
sklearn Tools Requiring fit(): Tools like
GridSearchCVwon’t work because they callfit(). Use nirs4all’s generator syntax for hyperparameter search instead.
See Also
Module-Level API -
nirs4all.run(),predict(), etc.U04_sklearn_integration.py - Complete example
U02_shap_sklearn.py - SHAP example
User Guide - Complete user guide