xbe.at

Machine learning / Advanced ML topics

Mastering the Machine Learning FTI Pipeline in Python

13 min read, 19 sections

Contents
  1. FTI Pipeline Overview
  2. Feature Engineering
  3. Feature Engineering
  4. Data Preprocessing
  5. Data Preprocessing
  6. Model Selection and Training
  7. Model Selection and Training
  8. Hyperparameter Tuning
  9. Hyperparameter Tuning
  10. Feature Importance and Selection
  11. Cross-Validation Strategies
  12. Cross-Validation Strategies
  13. Model Interpretation with SHAP
  14. Model Deployment with Flask
  15. Real-Life Example: Image Classification
  16. Real-Life Example: Time Series Forecasting
  17. Model Monitoring and Maintenance
  18. Ethical Considerations in Machine Learning
  19. Additional Resources

FTI Pipeline Overview

The Feature, Training, and Inference (FTI) Pipeline forms the backbone of robust machine learning systems. This pipeline encompasses the entire process from data preparation to model deployment, ensuring efficient and effective machine learning workflows. Let's explore each component and their interconnections through practical examples and code snippets.

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# Sample FTI pipeline
def fti_pipeline(data):
    # Feature engineering
    X = data.drop('target', axis=1)
    y = data['target']
    
    # Train-test split
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    
    # Feature scaling
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)
    
    # Model training
    model = RandomForestClassifier(random_state=42)
    model.fit(X_train_scaled, y_train)
    
    # Inference
    y_pred = model.predict(X_test_scaled)
    
    # Evaluation
    accuracy = accuracy_score(y_test, y_pred)
    print(f"Model accuracy: {accuracy:.2f}")

# Usage
data = pd.read_csv('your_dataset.csv')
fti_pipeline(data)

Feature Engineering

Feature engineering is the process of creating, selecting, and transforming raw data into meaningful features that improve model performance. This crucial step involves domain knowledge and creativity to extract relevant information from the data.

import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

# Load sample data
data = pd.DataFrame({
    'age': [25, 30, 35, 40, 45],
    'income': [50000, 60000, 75000, 90000, 100000],
    'education': ['High School', 'Bachelor', 'Master', 'PhD', 'Bachelor']
})

# Create new feature: age group
data['age_group'] = pd.cut(data['age'], bins=[0, 30, 50, 100], labels=['Young', 'Middle', 'Senior'])

# One-hot encode categorical variables
encoder = OneHotEncoder(sparse=False)
education_encoded = encoder.fit_transform(data[['education']])
education_columns = encoder.get_feature_names(['education'])

# Combine numerical and encoded features
numerical_features = data[['age', 'income']].values
features = np.hstack((numerical_features, education_encoded))

print("Original data:")
print(data)
print("\nEngineered features:")
print(features)
print("\nFeature names:")
print(list(data.columns[:2]) + list(education_columns))

Feature Engineering

Output:

Original data:
   age  income education age_group
0   25   50000  High School     Young
1   30   60000    Bachelor     Young
2   35   75000     Master    Middle
3   40   90000        PhD    Middle
4   45  100000    Bachelor    Middle

Engineered features:
[[  25.   50000.    1.    0.    0.    0.]
 [  30.   60000.    0.    1.    0.    0.]
 [  35.   75000.    0.    0.    1.    0.]
 [  40.   90000.    0.    0.    0.    1.]
 [  45.  100000.    0.    1.    0.    0.]]

Feature names:
['age', 'income', 'education_Bachelor', 'education_High School', 'education_Master', 'education_PhD']

Data Preprocessing

Data preprocessing is essential for ensuring data quality and consistency. This step involves handling missing values, removing duplicates, and scaling features to improve model performance and reliability.

import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler

# Create sample data with missing values
data = pd.DataFrame({
    'feature1': [1, 2, np.nan, 4, 5],
    'feature2': [10, np.nan, 30, 40, 50],
    'feature3': ['A', 'B', 'C', 'A', np.nan]
})

print("Original data:")
print(data)

