File size: 5,482 Bytes
519e9a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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()