├── Flask.pdf ├── src ├── Flask.pdf ├── request.py ├── app.py ├── model.py ├── index.html └── style.css ├── models └── model.pkl ├── LICENSE ├── input └── 50_Startup.csv └── README.md /Flask.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chiragsamal/Flask-Tutorial/HEAD/Flask.pdf -------------------------------------------------------------------------------- /src/Flask.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chiragsamal/Flask-Tutorial/HEAD/src/Flask.pdf -------------------------------------------------------------------------------- /models/model.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chiragsamal/Flask-Tutorial/HEAD/models/model.pkl -------------------------------------------------------------------------------- /src/request.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | url = 'http://localhost:5000/predict_api' 4 | r = requests.post(url,json={'experience':2, 'test_score':9, 'interview_score':6}) 5 | 6 | print(r.json()) -------------------------------------------------------------------------------- /src/app.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from flask import Flask, request, jsonify, render_template 3 | import pickle 4 | 5 | app = Flask(__name__) 6 | model = pickle.load(open('model.pkl', 'rb')) 7 | 8 | @app.route('/') 9 | def home(): 10 | return render_template('index.html') 11 | 12 | @app.route('/predict',methods=['POST']) 13 | def predict(): 14 | ''' 15 | For rendering results on HTML GUI 16 | ''' 17 | int_features = [int(x) for x in request.form.values()] 18 | final_features = [np.array(int_features)] 19 | prediction = model.predict(final_features) 20 | 21 | output = round(prediction[0], 2) 22 | 23 | return render_template('index.html', prediction_text='Employee Salary should be $ {}'.format(output)) 24 | 25 | @app.route('/predict_api',methods=['POST']) 26 | def predict_api(): 27 | ''' 28 | For direct API calls trought request 29 | ''' 30 | data = request.get_json(force=True) 31 | prediction = model.predict([np.array(list(data.values()))]) 32 | 33 | output = prediction[0] 34 | return jsonify(output) 35 | 36 | if __name__ == "__main__": 37 | app.run(debug=True) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Chirag Samal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/model.py: -------------------------------------------------------------------------------- 1 | # Importing the libraries 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import pandas as pd 5 | import pickle 6 | 7 | dataset = pd.read_csv('hiring.csv') 8 | 9 | dataset['experience'].fillna(0, inplace=True) 10 | 11 | dataset['test_score'].fillna(dataset['test_score'].mean(), inplace=True) 12 | 13 | X = dataset.iloc[:, :3] 14 | 15 | #Converting words to integer values 16 | def convert_to_int(word): 17 | word_dict = {'one':1, 'two':2, 'three':3, 'four':4, 'five':5, 'six':6, 'seven':7, 'eight':8, 18 | 'nine':9, 'ten':10, 'eleven':11, 'twelve':12, 'zero':0, 0: 0} 19 | return word_dict[word] 20 | 21 | X['experience'] = X['experience'].apply(lambda x : convert_to_int(x)) 22 | 23 | y = dataset.iloc[:, -1] 24 | 25 | #Splitting Training and Test Set 26 | #Since we have a very small dataset, we will train our model with all availabe data. 27 | 28 | from sklearn.linear_model import LinearRegression 29 | regressor = LinearRegression() 30 | 31 | #Fitting model with trainig data 32 | regressor.fit(X, y) 33 | 34 | # Saving model to disk 35 | pickle.dump(regressor, open('model.pkl','wb')) 36 | 37 | # Loading model to compare the results 38 | model = pickle.load(open('model.pkl','rb')) 39 | print(model.predict([[2, 9, 6]])) -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Machine Learning API 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |

Predict Profit

