为了账号安全,请及时绑定邮箱和手机立即绑定

使用flask将机器学习模型嵌入到web系统中

标签:
人工智能

在这篇文章中,主要介绍如何将一个机器学习的模型嵌入到web系统中,这篇文章的主要内容包括:

1、利用flask构建一个简单的web
2、将机器学习模型嵌入到web系统中
3、根据用户的反馈来更新模型

主要包括三个页面,评论提交页面、分类结果页面、感谢页面。当用户提交评论后跳转到结果页面,后台根据已有的模型来预测用户评论是属于正面评论还是负面评论,返回属于哪一种评论并且返回属于该种类的概率为多少。提供两个用户反馈结果按钮,如果用户点击正确按钮,则说明预测正确,否则预测错误,并将结果保存到SQLlite数据库中,然后再跳转到感谢页面。

一、项目结构


db:目录中存放SQLite数据库文件。

pkl:存放模型文件,stopwords.pk为停用词文件,classifer.pkl为模型文件。

static:为静态文件目录,主要存放js和css文件。

templates:为模板文件目录,用来存放html文件。

app.py:主要文件,包含界面跳转和模型预测等功能。

updatePkl.py:为模型更新文件。

vectorizer.py:将评论转换成为特征向量便于预测。

二、界面说明

界面做的比较简单,没有过多的去调整的样式,主要是实现功能。

1、用户提交评论界面


用户在这个界面可以输入自己的评论,并提交。

2、分类结果页面


用户可以通过这个页面查看自己评论的分类结果,并可以进行相应的反馈。如果,用户没有确认是否正确,SQLite数据库中将不会保存这条评论所属的类别。

3、感谢页面


通过这个界面可以跳转到,提交评论界面。利用SQLiteStudio可以查看数据库保存评论


三、功能的实现

1、将评论转成特征向量
  1. import re  

  2. import pickle  

  3. from sklearn.feature_extraction.text import HashingVectorizer  

  4. from nltk.stem.porter import PorterStemmer  

  5. import warnings  

  6. warnings.filterwarnings("ignore")  

  7.   

  8. #加载停用词  

  9. stop = pickle.load(open("pkl/stopwords.pkl","rb"))  

  10.   

  11. #删除HTML标记和标点符号,去除停用词  

  12. def tokenizer(text):  

  13.     #去除HTML标记  

  14.     text = re.sub("<[^>]*>","",text)  

  15.     #获取所有的表情符  

  16.     emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text.lower())  

  17.     #删除标点符号  

  18.     text = re.sub("[\W]+"," ",text.lower())+" ".join(emoticons).replace("-","")  

  19.     #删除停用词  

  20.     tokenized = [word for word in text.split() if word not in stop]  

  21.     #提取词干  

  22.     porter = PorterStemmer()  

  23.     #返回去除停用词之后的单词列表  

  24.     return [porter.stem(word) for word in tokenized]  

  25. #通过HashingVectorizer获取到评论的特征向量  

  26. vect = HashingVectorizer(decode_error="ignore",n_features=2**21,preprocessor=None,tokenizer=tokenizer)  

