I am currently developing a machine learning web application using tensorflow/keras and flask. For deployment I am using Google App Engine (GAE).
Locally I can run my application, get some data via the UI and display the prediction using my laoded models (there are four of them, all .h5 files)
I can deploy it on GAE without any errors but when I enter the link in my browser I get a '502 bad gateway' error and when I inspect the browser (Chrome) I can see three error messages saying 'failed to load resource'.
I am new to web development so I don't fully understand what and where the problem is. Do I need to declare my models in the .yaml file or load them specifically?
My .yaml file:
env: flex
runtime: python
runtime_config:
python_version: 3
My main.py file:
import pandas as pd
import tensorflow as tf
from keras.models import load_model
from keras.backend import set_session
from utils import instagram_scraper
from utils import image_preprocessing
from utils import label_encoding
from utils import overall_class_label
from sklearn.preprocessing import LabelEncoder
global sess
global graph
sess = tf.compat.v1.Session()
graph = tf.compat.v1.get_default_graph()
tf.compat.v1.keras.backend.set_session(sess)
num_attributes = 4
model = [[] for i in range(num_attributes)]
model[0] = load_model('./model/savemodels/glamorous_model.h5')
model[1] = load_model('./model/savemodels/rugged_model.h5')
model[2] = load_model('./model/savemodels/fun_model.h5')
model[3] = load_model('./model/savemodels/healthy_model.h5')
app = Flask(__name__)
def data_collection(brandname):
url = 'https://www.instagram.com/'+brandname+'/?hl=en'
scraper = instagram_scraper.InstagramScraper()
official_images = scraper.profile_page_posts(url)
return official_images
def data_preprocessing(official_images):
preprocessed_data = image_preprocessing.preprocessing(official_images)
return preprocessed_data
def make_prediction(preprocessed_data):
X_test = preprocessed_data
with graph.tf.compat.v1.as_default():
tf.compat.v1.keras.backend.set_session(sess)
y_pred = [[] for i in range(num_attributes)]
for i in range(num_attributes):
y_pred[i] = model[i].predict(X_test)
y_pred_label = overall_class_label.give_ovr_class_label_output(y_pred)
# convert from encoded label to label name
# encoded label
y_pred_lst = y_pred_label.tolist()
# map back to original label name
code2label = {0: 'glamorous', 1: 'rugged', 2: 'fun', 3: 'healthy'}
y_pred_lbnm = map(code2label.get, y_pred_lst)
y_pred_lbnm = list(y_pred_lbnm)
prediction = pd.Series(y_pred_lbnm).value_counts()
return prediction
#app.route("/", methods=["POST", "GET"])
def index():
if request.method == "POST":
brandname = request.form["brandname"]
return redirect(url_for("predict", brandname=brandname))
else:
return render_template("index.html")
#app.route("/predict/<brandname>", methods=["POST", "GET"])
def predict(brandname):
official_images = data_collection(brandname)
preprocessed_data = data_preprocessing(official_images)
prediction = make_prediction(preprocessed_data)
return render_template("predict.html", prediction=prediction)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
My app structure:
parent
--model
--savemodels
fun_model.h5
glamorous_model.h5
healthy_model.h5
rugged_model.h5
--static
style.css
--templates
index.html
predict.html
--utils
image_preprocessing.py
instagram_scraper.py
label_encoding.py
overall_class_label.py
app.yaml
main.py
requirements.txt
Any help is very much appreciated, thank you!
All the best,
snowe
Related
enter code here
import numpy as np
from flask import Flask, request, jsonify, render_template
import pickle
app = Flask(__name__)
results = pickle.load(
open("C:/Users/Faye/Desktop/xxxxxxxx/sentence-transformers/final.pkl", "rb") #is the problem with the pkl file? should the file contain only numbers or can it contain text too?
)
#app.route("/")
def home():
return render_template("search_engine.html") #html code is added and it works fine
#app.route("/predict", methods=["GET", "POST"]) # i have tried both methods get and post and only post
def predict():
int_features = [float(x) for x in request.form.values()]
final_features = [np.array(int_features)]
prediction = results.predict(final_features)
output = round(prediction[0], 2) #should the prediction part has different numbers?
return render_template(
"search_engine.html",
prediction_text="The best investor for you is: {}".format(output), #this prediction text is part of the html code.
)
#app.route("/predict_api", methods=["GET", "POST"])
def predict_api(): #should i add anything here on the api?
data = request.get_json(force=True)
prediction = results.predict([np.array(list(data.values()))])
output = prediction[0]
return jsonify(output)
if __name__ == "__main__":
app.run(debug=True)
The HTML code has been tested as a snippet and works fine. I have saved the predictive results of the embeddings as pkl file. I have imported on the app. I am making a semantic search engine with keyword matching but the app does not work. I receive this error 500 internal server error.
I have created a tensorflow model, saved it and have tested it. I really don't know how to use tensorflow serving and I'm not sure about the input and output nodes of my model to convert it into protobuf and then use tensorflow serving. So, I wanted to know if I can directly use the prediction function on flask and load the model there to make the predictions? I am really confused as to why we have to use only tensorflow serving to deploy tensorflow models? Is there any easier direct way?
You can, but you will need to set up a TensorFlow Serving server. Then you send a post request to the server.
Reference link here: Deploying-keras-models-using-tensorflow-serving-and-flask
Reference link here: Serving-TensorFlow flask client
"""This script wraps the client into a Flask server. It receives POST request with
prediction data, and forward the data to tensorflow server for inference.
"""
from flask import Flask, render_template, request, url_for, jsonify,Response
import json
import tensorflow as tf
import numpy as np
import os
import argparse
import sys
from datetime import datetime
from grpc.beta import implementations
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2
tf.app.flags.DEFINE_string('server', 'localhost:9000', 'PredictionService host:port')
FLAGS = tf.app.flags.FLAGS
app = Flask(__name__)
class mainSessRunning():
def __init__(self):
host, port = FLAGS.server.split(':')
channel = implementations.insecure_channel(host, int(port))
self.stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)
self.request = predict_pb2.PredictRequest()
self.request.model_spec.name = 'example_model'
self.request.model_spec.signature_name = 'prediction'
def inference(self, val_x):
# temp_data = numpy.random.randn(100, 3).astype(numpy.float32)
temp_data = val_x.astype(np.float32).reshape(-1, 3)
print("temp_data is:", temp_data)
data, label = temp_data, np.sum(temp_data * np.array([1, 2, 3]).astype(np.float32), 1)
self.request.inputs['input'].CopyFrom(
tf.contrib.util.make_tensor_proto(data, shape=data.shape))
result = self.stub.Predict(self.request, 5.0)
return result, label
run = mainSessRunning()
print("Initialization done. ")
# Define a route for the default URL, which loads the form
#app.route('/inference', methods=['POST'])
def inference():
request_data = request.json
input_data = np.expand_dims(np.array(request_data), 0)
result, label = run.inference(input_data)
di={"result":str(result),'label': label[0].tolist()}
return Response(json.dumps(di), mimetype='application/json')
From postman, I'm trying to send a GET request with params as Key:
path, Value: home/guest/images/abc.jpeg
I want to retrieve the same and use the Value as the argument of my function.
Somehow I'm unable to get the same, API not being called. Any input shall be helpful.
I'm new to writing REST APIs using Flask Python. I want to get the Value of the Params key: path as the TEST_PATH so that the rest of the code run as it should return the JSONP_data
from flask import Flask
from flask_cors import CORS
import pandas as pd
import datetime
import numpy as np
from flask import jsonify
import json
from pymongo import MongoClient
# set the project root directory as the static folder, you can set others.
app = Flask(__name__)
CORS(app)
counter=0
#app.route('/')
def api_root():
return ('Welcome')
#app.route('/generateTags/<id>', methods=['GET'])
def generateTags1(id):
file = json.loads(create_task(id))
TEST_PATH = file['path']
print(TEST_PATH)
import DenseNet
import Inception
import ResNet
import SqueezNet
from imageai.Prediction import ImagePrediction
prediction = ImagePrediction()
# TEST_PATH = '/home/anit/Documents/Image Analysis/ImageAI-master/Dataset'
dense_list=DenseNet.tag(TEST_PATH, DenseNet.prediction)
dense_list = ['DenseNet'] + dense_list.tolist()[0]
res_list=ResNet.tag(TEST_PATH, ResNet.prediction)
res_list = ['ResNet'] + res_list.tolist()[0]
incept_list=Inception.tag(TEST_PATH, Inception.prediction)
incept_list = ['Inception'] + incept_list.tolist()[0]
squeez_list=SqueezNet.tag(TEST_PATH, SqueezNet.prediction)
squeez_list = ['SqueezNet'] + squeez_list.tolist()[0]
d = {'filename':dense_list[1], 'models':{}}
for l in [dense_list,res_list, incept_list, squeez_list]:
#breakpoint()
d['models'][l[0]] = l[2:]
JSONP_data = jsonify(d)
return JSONP_data
if __name__ == '__main__':
app.run ()
I was trying to create a web application (REST API) for Image Recognition with Tensorflow + keras in Flask. I have tried to follow some resource available in internet and came up with a script as below
from imageai.Prediction import ImagePrediction
import os
execution_path = os.getcwd()
prediction = ImagePrediction()
prediction.setModelTypeAsResNet()
prediction.setModelPath( execution_path + "\\resnet50_weights_tf_dim_ordering_tf_kernels.h5")
prediction.loadModel()
for i in range(3):
predictions, percentage_probabilities = prediction.predictImage("C:\\Users\\Administrator\\Downloads\\pics\\banana"+str(i)+".jpg", result_count=5)
for index in range(len(predictions)):
print(predictions[index] , " : " , percentage_probabilities[index])
This worked fine as standalone script. Then I tried to convert the same to Flask Application and it starts failing .
import flask
from imageai.Prediction import ImagePrediction
import os
import json
import keras
# initialize our Flask application and the Keras model
app = flask.Flask(__name__)
def init():
global model
execution_path = os.getcwd()
model = ImagePrediction()
model.setModelTypeAsResNet()
model.setModelPath( os.path.join(os.getcwd(),"models","resnet50_weights_tf_dim_ordering_tf_kernels.h5"))
model.loadModel()
# API for prediction
#app.route("/predict", methods=["GET"])
def predict():
predictions, percentage_probabilities = model.predictImage( os.path.join(os.getcwd(),"pics","banana.jpg"), result_count=5)
mylist = []
for index in range(len(predictions)):
mydict = {}
mydict[predictions[index]]=percentage_probabilities[index]
mylist.append(mydict)
keras.backend.clear_session()
return sendResponse(json.dumps(mylist))
# Cross origin support
def sendResponse(responseObj):
response = flask.jsonify(responseObj)
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Methods', 'GET')
response.headers.add('Access-Control-Allow-Headers', 'accept,content-type,Origin,X-Requested-With,Content-Type,access_token,Accept,Authorization,source')
response.headers.add('Access-Control-Allow-Credentials', True)
return response
# if this is the main thread of execution first load the model and then start the server
if __name__ == "__main__":
print(("* Loading Keras model and Flask starting server..."
"please wait until server has fully started"))
init()
app.run(threaded=True)
I am building a data product (an NLP chat application) for which I am learning Flask so that the user can have a better UI to interact with my product.
I have written down the following code in Flask to get the user input and stored it in a variable.
main.py
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template('init.html')
#app.route('/handle_data', methods = ['POST', 'GET'])
def handle_data():
userQuestion = request.form['userQuestion']
print(userQuestion)
return render_template('init.html', userQuestion = userQuestion)
if __name__ == '__main__':
app.run()
init.html
<!DOCTYPE HTML>
<html>
<body>
<form action="{{ url_for('handle_data') }}" method="post">
<input type="text" name="userQuestion">
<input type="submit">
</form>
</body>
</html>
I've handled the form data and stored it in a variable userQuestion. I want to pass this variable to another python script which contains the code of my training model.
doc2vec_main.py
import gensim
import nltk
import numpy
from gensim import models
from gensim import utils
from gensim import corpora
from nltk.stem import PorterStemmer
ps = PorterStemmer()
sentence0 = models.doc2vec.LabeledSentence(words=[u'sampling',u'what',u'is',u'sampling'],tags=["SENT_0"])
sentence1 = models.doc2vec.LabeledSentence(words=[u'sampling',u'tell',u'me',u'about',u'sampling'],tags=["SENT_1"])
sentence2 = models.doc2vec.LabeledSentence(words=[u'elig',u'what',u'is',u'my',u'elig'],tags=["SENT_2"])
sentence3 = models.doc2vec.LabeledSentence(words=[u'eligiblity',u'limit', u'what',u'is',u'my'],tags=["SENT_3"])
sentence4 = models.doc2vec.LabeledSentence(words=[u'eligiblity',u'claim',u'how',u'much',u'can',u'I'],tags=["SENT_4"])
sentence5 = models.doc2vec.LabeledSentence(words=[u'retir',u'eligibility',u'claim',u'i',u'am',u'how',u'much',u'can',u'i'],tags=["SENT_5"])
# ... list of all the training set.
# User inputs a question
document = input("Ask a question:")
tokenized_document = list(gensim.utils.tokenize(document, lowercase = True, deacc = True))
stemmed_document = []
for w in tokenized_document:
stemmed_document.append(ps.stem(w))
sentence19 = models.doc2vec.LabeledSentence(words= stemmed_document, tags=["SENT_19"])
sentences = [sentence0,sentence1,sentence2,sentence3, sentence4, sentence5,sentence6, sentence7, sentence8, sentence9, sentence10, sentence11, sentence12, sentence13, sentence14, sentence15, sentence16, sentence17, sentence18, sentence19]
model = models.Doc2Vec(size=4, alpha=0.25, min_alpha=.025, min_count=1)
model.build_vocab(sentences)
for epoch in range(30):
model.train(sentences, total_examples=model.corpus_count, epochs =
model.iter)
model.alpha -= 0.002
model.min_alpha = model.alpha
model.save("my_model.doc2vec")
model_loaded = models.Doc2Vec.load('my_model.doc2vec')
print (model.docvecs.most_similar(["SENT_19"]))
My problem is I cannot find a way to connect doc2vec_main.py to main.py and pass the value of userQuestion to the document variable in doc2main.py
script. That is when a user inputs a question in the form and clicks submit, the value of the form get passed down to document in doc2vec_main.py and the remaining script runs.
I have searched a lot on the internet but it didn't help. Can you suggest me a way to do it? I'm a complete beginner in Flask so forgive me for any mistake.
I found a possible solution.
In your python script file import sys
when you run your script like this -> python doc2vec_main.py "question here"
you can access that variable through
>>> import sys
>>> print(sys.argv)
>>>['doc2vec_main.py', 'question here']
So then you can simply use this
document = sys.argv[1]
Okay we found the manuall way but you need to automate this with flask.
Inside flask app import os
and then when you want to execute your externall script do this
os.system("python doc2vec_main.py %s") % request.form['userQuestion']
You know this will work but wouldnt it be better to do this in one app only? it would be better.
import gensim
import nltk
import numpy
from gensim import models
from gensim import utils
from gensim import corpora
from nltk.stem import PorterStemmer
ps = PorterStemmer()
# load the model here
model_loaded = models.Doc2Vec.load('my_model.doc2vec')
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template('init.html')
#app.route('/handle_data', methods = ['POST', 'GET'])
def handle_data():
userQuestion = request.form['userQuestion']
print(userQuestion)
q_vector = doc2vec_main(userQuestion)
return render_template('init.html', userQuestion = userQuestion)
def doc2vec_main(document):
"""whatever you want to do with your pre-trained doc2vec model can go here. I assume that doc2vec_main meant to return vector for a given document. for training part of the code you should write a separate function."""
# your code here!
return "replace this with your vector"
if __name__ == '__main__':
app.run()
Put the script in another module of your Flask application, under a function that takes as argument the variable you want to process:
import gensim
import nltk
import numpy
from gensim import models
from gensim import utils
from gensim import corpora
from nltk.stem import PorterStemmer
def doc2vec(user_question):
# your code here...
In your handle_data Flask view just pass the value from the form to your function. Take into consideration that this could not work in case your function is expensive so you can't wait for the result during normal request/response http flow.