Spaces:
Running
Running
Deploy PyCaret model baseline_dt_20250426_212853.pkl
Browse files
README.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
-
sdk:
|
|
|
7 |
pinned: false
|
8 |
---
|
9 |
|
10 |
-
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: my-pycaret-app
|
3 |
+
emoji: π
|
4 |
+
colorFrom: blue
|
5 |
+
colorTo: green
|
6 |
+
sdk: streamlit
|
7 |
+
app_file: app.py
|
8 |
pinned: false
|
9 |
---
|
10 |
|
11 |
+
# my-pycaret-app
|
12 |
+
|
13 |
+
Simple prediction app deployed using Streamlit. Model file: `model.pkl`.
|
14 |
+
Check `requirements.txt` for dependencies.
|
app.py
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import streamlit as st
|
3 |
+
import pandas as pd
|
4 |
+
from pycaret.classification import load_model, predict_model
|
5 |
+
import os
|
6 |
+
import warnings # Added to potentially suppress warnings
|
7 |
+
import logging # Added for better debugging in the Space
|
8 |
+
|
9 |
+
# Configure simple logging for the Streamlit app
|
10 |
+
# Use Streamlit logger if available, otherwise basic config
|
11 |
+
try:
|
12 |
+
# Attempt to get logger specific to Streamlit context
|
13 |
+
logger = st.logger.get_logger(__name__)
|
14 |
+
except AttributeError: # Fallback for older Streamlit versions or different contexts
|
15 |
+
# Basic logging setup if Streamlit logger isn't available
|
16 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - StreamlitApp - %(levelname)s - %(message)s')
|
17 |
+
logger = logging.getLogger(__name__)
|
18 |
+
|
19 |
+
|
20 |
+
# --- Configuration ---
|
21 |
+
MODEL_FILE = "model.pkl" # Relative path within the Space
|
22 |
+
APP_TITLE = "my-pycaret-app"
|
23 |
+
|
24 |
+
# --- Load Model ---
|
25 |
+
# Use cache_resource for efficient loading
|
26 |
+
@st.cache_resource
|
27 |
+
def get_model():
|
28 |
+
logger.info(f"Attempting to load model from file: {MODEL_FILE}")
|
29 |
+
# Define the path expected by PyCaret's load_model (without extension)
|
30 |
+
model_load_path = MODEL_FILE.replace('.pkl','')
|
31 |
+
logger.info(f"Calculated PyCaret load path: '{model_load_path}'") # Escaped braces
|
32 |
+
|
33 |
+
if not os.path.exists(MODEL_FILE):
|
34 |
+
st.error(f"Model file '{MODEL_FILE}' not found in the Space repository.")
|
35 |
+
logger.error(f"Model file '{MODEL_FILE}' not found at expected path.")
|
36 |
+
return None
|
37 |
+
try:
|
38 |
+
# Suppress specific warnings during loading if needed
|
39 |
+
# warnings.filterwarnings("ignore", category=UserWarning, message=".*Trying to unpickle estimator.*")
|
40 |
+
logger.info(f"Calling PyCaret's load_model('{model_load_path}')...") # Escaped braces
|
41 |
+
# Ensure PyCaret logging doesn't interfere excessively if needed
|
42 |
+
# from pycaret.utils.generic import enable_colab
|
43 |
+
# enable_colab() # May help manage output/logging in some environments
|
44 |
+
model = load_model(model_load_path)
|
45 |
+
logger.info("PyCaret's load_model executed successfully.")
|
46 |
+
return model
|
47 |
+
except FileNotFoundError:
|
48 |
+
# Specific handling if load_model itself can't find related files (like preprocess.pkl)
|
49 |
+
st.error(f"Error loading model components for '{model_load_path}'. PyCaret's load_model failed, possibly missing auxiliary files.") # Escaped braces
|
50 |
+
logger.exception(f"PyCaret load_model failed for '{model_load_path}', likely due to missing components:") # Escaped braces
|
51 |
+
return None
|
52 |
+
except Exception as e:
|
53 |
+
# Catch other potential errors during model loading
|
54 |
+
st.error(f"An unexpected error occurred loading model '{model_load_path}': {e}") # Escaped braces around model_load_path
|
55 |
+
logger.exception("Unexpected model loading error details:") # Log full traceback
|
56 |
+
return None
|
57 |
+
|
58 |
+
model = get_model()
|
59 |
+
|
60 |
+
# --- App Layout ---
|
61 |
+
st.set_page_config(page_title=APP_TITLE, layout="centered")
|
62 |
+
st.title(APP_TITLE)
|
63 |
+
|
64 |
+
if model is None:
|
65 |
+
st.error("Model could not be loaded. Please check the application logs in the Space settings for more details. Application cannot proceed.")
|
66 |
+
else:
|
67 |
+
st.success("Model loaded successfully!") # Indicate success
|
68 |
+
st.write("Enter the input features below to get a prediction.")
|
69 |
+
|
70 |
+
# --- Input Widgets ---
|
71 |
+
with st.form("prediction_form"):
|
72 |
+
st.subheader("Input Features:")
|
73 |
+
# Dynamically generated widgets based on schema
|
74 |
+
input_PassengerId = st.number_input(label='PassengerId', format='%f', key='input_PassengerId')
|
75 |
+
input_Pclass = st.number_input(label='Pclass', format='%f', key='input_Pclass')
|
76 |
+
input_Name = st.number_input(label='Name', format='%f', key='input_Name')
|
77 |
+
input_Sex = st.number_input(label='Sex', format='%f', key='input_Sex')
|
78 |
+
input_Age = st.number_input(label='Age', format='%f', key='input_Age')
|
79 |
+
input_SibSp = st.number_input(label='SibSp', format='%f', key='input_SibSp')
|
80 |
+
input_Parch = st.number_input(label='Parch', format='%f', key='input_Parch')
|
81 |
+
input_Ticket = st.number_input(label='Ticket', format='%f', key='input_Ticket')
|
82 |
+
input_Fare = st.number_input(label='Fare', format='%f', key='input_Fare')
|
83 |
+
input_Cabin = st.number_input(label='Cabin', format='%f', key='input_Cabin')
|
84 |
+
input_Embarked = st.number_input(label='Embarked', format='%f', key='input_Embarked')
|
85 |
+
input_Survived = st.number_input(label='Survived', format='%f', key='input_Survived')
|
86 |
+
submitted = st.form_submit_button("Predict")
|
87 |
+
|
88 |
+
# --- Prediction Logic ---
|
89 |
+
if submitted:
|
90 |
+
try:
|
91 |
+
# Create DataFrame from inputs using original feature names as keys
|
92 |
+
# The values are automatically fetched by Streamlit using the keys assigned to widgets
|
93 |
+
input_data_dict = {'PassengerId': input_PassengerId, 'Pclass': input_Pclass, 'Name': input_Name, 'Sex': input_Sex, 'Age': input_Age, 'SibSp': input_SibSp, 'Parch': input_Parch, 'Ticket': input_Ticket, 'Fare': input_Fare, 'Cabin': input_Cabin, 'Embarked': input_Embarked, 'Survived': input_Survived} # Use triple braces for dict literal inside f-string
|
94 |
+
logger.info(f"Raw input data from form: {input_data_dict}")
|
95 |
+
input_data = pd.DataFrame([input_data_dict])
|
96 |
+
|
97 |
+
# Ensure correct dtypes based on schema before prediction
|
98 |
+
logger.info("Applying dtypes based on schema...")
|
99 |
+
# Use double braces for the schema dict literal in the generated code
|
100 |
+
for feature, f_type in {'PassengerId': 'numerical', 'Pclass': 'numerical', 'Name': 'numerical', 'Sex': 'numerical', 'Age': 'numerical', 'SibSp': 'numerical', 'Parch': 'numerical', 'Ticket': 'numerical', 'Fare': 'numerical', 'Cabin': 'numerical', 'Embarked': 'numerical', 'Survived': 'numerical'}.items():
|
101 |
+
if feature in input_data.columns: # Check if feature exists
|
102 |
+
try:
|
103 |
+
if f_type == 'numerical':
|
104 |
+
# Convert to numeric, coercing errors (users might enter text)
|
105 |
+
input_data[feature] = pd.to_numeric(input_data[feature], errors='coerce')
|
106 |
+
# Add elif for 'categorical' or other types if needed
|
107 |
+
# else:
|
108 |
+
# input_data[feature] = input_data[feature].astype(str) # Ensure string type
|
109 |
+
except Exception as type_e:
|
110 |
+
logger.warning(f"Could not convert feature '{feature}' to type '{f_type}'. Error: {type_e}")
|
111 |
+
# Decide how to handle type conversion errors, e.g., set to NaN or keep original
|
112 |
+
input_data[feature] = pd.NA # Set to missing if conversion fails
|
113 |
+
|
114 |
+
else:
|
115 |
+
logger.warning(f"Feature '{feature}' from schema not found in input form data.")
|
116 |
+
|
117 |
+
|
118 |
+
# Handle potential NaN values from coercion or failed conversion
|
119 |
+
if input_data.isnull().values.any():
|
120 |
+
st.warning("Some inputs might be invalid or missing. Attempting to handle missing values (e.g., replacing with 0).")
|
121 |
+
logger.warning(f"NaN values found in input data after type conversion/validation. Filling with 0. Data before fill:\n{input_data}")
|
122 |
+
# More robust imputation might be needed depending on the model
|
123 |
+
input_data.fillna(0, inplace=True) # Simple imputation strategy
|
124 |
+
logger.info(f"Data after filling NaN with 0:\n{input_data}")
|
125 |
+
|
126 |
+
|
127 |
+
st.write("Input Data for Prediction (after processing):")
|
128 |
+
st.dataframe(input_data)
|
129 |
+
|
130 |
+
# Make prediction
|
131 |
+
logger.info("Calling predict_model...")
|
132 |
+
with st.spinner("Predicting..."):
|
133 |
+
# Suppress prediction warnings if needed
|
134 |
+
# with warnings.catch_warnings():
|
135 |
+
# warnings.simplefilter("ignore")
|
136 |
+
predictions = predict_model(model, data=input_data)
|
137 |
+
logger.info("Prediction successful.")
|
138 |
+
|
139 |
+
st.subheader("Prediction Result:")
|
140 |
+
logger.info(f"Prediction output columns: {predictions.columns.tolist()}")
|
141 |
+
|
142 |
+
# Display relevant prediction columns (adjust based on PyCaret task)
|
143 |
+
# Common columns: 'prediction_label', 'prediction_score'
|
144 |
+
pred_col_label = 'prediction_label'
|
145 |
+
pred_col_score = 'prediction_score'
|
146 |
+
|
147 |
+
if pred_col_label in predictions.columns:
|
148 |
+
st.success(f"Predicted Label: **{predictions[pred_col_label].iloc[0]}**")
|
149 |
+
elif pred_col_score in predictions.columns: # Show score if label not present (e.g., regression)
|
150 |
+
st.success(f"Prediction Score: **{predictions[pred_col_score].iloc[0]:.4f}**")
|
151 |
+
else:
|
152 |
+
# Fallback: Display the last column as prediction if specific ones aren't found
|
153 |
+
try:
|
154 |
+
last_col_name = predictions.columns[-1]
|
155 |
+
st.info(f"Prediction Output (Column: '{last_col_name}'): **{predictions[last_col_name].iloc[0]}**")
|
156 |
+
logger.warning(f"Could not find 'prediction_label' or 'prediction_score'. Displaying last column: '{last_col_name}'")
|
157 |
+
except IndexError:
|
158 |
+
st.error("Prediction result DataFrame is empty.")
|
159 |
+
logger.error("Prediction result DataFrame is empty.")
|
160 |
+
|
161 |
+
|
162 |
+
# Show full prediction output optionally
|
163 |
+
with st.expander("See Full Prediction Output DataFrame"):
|
164 |
+
st.dataframe(predictions)
|
165 |
+
|
166 |
+
except Exception as e:
|
167 |
+
st.error(f"An error occurred during prediction: {e}")
|
168 |
+
logger.exception("Prediction error details:") # Log full traceback
|
169 |
+
|
model.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d027abd627a584c17c7db89b3f348f88612ed2dddd9f2e6085f45dab538e777c
|
3 |
+
size 126186
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit>=1.20.0 # Specify a recent streamlit version
|
2 |
+
pycaret[full]==3.3.2
|
3 |
+
pandas>=1.5.0 # Specify recent pandas
|
4 |
+
scikit-learn # Often needed by PyCaret under the hood, ensure compatibility with pycaret version if possible
|
5 |
+
python-dotenv # Needed if app uses .env itself, though typically not needed in deployed Space
|
6 |
+
# Add any other specific dependencies your model might need here
|
7 |
+
# Example: numpy, joblib, etc.
|