Skip to content

End-to-End ML-Powered Sarajevo Real Estate Application#10

Open
musss2003 wants to merge 66 commits intomainfrom
mustafa_branch
Open

End-to-End ML-Powered Sarajevo Real Estate Application#10
musss2003 wants to merge 66 commits intomainfrom
mustafa_branch

Conversation

@musss2003
Copy link
Copy Markdown
Collaborator

Home Page – Price Prediction

Added a home screen where users can select a feature set (location, size, rooms, condition, etc.).

The app uses trained ML regression models to predict the expected market price of a property.

Predictions are returned instantly and are based on cleaned, preprocessed historical data.

All ML models are loaded once at application startup and reused across requests to ensure fast response times and improved stability.

Prediction History

Implemented prediction history tracking, allowing users to review previously generated price predictions.

Enables comparison and transparency of model outputs over time.

Listings & Deal Score Evaluation

Integrated real estate listings enriched with predicted prices.

Each listing is assigned a Deal Score (0–100) that reflects how favorable the asking price is compared to the predicted market value.

Deal Score Logic

def deal_score_from_diff(diff_pct: float, min_diff: float, max_diff: float) -> int:
"""
Convert relative price difference to a deal score in range [0, 100].

Negative diff -> cheaper than expected -> higher score
Positive diff -> overpriced -> lower score
"""
if max_diff == min_diff:
    return 50

diff_pct = max(min_diff, min(max_diff, diff_pct))
score = (max_diff - diff_pct) / (max_diff - min_diff) * 100
return int(round(max(0, min(100, score))))

Lower-than-expected prices result in higher scores.

Overpriced listings receive lower scores.

Scores are normalized using observed market ranges to ensure consistency.

Favorites Management

Added the ability to add and remove listings from favorites.

Favorites are persisted and can be revisited later by the user.

Improves usability and supports shortlisting of interesting properties.

Statistics & Market Insights

Implemented a statistics section based on cleaned and preprocessed data stored in the database.

Includes:

  • Price distribution and averages
  • Price per square meter
  • Municipality and condition distributions
  • Accessibility metrics (distance to POIs)

All statistics are computed from validated, normalized data produced during preprocessing.

ML & Data Integration Improvements

ML models are loaded once on first application run and reused across the app lifecycle.

POI (Points of Interest) data is also cached and reused.

musss2003 and others added 30 commits October 28, 2025 18:34
Written the project pitch related to our data and added a notebook that does feature analysis
Generated by create-expo-app 3.5.3.
Updated README to reflect project details and features.
All code errors have been successfully resolved:

Renamed use-prediction-history.ts to use-prediction-history.tsx - The file contained JSX code but had a .ts extension

Fixed import paths - Updated all imports to use the correct kebab-case filenames:

usePredictionHistory → use-prediction-history
useColorScheme → use-color-scheme
Colors → imported from theme.ts
Created missing TabBarIcon component - Added the component that was being imported but didn't exist

Fixed TypeScript return type - Added proper React import and return type annotation for PredictionHistoryProvider
Supabase client with AsyncStorage for persistent sessions
AuthContext provider with global auth state
API service with automatic JWT token injection
Sign in/up screens with modern gradient UI
Updated Screens:

Profile Tab - Shows user info, menu items, and sign out button (or guest features for non-authenticated users)
Predict Screen - Now uses makePrediction() from API service with auth headers, displays user email in header
History Screen - Fetches user-specific predictions from backend for authenticated users, falls back to local storage for guests
@musss2003
Copy link
Copy Markdown
Collaborator Author

Question regarding rentals model input features

I wanted to double-check one thing before we merge.

In the backend, feature construction for predictions currently includes the condition field:

def build_features_from_request(req, poi_data):
    point = Point(req.longitude, req.latitude)
    point = gpd.GeoSeries([point], crs="EPSG:4326").to_crs(epsg=32634).iloc[0]

    features = {
        "condition": req.condition,
        "rooms": req.rooms,
        "square_m2": req.square_m2,
        "equipment": req.equipment,
        "level": req.level,
        "heating": req.heating,
    }

    for poi_name, pois in poi_data.items():
        col = f"closest_{poi_name}_m"
        idx = pois.sindex.nearest(point, 1)[1][0]
        features[col] = point.distance(pois.geometry.iloc[idx])

    return pd.DataFrame([features])

For rentals, the frontend will not send condition (as agreed earlier), so it will be empty on the backend.

Can you confirm whether condition was dropped from the rentals model during training, or whether the model expects it to be present ?

I just want to make sure this won’t affect rental predictions once this PR is merged, since after merging I plan to deploy the backend to AWS EC2.

Thanks!

@EmreArapcicUevak
Copy link
Copy Markdown
Owner

Question regarding rentals model input features

I wanted to double-check one thing before we merge.

In the backend, feature construction for predictions currently includes the condition field:


def build_features_from_request(req, poi_data):

    point = Point(req.longitude, req.latitude)

    point = gpd.GeoSeries([point], crs="EPSG:4326").to_crs(epsg=32634).iloc[0]



    features = {

        "condition": req.condition,

        "rooms": req.rooms,

        "square_m2": req.square_m2,

        "equipment": req.equipment,

        "level": req.level,

        "heating": req.heating,

    }



    for poi_name, pois in poi_data.items():

        col = f"closest_{poi_name}_m"

        idx = pois.sindex.nearest(point, 1)[1][0]

        features[col] = point.distance(pois.geometry.iloc[idx])



    return pd.DataFrame([features])



For rentals, the frontend will not send condition (as agreed earlier), so it will be empty on the backend.

Can you confirm whether condition was dropped from the rentals model during training, or whether the model expects it to be present ?

I just want to make sure this won’t affect rental predictions once this PR is merged, since after merging I plan to deploy the backend to AWS EC2.

Thanks!

We haven't agree on rentals dropping all of the conditions. In the feature analysis notebook rentals just cannot have the "in constructions" and "needs renovation" as their condition. As logically you cannot rent an apartment that isn't built nor the one that needs repairs. The features for both rentals and sales are the same just the domain is difference for some

@musss2003
Copy link
Copy Markdown
Collaborator Author

Here is the core logic for our model, where i differentiated ConditionType for Sale and Rent, maybe you can take a look one more time at this file: backend/app/api/predict.py

@EmreArapcicUevak EmreArapcicUevak self-assigned this Dec 25, 2025
Copy link
Copy Markdown
Owner

@EmreArapcicUevak EmreArapcicUevak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just please close pending reviews with the reference to the commit and changes that were done to the target file

Copy link
Copy Markdown
Owner

@EmreArapcicUevak EmreArapcicUevak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these changes fixed what I wanted. The only think I really want changed is the flats.csv file to be removed. Other changes are optional good job Mustafa :)

…fic function so predict api does not know anything about that
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants