I want to crete a handwritten digit recognition model. And this ml model work as per my need in colab. I upload a photo from from trainig set and it gives the prediction. But when I tried to connect with flask. I needed to dump the model. And in every solution I search they dumped some object that are inbuilt library function. Here I tried to dump the object of the class I created, but it's giving me error. my ml code
import pandas as pd
import numpy as np
import pickle
from keras.datasets import mnist
import matplotlib.pyplot as plt
class hrd:
def ReLU(Z):
return np.maximum(Z,0)
def derivative_ReLU(Z):
return Z > 0
def softmax(Z):
"""Compute softmax values for each sets of scores in x."""
exp = np.exp(Z - np.max(Z)) #le np.max(Z) evite un overflow en diminuant le contenu de exp
return exp / exp.sum(axis=0)
def init_params(size):
W1 = np.random.rand(10,size) - 0.5
b1 = np.random.rand(10,1) - 0.5
W2 = np.random.rand(10,10) - 0.5
b2 = np.random.rand(10,1) - 0.5
return W1,b1,W2,b2
def forward_propagation(X,W1,b1,W2,b2):
Z1 = W1.dot(X) + b1 #10, m
A1 = ReLU(Z1) # 10,m
Z2 = W2.dot(A1) + b2 #10,m
A2 = softmax(Z2) #10,m
return Z1, A1, Z2, A2
def one_hot(Y):
''' return an 0 vector with 1 only in the position correspondind to the value in Y'''
one_hot_Y = np.zeros((Y.max()+1,Y.size)) #si le chiffre le plus grand dans Y est 9 ca fait 10 lignes
one_hot_Y[Y,np.arange(Y.size)] = 1 # met un 1 en ligne Y[i] et en colonne i, change l'ordre mais pas le nombre
return one_hot_Y
def backward_propagation(X, Y, A1, A2, W2, Z1, m):
one_hot_Y = one_hot(Y)
dZ2 = 2*(A2 - one_hot_Y) #10,m
dW2 = 1/m * (dZ2.dot(A1.T)) # 10 , 10
db2 = 1/m * np.sum(dZ2,1) # 10, 1
dZ1 = W2.T.dot(dZ2)*derivative_ReLU(Z1) # 10, m
dW1 = 1/m * (dZ1.dot(X.T)) #10, 784
db1 = 1/m * np.sum(dZ1,1) # 10, 1
return dW1, db1, dW2, db2
def update_params(alpha, W1, b1, W2, b2, dW1, db1, dW2, db2):
W1 -= alpha * dW1
b1 -= alpha * np.reshape(db1, (10,1))
W2 -= alpha * dW2
b2 -= alpha * np.reshape(db2, (10,1))
return W1, b1, W2, b2
def get_predictions(A2):
return np.argmax(A2, 0)
def get_accuracy(predictions, Y):
return np.sum(predictions == Y)/Y.size
def gradient_descent(X, Y, alpha, iterations):
size , m = X.shape
W1, b1, W2, b2 = init_params(size)
for i in range(iterations):
Z1, A1, Z2, A2 = forward_propagation(X, W1, b1, W2, b2)
dW1, db1, dW2, db2 = backward_propagation(X, Y, A1, A2, W2, Z1, m)
W1, b1, W2, b2 = update_params(alpha, W1, b1, W2, b2, dW1, db1, dW2, db2)
if (i+1) % int(iterations/10) == 0:
print(f"Iteration: {i+1} / {iterations}")
prediction = get_predictions(A2)
print(f'{get_accuracy(prediction, Y):.3%}')
return W1, b1, W2, b2
def make_predictions(X, W1 ,b1, W2, b2):
_, _, _, A2 = forward_propagation(X, W1, b1, W2, b2)
predictions = get_predictions(A2)
return predictions
def show_prediction(index,X, Y, W1, b1, W2, b2):
# None => cree un nouvel axe de dimension 1, cela a pour effet de transposer X[:,index] qui un np.array de dimension 1 (ligne) et qui devient un vecteur (colonne)
# ce qui correspond bien a ce qui est demande par make_predictions qui attend une matrice dont les colonnes sont les pixels de l'image, la on donne une seule colonne
vect_X = X[:, index,None]
prediction = make_predictions(vect_X, W1, b1, W2, b2)
label = Y[index]
print("Prediction: ", prediction)
print("Label: ", label)
current_image = vect_X.reshape((WIDTH, HEIGHT)) * SCALE_FACTOR
plt.gray()
plt.imshow(current_image, interpolation='nearest')
plt.show()
def show_from_input(vect_X, W1, b1, W2, b2):
prediction = make_predictions(vect_X, W1, b1, W2, b2)
return prediction
#label = Y[index]
#print("Prediction: ", prediction)
#current_image = vect_X.reshape((WIDTH, HEIGHT)) * SCALE_FACTOR
#plt.gray()
#plt.imshow(current_image, interpolation='nearest')
#plt.show()
def predict(a):
show_from_input(a, W1, b1, W2, b2)
############## MAIN ##############
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
SCALE_FACTOR = 255 # TRES IMPORTANT SINON OVERFLOW SUR EXP
WIDTH = X_train.shape[1]
HEIGHT = X_train.shape[2]
X_train = X_train.reshape(X_train.shape[0],WIDTH*HEIGHT).T / SCALE_FACTOR
X_test = X_test.reshape(X_test.shape[0],WIDTH*HEIGHT).T / SCALE_FACTOR
W1, b1, W2, b2 = hrd.gradient_descent(X_train, Y_train, 0.15, 200)
pickle.dump(kt,open('model.pkl','wb'))
model=pickle.load(open('model.pkl','rb'))
It's giving me the error
File "app.py", line 17, in <module>
model=pickle.load(open('model.pkl','rb'))
AttributeError: Can't get attribute 'hrd' on <module '__main__' from 'app.py'>
And my server flask code:
from flask import Flask, flash, request, redirect, url_for, render_template
import urllib.request
import os
import pickle
from werkzeug.utils import secure_filename
app = Flask(__name__)
UPLOAD_FOLDER = 'static/uploads/'
app.secret_key = "secret key"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
model=pickle.load(open('model.pkl','rb'))
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/')
def home():
return render_template('index.html')
@app.route('/', methods=['POST'])
def upload_image():
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No image selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
#print('upload_image filename: ' + filename)
flash('Image successfully uploaded and displayed below')
img = cv2.imread(filename,0)
resized = cv2.resize(img, (28,28))
features = resized.reshape(1,-1) / SCALE_FACTOR
#print(X_test[:,100,None])
x = model.predict(features[0][:,None])
return render_template('index.html',pred = x, filename=filename)
else:
flash('Allowed image types are - png, jpg, jpeg, gif')
return redirect(request.url)
@app.route('/display/<filename>')
def display_image(filename):
#print('display_image filename: ' + filename)
return redirect(url_for('static', filename='uploads/' + filename), code=301)
if __name__ == "__main__":
app.run()
enter code here