18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
29 |
30 | {{ prediction_text }} 31 | 32 |
33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /input/50_Startup.csv: -------------------------------------------------------------------------------- 1 | R&D Spend,Administration,Marketing,Profit 2 | 165349.2,136897.8,471784.1,192261.83 3 | 162597.7,151377.59,443898.53,191792.06 4 | 153441.51,101145.55,407934.54,191050.39 5 | 144372.41,118671.85,383199.62,182901.99 6 | 142107.34,91391.77,366168.42,166187.94 7 | 131876.9,99814.71,362861.36,156991.12 8 | 134615.46,147198.87,127716.82,156122.51 9 | 130298.13,145530.06,323876.68,155752.6 10 | 120542.52,148718.95,311613.29,152211.77 11 | 123334.88,108679.17,304981.62,149759.96 12 | 101913.08,110594.11,229160.95,146121.95 13 | 100671.96,91790.61,249744.55,144259.4 14 | 93863.75,127320.38,249839.44,141585.52 15 | 91992.39,135495.07,252664.93,134307.35 16 | 119943.24,156547.42,256512.92,132602.65 17 | 114523.61,122616.84,261776.23,129917.04 18 | 78013.11,121597.55,264346.06,126992.93 19 | 94657.16,145077.58,282574.31,125370.37 20 | 91749.16,114175.79,294919.57,124266.9 21 | 86419.7,153514.11,0,122776.86 22 | 76253.86,113867.3,298664.47,118474.03 23 | 78389.47,153773.43,299737.29,111313.02 24 | 73994.56,122782.75,303319.26,110352.25 25 | 67532.53,105751.03,304768.73,108733.99 26 | 77044.01,99281.34,140574.81,108552.04 27 | 64664.71,139553.16,137962.62,107404.34 28 | 75328.87,144135.98,134050.07,105733.54 29 | 72107.6,127864.55,353183.81,105008.31 30 | 66051.52,182645.56,118148.2,103282.38 31 | 65605.48,153032.06,107138.38,101004.64 32 | 61994.48,115641.28,91131.24,99937.59 33 | 61136.38,152701.92,88218.23,97483.56 34 | 63408.86,129219.61,46085.25,97427.84 35 | 55493.95,103057.49,214634.81,96778.92 36 | 46426.07,157693.92,210797.67,96712.8 37 | 46014.02,85047.44,205517.64,96479.51 38 | 28663.76,127056.21,201126.82,90708.19 39 | 44069.95,51283.14,197029.42,89949.14 40 | 20229.59,65947.93,185265.1,81229.06 41 | 38558.51,82982.09,174999.3,81005.76 42 | 28754.33,118546.05,172795.67,78239.91 43 | 27892.92,84710.77,164470.71,77798.83 44 | 23640.93,96189.63,148001.11,71498.49 45 | 15505.73,127382.3,35534.17,69758.98 46 | 22177.74,154806.14,28334.72,65200.33 47 | 1000.23,124153.04,1903.93,64926.08 48 | 1315.46,115816.21,297114.46,49490.75 49 | 0,135426.92,0,42559.73 50 | 542.05,51743.15,0,35673.41 51 | 0,116983.8,45173.06,14681.4 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flask Tutorial 2 | ![Flask](https://miro.medium.com/max/1760/1*ZDXzEwWqdDwu95G374AM0g.jpeg) 3 | 4 | Read blog on Flask Tutorial at [Build the first Flask Python web app framework](https://medium.com/analytics-vidhya/https-medium-com-chirag6891-build-the-first-flask-python-e278b52473f3) 5 | 6 | ## ML Model Flask-Deployment 7 | This is a demo project to elaborate how Machine Learn Models are deployed on production using Flask API 8 | 9 | ### Prerequisites 10 | - Scikit Learn 11 | - Pandas 12 | - Numpy 13 | - Flask 14 | 15 | ### Project Structure 16 | This project has four major parts : 17 | 1. model.py - This contains code fot our Machine Learning model to predict employee salaries absed on trainign data in '50_Startup.csv' file. 18 | 2. app.py - This contains Flask APIs that receives employee details through GUI or API calls, computes the precited value based on our model and returns it. 19 | 3. request.py - This uses requests module to call APIs already defined in app.py and dispalys the returned value. 20 | 4. templates - This folder contains the HTML template to allow user to enter employee detail and displays the predicted employee salary. 21 | 22 | ### Running the project 23 | 1. Ensure that you are in the project home directory. Create the machine learning model by running below command - 24 | ``` 25 | python model.py 26 | ``` 27 | This would create a serialized version of our model into a file model.pkl 28 | 29 | 2. Run app.py using below command to start Flask API 30 | ``` 31 | python app.py 32 | ``` 33 | By default, flask will run on http://127.0.0.1:5000/ (localhost) 34 | 35 | 3. Navigate to URL http://127.0.0.1:5000/ (localhost) 36 | 37 | 38 | ### Contributors 39 |


Chirag Samal

💻 📖 🚧 🤔 💬

40 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Open+Sans); 2 | .btn { display: inline-block; *display: inline; *zoom: 1; padding: 4px 10px 4px; margin-bottom: 0; font-size: 13px; line-height: 18px; color: #333333; text-align: center;text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); vertical-align: middle; background-color: #f5f5f5; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#ffffff, endColorstr=#e6e6e6, GradientType=0); border-color: #e6e6e6 #e6e6e6 #e6e6e6; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border: 1px solid #e6e6e6; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; } 3 | .btn:hover, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { background-color: #e6e6e6; } 4 | .btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } 5 | .btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } 6 | .btn-primary, .btn-primary:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; } 7 | .btn-primary.active { color: rgba(255, 255, 255, 0.75); } 8 | .btn-primary { background-color: #4a77d4; background-image: -moz-linear-gradient(top, #6eb6de, #4a77d4); background-image: -ms-linear-gradient(top, #6eb6de, #4a77d4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6eb6de), to(#4a77d4)); background-image: -webkit-linear-gradient(top, #6eb6de, #4a77d4); background-image: -o-linear-gradient(top, #6eb6de, #4a77d4); background-image: linear-gradient(top, #6eb6de, #4a77d4); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#6eb6de, endColorstr=#4a77d4, GradientType=0); border: 1px solid #3762bc; text-shadow: 1px 1px 1px rgba(0,0,0,0.4); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5); } 9 | .btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { filter: none; background-color: #4a77d4; } 10 | .btn-block { width: 100%; display:block; } 11 | 12 | * { -webkit-box-sizing:border-box; -moz-box-sizing:border-box; -ms-box-sizing:border-box; -o-box-sizing:border-box; box-sizing:border-box; } 13 | 14 | html { width: 100%; height:100%; overflow:hidden; } 15 | 16 | body { 17 | width: 100%; 18 | height:100%; 19 | font-family: 'Open Sans', sans-serif; 20 | background: #092756; 21 | color: #fff; 22 | font-size: 18px; 23 | text-align:center; 24 | letter-spacing:1.2px; 25 | background: -moz-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%),-moz-linear-gradient(top, rgba(57,173,219,.25) 0%, rgba(42,60,87,.4) 100%), -moz-linear-gradient(-45deg, #670d10 0%, #092756 100%); 26 | background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -webkit-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -webkit-linear-gradient(-45deg, #670d10 0%,#092756 100%); 27 | background: -o-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -o-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -o-linear-gradient(-45deg, #670d10 0%,#092756 100%); 28 | background: -ms-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -ms-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -ms-linear-gradient(-45deg, #670d10 0%,#092756 100%); 29 | background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), linear-gradient(to bottom, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), linear-gradient(135deg, #670d10 0%,#092756 100%); 30 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3E1D6D', endColorstr='#092756',GradientType=1 ); 31 | 32 | } 33 | .login { 34 | position: absolute; 35 | top: 40%; 36 | left: 50%; 37 | margin: -150px 0 0 -150px; 38 | width:400px; 39 | height:400px; 40 | } 41 | 42 | .login h1 { color: #fff; text-shadow: 0 0 10px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; } 43 | 44 | input { 45 | width: 100%; 46 | margin-bottom: 10px; 47 | background: rgba(0,0,0,0.3); 48 | border: none; 49 | outline: none; 50 | padding: 10px; 51 | font-size: 13px; 52 | color: #fff; 53 | text-shadow: 1px 1px 1px rgba(0,0,0,0.3); 54 | border: 1px solid rgba(0,0,0,0.3); 55 | border-radius: 4px; 56 | box-shadow: inset 0 -5px 45px rgba(100,100,100,0.2), 0 1px 1px rgba(255,255,255,0.2); 57 | -webkit-transition: box-shadow .5s ease; 58 | -moz-transition: box-shadow .5s ease; 59 | -o-transition: box-shadow .5s ease; 60 | -ms-transition: box-shadow .5s ease; 61 | transition: box-shadow .5s ease; 62 | } 63 | input:focus { box-shadow: inset 0 -5px 45px rgba(100,100,100,0.4), 0 1px 1px rgba(255,255,255,0.2); } 64 | --------------------------------------------------------------------------------