9.4 将电影分类器嵌入Web应用
目前,我们对使用Flask进行Web开发有了一定的认识,下面更进一步,将电影分类器嵌入到Web应用中。在本节,我们先开发一个Web应用,此应用会提示用户输入一个电影评论,如下图所示:
在评论提交后,会返回一个新的页面,页面中会显示预测类标及评论属于此类别的概率。此外,用户还可以使用“正确”(Correct)或者“不正确”(Incorrect)两个按钮对预测结果做出反馈,如下图所示:
如果用户点击了“正确”或者“不正确”按钮,分类模型将基于用户的反馈进行更新。此外,对于用户输入的评论文本,以及从按钮点击中推测出的类标等信息,我们将使用SQLite数据库进行保存,为将来的预测提供参考。用户点击反馈按钮后看到的第三个页面,显示了简单的感谢信息和一个“提交其他评论”(Submit another review)按钮,此按钮将页面重定向到起始页面。如下图所示:
在详细学习此Web应用的代码之前,建议读者通过http://raschkas.pythonanywhere.com了解一下此应用的示例,以对本小节待讲解内容有个更好的认识。
从全局角度出发,我们先看一下此电影评论分类应用的目录结构,如下图所示:
在本章前面的小节中,我们已经创建了vecorizer.py文件、SQLite数据库reviews.sqlite,以及可以保存经过序列化的Python对象的pkl_objects子目录。
主目录下的app.py文件是包含Flask代码的Python脚本,在Web应用中,我们将使用review.sqlite数据库文件(本章前面小节中创建的文件)保存用户提交的电影评论数据。templates子目录存储将被Flask渲染的HTML模板文件;static子目录仅包含一个简单的CSS文件,用于调整HTML页面渲染效果。
由于app.py文件较长,我们分两步来分析。首先导入所需的Python模块及对象,并通过反序列化恢复我们的分类模型:
我们对app.py的第一部分内容应该很熟悉了。首先导入了HashingVectorizer并对逻辑斯谛回归分类器进行反序列化操作。接下来,定义了一个classify函数返回针对给定文本文档的预测类标及其对应的概率。当文档及其对应类标可用时[1],可使用train函数更新分类器模型。使用sqlite_entry函数,我们可以将用户输入的评论信息及其对应的类标,以及时间戳等存入SQLite数据库。请注意,如果重启了Web应用,那么clf对象将被重置为其原始的序列化状态。在本章最后,读者将学到如何使用SQLite数据库收集到的数据对分类器进行永久更新。
app.py第二部分的内容看起来也非常熟悉:
我们定义了一个ReviewForm类来实例化TextAreaField对象,它将在模版文件review-form.html(Web应用的起始页)中被渲染。此对象同样也会被index函数所渲染。以validators.length(min=15)为参数,可以限制用户的输入至少为15个字符。在result函数内,我们能够获取到用户在Web表单中提交的内容,并将其传递给电影评论分类器以预测情感倾向,预测结果将显示在渲染后的results.html模板中。
乍一看,feedback函数好像有些复杂。如果用户在results.html页面点击了“正确”或“不正确”反馈按钮,此函数将分析出正确的类标,并将正确的情感预测转换成整数类标,以便使用train函数更新分类器,train函数在app.py脚本的第一部分已经做了介绍。此外,如果用户提交了反馈,sqlite_entry函数就会在SQLite数据库中插入一条新的数据,最后thanks.html模板就会被渲染出来以感谢用户的反馈。
接下来,看一下reviewform.html模板,它是Web应用的起始页面:
在此,我们导入了本章的9.3.2节中定义的_formhelpers.html模板。宏中的render_field函数用于渲染TextAreaField对象,此对象用于收集用户填写的电影评论信息,并可通过页面底部的“提交评论”(Submit review)按钮将信息提交到服务器。此TextAreaField对象的宽度为30个列宽,高度为10行。
下一个模板,results.html,看上去很有趣:
首先,我们通过{{content}}、{{prediction}},以及{{probability}}分别插入了用户提交的评论、预测类标,以及对应的概率。读者可能注意到了,我们在包含“正确”及“不正确”按钮的表单中第二次使用了{{content}}和{{prediction}}占位符。这种旨在当用户点击了任一按钮后,以POST方式将数据返回给服务器,以便进行更新模型和存储评论数据。此外,我们在results.html文件的头部导入了CSS文件(style.css)。此文件的设置非常简单:它将Web应用中内容的宽度设置为600像素,并使用<div id=“button”>将“正确”与“不正确”按钮下移了20像素:
此CSS文件仅相当于一个占位符,读者可以根据自己的喜好任意调整页面的显示方式。
Web应用要实现的最后一个模板页面是thanks.html。顾名思义,此页面以友好的方式在用户点击“正确”或“不正确”按钮给出反馈后表示了感谢。此外,在页面的底部,我们给出了一个“提交其他评论”的按钮,它可以将用户重定向到起始页。thanks.html的内容如下:
在进入下一小节并将应用部署到公共Web服务器上之前,我们不妨在终端窗口中输入如下命令,从而在本地环境中启动Web应用:
完成Web应用的测试后,不要忘记将app.py脚本中app.run()命令的debug=True参数去掉。
[1] 即用户输入文档,并对预测结果做了相关反馈时。——译者注