| """ |
| Machine Learning Model for Predictive Maintenance |
| Uses Random Forest Classifier for failure prediction |
| """ |
|
|
| import pandas as pd |
| import numpy as np |
| import pickle |
| from sklearn.ensemble import RandomForestClassifier |
| from sklearn.metrics import ( |
| accuracy_score, precision_score, recall_score, f1_score, |
| confusion_matrix, classification_report, roc_auc_score |
| ) |
| import warnings |
| warnings.filterwarnings('ignore') |
|
|
| class PredictiveMaintenanceModel: |
| def __init__(self): |
| """Initialize the model""" |
| self.model = RandomForestClassifier( |
| n_estimators=100, |
| max_depth=10, |
| min_samples_split=5, |
| min_samples_leaf=2, |
| random_state=42, |
| class_weight='balanced' |
| ) |
| self.is_trained = False |
| self.feature_importance_ = None |
| |
| def train(self, X_train, y_train): |
| """Train the model""" |
| print("Training Random Forest Classifier...") |
| self.model.fit(X_train, y_train) |
| self.is_trained = True |
| |
| |
| self.feature_importance_ = pd.DataFrame({ |
| 'feature': X_train.columns, |
| 'importance': self.model.feature_importances_ |
| }).sort_values('importance', ascending=False) |
| |
| print("Model training complete!") |
| return self |
| |
| def predict(self, X): |
| """Make predictions""" |
| if not self.is_trained: |
| raise ValueError("Model must be trained first!") |
| return self.model.predict(X) |
| |
| def predict_proba(self, X): |
| """Get prediction probabilities""" |
| if not self.is_trained: |
| raise ValueError("Model must be trained first!") |
| return self.model.predict_proba(X) |
| |
| def evaluate(self, X_test, y_test): |
| """Evaluate the model""" |
| if not self.is_trained: |
| raise ValueError("Model must be trained first!") |
| |
| |
| y_pred = self.predict(X_test) |
| y_pred_proba = self.predict_proba(X_test)[:, 1] |
| |
| |
| accuracy = accuracy_score(y_test, y_pred) |
| precision = precision_score(y_test, y_pred, zero_division=0) |
| recall = recall_score(y_test, y_pred, zero_division=0) |
| f1 = f1_score(y_test, y_pred, zero_division=0) |
| roc_auc = roc_auc_score(y_test, y_pred_proba) |
| |
| |
| cm = confusion_matrix(y_test, y_pred) |
| |
| |
| report = classification_report(y_test, y_pred, zero_division=0) |
| |
| results = { |
| 'accuracy': accuracy, |
| 'precision': precision, |
| 'recall': recall, |
| 'f1_score': f1, |
| 'roc_auc': roc_auc, |
| 'confusion_matrix': cm, |
| 'classification_report': report, |
| 'y_pred': y_pred, |
| 'y_pred_proba': y_pred_proba |
| } |
| |
| print("="*60) |
| print("MODEL EVALUATION RESULTS") |
| print("="*60) |
| print(f"Accuracy: {accuracy:.4f}") |
| print(f"Precision: {precision:.4f}") |
| print(f"Recall: {recall:.4f}") |
| print(f"F1-Score: {f1:.4f}") |
| print(f"ROC-AUC: {roc_auc:.4f}") |
| print("\nConfusion Matrix:") |
| print(cm) |
| print("\nClassification Report:") |
| print(report) |
| |
| return results |
| |
| def predict_maintenance(self, X, tool_wear_values=None): |
| """ |
| Predict maintenance needs and time to failure |
| |
| Args: |
| X: Feature matrix |
| tool_wear_values: Array of tool wear values (optional) |
| |
| Returns: |
| DataFrame with predictions and maintenance recommendations |
| """ |
| if not self.is_trained: |
| raise ValueError("Model must be trained first!") |
| |
| |
| failure_pred = self.predict(X) |
| failure_proba = self.predict_proba(X)[:, 1] |
| |
| |
| |
| avg_tool_wear_at_failure = 120 |
| |
| if tool_wear_values is None: |
| |
| if 'Tool wear [min]' in X.columns: |
| tool_wear_values = X['Tool wear [min]'].values |
| else: |
| tool_wear_values = np.zeros(len(X)) |
| else: |
| |
| tool_wear_values = np.array(tool_wear_values) |
| |
| if tool_wear_values.ndim == 0: |
| tool_wear_values = np.array([tool_wear_values]) |
| |
| |
| if len(tool_wear_values) != len(failure_pred): |
| |
| if len(tool_wear_values) == 1: |
| tool_wear_values = np.repeat(tool_wear_values, len(failure_pred)) |
| else: |
| raise ValueError(f"tool_wear_values length ({len(tool_wear_values)}) doesn't match predictions length ({len(failure_pred)})") |
| |
| |
| time_to_failure = np.maximum(0, avg_tool_wear_at_failure - tool_wear_values) |
| |
| |
| maintenance_status = [] |
| maintenance_urgency = [] |
| |
| for i in range(len(failure_pred)): |
| |
| tool_wear_exceeded = tool_wear_values[i] >= avg_tool_wear_at_failure |
| tool_wear_severely_exceeded = tool_wear_values[i] >= (avg_tool_wear_at_failure * 1.5) |
| |
| |
| if failure_pred[i] == 1: |
| |
| maintenance_status.append("IMMEDIATE MAINTENANCE REQUIRED") |
| maintenance_urgency.append("CRITICAL") |
| elif tool_wear_severely_exceeded and failure_proba[i] > 0.2: |
| |
| maintenance_status.append("IMMEDIATE MAINTENANCE REQUIRED - Tool wear severely exceeded threshold") |
| maintenance_urgency.append("CRITICAL") |
| elif tool_wear_severely_exceeded: |
| |
| maintenance_status.append("URGENT MAINTENANCE NEEDED - Tool wear severely exceeded (monitor closely)") |
| maintenance_urgency.append("HIGH") |
| elif tool_wear_exceeded and failure_proba[i] > 0.3: |
| |
| maintenance_status.append("IMMEDIATE MAINTENANCE REQUIRED - Tool wear exceeded threshold") |
| maintenance_urgency.append("CRITICAL") |
| elif tool_wear_exceeded: |
| |
| maintenance_status.append("URGENT MAINTENANCE NEEDED - Tool wear exceeded threshold") |
| maintenance_urgency.append("HIGH") |
| elif failure_proba[i] > 0.7: |
| |
| maintenance_status.append("Maintenance needed soon") |
| maintenance_urgency.append("HIGH") |
| elif failure_proba[i] > 0.4: |
| |
| maintenance_status.append("Schedule maintenance") |
| maintenance_urgency.append("MEDIUM") |
| elif time_to_failure[i] < 20: |
| |
| maintenance_status.append("Monitor closely - Maintenance needed within 20 minutes") |
| maintenance_urgency.append("MEDIUM") |
| elif time_to_failure[i] < 60: |
| |
| maintenance_status.append("Monitor closely - Maintenance needed within 1 hour") |
| maintenance_urgency.append("MEDIUM") |
| else: |
| |
| maintenance_status.append("No immediate maintenance needed") |
| maintenance_urgency.append("LOW") |
| |
| results_df = pd.DataFrame({ |
| 'Failure_Predicted': failure_pred, |
| 'Failure_Probability': failure_proba, |
| 'Time_to_Failure_Minutes': time_to_failure, |
| 'Maintenance_Status': maintenance_status, |
| 'Maintenance_Urgency': maintenance_urgency |
| }) |
| |
| return results_df |
| |
| |
| def get_feature_importance(self): |
| """Get feature importance""" |
| if self.feature_importance_ is None: |
| raise ValueError("Model must be trained first!") |
| return self.feature_importance_ |
| |
| def save_model(self, filepath='predictive_maintenance_model.pkl'): |
| """Save the trained model""" |
| if not self.is_trained: |
| raise ValueError("Model must be trained first!") |
| |
| with open(filepath, 'wb') as f: |
| pickle.dump(self.model, f) |
| print(f"Model saved to {filepath}") |
| |
| def load_model(self, filepath='predictive_maintenance_model.pkl'): |
| """Load a trained model""" |
| with open(filepath, 'rb') as f: |
| self.model = pickle.load(f) |
| self.is_trained = True |
| print(f"Model loaded from {filepath}") |