Skip to content

Commit

Permalink
Add confidence interval calculation to application
Browse files Browse the repository at this point in the history
  • Loading branch information
davydantoniuk committed Jan 1, 2025
1 parent 866d4fd commit eb8c657
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
27 changes: 22 additions & 5 deletions app/price_predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
from fastapi.templating import Jinja2Templates
import pandas as pd
import joblib
import numpy as np
from scipy.stats import norm

# Load the trained model and scaler
model = joblib.load("../model_components/final_catboost_model.joblib")
scaler = joblib.load("../model_components/scaler.joblib")
X_columns = joblib.load("../model_components/X_columns.joblib")
y = joblib.load("../model_components/y.joblib")
y_pred = joblib.load("../model_components/y_pred.joblib")
numerical_columns = ["Area", "Rooms"]

# Initialize FastAPI and templates
app = FastAPI()
templates = Jinja2Templates(directory="templates")

# Define the prediction function
def predict_house_price(model, area, elevator, rooms, floor, region, year_of_building):
if floor == 0:
floor_category = "parter"
Expand Down Expand Up @@ -58,12 +61,18 @@ def predict_house_price(model, area, elevator, rooms, floor, region, year_of_bui
predicted_price = model.predict(input_data)
return predicted_price[0]

# Route for rendering the HTML form
def calculate_individual_confidence_interval(y_true, y_pred, prediction, alpha=0.05):
residuals = y_true - y_pred
standard_error = np.std(residuals, ddof=1)
margin_of_error = norm.ppf(1 - alpha / 2) * standard_error
lower_bound = prediction - margin_of_error
upper_bound = prediction + margin_of_error
return lower_bound, upper_bound

@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
return templates.TemplateResponse("index.html", {"request": request})

# Route for handling the form submission and returning the prediction
@app.post("/predict/", response_class=HTMLResponse)
async def predict(
request: Request,
Expand All @@ -72,18 +81,26 @@ async def predict(
rooms: int = Form(...),
floor: int = Form(...),
region: str = Form(...),
year_of_building: int = Form(...)
year_of_building: int = Form(...),
alpha: float = Form(0.05),
):
if elevator not in [0, 1]:
raise HTTPException(status_code=400, detail="Invalid value for elevator. Must be 0 or 1.")

predicted_price = predict_house_price(model, area, elevator, rooms, floor, region, year_of_building)
lower, upper = calculate_individual_confidence_interval(y, y_pred, predicted_price, alpha)
confidence_level = (1 - alpha) * 100

return templates.TemplateResponse("index.html", {
"request": request,
"predicted_price": f"{predicted_price:,.2f}",
"confidence_interval": f"[{lower:,.2f}, {upper:,.2f}]",
"confidence_level": confidence_level,
"area": area,
"elevator": elevator,
"rooms": rooms,
"floor": floor,
"region": region,
"year_of_building": year_of_building
"year_of_building": year_of_building,
"alpha": alpha,
})
16 changes: 14 additions & 2 deletions app/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 300px;
margin: 20px auto; /* Center the container */
overflow: hidden; /* Prevent horizontal scrolling */
margin: 20px auto;
overflow: hidden;
}
h1 {
text-align: center;
Expand Down Expand Up @@ -61,15 +61,19 @@ <h1>House Price Prediction</h1>
<form action="/predict/" method="post">
<label for="area">Area (m²):</label>
<input type="number" id="area" name="area" step="0.01" value="{{ area or '' }}" required>

<label for="elevator">Elevator:</label>
<select id="elevator" name="elevator" required>
<option value="1" {% if elevator == 1 %}selected{% endif %}>Yes</option>
<option value="0" {% if elevator == 0 %}selected{% endif %}>No</option>
</select>

<label for="rooms">Number of Rooms:</label>
<input type="number" id="rooms" name="rooms" value="{{ rooms or '' }}" required>

<label for="floor">Floor:</label>
<input type="number" id="floor" name="floor" value="{{ floor or '' }}" required>

<label for="region">Region:</label>
<input type="text" id="region" name="region" list="regions" value="{{ region or '' }}" required>
<datalist id="regions">
Expand Down Expand Up @@ -101,13 +105,21 @@ <h1>House Price Prediction</h1>
<option value="Za Cukrownią">
<option value="Zemborzyce">
</datalist>

<label for="year_of_building">Year of Building:</label>
<input type="number" id="year_of_building" name="year_of_building" value="{{ year_of_building or '' }}" required>

<label for="alpha">Significance Level (α):</label>
<input type="number" id="alpha" name="alpha" step="0.01" min="0" max="1" value="{{ alpha or 0.05 }}" required>

<button type="submit">Predict Price</button>
</form>

{% if predicted_price %}
<div class="result">
<h2>Predicted Price: {{ predicted_price }} PLN</h2>
<p style="text-align: center;">{{ confidence_level }}% Confidence Interval</p>
<p style="text-align: center;">{{ confidence_interval }}</p>
</div>
{% endif %}
</div>
Expand Down

0 comments on commit eb8c657

Please sign in to comment.