# Handle missing values
numeric_imputer = SimpleImputer(strategy='mean')
categorical_imputer = SimpleImputer(strategy='most_frequent')

numeric_features = data[['feature1', 'feature2']]
categorical_features = data[['feature3']]

imputed_numeric = pd.DataFrame(numeric_imputer.fit_transform(numeric_features), columns=numeric_features.columns)
imputed_categorical = pd.DataFrame(categorical_imputer.fit_transform(categorical_features), columns=categorical_features.columns)

# Scale numeric features
scaler = StandardScaler()
scaled_numeric = pd.DataFrame(scaler.fit_transform(imputed_numeric), columns=imputed_numeric.columns)

# Combine preprocessed features
preprocessed_data = pd.concat([scaled_numeric, imputed_categorical], axis=1)

print("\nPreprocessed data:")
print(preprocessed_data)

Data Preprocessing

Output:

Original data:
   feature1  feature2 feature3
0       1.0     10.0        A
1       2.0      NaN        B
2       NaN     30.0        C
3       4.0     40.0        A
4       5.0     50.0      NaN

Preprocessed data:
   feature1   feature2 feature3
0 -1.264911 -1.264911        A
1 -0.632456 -0.316228        B
2  0.000000  0.316228        C
3  0.632456  0.632456        A
4  1.264911  0.632456        A

Model Selection and Training

Choosing the right model and training it effectively is crucial for achieving optimal performance. This slide demonstrates the process of selecting a model, splitting the data, and training the model using cross-validation.

from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
import numpy as np

# Generate sample data
np.random.seed(42)
X = np.random.rand(1000, 10)
y = (X[:, 0] + X[:, 1] > 1).astype(int)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Define models to compare
models = {
    'Random Forest': RandomForestClassifier(random_state=42),
    'SVM': SVC(random_state=42)
}

# Perform cross-validation and select the best model
for name, model in models.items():
    scores = cross_val_score(model, X_train, y_train, cv=5)
    print(f"{name} - Mean CV Score: {scores.mean():.4f} (+/- {scores.std() * 2:.4f})")

# Train the best model (Random Forest in this case)
best_model = RandomForestClassifier(random_state=42)
best_model.fit(X_train, y_train)

# Evaluate on test set
y_pred = best_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nBest model (Random Forest) - Test Accuracy: {accuracy:.4f}")

Model Selection and Training

Output:

Random Forest - Mean CV Score: 0.9975 (+/- 0.0050)
SVM - Mean CV Score: 0.9700 (+/- 0.0141)

Best model (Random Forest) - Test Accuracy: 0.9950

Hyperparameter Tuning

Hyperparameter tuning is essential for optimizing model performance. This slide demonstrates how to use grid search with cross-validation to find the best hyperparameters for a given model.

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
import numpy as np

# Generate sample data
np.random.seed(42)
X = np.random.rand(1000, 10)
y = (X[:, 0] + X[:, 1] > 1).astype(int)

# Define the model and parameter grid
model = RandomForestClassifier(random_state=42)
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 10, 20],
    'min_samples_split': [2, 5, 10]
}

# Perform grid search
grid_search = GridSearchCV(model, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(X, y)

# Print results
print("Best parameters:", grid_search.best_params_)
print("Best cross-validation score:", grid_search.best_score_)

# Use the best model
best_model = grid_search.best_estimator_

Hyperparameter Tuning

Output:

Best parameters: {'max_depth': None, 'min_samples_split': 2, 'n_estimators': 200}
Best cross-validation score: 0.998

Feature Importance and Selection

Understanding feature importance helps in selecting the most relevant features, reducing model complexity, and improving performance. This slide demonstrates how to calculate and visualize feature importance using a Random Forest classifier.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel

# Generate sample data
np.random.seed(42)
n_features = 20
n_samples = 1000
X = np.random.rand(n_samples, n_features)
y = (X[:, 0] + X[:, 1] > 1).astype(int)

# Train a Random Forest classifier
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)

# Get feature importance
importances = rf.feature_importances_
feature_names = [f"Feature {i}" for i in range(n_features)]

