django 热启动_从0开始算法服务接口开发

一、写在前面的话

1.1 本文介绍

在我们的日常工作中,很多算法同学可能会遇到一个问题,那就是console in,console out,这个时候会发现这种模式在做实验,复现paper的时候还可以,但是在工作过程中,这种模式和工程化相差甚远。(在实际工作中,算法的工作需要给算法模型提供接口,供工程部门或者客户调用)。所以这里就提到一个重要概念:

本文将会从0开始搭建一个算法模型,然后基于该模型开放

So,读了本文,算法工程化不是梦,迎娶白富美指日可待!!!

1.2 本文内容开发环境搭建

构建算法模型(本文案例为基于bert fine-tune的文本分类模型)

基于django的接口开发

tensorflow server 安装部署

接口测试

1.3 本文相关

1、本文中的代码和数据均开源在github上,可以完整运行。github地址为:https://github.com/charlesXu86/HelloWorld​github.com

2、本文中的数据和代码不涉及业务,可以放心引用,放心git clone。

3、不建议star本项目,如果觉得这篇文章对你有用,star我别的项目吧。嘿嘿嘿~~吼吼

二、Django Server开发

2.1 Django开发环境

本文需要的开发环境要求为:

python 3.6 + Django + Tensorflow + pycharm(可选)+ docker

a. 首先安装django

pip install django

b. 新建一个django的项目

新建django项目有两种方式:一种是通过shell终端,另外一种是通过pycharm搭建,两种方式殊途同归,大家可以通过自己的习惯选择。

shell 模式:

django-admin startproject HelloWorld

pycharm懒人模式:

File ->New project 选中Django

图一 pycharm新建Django工程

稍等片刻,此时在你的目录下会有一个名叫HelloWorld的Django项目:

$ cd HelloWorld/

$ tree

.

|-- HelloWorld

| |-- __init__.py

| |-- settings.py

| |-- urls.py

| `-- wsgi.py

`-- manage.py

目录说明:HelloWorld: 项目的容器。

manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。

HelloWorld/__init__.py: 一个空文件,告诉 Python 该目录是一个 Python 包。

HelloWorld/settings.py: 该 Django 项目的设置/配置。

HelloWorld/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站"目录"。

HelloWorld/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。

注:上述标红的两个文件在后续接口开发的过程中会有改动,后续一一说明

(知乎居然没有标红功能)settings.py urls.pyyypppy..ssllrr u . . u ur . . .

c. 启动项目

项目新建好了就可以测试启动项目了,此时也可以使用两种模式:

shell模式:

python manage.py runserver 0.0.0.0:8000 后面两个参数为 ip:port

后台启动:

nohup python manage.py runserver 172.16.19.74:8009 > /home/logs/bot_log 2>&1 &

pycharm模式:

图二 启动项目

启动成功的界面:

图三 项目启动成功

同时,你也可以在pycharm里面设置参数,指定ip,端口,gpu,远程解释器等等(万能的pycharm)

图四 运行配置

在图四中:

Host:指定项目运行的ip,这里可以指定你的服务器地址

Port:指定运行端口

Additional options:指定项目运行的额外参数,例如指定显卡

Python interpreter:指定python解释器。现在很多人的工作模式是在本地写代码,在远程服务器上run,pycharm提供了很好的功能,可以连接远程服务器,AutoUpload,无缝run。这里就不做说明了,如果有不回配置的,请@我。

至此,Django项目搭建完成。

注:1、shell模式中的后两个参数为ip:port,在这里可以指定你的运行ip和端口

2、图二中pycharm启动项目的图中,1为运行模式启动,2为debug模式启动,为了方便调试代码,一般选用2

4、Django是一个非常优秀的Web端框架,有很强的扩展性,包括权限、数据库,视图等等,因为我们关注的是接口开发,所以其他功能忽略。

5、很多人会拿Django和Flask做比较,觉得Flask更轻量级,开发也很快捷,个人觉得开发接口的话,代码都很小,不做比较。

2.2 构建深度学习模型

项目搭建好了,我们现在开始构建算法模型,在这里我们选用的案例为基于bert fine-tune的语义相似度匹配模型,数据为LCMQC的数据。下面来说明怎么构建模型。

a. 新建文件夹

按照我的开发习惯,我会按照模块来新建文件夹或者python package,这样看起来清新舒适,后期维护起来也比较方便。在这里我们新建一个python package,名字叫HelloWorld_model,这个package转门存放我们的算法代码,因为我们一个服务不会只提供一个接口,每一个算法模型(代码)用一个文件夹管理,方便管理。新建好的文件目录为:

图五 model模块

这个红色框框里存放我们的算法代码。

b. 构建算法模型

在这里我用原生Tensorflow (版本为1.14)构建的基于bert fine-tune的语义相似度模型,代码参考的google 的bert官方代码。代码实现细节我就不细说了,但是我会说明我的一些改动。

数据格式:

图六 bert similar数据

数据的格式为: sentence1\tsentence2\tlabel

代码:

图七 代码结构

config_bert.py: 模型的超参数配置等,包括加载预训练模型文件

run_similarity_bert.py: 模型实现。代码细节请移步github。

在这里我要对run_similarity_bert.py代码做一些说明:

1、代码的开头有

from bert4tf import modeling

from bert4tf import tokenization

from bert4tf import optimization

