Spaces:
Sleeping
Sleeping
import streamlit as st | |
import torch | |
import joblib | |
import numpy as np | |
from PIL import Image | |
import shap | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
# Load the model and scalers | |
def load_model_and_scalers(): | |
loaded_model = torch.jit.load('model.pt') | |
loaded_scaler1 = joblib.load('scaler1.pkl') | |
loaded_scaler2 = joblib.load('scaler2.pkl') | |
return loaded_model, loaded_scaler1, loaded_scaler2 | |
loaded_model, loaded_scaler1, loaded_scaler2 = load_model_and_scalers() | |
# Add this new function to load the training data | |
def load_training_data(): | |
data = pd.read_excel("peak5.xlsx") | |
X = data.iloc[:, 0:7].to_numpy() | |
return X, data.columns[:7].tolist() | |
X_train, feature_names = load_training_data() | |
# Create a wrapper function for SHAP | |
def f(X): | |
with torch.no_grad(): | |
X_tensor = torch.tensor(X, dtype=torch.float32) | |
output = loaded_model(X_tensor).numpy() | |
return loaded_scaler2.inverse_transform(output) | |
def add_logo(logo_path, size=(200, 150)): | |
logo = Image.open('logoAI.png') | |
logo = logo.resize(size) | |
st.image(logo, use_column_width=False) | |
st.title('Explainable AI (XAI) for Predicting Peak Particle Velocity in Pile Driving on Bangkok Subsoil') | |
add_logo("logoAI.png") | |
# Create input fields | |
st.header('Enter Input Values:') | |
pile_width = st.number_input('Pile width (mm)', value=300.0,min_value=260.0,max_value=800.0) | |
pile_length = st.number_input('Pile length (m)', value=18.0,min_value=15.0,max_value=20.0) | |
weight = st.number_input('Weight (ton)', value=4.2,min_value=3.0,max_value=6.0) | |
drop_height = st.number_input('Drop height (m)', value=0.5) | |
distance = st.number_input('Distance (m)', min_value=3.0,value=9.0) | |
location = st.selectbox('Location', ['On ground', 'On foundation', 'On building'], index=0) | |
trigger = st.selectbox('Trigger', ['Longitudinal', 'Transverse', 'Vertical'], index=0) | |
# Convert location and trigger to numerical values | |
location_value = ['On ground', 'On foundation', 'On building'].index(location) + 1 | |
trigger_value = ['Longitudinal', 'Transverse', 'Vertical'].index(trigger) + 1 | |
# Button to make prediction | |
if st.button('Make Prediction'): | |
# Prepare input data | |
input = np.array([pile_width, pile_length, weight, drop_height, distance, location_value, trigger_value]) | |
inputx = np.reshape(input, (1, 7)) | |
# Transform input data | |
X_test1 = loaded_scaler1.transform(inputx).astype(np.float32) | |
X_test1 = torch.from_numpy(X_test1) | |
# Make prediction | |
with torch.no_grad(): | |
test_outputs = loaded_model(X_test1) | |
test_outputs2 = loaded_scaler2.inverse_transform(test_outputs.cpu()) | |
# Display results | |
st.subheader('Prediction Results:') | |
st.write(f"Peak Particle Velocity: {test_outputs2[0][0]:.2f} mm/s") | |
# Add SHAP explanation | |
st.subheader('Explanation of Prediction:') | |
# Create SHAP explainer | |
explainer = shap.KernelExplainer(f, shap.sample(loaded_scaler1.transform(X_train), 100)) | |
shap_values = explainer.shap_values(X_test1.numpy()) | |
# Create SHAP waterfall plot | |
shap_values_single = shap_values[0].flatten() | |
expected_value = explainer.expected_value[0] | |
# Convert feature values to strings | |
feature_values = [f"{x:.1f}" for x in inputx[0]] | |
explanation = shap.Explanation( | |
values=shap_values_single, | |
base_values=expected_value, | |
data=feature_values, | |
feature_names=feature_names | |
) | |
fig, ax = plt.subplots() | |
shap.plots.waterfall(explanation, show=False) | |
st.pyplot(fig) | |
st.sidebar.header('About') | |
st.sidebar.info('This app uses a pre-trained PyTorch model to predict peak particle velocity based on user input. It is specifically designed for Bangkok sub-soil conditions.\n paper:https://arxiv.org/abs/2409.05918') |