AI & Machine Learning Topic
Model Evaluation: How Good is Your Model?
You can't just trust that a trained model will work well. You need to measure its performance rigorously.
The Fundamental Problem: Train-Test Split
The biggest mistake beginners make is testing a model on the same data it was trained on. This leads to overfitting - the model memorizes the training data but fails on new, unseen data.
python
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Train on training data ONLY
model = RandomForestClassifier()
model.fit(X_train, y_train)
# Test on unseen testing data
predictions = model.predict(X_test)
Classification Metrics: Beyond Just "Accuracy"
When dealing with classification problems (cat vs dog, spam vs not spam), accuracy alone can be misleading.
Confusion Matrix: The Foundation
A table that shows the four possible outcomes of predictions:
text
Actual
Positive Negative
Predicted
Positive TP (True Positive) FP (False Positive)
Negative FN (False Negative) TN (True Negative)
python
from sklearn.metrics import confusion_matrix, classification_report cm = confusion_matrix(y_true, y_pred) print(cm) # Output: [[TN, FP], # [FN, TP]]
Key Metrics Derived from Confusion Matrix:
-
Accuracy: Overall, how often is the model correct?
-
Formula: (TP + TN) / Total
-
When to use: When classes are balanced
-
-
Precision: When it predicts "positive", how often is it correct?
-
Formula: TP / (TP + FP)
-
Interpretation: "How reliable are positive predictions?"
-
Use case: Spam detection (minimize false positives - don't want good emails marked as spam)
-
-
Recall (Sensitivity): How many actual positives did it catch?
-
Formula: TP / (TP + FN)
-
Interpretation: "How many sick people did we identify?"
-
Use case: Disease detection (minimize false negatives - don't want to miss sick people)
-
-
F1-Score: The harmonic mean of Precision and Recall
-
Formula: 2 * (Precision * Recall) / (Precision + Recall)
-
When to use: When you need a balance between precision and recall
-
python
from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score
print(f"Accuracy: {accuracy_score(y_test, predictions):.2f}")
print(f"Precision: {precision_score(y_test, predictions):.2f}")
print(f"Recall: {recall_score(y_test, predictions):.2f}")
print(f"F1-Score: {f1_score(y_test, predictions):.2f}")
# Or get everything at once:
print(classification_report(y_test, predictions))
Regression Metrics
For predicting continuous values (house prices, temperatures):
-
Mean Absolute Error (MAE): Average of absolute errors
-
Mean Squared Error (MSE): Average of squared errors (punishes large errors more)
-
R² Score: How much variance is explained by the model (0-1, higher is better)
python
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
print(f"MAE: {mean_absolute_error(y_test, predictions):.2f}")
print(f"MSE: {mean_squared_error(y_test, predictions):.2f}")
print(f"R²: {r2_score(y_test, predictions):.2f}")
Model Optimization: Making Your Model Better
Cross-Validation: More Robust Evaluation
Train-test split only gives you one performance estimate. Cross-validation gives you multiple, more reliable estimates.
K-Fold Cross-Validation
Splits data into K folds, uses each fold as test set once:
text
Fold 1: [Test][Train][Train][Train][Train] Fold 2: [Train][Test][Train][Train][Train] Fold 3: [Train][Train][Test][Train][Train] ...
python
from sklearn.model_selection import cross_val_score
# 5-fold cross-validation
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"Cross-val scores: {scores}")
print(f"Mean accuracy: {scores.mean():.2f} (+/- {scores.std() * 2:.2f})")
Stratified K-Fold
Preserves the percentage of samples for each class (important for imbalanced datasets).
Hyperparameter Tuning: Finding the Best Model Settings
Models have "knobs" you can adjust (hyperparameters). Finding the right settings dramatically improves performance.
Grid Search
Systematically tries all combinations of hyperparameters:
python
from sklearn.model_selection import GridSearchCV
# Define parameter grid
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [3, 5, 7, None],
'min_samples_split': [2, 5, 10]
}
# Search for best parameters
grid_search = GridSearchCV(
RandomForestClassifier(),
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1
)
grid_search.fit(X_train, y_train)
print(f"Best parameters: {grid_search.best_params_}")
print(f"Best cross-val score: {grid_search.best_score_:.2f}")
# Use the best model
best_model = grid_search.best_estimator_
Randomized Search
More efficient for large parameter spaces - samples random combinations.
python
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint
param_dist = {
'n_estimators': randint(50, 500),
'max_depth': randint(3, 20),
'min_samples_split': randint(2, 20)
}
random_search = RandomizedSearchCV(
RandomForestClassifier(),
param_dist,
n_iter=50, # Number of random combinations to try
cv=5,
scoring='accuracy',
n_jobs=-1,
random_state=42
)
Putting It All Together: Complete Workflow
python
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
import pandas as pd
# 1. Load and prepare data
# df = pd.read_csv('data.csv')
# X = df.drop('target', axis=1)
# y = df['target']
# 2. Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 3. Define and tune model
param_grid = {
'n_estimators': [100, 200],
'max_depth': [5, 10, None]
}
grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=5,
scoring='f1'
)
# 4. Train and optimize
grid_search.fit(X_train, y_train)
best_model = grid_search.best_estimator_
# 5. Evaluate final model
final_predictions = best_model.predict(X_test)
print("Best Parameters:", grid_search.best_params_)
print("\nClassification Report:")
print(classification_report(y_test, final_predictions))
# 6. Cross-validation score for final estimate
cv_scores = cross_val_score(best_model, X, y, cv=5, scoring='f1')
print(f"\nCross-val F1 scores: {cv_scores}")
print(f"Average F1: {cv_scores.mean():.3f} (+/- {cv_scores.std() * 2:.3f})")
Key Takeaways
-
Never test on training data - always use proper train-test splits
-
Choose metrics wisely - accuracy isn't always the right choice
-
Use cross-validation for more reliable performance estimates
-
Hyperparameter tuning is essential for optimal performance
-
Different problems need different metrics:
-
Medical diagnosis: Focus on Recall (minimize false negatives)
-
Spam detection: Focus on Precision (minimize false positives)
-
Balanced classification: Accuracy or F1-score
-
Regression: MAE, MSE, or R²
-
This process turns machine learning from "throwing models at data" into a systematic, measurable engineering discipline where you can confidently say "this model works well because..."
Comments (0)
No comments yet. Be the first to comment!