import pandas as pd import numpy as np import gradio as gr import joblib # For loading the model import matplotlib.pyplot as plt import io from PIL import Image # Load the scaler and model scaler_path = "scaler.pkl" model_path = "ebm_model.pkl" # Load the pre-trained scaler and model scaler = joblib.load(scaler_path) ebm = joblib.load(model_path) print("Loaded saved model and scaler.") # Global variable to store the most recent input data for explanation last_input_data_scaled = None # Define prediction function def predict_strength(cement, blast_furnace_slag, fly_ash, water, superplasticizer, coarse_aggregate, fine_aggregate, age): global last_input_data_scaled input_data = pd.DataFrame({ 'cement': [cement], 'blast_furnace_slag': [blast_furnace_slag], 'fly_ash': [fly_ash], 'water': [water], 'superplasticizer': [superplasticizer], 'coarse_aggregate': [coarse_aggregate], 'fine_aggregate': [fine_aggregate], 'age': [age] }) last_input_data_scaled = scaler.transform(input_data) prediction = ebm.predict(last_input_data_scaled) return prediction[0] # Explanation function for dynamic detailed report and enhanced visual def show_local_explanation(): if last_input_data_scaled is not None: local_exp = ebm.explain_local(last_input_data_scaled) contributions = local_exp.data(0)['scores'] names = local_exp.data(0)['names'] # Generate dynamic, user-friendly text report based on contributions report_lines = [] for name, contribution in zip(names, contributions): abs_contribution = abs(contribution) if contribution > 0: if abs_contribution > 10: report_lines.append(f"- {name.capitalize()} strongly contributes to concrete strength (+{contribution:.2f}).") else: report_lines.append(f"- {name.capitalize()} has a minor positive effect on concrete strength (+{contribution:.2f}).") elif contribution < 0: if abs_contribution > 10: report_lines.append(f"- {name.capitalize()} significantly reduces concrete strength ({contribution:.2f}). Consider adjusting this component.") else: report_lines.append(f"- {name.capitalize()} has a slight negative effect on concrete strength ({contribution:.2f}).") # Join lines into a single report report = "\n".join(report_lines) # Enhanced Plotting fig, ax = plt.subplots(figsize=(10, 6)) colors = ['red' if x < 0 else 'green' for x in contributions] ax.barh(names, contributions, color=colors) ax.set_xlabel('Contribution to Prediction') ax.set_title('Local Explanation for the Most Recent Prediction') # Save plot to a buffer buf = io.BytesIO() plt.savefig(buf, format='png', bbox_inches='tight') buf.seek(0) plt.close() # Load image for display img = Image.open(buf) img_array = np.array(img) return img_array, report else: return None, "No prediction has been made yet." # Function to provide the PDF guide def download_guide(): pdf_path = "Guide.pdf" # Path to the uploaded guide return pdf_path # Gradio interface setup with introduction and instructions with gr.Blocks() as app: gr.Markdown("## Concrete Strength Prediction App") gr.Markdown(""" This app predicts the compressive strength of concrete based on its composition using the Explainable Boosting Machine (EBM). EBM is a transparent, interpretable machine learning model that combines the power of boosting techniques with interpretable models, making it easier to explain prediction outcomes. """) gr.Markdown("### Instructions") gr.Markdown(""" - Enter the composition of the concrete in the input fields. - Click 'Predict Concrete Strength' to see the predicted strength. - Click 'Show Detailed Report' to see a breakdown of each feature's impact on the prediction. - Click 'Download Guide' to learn about the concrete mix components and input guidelines. """) with gr.Row(): cement = gr.Number(label="Cement") slag = gr.Number(label="Blast Furnace Slag") fly_ash = gr.Number(label="Fly Ash") water = gr.Number(label="Water") superplasticizer = gr.Number(label="Superplasticizer") coarse_agg = gr.Number(label="Coarse Aggregate") fine_agg = gr.Number(label="Fine Aggregate") age = gr.Number(label="Age") download_btn = gr.Button("Download Guide") predict_btn = gr.Button("Predict Concrete Strength") explanation_btn = gr.Button("Show Detailed Report") guide_file = gr.File(label="Guide Download") result = gr.Textbox(label="Predicted Concrete Strength") local_image = gr.Image(label="Local Explanation", type="numpy") explanation_text = gr.Textbox(label="Feature Impact Report") download_btn.click( fn=download_guide, inputs=[], outputs=guide_file ) predict_btn.click( fn=predict_strength, inputs=[cement, slag, fly_ash, water, superplasticizer, coarse_agg, fine_agg, age], outputs=result ) explanation_btn.click( fn=show_local_explanation, inputs=[], outputs=[local_image, explanation_text] ) app.launch()