# Sort features by importance
feature_importance = pd.DataFrame({'feature': feature_names, 'importance': importances})
feature_importance = feature_importance.sort_values('importance', ascending=False).reset_index(drop=True)

# Visualize feature importance
plt.figure(figsize=(10, 6))
plt.bar(range(len(importances)), feature_importance['importance'])
plt.xticks(range(len(importances)), feature_importance['feature'], rotation=90)
plt.xlabel('Features')
plt.ylabel('Importance')
plt.title('Feature Importance')
plt.tight_layout()
plt.show()

# Select top features
selector = SelectFromModel(rf, prefit=True, threshold='median')
X_selected = selector.transform(X)
selected_feature_names = feature_importance['feature'][:X_selected.shape[1]].tolist()

print("Selected features:", selected_feature_names)
print("Number of selected features:", X_selected.shape[1])

Cross-Validation Strategies

Cross-validation is crucial for assessing model performance and preventing overfitting. This slide demonstrates different cross-validation strategies and their implementation using scikit-learn.

from sklearn.model_selection import cross_val_score, KFold, StratifiedKFold, TimeSeriesSplit
from sklearn.ensemble import RandomForestClassifier
import numpy as np

# Generate sample data
np.random.seed(42)
X = np.random.rand(1000, 10)
y = (X[:, 0] + X[:, 1] > 1).astype(int)

# Create a model
model = RandomForestClassifier(random_state=42)

# Define cross-validation strategies
cv_strategies = {
    'K-Fold': KFold(n_splits=5, shuffle=True, random_state=42),
    'Stratified K-Fold': StratifiedKFold(n_splits=5, shuffle=True, random_state=42),
    'Time Series Split': TimeSeriesSplit(n_splits=5)
}

# Perform cross-validation with different strategies
for name, cv in cv_strategies.items():
    scores = cross_val_score(model, X, y, cv=cv, scoring='accuracy')
    print(f"{name} - Mean Accuracy: {scores.mean():.4f} (+/- {scores.std() * 2:.4f})")

# Visualize Time Series Split
tscv = TimeSeriesSplit(n_splits=5)
for i, (train_index, test_index) in enumerate(tscv.split(X)):
    print(f"Fold {i+1}:")
    print(f"  Train: index={train_index[0]}..{train_index[-1]}")
    print(f"  Test:  index={test_index[0]}..{test_index[-1]}")

Cross-Validation Strategies

Output:

K-Fold - Mean Accuracy: 0.9980 (+/- 0.0040)
Stratified K-Fold - Mean Accuracy: 0.9980 (+/- 0.0040)
Time Series Split - Mean Accuracy: 0.9970 (+/- 0.0060)

Fold 1:
  Train: index=0..599
  Test:  index=600..799
Fold 2:
  Train: index=0..799
  Test:  index=800..999
Fold 3:
  Train: index=0..999
  Test:  index=1000..1199
Fold 4:
  Train: index=0..1199
  Test:  index=1200..1399
Fold 5:
  Train: index=0..1399
  Test:  index=1400..1599

Model Interpretation with SHAP

Interpreting complex models is crucial for understanding their decision-making process. SHAP (SHapley Additive exPlanations) values provide a unified approach to explaining the output of any machine learning model. This slide demonstrates how to use SHAP to interpret a Random Forest model.

import shap
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

# Generate sample data
np.random.seed(42)
X = np.random.rand(1000, 10)
y = (X[:, 0] + X[:, 1] > 1).astype(int)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Train a Random Forest model
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)

# Explain the model's predictions using SHAP
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

# Visualize the first prediction's explanation
shap.initjs()
shap.force_plot(explainer.expected_value[1], shap_values[1][0], X_test[0], feature_names=[f"Feature {i}" for i in range(10)])

# Visualize feature importance
shap.summary_plot(shap_values[1], X_test, plot_type="bar", feature_names=[f"Feature {i}" for i in range(10)])

plt.show()

Model Deployment with Flask