2、主要功能

  1. import pickle  

  2. import sqlite3  

  3. import numpy as np  

  4. from flask import Flask,render_template,request  

  5. from wtforms import Form,TextAreaField,validators  

  6. from flask_web.vectorizer import vect  

  7.   

  8. #创建一个falsk对象  

  9. app = Flask(__name__)  

  10. #加载分类模型  

  11. clf = pickle.load(open("pkl/classifier.pkl","rb"))  

  12.   

  13. #创建一个评论数据库,在app.py运行之前先运行这个方法  

  14. def create_review_db():  

  15.     conn = sqlite3.connect("db/move_review.db")  

  16.     c = conn.cursor()  

  17.     #move_review主要包括四个字段,review_id(评论ID,主键自增)、review(评论内容)、sentiment(评论类别)、review_date(评论日期)  

  18.     c.execute("CREATE TABLE move_review (review_id INTEGER PRIMARY KEY AUTOINCREMENT,review TEXT"  

  19.               ",sentiment INTEGER,review_date TEXT)")  

  20.     conn.commit()  

  21.     conn.close()  

  22.   

  23. #将评论保存到数据库中  

  24. def save_review(review,label):  

  25.     conn = sqlite3.connect("db/move_review.db")  

  26.     c = conn.cursor()  

  27.     #向数据库中插入评论  

  28.     c.execute("INSERT INTO move_review (review,sentiment,review_date) VALUES "  

  29.               "(?,?,DATETIME('now'))",(review,label))  

  30.     conn.commit()  

  31.     conn.close()  

  32.   

  33. #获取评论的分类结果  

  34. def classify_review(review):  

  35.     label = {0:"negative",1:"positive"}  

  36.     #将评论转换成为特征向量  

  37.     X = vect.transform(review)  

  38.     #获取评论整数类标  

  39.     Y = clf.predict(X)[0]  

  40.     #获取评论的字符串类标  

  41.     label_Y = label[Y]  

  42.     #获取评论所属类别的概率  

  43.     proba = np.max(clf.predict_proba(X))  

  44.     return Y,label_Y,proba  

  45.   

  46.   

  47. #跳转到用户提交评论界面  

  48. @app.route("/")  

  49. def index():  

  50.     #验证用户输入的文本是否有效  

  51.     form = ReviewForm(request.form)  

  52.     return render_template("index.html",form=form)  

  53.   

  54. #跳转到评论分类结果界面  

  55. @app.route("/main",methods=["POST"])  

  56. def main():  

  57.     form = ReviewForm(request.form)  

  58.     if request.method == "POST" and form.validate():  

  59.         #获取表单提交的评论  

  60.         review_text = request.form["review"]  

  61.         #获取评论的分类结果,类标、概率  

  62.         Y,lable_Y,proba = classify_review([review_text])  

  63.         #将概率保存2为小数并转换成为百分比的形式  

  64.         proba = float("%.4f"%proba) * 100  

  65.         #将分类结果返回给界面进行显示  

  66.         return render_template("reviewform.html",review=review_text,Y=Y,label=lable_Y,probability=proba)  

  67.     return render_template("index.html",form=form)  

  68.   

  69. #用户感谢界面  

  70. @app.route("/tanks",methods=["POST"])  

  71. def tanks():  

  72.     #判断用户点击的是分类正确按钮还是错误按钮  

  73.     btn_value = request.form["feedback_btn"]  

  74.     #获取评论  

  75.     review = request.form["review"]  

  76.     #获取评论所属类标  

  77.     label_temp = int(request.form["Y"])  

  78.     #如果正确,则类标不变  

  79.     if btn_value == "Correct":  

  80.         label = label_temp  

  81.     else:  

  82.         #如果错误,则类标相反  

  83.         label = 1 - label_temp  

  84.   

  85.     save_review(review,label)  

  86.     return render_template("tanks.html")  

  87.   

  88. class ReviewForm(Form):  

  89.     review = TextAreaField("",[validators.DataRequired()])  

  90.   

  91. if __name__ == "__main__":  

  92.     #启动服务  

  93.     app.run()  

3、模型更新

  1. import pickle  

  2. import sqlite3  

  3. import numpy as np  

  4. from flask_web.vectorizer import vect  

  5.   

  6. #更新模型方法,每次更新10000条评论  

  7. def update_pkl(db_path,clf,batch_size=10000):  

  8.     conn = sqlite3.connect(db_path)  

  9.     c = conn.cursor()  

  10.     c.execute("SELECT * from review")  

  11.     #获取到所有的评论  

  12.     results = c.fetchmany(batch_size)  

  13.     while results:  

  14.         data = np.array(results)  

  15.         #获取评论  

  16.         X = data[:,1]  

  17.         #获取  

  18.         Y = int(data[:,2])  

  19.         classes = np.array([0,1])  

  20.         #将评论转成特征向量  

  21.         x_train = vect.transform(X)  

  22.         #更新模型  

  23.         clf.partial_fit(x_train,Y,classes=classes)  

  24.         results = c.fetchmany(batch_size)  

  25.     conn.close()  

  26.     return None  

  27.   

  28. if __name__ == "__main__":  

  29.     #加载模型  

  30.     clf = pickle.load(open("pkl/classifier.pkl", "rb"))  

  31.     #更新模型  

  32.     update_pkl("db/move_review.db",clf)  

  33.     #保存模型  

  34.     pickle.dump(clf,open("pkl/classifier.pkl","wb"),protocol=4)  

为什么要将更新模型用另一个文件运行,而不是在用户提交反馈之后就直接更新模型?

如果在同一时间评论的用户多的话,直接在用户提交反馈之后就更新模型,可能会造成在更新模型文件的时候会损坏模型文件。建议,在本地更新模型文件之后,再上传到服务器。


原文出处

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消