2016-07-26 1 views
0

J'essaie de construire un outil de prédiction en utilisant le Naive Bayes Classifier de SK-Learn et le micro-framework Python Flask. A partir de ce que j'ai googlé, je peux décaper le modèle puis décocher le modèle lorsque je charge l'application sur le navigateur, mais comment puis-je faire exactement cela?Comment intégrer un modèle formé SK-Learn Naive Bayes dans une application web de prédiction Python Flask?

Mon application doit recevoir des valeurs d'entrée utilisateur, puis transmettre ces valeurs au modèle, puis afficher les valeurs prédites aux utilisateurs (en tant que graphiques d3, d'où la nécessité de convertir les valeurs prédites au format JSON).

C'est ce que je l'ai essayé jusqu'à présent:

Décapage le modèle

from sklearn.naive_bayes import GaussianNB 
import numpy as np 
import csv 

def loadCsv(filename): 
    lines = csv.reader(open(filename,"rb")) 
    dataset = list(lines) 
    for i in range(len(dataset)): 
     dataset[i] = [float(x) for x in dataset[i]] 
    return dataset 

datasetX = loadCsv("pollutants.csv") 
datasetY = loadCsv("acute_bronchitis.csv") 

X = np.array(datasetX) 
Y = np.array(datasetY).ravel() 

model = GaussianNB() 
model.fit(X,Y) 

#import pickle 
from sklearn.externals import joblib 
joblib.dump(model,'acute_bronchitis.pkl') 

Le formulaire HTML pour collecter les entrées utilisateur:

<form class = "prediction-options" method = "post" action = "/prediction/results"> 
    <input type = "range" class = "prediction-option" name = "aqi" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">AQI</label> 
    <input type = "range" class = "prediction-option" name = "pm2_5" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">PM2.5</label> 
    <input type = "range" class = "prediction-option" name = "pm10" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">PM10</label> 
    <input type = "range" class = "prediction-option" name = "so2" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">SO2</label> 
    <input type = "range" class = "prediction-option" name = "no2" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">NO2</label> 
    <input type = "range" class = "prediction-option" name = "co" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">CO</label> 
    <input type = "range" class = "prediction-option" name = "o3" min = 0 max = 100 value = 0></input> 
    <label class = "prediction-option-label">O3</label> 
    <input type = "submit" class = "submit-prediction-options" value = "Get Patient Estimates" /> 
</form> 

Le Python Flacon app.py:

from flask import Flask, render_template, request 
import json 
from sklearn.naive_bayes import GaussianNB 
import numpy as np 
import pickle as pkl 
from sklearn.externals import joblib 

model_acute_bronchitis = pkl.load(open('data/acute_bronchitis.pkl')) 

@app.route("/prediction/results", methods = ['POST']) 
def predict(): 
    input_aqi = request.form['aqi'] 
    input_pm2_5 = request.form['pm2_5'] 
    input_pm10 = request.form['pm10'] 
    input_so2 = request.form['so2'] 
    input_no2 = request.form['no2'] 
    input_co = request.form['co'] 
    input_o3 = request.form['o3'] 

    input_list = [[input_aqi,input_pm2_5,input_pm10,input_so2,input_no2,input_co,input_o3]] 

    output_acute_bronchitis = model_acute_bronchitis.predict(input_list) 
    prediction = json.dumps(output_acute_bronchitis) 
    return prediction 

Cependant, je reçu le message d'erreur suivant: TypeError: 'NDArrayWrapper' object does not support indexing que je trouvais pourrait être causé par l'utilisation de JOBLIB de sk-apprendre à décaper le modèle.

Alors, j'ai essayé de voir si je pouvais utiliser la fonction de charge de JOBLIB pour charger le modèle Flask à la place, et je reçu ce message d'erreur:

/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/sklearn/utils/validation.py:386: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and willraise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample. 
    DeprecationWarning) 
[2016-07-27 12:45:30,747] ERROR in app: Exception on /prediction/results [POST] 
Traceback (most recent call last): 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/flask/app.py", line 1988, in wsgi_app 
response = self.full_dispatch_request() 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/flask/app.py", line 1641, in full_dispatch_request 
rv = self.handle_user_exception(e) 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/flask/app.py", line 1544, in handle_user_exception 
reraise(exc_type, exc_value, tb) 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/flask/app.py", line 1639, in full_dispatch_request 
rv = self.dispatch_request() 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/flask/app.py", line 1625, in dispatch_request 
return self.view_functions[rule.endpoint](**req.view_args) 
    File "app.py", line 95, in predict 
output_acute_bronchitis = model_acute_bronchitis.predict(input_list) 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/sklearn/naive_bayes.py", line 65, in predict 
jll = self._joint_log_likelihood(X) 
    File "/Users/Vanessa/Desktop/User/lib/python2.7/site-packages/sklearn/naive_bayes.py", line 394, in _joint_log_likelihood 
n_ij -= 0.5 * np.sum(((X - self.theta_[i, :]) ** 2)/
TypeError: ufunc 'subtract' did not contain a loop with signature matching types dtype('<U32') dtype('<U32') dtype('<U32') 
127.0.0.1 - - [27/Jul/2016 12:45:30] "POST /prediction/results HTTP/1.1" 500 - 

Qu'est-ce que je fais mal? Existe-t-il des alternatives plus simples pour faire ce que j'espère accomplir?

+0

Pourriez-vous s'il vous plaît donner la trace entière de la pile pour l'erreur 'ufunc' soustraire '... '? –

Répondre

2

Je pense que le problème avec votre code est que les données de votre formulaire sont lues comme une chaîne. Par exemple, dans input_aqi = request.form['aqi'], input_aqi a une chaîne. Par conséquent, dans output_acute_bronchitis = model_acute_bronchitis.predict(input_list), vous finissez par passer predict un tableau de chaînes en raison de laquelle vous voyez cette erreur. Vous pouvez résoudre ce problème en convertissant simplement toutes vos entrées de formulaire à flotteurs comme suit:

input_aqi = float(request.form['aqi']) 

Vous devrez le faire pour toutes les entrées de formulaire que vous mettez dans input_list.

Espérons que ça aide.

+0

Merci pour la réponse! Comment puis-je afficher les résultats de prédiction sur la page Web? (c'est-à-dire que la page Web devrait rester la même sauf avec l'ajout d'un nouvel élément montrant les résultats de la prédiction) –

+0

Salut Vanessa, Je suis content d'avoir pu résoudre votre problème. Je m'excuse, je ne connais pas la réponse à cette question car je n'ai pas beaucoup d'expérience de développement Web avec Flask. J'ai beaucoup d'expérience avec Sklearn mais pas avec Flask. Vous pouvez peut-être poster une question distincte avec le tag Flask afin que les personnes qui connaissent bien Flask puissent vous guider. –