Machine Learning
The FTIRdataanalysis class provides comprehensive machine learning capabilities for FTIR plastic classification, including model evaluation, hyperparameter tuning, and explainability analysis.
Overview
The machine learning workflow includes:
Data preparation: Train/test split and scaling
Model evaluation: Test 20+ classification algorithms
Model comparison: Visualize performance metrics
Hyperparameter tuning: Optimize top models
Model interpretation: SHAP explainability analysis
from xpectrass import FTIRdataanalysis
# Initialize with preprocessed data
analysis = FTIRdataanalysis(processed_df, label_column="type", random_state=42)
Data Preparation
Train/Test Split
# Prepare data for machine learning
analysis.ml_prepare_data(
test_size=0.2 # 20% for testing
)
print(f"Training samples: {len(analysis.y_train)}")
print(f"Test samples: {len(analysis.y_test)}")
print(f"Features: {analysis.x_train_scaled.shape[1]}")
print(f"Classes: {analysis.class_names}")
Attributes created:
x_train_scaled,x_test_scaled: Standardized feature matricesx_train_raw,x_test_raw: Raw (unscaled) feature matricesy_train,y_test: Labelsclass_names: Unique class labelsscaler: Fitted StandardScalerlabel_encoder: Fitted LabelEncoderwavenumbers: Array of wavenumber valuesdir_: Dictionary containing all of the above
Available Models
View All Models
# See available classification models
models = analysis.available_models()
print(f"Total models: {len(models)}")
for model_name in models:
print(f" - {model_name}")
Model Categories
The library includes 20+ classification algorithms across multiple families:
Linear Models:
Logistic Regression
Ridge Classifier
SGD Classifier
Tree-Based Models:
Decision Tree
Random Forest
Extra Trees
AdaBoost
Gradient Boosting
Ensemble Models:
XGBoost (multiple configs)
LightGBM (multiple configs)
Naive Bayes:
Gaussian Naive Bayes
Multinomial Naive Bayes
Support Vector Machines:
Linear SVM
RBF SVM
Poly SVM
Nearest Neighbors:
K-Nearest Neighbors (multiple K values)
Neural Networks:
Multi-Layer Perceptron (multiple architectures)
Discriminant Analysis:
Linear Discriminant Analysis
Quadratic Discriminant Analysis
Running Models
Run a Single Model
# Run specific model
results = analysis.run_a_model(
model_name='XGBoost (100)',
model=None,
cv_folds=5,
plot_confusion=True,
save_plot_path=None,
print_test_result=True
)
overall, per_class, confusion_matrix = results
print(f"Accuracy: {overall['accuracy']:.3f}")
print(f"F1 (weighted): {overall['f1_weighted']:.3f}")
Run All Models
Evaluate all available models with cross-validation:
# Run all models
results = analysis.run_all_models(
test_size=0.2,
plot_comparison=True,
accuracy_threshold=0.9,
top_n_methods=20,
save_plot_path=None
)
# View results sorted by F1 score
print(results.sort_values('test_f1', ascending=False))
# Save results
analysis.results_all = results # Stored for later use
Results DataFrame includes:
model_name: Model nametest_accuracy: Test set accuracytest_precision: Weighted precisiontest_recall: Weighted recalltest_f1: Weighted F1 scorey_pred: Predicted labelsy_proba: Predicted probabilitiestrain_accuracy: Training accuracycv_mean: Mean cross-validation scorecv_std: CV standard deviationoverfit_gap: Difference between train and test accuracytrain_time: Training time (seconds)pred_time: Prediction time (seconds)
View Top Models
# Get top 10 models by F1 score
top_models = results.nlargest(10, 'test_f1')
print(top_models[['model_name', 'test_accuracy', 'test_f1', 'cv_mean']])
Model Comparison Visualization
When plot_comparison=True (the default), run_all_models() automatically generates four visualization plots:
Model Comparison Plot
Bar plot of model performance sorted by test accuracy
Shows top N models (controlled by
top_n_methodsparameter)Error bars showing CV standard deviation
Color-coded by performance
Family Comparison Plot
Average performance per model family (e.g., tree-based vs ensemble vs linear)
Violin plots showing distribution within each family
Best model in each family highlighted
Efficiency Analysis Plot
Scatter plot: Training time vs F1 score
Helps identify fast, accurate models
Models above the
accuracy_thresholdare highlighted
Overfitting Analysis Plot
Train score vs test score comparison
Diagonal line = perfect generalization
Points above line indicate overfitting
Shows top N models (controlled by
top_n_methodsparameter)
Hyperparameter Tuning
Tune Top Models
Optimize hyperparameters for best-performing models:
# Tune top 2 models (must run run_all_models() first)
results = analysis.run_all_models()
tuned_results = analysis.model_parameter_tuning(
number_of_models=2 # Number of top models to tune
)
Note: You must call
run_all_models()beforemodel_parameter_tuning(), as it relies onself.results_allandself.dir_being set.
Tuning Search Spaces:
Each model has a predefined search space covering important hyperparameters:
Random Forest: n_estimators, max_depth, min_samples_split, max_features
XGBoost: learning_rate, max_depth, n_estimators, subsample, colsample_bytree
LightGBM: learning_rate, num_leaves, max_depth, feature_fraction
SVM: C, gamma, kernel
KNN: n_neighbors, weights, metric
Model Interpretation
SHAP Explainability
Understand which spectral features drive predictions:
# Explain model predictions with SHAP
shap_results = analysis.explain_by_shap(
model_name='XGBoost (100)', # Model to explain
max_display=20, # Max features to display in SHAP plots
sample_size=100, # Background samples for SHAP values
test_size=0.2, # Train/test split ratio
cv_folds=5, # Cross-validation folds
save_plot_path=None # Path to save SHAP plots
)
# Results are stored in analysis.shap_results
Plots generated:
Summary plot: Shows global feature importance
Beeswarm plot: Feature importance with value distributions
Local SHAP Interpretation
Explain individual predictions:
# Plot decision plot for a single test sample
# (must call explain_by_shap() first)
analysis.local_shap_plot(
sample_index=0, # Index of test sample to explain
figsize=(10, 8),
save_plot_path=None
)
Decision plot shows:
How features push prediction from base value to final prediction
Feature contributions for specific samples
Comparison across multiple samples
Feature Importance by Wavenumber
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Get feature importance as DataFrame
importance_df = pd.DataFrame({
'wavenumber': analysis.wavenumbers,
'importance': np.abs(shap_results['shap_values']).mean(0)
})
# Plot top important wavenumbers
top_features = importance_df.nlargest(20, 'importance')
plt.figure(figsize=(10, 6))
plt.bar(top_features['wavenumber'], top_features['importance'])
plt.xlabel('Wavenumber (cm⁻¹)')
plt.ylabel('Mean |SHAP value|')
plt.title('Top 20 Discriminative Wavenumbers')
plt.show()
Complete Machine Learning Workflow
from xpectrass import FTIRdataprocessing, FTIRdataanalysis
from xpectrass.data import load_jung_2018
# 1. Load and preprocess data
print("Loading and preprocessing data...")
df = load_jung_2018()
ftir = FTIRdataprocessing(df, label_column="type")
ftir.run()
processed_df = ftir.df_norm
# 2. Initialize analysis
analysis = FTIRdataanalysis(
processed_df,
dataset_name="Jung_2018",
label_column="type",
random_state=42
)
# 3. Run all models (automatically prepares data)
print("\nEvaluating all models...")
results = analysis.run_all_models(
test_size=0.2,
plot_comparison=True,
accuracy_threshold=0.9,
top_n_methods=20
)
# 4. Display top models
print("\n" + "="*60)
print("TOP 10 MODELS")
print("="*60)
top10 = results.nlargest(10, 'test_f1')
print(top10[['model_name', 'test_accuracy', 'test_f1', 'cv_mean', 'train_time']])
# 5. Tune top models
print("\nTuning top 2 models...")
tuned = analysis.model_parameter_tuning(number_of_models=2)
# 6. Explain best model with SHAP
print("\nExplaining with SHAP...")
analysis.explain_by_shap(
model_name='XGBoost (100)',
max_display=20,
sample_size=100
)
# 7. Local explanations
print("\nGenerating local explanations...")
analysis.local_shap_plot(sample_index=0)
# 8. Save results
results.to_csv("model_comparison_results.csv", index=False)
print("\n✓ Machine learning workflow complete!")
Cross-Dataset Validation
Test model generalization across different datasets:
from xpectrass.data import load_jung_2018, load_frond_2021
# Train on one dataset
df_train = load_jung_2018()
# ... preprocess ...
analysis_train = FTIRdataanalysis(df_train, label_column="type")
analysis_train.ml_prepare_data(test_size=0.2)
# Test on another dataset
df_test = load_frond_2021()
# ... preprocess with same pipeline ...
analysis_test = FTIRdataanalysis(df_test, label_column="type")
# Evaluate cross-dataset performance
# (Note: Requires manual model training and prediction)
Tips and Best Practices
Data Preparation
Always preprocess first: Baseline correction, denoising, normalization
Use stratified split: Maintains class balance in train/test sets
Set random_state: For reproducible results
Check class balance: Imbalanced classes may require special handling
Model Selection
Start with all models: Run
run_all_models()to get baselineConsider speed vs accuracy: Use efficiency analysis plot
Check cross-validation scores: Models with low CV std are more stable
Don’t overfit: Monitor overfitting analysis plot
Hyperparameter Tuning
Tune top 3-5 models: No need to tune everything
Use cross-validation: Prevents overfitting to test set
Increase n_iter for better results: 50-100 iterations recommended
Be patient: Tuning can take time for complex models
Model Interpretation
Use SHAP for final model: Understand what features matter
Check if important wavenumbers make sense: Should align with chemistry
Validate with domain knowledge: Peak assignments should be reasonable
Use local explanations: Understand individual predictions
Performance Metrics
Choose metrics appropriate for your problem:
Accuracy: Overall correctness (good for balanced datasets)
F1 Score: Harmonic mean of precision and recall (better for imbalanced data)
Precision: Minimize false positives
Recall: Minimize false negatives
Common Issues and Solutions
Issue: Poor Model Performance
Solutions:
Check preprocessing: Baseline correction, normalization
Remove outliers: Use data validation
Try feature selection: Remove noisy wavenumber regions
Increase training data: Combine multiple datasets
Check class balance: Use class weights or resampling
Issue: Overfitting
Solutions:
Use cross-validation consistently
Reduce model complexity
Increase training data
Apply regularization
Use ensemble methods
Issue: Slow Training
Solutions:
Use
n_jobs=-1for parallelizationReduce sample size for initial testing
Start with fast models (Logistic Regression, Linear SVM)
Reduce n_iter for hyperparameter tuning
Issue: SHAP Takes Too Long
Solutions:
Reduce
sample_sizeparameter (50-100 is usually sufficient)Use TreeExplainer for tree-based models (faster)
Use KernelExplainer sample size parameter
Explain fewer samples
Model Export and Deployment
Save Trained Model
import joblib
# Train your best model
best_model_name = tuned.iloc[0]['model']
# ... train model ...
# Save model
joblib.dump(model, 'best_ftir_classifier.pkl')
# Save preprocessing parameters
joblib.dump({
'scaler': analysis.scaler,
'class_names': analysis.class_names,
'wavenumbers': analysis.wavenumbers
}, 'preprocessing_params.pkl')
Load and Use Model
import joblib
import pandas as pd
# Load model and parameters
model = joblib.load('best_ftir_classifier.pkl')
params = joblib.load('preprocessing_params.pkl')
# Preprocess new data
# ... apply same preprocessing pipeline ...
# Predict
predictions = model.predict(new_data_scaled)
probabilities = model.predict_proba(new_data_scaled)
print(f"Predictions: {predictions}")
print(f"Probabilities: {probabilities}")
Next Steps
See Analysis for exploratory data analysis
See Preprocessing Pipeline for data preparation
See Examples for complete workflows
Check API Reference for detailed function documentation