这个bert4tf是我自己封装的一个pypi的包,目前V1.0版本只支持加载bert,(超级简单的封装)。您可以

pip install bert4tf

如果不想安装,也可以将bert的三个源码文件放到项目文件夹来引用他。

2、代码里加入了python的queen(队列)包,在整个predict的预测流程为:

请求 -> 入队 -> 模型推断 -> 出队 -> 返回

3、模型predict的方法为:

def predict(self, sentence1, sentence2):

if self.mode is None:

raise ValueError("Please set the 'mode' parameter")

self.input_queue.put([(sentence1, sentence2)])

prediction = self.output_queue.get()

return prediction

这个方法在BertSim 类下,这样写的好处是工程部署以后,每次只需要在服务启动时初始化一次模型(初始化会非常慢)。

注:1、bert4tf是我自己开发的一个包,目前V1.0版本只支持加载bert,现在正在积极开发V2.0,此版本支持tf2.0,支持加载bert、albert、roberta权重,支持layer操作等等功能

2、也有其他大佬做了相关工作,我开发这个的目的一方面是自己学习,另一方面是为了自己定制化调用

2.3 开发RESTful API

模型构建好了我们就可以开发接口了,在这里我们用django的一个新命令来新建一个接口模块:

python manage.py startapp HelloWorld_rest

然后在该模块下新建一个名为Api的文件夹,将HelloWorld模块里的url.py文件复制到HelloWorld_rest目录下。

图八 加入rest模块结构

至此,整个项目的全部结构已基本完成,接下来我来讲述api路由,接受post请求,传入模型预测,接收预测结果,接口返回的整个流程。

a. 在Api文件下新建一个文件夹

图九 Api目录

Similar_server.py: 接受post请求的入口,这个方法的作用是解析请求参数,把解析好的参数传入模型,接收到模型预测结果后,再封装成JsonReponse的格式返回。

Get_similar.py:这是一个中间过渡方法。这个方法存在的意义是将模型和接口解耦。因为我们很多时候在接收到模型的返回之后还有一些逻辑操作,这些操作既不方便写在模型文件里,也不方便写在接口文件里。

写到这里,你以为接口开发就完成了吗?No!因为还有一个重要的工作没做,那就是配置接口路由

b. 配置接口路由

图十 路由配置文件

首先配置图十中1,1中urls.py的完整代码为:

from django.contrib import admin

from django.urls import path, include

urlpatterns = [

path('admin/', admin.site.urls),

path('api/', include("HelloWorld_rest.urls")),

]

在这里加入了一行

path('api/', include("HelloWorld_rest.urls")),

这个urls.py文件起到一个全局路由的作用,加入的这一行代码的意思是路由到我们的rest模块下的urls.py文件中,第一个参数是路径。

然后修改图十中2的urls.py文件,这个文件的作用是路由到我们的接口中,代码为:

from django.urls import path

from HelloWorld_rest.Api.similar.Similar_server import sim_server

urlpatterns = [

path('similar', sim_server)

]

第一个参数是我们的接口url,和前面的文件拼接起来就是api/similar.

c. 修改全局配置文件settings.py

到目前为止,接口开发工作已经完成,但是在请求的时候可能还存在一些问题,比如无法接受接口的返回值,安全验证错误等,这是我们要修改一下全局配置文件settings.py,修改内容如下:

1、ALLOWED_HOSTS = ['*'] *的意思是接受任何ip请求,同时你也可以指定ip,以“,”分隔

2、注释掉MIDDLEWARE中“django.middleware.csrf.CsrfViewMiddleware”这一行

3、将语言和时区修改为

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

4、当你请求远程服务器时,请确保你关闭了防火墙,或者添加了ip白名单

d. 启动服务

图十一 启动服务

点击七星瓢虫按钮,以debug模式启动服务,正常启动后你将看到:

图十二 服务启动成功

e. 接口测试

我是在mac下用的ApiPost工具来测试的,同时你也可以使用postman,接口的url为:

ip:port/api/你定义的接口名称

测试结果如下所示:

图十三 接口测试结果

通过上图我们可以看到,测试的这两句话的语义相似度为0.939,效果还可以,但是我在2080的gpu服务器上匹配一次需要花费80ms左右,在某些qps要求较高的场景下,这个速度太慢了,所以接下来的一个工作就是不丧失精度的条件下提高接口的响应。比如:

1、使用albert(会丧失精度,空间换时间)

2、使用DistilBert

3、提高数据传输速率等等

2.4 小结

接口的开发工作完成了,现在做一些总结,纵观上述的开发流程,代码量是不大的,主要的代码还是构建一个好的模型,但是在开发的过程中也需要注意一些问题:

1、predict函数一定要写在一个class下,在服务启动的时候初始化这个类(只初始化一次),这样才能保证后续的每次请求快速得到模型的返回结果。

2、在请求量大的时候需要注意并发,比如我在构建模型的时候用到了队列

3、在一个服务有多个模型的时候,这个时候在django的作用下,有时模型的session会发生错乱,从而报错。这类情况已有解决方案,后续说明

4、django还有一个非常好的功能,就是热启动,何为热启动呢,就是当你的代码发生任何改动时,django会检测到,然后自动重启项目。

三、Tensorflow server 开发搭建

明天更新~~

你可能感兴趣的:(django,热启动)