Spaces:
Runtime error
Runtime error
| import matplotlib.pyplot as plt | |
| import pandas as pd | |
| import numpy as np | |
| import os | |
| import lime | |
| import lime.lime_tabular | |
| from . import config | |
| def plot_rf_feature_importance(model, feature_names): | |
| """ | |
| Plots and saves the Feature Importance for a Random Forest model. | |
| """ | |
| if not hasattr(model, 'feature_importances_'): | |
| return None | |
| importances = model.feature_importances_ | |
| indices = np.argsort(importances)[::-1] | |
| sorted_names = [feature_names[i] for i in indices] | |
| plt.figure(figsize=(14, 8)) | |
| plt.title("Random Forest: Feature Importance (Global XAI)") | |
| plt.bar(range(len(importances)), importances[indices], align="center", color='teal') | |
| plt.xticks(range(len(importances)), sorted_names, rotation=90) | |
| plt.xlim([-1, len(importances)]) | |
| plt.ylabel("Relative Importance") | |
| plt.tight_layout() | |
| save_path = os.path.join(config.MODEL_DIR, 'rf_feature_importance.png') | |
| plt.savefig(save_path) | |
| plt.close() | |
| print(f"Global XAI Plot saved to {save_path}") | |
| def generate_lime_explanations(model, X_train, X_test, y_test, feature_names, class_names, model_name, num_samples=3): | |
| """ | |
| Generates LIME (Local Interpretable Model-agnostic Explanations) for specific test instances. | |
| This works for ANY model (RF, SVM, etc.). | |
| """ | |
| print(f" Initializing LIME Explainer for {model_name}...") | |
| # 1. Initialize Explainer | |
| # LIME needs the training data to learn the distribution of features (mean, std, etc.) | |
| explainer = lime.lime_tabular.LimeTabularExplainer( | |
| training_data=np.array(X_train), | |
| feature_names=feature_names, | |
| class_names=class_names, | |
| mode='classification', | |
| verbose=False | |
| ) | |
| # 2. Pick sample indices to explain | |
| # We pick evenly spaced samples from the test set to get a variety | |
| indices = np.linspace(0, len(X_test) - 1, num_samples, dtype=int) | |
| output_dir = os.path.join(config.MODEL_DIR, 'lime_explanations') | |
| os.makedirs(output_dir, exist_ok=True) | |
| for i in indices: | |
| # 3. Generate Explanation | |
| # LIME perturbs this specific instance and sees how the model's prediction changes | |
| exp = explainer.explain_instance( | |
| data_row=X_test[i], | |
| predict_fn=model.predict_proba, | |
| num_features=10, | |
| top_labels=1 | |
| ) | |
| # 4. Save Plot | |
| # FIX: We must explicitly tell pyplot which label to plot. | |
| # exp.local_exp keys are the class indices that were explained. | |
| # Since we used top_labels=1, there is only one key. | |
| available_labels = list(exp.local_exp.keys()) | |
| if not available_labels: | |
| continue | |
| explained_label_idx = available_labels[0] | |
| # Get class name for title | |
| pred_label_name = class_names[explained_label_idx] | |
| true_label_name = class_names[y_test[i]] | |
| # Pass the specific label we computed to avoid KeyError | |
| fig = exp.as_pyplot_figure(label=explained_label_idx) | |
| plt.title(f"LIME ({model_name}): Test Inst {i}\nTrue: {true_label_name} | Pred: {pred_label_name}") | |
| plt.tight_layout() | |
| save_path = os.path.join(output_dir, f'{model_name}_inst_{i}_lime.png') | |
| plt.savefig(save_path) | |
| plt.close() | |
| print(f" LIME explanations saved to {output_dir}") |