File structure
How to creates an app instance, loads configuration settings, initializes extensions, loads necessary artifacts, registers blueprints, creates database tables, and returns the app instance using init.py
Deploy ML model in flask and test using postman
Deploy ML model in flask and test using Web Interface
File structure
This image shows the file structure of a Python Flask project, likely created using an IDE like PyCharm. Here’s an explanation of the components:
flaskProject: This is the root directory of your Flask project.
.venv: This directory contains the virtual environment for your project. A virtual environment isolates your project’s dependencies from other projects on your system.
artifacts:
banglore_home_prices_model.pickle
: This is a serialized file, likely a machine learning model saved using Python's pickle module. The model seems to predict home prices in Bangalore.
columns.json
: This file likely contains the column names or features used in the model.
static:
app.css
: This file likely contains the CSS styles for your web application.
app.js
: This JavaScript file might handle client-side interactivity and other dynamic functionalities in your web application.
templates: This folder is where you store HTML files that are rendered by Flask. Flask uses the Jinja2 templating engine to render these HTML templates.
app.html
: Likely an HTML template related to the main app functionality.
index.html
: The main landing page or home page of the web application.
layout.html
: A base template that includes common HTML elements like header, footer, and navigation. Other HTML templates can extend this one.
tasks.html
: This template might handle tasks or a task list in your application.
init.py: This file turns the directory into a Python package. It can also initialize your Flask application or other components.
app.py: This is the main Python file where the Flask app is likely defined. It probably contains route definitions and application logic.
config.py: A configuration file where you might define settings for the Flask app, like database connections, secret keys, and other configurations.
extensions.py: This file likely imports and initializes Flask extensions, such as SQLAlchemy for database interaction or Flask-Migrate for database migrations.
models.py: This file usually contains the database models, which define the structure of the database tables and relationships between them.
requirement.txt: A text file listing the Python packages required for your project. This file is used to install dependencies using pip.
util.py: Utility functions that are used throughout the project might be stored here.
views.py: This file typically contains the view functions or route handlers, which determine what content is displayed when a user accesses different URLs in your application.
How to creates an app instance using init.py
Imports:
from flask import Flask
from .config import Config
from .extensions import db
from .views import main
import util # Ensure this import is correct and points to your util.py
Flask: The Flask class is imported from the flask package, which is the core of a Flask web application.
Config: The Config class is imported from your project’s config.py file. This class likely holds configuration settings for the Flask app, such as database URLs, secret keys, and other important settings.
db: This is likely an instance of SQLAlchemy, a Flask extension for database management, imported from extensions.py.
main: This is a Blueprint (a modular component of a Flask app) imported from views.py. It contains the routes and views for your application.
util: This import points to the util.py file. It’s used to load saved artifacts (like models or data) when the application starts.
- Function Definition:
def create_app():
This function is a factory function for creating and configuring an instance of the Flask application. It’s a common pattern in Flask to allow the creation of multiple instances of the app with different configurations.
- Create Flask App Instance:
app = Flask(__name__)
A new instance of the Flask application is created. name helps Flask understand the location of the application for resources and templates.
- Load Configuration:
app.config.from_object(Config)
This line loads the configuration settings from the Config class in config.py into the Flask app. This might include settings like SQLALCHEMY_DATABASE_URI, DEBUG, or SECRET_KEY.
- Initialize Extensions:
db.init_app(app)
Here, the db object (an instance of SQLAlchemy) is initialized with the app. This binds the SQLAlchemy instance to the Flask app, allowing database operations.
-
Load Saved Artifacts:
util.load_saved_artifacts() # Add this line to load the artifacts
This line ensures that certain artifacts, like machine learning models or configurations stored in files, are loaded into memory when the app starts. The load_saved_artifacts function is expected to be defined in the util.py file. -
Register Blueprints:
app.register_blueprint(main)
The main Blueprint is registered with the Flask app. Blueprints allow you to organize your application into smaller components. Here, main could include several routes and views that are part of your application. Create Database Tables:
with app.app_context():
db.create_all()
This block of code creates the necessary database tables as defined by your SQLAlchemy models. app.app_context() ensures that the database creation happens within the app’s context, which is necessary for certain operations like database transactions.
- Return the App Instance:
return app
Finally, the create_app function returns the configured Flask app instance. This allows the application to be run by a WSGI server, or for the app instance to be used in testing.
Summary:
This init.py file follows a common pattern for Flask applications. It creates an app instance, loads configuration settings, initializes extensions, loads necessary artifacts, registers blueprints, creates database tables, and returns the app instance. This modular and flexible approach allows for easier testing, scaling, and management of the Flask application
Deploy ML model in flask and test using postman
utils.py
import pickle
import json,sklearn
import numpy as np
__locations = None
__data_columns = None
__model = None
def get_estimated_price(location,sqft,bhk,bath):
try:
loc_index = __data_columns.index(location.lower())
except:
loc_index = -1
x = np.zeros(len(__data_columns))
x[0] = sqft
x[1] = bath
x[2] = bhk
if loc_index>=0:
x[loc_index] = 1
return round(__model.predict([x])[0],2)
def load_saved_artifacts():
print("loading saved artifacts...start")
global __data_columns
global __locations
with open("./artifacts/columns.json", "r") as f:
__data_columns = json.load(f)['data_columns']
print(f"Loaded data columns: {__data_columns}")
__locations = __data_columns[3:] # first 3 columns are sqft, bath, bhk
print(f"Loaded locations: {__locations}")
global __model
if __model is None:
with open('./artifacts/banglore_home_prices_model.pickle', 'rb') as f:
__model = pickle.load(f)
print("loading saved artifacts...done")
def get_location_names():
print(f"Returning locations: {__locations}")
return __locations
def get_data_columns():
return __data_columns
if __name__ == '__main__':
load_saved_artifacts()
print(get_location_names())
print(get_estimated_price('1st Phase JP Nagar',1000, 3, 3))
print(get_estimated_price('1st Phase JP Nagar', 1000, 2, 2))
print(get_estimated_price('Kalhalli', 1000, 2, 2)) # other location
print(get_estimated_price('Ejipura', 1000, 2, 2)) # other location
This Python script is part of a machine learning application that predicts home prices based on certain input features like location, square footage, number of bedrooms (BHK), and number of bathrooms. The script primarily loads saved artifacts (model and column information), processes input data, and provides functions to estimate the price of a home. Let’s break down each part of the code:
- Imports:
import pickle
import json
import sklearn
import numpy as np
pickle: This module is used for serializing and deserializing Python objects. In this context, it is used to load a pre-trained machine learning model from a file.
json: This module is used to handle JSON data. The script uses it to load a JSON file that contains information about the model's input data columns.
sklearn: This module is a part of scikit-learn, a popular machine learning library in Python. Although it's imported, it's not directly used in the script, but it might be necessary for the deserialization of the model.
numpy (np): This library is used for numerical operations. It’s commonly used in machine learning for handling arrays and matrices.
- Global Variables:
__locations = None
__data_columns = None
__model = None
These are global variables used to store:
__locations: The list of locations available in the model.
__data_columns: The list of all data columns used by the model, including the locations and other features.
__model: The trained machine learning model loaded from a file.
- Function: get_estimated_price()
def get_estimated_price(location, sqft, bhk, bath):
try:
loc_index = __data_columns.index(location.lower())
except:
loc_index = -1
x = np.zeros(len(__data_columns))
x[0] = sqft
x[1] = bath
x[2] = bhk
if loc_index >= 0:
x[loc_index] = 1
return round(__model.predict([x])[0], 2)
Purpose
: This function takes in the location, square footage, number of bedrooms (BHK), and number of bathrooms and returns an estimated home price.
Steps:
loc_index: It attempts to find the index of the location in the data_columns list. If the location is not found, loc_index is set to -1.
x = np.zeros(len(data_columns)): An array x is created with the same length as __data_columns, initialized with zeros.
Setting the values: The first three elements of x are set to sqft, bath, and bhk. If the location is found (loc_index >= 0), the corresponding index in x is set to 1 (indicating that this location is active).
Prediction: The model (loaded into __model) predicts the price using the array x, and the result is rounded to two decimal places before being returned.
- Function: load_saved_artifacts()
def load_saved_artifacts():
print("loading saved artifacts...start")
global __data_columns
global __locations
with open("./artifacts/columns.json", "r") as f:
__data_columns = json.load(f)['data_columns']
print(f"Loaded data columns: {__data_columns}")
__locations = __data_columns[3:] # first 3 columns are sqft, bath, bhk
print(f"Loaded locations: {__locations}")
global __model
if __model is None:
with open('./artifacts/banglore_home_prices_model.pickle', 'rb') as f:
__model = pickle.load(f)
print("loading saved artifacts...done")
Purpose
: This function loads the necessary artifacts (like the model and data columns) from disk into memory so they can be used in the application.
Steps:
Loading columns.json: It opens the columns.json file and loads its contents. This JSON file contains the list of data columns used by the model.
Extracting __data_columns: It stores the loaded data columns into the global variable __data_columns.
Extracting __locations: It slices the __data_columns array to get only the location names (assuming the first three columns are sqft, bath, and bhk).
Loading the model: It checks if the model is already loaded. If not, it opens the banglore_home_prices_model.pickle file and loads the model using pickle.
Completion message: It prints a message indicating that the artifacts have been successfully loaded.
- Function: get_location_names()
def get_location_names():
print(f"Returning locations: {__locations}")
return __locations
Purpose
: This function returns the list of location names that were loaded into __locations by the load_saved_artifacts() function.
Steps:
It prints the list of locations (for debugging purposes).
It returns the list of locations.
- Function: get_data_columns()
def get_data_columns():
return __data_columns
Purpose
: This function returns the list of data columns that were loaded into __data_columns.
Steps:
It simply returns the __data_columns list.
- Main Block (name == 'main'):
if __name__ == '__main__':
load_saved_artifacts()
print(get_location_names())
print(get_estimated_price('1st Phase JP Nagar',1000, 3, 3))
print(get_estimated_price('1st Phase JP Nagar', 1000, 2, 2))
print(get_estimated_price('Kalhalli', 1000, 2, 2)) # other location
print(get_estimated_price('Ejipura', 1000, 2, 2)) # other location
Purpose
: This block is executed when the script is run directly (not imported as a module).
Steps:
load_saved_artifacts()
: It calls the load_saved_artifacts() function to load the necessary data and model into memory.
get_location_names()
: It prints the list of available locations.
get_estimated_price()
: It prints the estimated prices for several test cases. These are examples of how the get_estimated_price() function can be used with different inputs.
Summary:
Loading Artifacts
: The script loads the machine learning model and column data from disk so that they can be used for predictions.
Prediction Function
: The get_estimated_price() function uses the loaded model and data to predict the price of a home based on user inputs like location, square footage, BHK, and bathrooms.
Helper Functions
: There are helper functions like get_location_names() and get_data_columns() to provide easy access to the list of locations and data columns.
Testing
: The script includes a main block to test the functionality directly, which is useful during development
view.py
This file typically contains the view functions or route handlers, which determine what content is displayed when a user accesses different URLs in your application
@main.route('/get_location_names', methods=['GET'])
def get_location_names():
response = jsonify({
'locations': util.get_location_names()
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
@main.route('/predict_home_price', methods=['GET', 'POST'])
def predict_home_price():
total_sqft = float(request.form['total_sqft'])
location = request.form['location']
bhk = int(request.form['bhk'])
bath = int(request.form['bath'])
response = jsonify({
'estimated_price': util.get_estimated_price(location, total_sqft, bhk, bath)
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
Test using postman
@main.route('/get_location_names', methods=['GET'])
@main.route('/predict_home_price', methods=['GET', 'POST'])
`parameter`
util.get_estimated_price(location, total_sqft, bhk, bath)
Deploy ML model in flask and test using Web Interface
step1:design HTML template related to the main app functionality.
here for total square fit we use text filed
bhk,bath== use radio button
location ===use drop down get data from artifacts model
app.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bangalore Home Price Prediction</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- Update the path to app.js -->
<script src="{{ url_for('static', filename='app.js') }}"></script>
<!-- Update the path to app.css -->
<link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
</head>
<body>
<div class="img"></div>
<!-- Combined all form elements into a single form -->
<form class="form">
<h2>Area (Square Feet)</h2>
<label for="uiSqft"></label>
<input class="area" type="text" id="uiSqft" name="Squareft" value="1000">
<h2>BHK</h2>
<div class="switch-field">
<input type="radio" id="radio-bhk-1" name="uiBHK" value="1"/>
<label for="radio-bhk-1">1</label>
<input type="radio" id="radio-bhk-2" name="uiBHK" value="2" checked/>
<label for="radio-bhk-2">2</label>
<input type="radio" id="radio-bhk-3" name="uiBHK" value="3"/>
<label for="radio-bhk-3">3</label>
<input type="radio" id="radio-bhk-4" name="uiBHK" value="4"/>
<label for="radio-bhk-4">4</label>
<input type="radio" id="radio-bhk-5" name="uiBHK" value="5"/>
<label for="radio-bhk-5">5</label>
</div>
<h2>Bath</h2>
<div class="switch-field">
<input type="radio" id="radio-bath-1" name="uiBathrooms" value="1"/>
<label for="radio-bath-1">1</label>
<input type="radio" id="radio-bath-2" name="uiBathrooms" value="2" checked/>
<label for="radio-bath-2">2</label>
<input type="radio" id="radio-bath-3" name="uiBathrooms" value="3"/>
<label for="radio-bath-3">3</label>
<input type="radio" id="radio-bath-4" name="uiBathrooms" value="4"/>
<label for="radio-bath-4">4</label>
<input type="radio" id="radio-bath-5" name="uiBathrooms" value="5"/>
<label for="radio-bath-5">5</label>
</div>
<h2>Location</h2>
<div>
<select class="location" id="uiLocations">
<option value="" disabled selected>Choose a Location</option>
<option>Electronic City</option>
<option>Rajaji Nagar</option>
</select>
</div>
<button class="submit" onclick="onClickedEstimatePrice()" type="button">Estimate Price</button>
<div id="uiEstimatedPrice" class="result"><h2></h2></div>
</form>
</body>
</html>
step2:This JavaScript file might handle client-side interactivity and other dynamic functionalities in your web application.
get location on page load and when u click estimated price then call this function here
app.js
function getBathValue() {
var uiBathrooms = document.getElementsByName("uiBathrooms");
for(var i in uiBathrooms) {
if(uiBathrooms[i].checked) {
return parseInt(i)+1;
}
}
return -1; // Invalid Value
}
function getBHKValue() {
var uiBHK = document.getElementsByName("uiBHK");
for(var i in uiBHK) {
if(uiBHK[i].checked) {
return parseInt(i)+1;
}
}
return -1; // Invalid Value
}
function onClickedEstimatePrice() {
console.log("Estimate price button clicked");
var sqft = document.getElementById("uiSqft");
var bhk = getBHKValue();
var bathrooms = getBathValue();
var location = document.getElementById("uiLocations");
var estPrice = document.getElementById("uiEstimatedPrice");
var url = "http://127.0.0.1:5000/predict_home_price"; //Use this if you are NOT using nginx which is first 7 tutorials
//var url = "/api/predict_home_price"; // Use this if you are using nginx. i.e tutorial 8 and onwards
$.post(url, {
total_sqft: parseFloat(sqft.value),
bhk: bhk,
bath: bathrooms,
location: location.value
},function(data, status) {
console.log(data.estimated_price);
estPrice.innerHTML = "<h2>" + data.estimated_price.toString() + " Lakh</h2>";
console.log(status);
});
}
function onPageLoad() {
console.log("document loaded");
var url = "http://127.0.0.1:5000/get_location_names"; // Ensure this is correct
$.get(url, function(data, status) {
console.log("got response for get_location_names request");
if (data) {
var locations = data.locations;
var uiLocations = document.getElementById("uiLocations");
$('#uiLocations').empty();
for (var i in locations) {
var opt = new Option(locations[i]);
$('#uiLocations').append(opt);
}
}
});
}
window.onload = onPageLoad;
step3:when we click estimated price then we call route
var url = "http://127.0.0.1:5000/get_location_names";
@main.route('/predict_home_price', methods=['GET', 'POST'])
@main.route('/get_location_names', methods=['GET'])
def get_location_names():
response = jsonify({
'locations': util.get_location_names()
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
@main.route('/predict_home_price', methods=['GET', 'POST'])
def predict_home_price():
total_sqft = float(request.form['total_sqft'])
location = request.form['location']
bhk = int(request.form['bhk'])
bath = int(request.form['bath'])
response = jsonify({
'estimated_price': util.get_estimated_price(location, total_sqft, bhk, bath)
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
step5: now we call util.py to estimate price
def predict_home_price()
{
response = jsonify({
'estimated_price': util.get_estimated_price(location, total_sqft, bhk, bath)
})
}
util.py
import pickle
import json,sklearn
import numpy as np
__locations = None
__data_columns = None
__model = None
def get_estimated_price(location,sqft,bhk,bath):
try:
loc_index = __data_columns.index(location.lower())
except:
loc_index = -1
x = np.zeros(len(__data_columns))
x[0] = sqft
x[1] = bath
x[2] = bhk
if loc_index>=0:
x[loc_index] = 1
return round(__model.predict([x])[0],2)
def load_saved_artifacts():
print("loading saved artifacts...start")
global __data_columns
global __locations
with open("./artifacts/columns.json", "r") as f:
__data_columns = json.load(f)['data_columns']
print(f"Loaded data columns: {__data_columns}")
__locations = __data_columns[3:] # first 3 columns are sqft, bath, bhk
print(f"Loaded locations: {__locations}")
global __model
if __model is None:
with open('./artifacts/banglore_home_prices_model.pickle', 'rb') as f:
__model = pickle.load(f)
print("loading saved artifacts...done")
def get_location_names():
print(f"Returning locations: {__locations}")
return __locations
def get_data_columns():
return __data_columns
if __name__ == '__main__':
load_saved_artifacts()
print(get_location_names())
print(get_estimated_price('1st Phase JP Nagar',1000, 3, 3))
print(get_estimated_price('1st Phase JP Nagar', 1000, 2, 2))
print(get_estimated_price('Kalhalli', 1000, 2, 2)) # other location
print(get_estimated_price('Ejipura', 1000, 2, 2)) # other location
output
Top comments (0)