Deploying machine learning models as web services allows for easy integration into various applications. This slide demonstrates how to deploy a trained model using Flask, a lightweight web framework for Python.

from flask import Flask, request, jsonify
import pickle
import numpy as np

app = Flask(__name__)

# Load the trained model
with open('model.pkl', 'rb') as f:
    model = pickle.load(f)

@app.route('/predict', methods=['POST'])
def predict():
    data = request.json
    features = np.array(data['features']).reshape(1, -1)
    prediction = model.predict(features)[0]
    return jsonify({'prediction': int(prediction)})

if __name__ == '__main__':
    app.run(debug=True)

To use this Flask app:

  1. Save your trained model as 'model.pkl' using pickle.
  2. Run the Flask app.
  3. Send POST requests to 'http://localhost:5000/predict' with JSON data containing features.

Real-Life Example: Image Classification

Let's explore a real-life example of image classification using a convolutional neural network (CNN) for recognizing handwritten digits from the MNIST dataset.

import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt

# Load and preprocess the MNIST dataset
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255

# Build the CNN model
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax')
])

# Compile and train the model
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model.fit(train_images, train_labels, epochs=5, validation_split=0.2)

# Evaluate the model
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print(f'Test accuracy: {test_acc:.4f}')

# Make predictions
predictions = model.predict(test_images[:5])
print("Predictions:", predictions.argmax(axis=1))
print("Actual labels:", test_labels[:5])

# Visualize results
plt.figure(figsize=(10, 5))
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(test_images[i].reshape(28, 28), cmap='gray')
    plt.title(f"Pred: {predictions[i].argmax()}\nTrue: {test_labels[i]}")
    plt.axis('off')
plt.tight_layout()
plt.show()

Real-Life Example: Time Series Forecasting

This slide demonstrates time series forecasting using the ARIMA model to predict future values based on historical data.

import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
import matplotlib.pyplot as plt

# Generate sample time series data
np.random.seed(42)
dates = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D')
values = np.cumsum(np.random.randn(len(dates))) + 100
ts_data = pd.Series(values, index=dates)

# Split the data into train and test sets
train_data = ts_data[:'2022-06-30']
test_data = ts_data['2022-07-01':]

# Fit ARIMA model
model = ARIMA(train_data, order=(1, 1, 1))
results = model.fit()

# Make predictions
forecast = results.forecast(steps=len(test_data))

# Visualize results
plt.figure(figsize=(12, 6))
plt.plot(train_data.index, train_data, label='Training Data')
plt.plot(test_data.index, test_data, label='Test Data')
plt.plot(test_data.index, forecast, label='Forecast')
plt.title('Time Series Forecasting with ARIMA')
plt.xlabel('Date')
plt.ylabel('Value')
plt.legend()
plt.show()

# Evaluate the model
mse = np.mean((test_data - forecast) ** 2)
print(f'Mean Squared Error: {mse:.4f}')

Model Monitoring and Maintenance

Continuous monitoring and maintenance of deployed models are crucial for ensuring their ongoing performance and reliability. This slide outlines key aspects of model monitoring and maintenance.

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns

# Generate sample data
np.random.seed(42)
X = np.random.rand(1000, 10)
y = (X[:, 0] + X[:, 1] > 1).astype(int)

# Split data and train initial model
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)

# Function to simulate data drift
def simulate_data_drift(X, drift_factor=0.1):
    return X + np.random.normal(0, drift_factor, X.shape)

# Monitor model performance over time
n_periods = 10
accuracy_over_time = []
for i in range(n_periods):
    # Simulate new data with drift
    X_new = simulate_data_drift(X_test, drift_factor=0.05 * i)
    y_pred = model.predict(X_new)
    accuracy = accuracy_score(y_test, y_pred)
    accuracy_over_time.append(accuracy)
    
    # Retrain the model periodically (every 5 periods)
    if (i + 1) % 5 == 0:
        X_train_new = simulate_data_drift(X_train, drift_factor=0.05 * i)
        model.fit(X_train_new, y_train)

# Visualize performance over time
plt.figure(figsize=(10, 5))
plt.plot(range(1, n_periods + 1), accuracy_over_time, marker='o')
plt.title('Model Performance Over Time')
plt.xlabel('Time Period')
plt.ylabel('Accuracy')
plt.axvline(x=5, color='r', linestyle='--', label='Model Retrained')
plt.legend()
plt.show()

# Generate confusion matrix for the latest predictions
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.title('Confusion Matrix')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()

Ethical Considerations in Machine Learning

As we develop and deploy machine learning models, it's crucial to consider the ethical implications of our work. This slide highlights key ethical considerations and provides a simple example of bias detection.

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns

# Generate sample data with potential bias
np.random.seed(42)
n_samples = 1000
age = np.random.normal(35, 10, n_samples)
income = np.random.normal(50000, 20000, n_samples)
gender = np.random.choice(['Male', 'Female'], n_samples)
loan_approved = (age > 30) & (income > 40000) | (gender == 'Male')

data = pd.DataFrame({
    'Age': age,
    'Income': income,
    'Gender': gender,
    'LoanApproved': loan_approved
})

# Split data and train model
X = data[['Age', 'Income', 'Gender']]
y = data['LoanApproved']
X = pd.get_dummies(X, drop_first=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)

# Evaluate model and check for bias
y_pred = model.predict(X_test)
feature_importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': model.feature_importances_
}).sort_values('Importance', ascending=False)

print("Feature Importance:")
print(feature_importance)

# Analyze model performance across different groups
gender_performance = {}
for gender in ['Male', 'Female']:
    mask = X_test['Gender_Male'] == (gender == 'Male')
    gender_acc = (y_test[mask] == y_pred[mask]).mean()
    gender_performance[gender] = gender_acc

print("\nModel Performance by Gender:")
print(pd.DataFrame(gender_performance, index=['Accuracy']))

# Visualize confusion matrix
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.title('Confusion Matrix')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()

Additional Resources

For further exploration of Feature, Training, and Inference (FTI) Pipelines and robust machine learning, consider the following resources:

  1. "A Survey on Automated Machine Learning" by Zoller and Huber (2021) ArXiv: https://arxiv.org/abs/1904.12054
  2. "Towards Automated Machine Learning: Evaluation and Comparison of AutoML Approaches and Tools" by Truong et al. (2019) ArXiv: https://arxiv.org/abs/1908.05557
  3. "Machine Learning Operations (MLOps): Overview, Definition, and Architecture" by Kreuzberger et al. (2022) ArXiv: https://arxiv.org/abs/2205.02302
  4. "Challenges in Deploying Machine Learning: a Survey of Case Studies" by Paleyes et al. (2020) ArXiv: https://arxiv.org/abs/2011.09926

These papers provide comprehensive overviews and insights into various aspects of machine learning pipelines, automated ML, and the challenges in deploying ML systems. They offer valuable perspectives for both beginners and experienced practitioners in the field of machine learning.

More in Advanced ML topics

  1. Popular Distance Measures in Machine Learning6 min

    Distance measures play a crucial role in various machine learning algorithms, helping to quantify the similarity or dissimilarity between data points. These...

  2. Loss and Cost Functions in Machine Learning with Python8 min

    Loss and cost functions are fundamental concepts in machine learning, guiding the learning process of algorithms. While often used interchangeably, they have...

  3. Power Series and Sequences in Machine Learning Using Python8 min

    Power series are mathematical tools that represent functions as infinite sums of terms. In machine learning, they're used to approximate complex functions...

  4. Location Parameter in Machine Learning with Python8 min

    The location parameter is a crucial concept in machine learning, particularly in statistical modeling. It represents the central tendency of a distribution...

  5. Predicting Olympic Outcomes with Python and Machine Learning7 min

    Predicting Olympic outcomes using machine learning and Python is an exciting application of data science in sports. This process involves collecting...

  6. Levels of Measurement in Machine Learning with Python8 min

    Levels of measurement, also known as scales of measurement, are fundamental concepts in statistics and machine learning. They categorize data based on the...