如何在后台部署深度学习模型
最近刚开始使用theano, 经验不多,连个基本的模型都跑不通,于是去看了下Keras,源码比较简洁,可以当作theano的示例教程来看,感受如下:
文档看似很全,每个layer是干啥的,每个参数是啥都写了,但是不去读代码,实际很多人是无法从文档理解其具体用法的。这点看issue里的讨论里可以看出。同样,example似乎很多,而且都能直接run,还都是real world的数据集,看似很好,但是实际上,对于新手,如果需要的模型跟example里的不完全一样,不容易搞懂到底需要把输入输出的数据搞成啥格式。举个例子,example都是做的classification的,没有做sequence labeling的例子,如果想拿来做个pos tagging,不知道数据如何组织。当然,这些其实花一天读下代码或者好好翻翻issue讨论就可以解决了,但我相信不少人不会去认真读代码或者看讨论,而是直接换个工具。我感觉目前的doc只有懂了代码的人才能看懂,不懂得看文档还是没啥用。
2.项目很简单所以开发者不多,但是很活跃,每天都有新东西加进去。今天增加了一个新的分支后端可以用theano或者tensorflow了,不过貌似由于不支持scan,backend用tensorflow的没实现recurrent layer。他们也意识到文档的问题,觉得需要为小白用户多加点tutorial而不是光给develop看。
我没用过其他的framework,仅说keras拿来学习theano基本用法,很不错
库本身的代码,比较简单易读,我作为python菜鸟,也能看懂。目前model有sequential和grapgh两种,前者并不是指recurrent而是说网络是一层层堆的(也包括recurrent).其他的主要概念包括layer,regularizer, optimizer,objective都分离开。layer用于build每层的输出函数,model会用最后一层的输出,根据objective和每个layer的regularizer来确定最终的cost,然后在update时用optimizer来更新参数。把这四个看下加上model里的fit函数,就会用theano啦。很多模型都能cover,seq2seq这种也有现成的可用。建议不要光看example,多看看github上的 issues讨论,实在找不到,直接提问。效率方面,我不懂theano怎么优化,感觉keras的这种封装,没什么成本,跟自己用原生theano是一样的。当然,theano本身就好慢啊。。估计是我不懂用吧。。
作者:圣行
链接:https://www.zhihu.com/question/30091667/answer/47951446
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
matlab 和python没有用过。如果是习惯用opencv的话,可以使用memory_data,请参考这个链接里的例子:C++ Image Classification with memory_data_param · Issue #1443 · BVLC/caffe · GitHub
给一个具体点的例子吧(不知道贴代码是不是有点不合知乎气质?),总共分三步:
第一步,构造网络:
enum Phase p = TEST;
Net caffe_test_net(argv[1],p);
caffe_test_net.CopyTrainedLayersFrom(argv[2]);
第二步,构造数据并加入到网络输入层:
//create the input data
vector md_images;
vector md_labels;
//////operations for the input data
Mat original = imread("images\\lena_gray.png"); //随便的图片,没有实用意义,可忽略
Mat *sub_img = new Mat;
for (int i = 0; i < 10; i++){
original(Range(i, i + 28), Range(i, i + 28)).copyTo(*sub_img); // 28x28,可以直接用lenet
md_images.push_back(*sub_img);
md_labels.push_back(0);
}
第三步,执行test操作:
for (int i = 0; i < 10; i++){
const vector*>& result = caffe_test_net.ForwardPrefilled();
搭建深度学习后台服务器
我们的Keras深度学习REST API将能够批量处理图像,扩展到多台机器(包括多台web服务器和Redis实例),并在负载均衡器之后进行循环调度。
为此,我们将使用:
KerasRedis(内存数据结构存储)
Flask (Python的微web框架)
消息队列和消息代理编程范例
在我们的机器上运行Redis
将数据(图像)按照队列的方式用Redis存储,并依次由我们的REST API处理
为新批输入图像循环访问Redis
对图像进行分类并将结果返回给客户端
- conda install redis
- resdis-server
- redis-server
- python run_keras_server.py
- curl -X POST -F image=@jemma.png 'http://localhost:5000/predict'
- {"predictions": [{"label": "beagle","probability": 0.9461546540260315},{"label": "bluetick","probability": 0.031958919018507004},{"label": "redbone","probability": 0.006617196369916201},{"label": "Walker_hound","probability": 0.0033879687543958426},{"label": "Greater_Swiss_Mountain_dog","probability": 0.0025766862090677023}],"success": true}
- # import the necessary packagesimport requests# initialize the Keras REST API endpoint URL along with the input# image pathKERAS_REST_API_URL = "http://localhost:5000/predict"IMAGE_PATH = "jemma.png"
- # load the input image and construct the payload for the requestimage = open(IMAGE_PATH, "rb").read()payload = {"image": image}# submit the requestr = requests.post(KERAS_REST_API_URL, files=payload).json()# ensure the request was sucessfulif r["success"]: # loop over the predictions and display them for (i, result) in enumerate(r["predictions"]): print("{}. {}: {:.4f}".format(i + 1, result["label"], result["probability"]))# otherwise, the request failedelse: print("Request failed")
- python simple_request.py
本篇文章的整体思路如下:
我们将首先简要讨论Redis数据存储,以及如何使用它促进消息队列和消息代理。然后,我们将通过安装所需的Python包来配置Python开发环境,以构建我们的Keras深度学习REST API。一旦配置了开发环境,就可以使用Flask web框架实现实际的Keras深度学习REST API。在实现之后,我们将启动Redis和Flask服务器,然后使用cURL和Python向我们的深度学习API端点提交推理请求。最后,我们将以对构建自己的深度学习REST API时应该牢记的注意事项的简短讨论结束。
第一部分:简要介绍Redis如何作为REST API消息代理/消息队列
图片1:Redis可以用作我们深度学习REST API的消息代理/消息队列
Redis是内存中的数据存储。它不同于简单的键/值存储(比如memcached),因为它可以存储实际的数据结构。今天我们将使用Redis作为消息代理/消息队列。这包括:
文章中对Redis官网有一个超链接(https://redis.io/topics/introduction),但是要翻出去,所以我就截图一个图片放上去仅供参考。
第二部分:安装和配置Redis
官网做法,linux系统的安装:
自己的安装方法:
开启方式相同:
结果:
测试和原文的命令一致。
第三部分:配置Python开发环境以构建Keras REST API
文章中说需要创建新的虚拟环境来防止影响系统级别的python项目(但是我没有创建),但是还是需要安装rest api所需要依赖的包。以下为所需要的包。
第四部分:实现可扩展的Keras REST API
首先是Keras Redis Flask REST API数据流程图
让我们开始构建我们的服务器脚本。为了方便起见,我在一个文件中实现了服务器,但是它可以按照您认为合适的方式模块化。为了获得最好的结果和避免复制/粘贴错误,我建议您使用本文的“下载”部分来获取相关的脚本和图像。
为了简单起见,我们将在ImageNet数据集上使用ResNet预训练。我将指出在哪里可以用你自己的模型交换ResNet。flask模块包含flask库(用于构建web API)。redis模块将使我们能够与redis数据存储接口。从这里开始,让我们初始化将在run_keras_server.py中使用的常量.
我们将向服务器传递float32图像,尺寸为224 x 224,包含3个通道。我们的服务器可以处理一个BATCH_SIZE = 32。如果您的生产系统上有GPU(s),那么您需要调优BATCH_SIZE以获得最佳性能。我发现将SERVER_SLEEP和CLIENT_SLEEP设置为0.25秒(服务器和客户端在再次轮询Redis之前分别暂停的时间)在大多数系统上都可以很好地工作。如果您正在构建一个生产系统,那么一定要调整这些常量。
让我们启动我们的Flask app和Redis服务器:
在这里你可以看到启动Flask是多么容易。在运行这个服务器脚本之前,我假设Redis服务器正在运行(之前的redis-server)。我们的Python脚本连接到本地主机6379端口(Redis的默认主机和端口值)上的Redis存储。不要忘记将全局Keras模型初始化为None。接下来我们来处理图像的序列化:
Redis将充当服务器上的临时数据存储。图像将通过诸如cURL、Python脚本甚至是移动应用程序等各种方法进入服务器,而且,图像只能每隔一段时间(几个小时或几天)或者以很高的速率(每秒几次)进入服务器。我们需要把图像放在某个地方,因为它们在被处理前排队。我们的Redis存储将作为临时存储。
为了将图像存储在Redis中,需要对它们进行序列化。由于图像只是数字数组,我们可以使用base64编码来序列化图像。使用base64编码还有一个额外的好处,即允许我们使用JSON存储图像的附加属性。
base64_encode_image函数处理序列化。类似地,在通过模型传递图像之前,我们需要反序列化图像。这由base64_decode_image函数处理。
预处理图片
我已经定义了一个prepare_image函数,它使用Keras中的ResNet50实现对输入图像进行预处理,以便进行分类。在使用您自己的模型时,我建议修改此函数,以执行所需的预处理、缩放或规范化。
从那里我们将定义我们的分类方法
classify_process函数将在它自己的线程中启动,我们将在下面的__main__中看到这一点。该函数将从Redis服务器轮询图像批次,对图像进行分类,并将结果返回给客户端。
在model = ResNet50(weights="imagenet")这一行中,我将这个操作与终端打印消息连接起来——根据Keras模型的大小,加载是即时的,或者需要几秒钟。
加载模型只在启动这个线程时发生一次——如果每次我们想要处理一个映像时都必须加载模型,那么速度会非常慢,而且由于内存耗尽可能导致服务器崩溃。
加载模型后,这个线程将不断轮询新的图像,然后将它们分类(注意这部分代码应该时尚一部分的继续)
在这里,我们首先使用Redis数据库的lrange函数从队列(第79行)中获取最多的BATCH_SIZE图像。
从那里我们初始化imageIDs和批处理(第80和81行),并开始在第84行开始循环队列。
在循环中,我们首先解码对象并将其反序列化为一个NumPy数组image(第86-88行)。
接下来,在第90-96行中,我们将向批处理添加图像(或者如果批处理当前为None,我们将该批处理设置为当前图像)。
我们还将图像的id附加到imageIDs(第99行)。
让我们完成循环和函数
在这个代码块中,我们检查批处理中是否有图像(第102行)。如果我们有一批图像,我们通过模型(第105行)对整个批进行预测。从那里,我们循环一个图像和相应的预测结果(110-122行)。这些行向输出列表追加标签和概率,然后使用imageID将输出存储在Redis数据库中(第116-122行)。
我们使用第125行上的ltrim从队列中删除了刚刚分类的图像集。最后,我们将睡眠设置为SERVER_SLEEP时间并等待下一批图像进行分类。下面我们来处理/predict我们的REST API端点
稍后您将看到,当我们发布到REST API时,我们将使用/predict端点。当然,我们的服务器可能有多个端点。我们使用@app。路由修饰符以第130行所示的格式在函数上方定义端点,以便Flask知道调用什么函数。我们可以很容易地得到另一个使用AlexNet而不是ResNet的端点,我们可以用类似的方式定义具有关联函数的端点。你懂的,但就我们今天的目的而言,我们只有一个端点叫做/predict。
我们在第131行定义的predict方法将处理对服务器的POST请求。这个函数的目标是构建JSON数据,并将其发送回客户机。如果POST数据包含图像(第137和138行),我们将图像转换为PIL/Pillow格式,并对其进行预处理(第141-143行)。
在开发这个脚本时,我花了大量时间调试我的序列化和反序列化函数,结果发现我需要第147行将数组转换为C-contiguous排序(您可以在这里了解更多)。老实说,这是一个相当大的麻烦事,但我希望它能帮助你站起来,快速跑。
如果您想知道在第99行中提到的id,那么实际上是使用uuid(通用唯一标识符)在第151行生成的。我们使用UUID来防止hash/key冲突。
接下来,我们将图像的id和base64编码附加到d字典中。使用rpush(第153行)将这个JSON数据推送到Redis db非常简单。
让我们轮询服务器以返回预测
我们将持续循环,直到模型服务器返回输出预测。我们开始一个无限循环,试图得到157-159条预测线。从这里,如果输出包含预测,我们将对结果进行反序列化,并将结果添加到将返回给客户机的数据中。我们还从db中删除了结果(因为我们已经从数据库中提取了结果,不再需要将它们存储在数据库中),并跳出了循环(第163-172行)。
否则,我们没有任何预测,我们需要睡觉,继续投票(第176行)。如果我们到达第179行,我们已经成功地得到了我们的预测。在本例中,我们向客户机数据添加True的成功值(第179行)。注意:对于这个示例脚本,我没有在上面的循环中添加超时逻辑,这在理想情况下会为数据添加一个False的成功值。我将由您来处理和实现。最后我们称烧瓶。jsonify对数据,并将其返回给客户端(第182行)。这就完成了我们的预测函数。
为了演示我们的Keras REST API,我们需要一个__main__函数来实际启动服务器
第186-196行定义了__main__函数,它将启动classify_process线程(第190-192行)并运行Flask应用程序(第196行)。
第五部分:启动可伸缩的Keras REST API
要测试我们的Keras深度学习REST API,请确保使用本文的“下载”部分下载源代码示例图像。从这里,让我们启动Redis服务器,如果它还没有运行:
然后,在另一个终端中,让我们启动REST API Flask服务器:
另外,我建议在向服务器提交请求之前,等待您的模型完全加载到内存中。现在我们可以继续使用cURL和Python测试服务器。
第七部分:使用cURL访问Keras REST API
使用cURL来测试我们的Keras REST API服务器。这是我的家庭小猎犬Jemma。根据我们的ResNet模型,她被归类为一只拥有94.6%自信的小猎犬。
你会在你的终端收到JSON格式的预测:
第六部分:使用Python向Keras REST API提交请求
如您所见,使用cURL验证非常简单。现在,让我们构建一个Python脚本,该脚本将发布图像并以编程方式解析返回的JSON。
让我们回顾一下simple_request.py
我们在这个脚本中使用Python请求来处理向服务器提交数据。我们的服务器运行在本地主机上,可以通过端口5000访问端点/predict,这是KERAS_REST_API_URL变量(第6行)指定的。
我们还定义了IMAGE_PATH(第7行)。png与我们的脚本在同一个目录中。如果您想测试其他图像,请确保指定到您的输入图像的完整路径。
让我们加载图像并发送到服务器:
我们在第10行以二进制模式读取图像并将其放入有效负载字典。负载通过请求发送到服务器。在第14行发布。如果我们得到一个成功消息,我们可以循环预测并将它们打印到终端。我使这个脚本很简单,但是如果你想变得更有趣,你也可以使用OpenCV在图像上绘制最高的预测文本。
第七部分:运行简单的请求脚本
编写脚本很容易。打开终端并执行以下命令(当然,前提是我们的Flask服务器和Redis服务器都在运行)。
使用Python以编程方式使用我们的Keras深度学习REST API的结果
第八部分:扩展深度学习REST API时的注意事项
如果您预期在深度学习REST API上有较长一段时间的高负载,那么您可能需要考虑一种负载平衡算法,例如循环调度,以帮助在多个GPU机器和Redis服务器之间平均分配请求。
记住,Redis是内存中的数据存储,所以我们只能在队列中存储可用内存中的尽可能多的图像。
使用float32数据类型的单个224 x 224 x 3图像将消耗602112字节的内存。
产品经理的核心竞争力是什么?为什么
产品经理的核心能力有四点:一 持续学习的能力、二 精于业务的能力、三 创新思维的能力、四 超强沟通能力 一 持续学习的能力 产品经理作为企业和公司的核心领军队伍,需要对公司的产品进行不断完善和推进,才能够在与时俱进中,杀出自己的一条路,否则就会在互联网的滚滚洪流中被淘汰。所以这就需要...
世纪前沿·生活在极限之内:生态学、经济和人口禁忌本书目录
牛仔经济学与飞船生态学:两种视角碰撞,揭示资源利用的真相。增长的真伪:真实与虚构的增长理论,何者为真?人口的指数膨胀:马尔萨斯理论的遗产与现实的差距。数量调控的探索:寻找自然与人为调节的平衡点。生成未来的蓝图:如何规划并塑造未来世界?限制的视角:束缚还是解放,界限何在?从煤炭到丘疹的变迁...
如何正确认识大数据的价值和效益
推进我国数字经济发展要注重加强网络设施建设,夯实数字经济基础支撑。例如,要持续深入实施网络提速降费,推动国家大数据中心建设。要深入推进“两化”融合,提升数字经济应用水平,推进大数据在研发设计、生产制造、管理决策、售后服务等全流程的深度应用。培育个性化定制、众包设计、协同制造等数据驱动的制造业新...
您怎么看待这一现象?
我们开设“关注高质量人才培养”专栏,围绕人才培养关键问题,从不同的教育学段、不同的教育类型、不同的培养环节等角度,开展全年的系列报道,多维度探讨“强国建设 教育何为”这一时代课题,努力为系列强国目标提供强有力的人才和智力支撑。“如何破解工科人才培养困局”是我们的第一个系列。也欢迎来信来电,与我们一起...
影响小学生课堂学习的主要因素
一、主观因素 在学习知识时,有些人总认为“越多越好”,但有的教师和学生也并不完全认同这样的观点。如果教师或学生学的知识很多,可都是一知半解、囫囵吞枣,那我们宁愿要少而精的知识。笔者认为,作为教师应当具有广而博的知识,广而博的知识对提高学生的学习兴趣、促进对知识的理解与能力的形成无...
如何提高自己分析问题解决问题的能力
商场如战场。很多谍报类、间谍类、破案类电视剧里面都有丰富的案例,主人公是怎么破案,怎么分析问题和破解问题的。有很多可以学习的地方。看看这一类的电视剧,是可以学到很多东西的,例如最近热播的《麻雀》《胭脂》里面就有很多案例可供学习。提高自己的想象力 在很多时候你未实践,或者一件已经过去的...
艺术的人学:重新解读西方文学经典目录
艺术的人学,是一场对西方文学经典的深度探索。首先,我们从希腊神话的镜子中揭示神与人的关系,理解神如何反映人的本质(第一讲:神,是人的镜子——解读希腊神话)。接着,跟随荷马的脚步,我们审视时代的英雄与史诗中的英雄主义(第二讲:时代的英雄——解读荷马和荷马史诗)。索福克勒斯的《俄狄浦...
研学意义何在?
更是生活中的实践,而“游”是连接知与行的桥梁,确保了“研”有所得、“学”有所获。在每个孩子的成长历程中,研学是一次宝贵的人生旅程,它不仅仅是暂时的离开,更是深度的体验和认知的飞跃。让我们期待更多的孩子在研学的道路上,收获知识,收获成长,实现真正的知行合一。
怎么建立一个简单的网站
根据你的需求,完全可以用建站模板操作,以“上线了”建站平台为例,演示一下如何建站:第一步:打开这个建站平台的官网,注册好账户后选择“创建网站”,会跳出一个模板界面。第二步:选择一个你喜欢的行业和模板,点击“开始编辑”,会跳入到网页编辑器后台。第三步:在编辑器后台中输入你想要写的内容...
请问c++主要用来编什么,具体点,以前学过vc
VC更是包含了windows公司的标准类库MFC,这样就能编写出具有友好图形界面的程序了。关于学习C++的步骤,首先你要学会编写控制台程序,就是那个在黑框框里运行的程序,不要嫌它难看,这是训练你编程思维的一个必要的过程,当你开始学类以后,可以尝试的编写一些MFC的小程序,甚至是小游戏,充分享受编程的...
习素慢肾: 有两个思路. 一个online方式: 移动端做初步预处理,把数据传到服务器执行深度学习模型,现在很多APP都是这个思路, 优点是这个方式部署相对简单,现成的框架(caffe,theano,mxnet,Torch) 做下封装就可以直接拿来用,服务器性能大, ...
霸州市19148097433: 如何搭建一台深度学习服务器 - ?
习素慢肾: A、购买组装好的服务器,例如NVIDIA DIGITS DEVBOX B、购买云服务,例如Amazon的GPU服务 C、自己攒一台深度学习服务器
霸州市19148097433: 如何从零使用 Keras + TensorFlow 开发一个复杂深度学习模型 - ?
习素慢肾: 最近刚开始使用theano, 经验不多,连个基本的模型都跑不通,于是去看了下Keras,源码比较简洁,可以当作theano的示例教程来看,感受如下: 1. 文档看似很全,每个layer是干啥的,每个参数是啥都写了,但是不去读代码,实际很多人是...
霸州市19148097433: 如何在linux系统下安装深度学习的caffe框架 - ?
习素慢肾: Caffe需要预先安装一些依赖项,首先是CUDA驱动.不论是CentOS还是Ubuntu都预装了开源的nouveau显卡驱动(SUSE没有这种问题),如果不禁用,则CUDA驱动不能正确安装.以Ubuntu为例,介绍一下这里的处理方法,当然也有其他处...
霸州市19148097433: 如何将深度学习Caffe做成一个动态库,方便在其他应用程序中调用 - ?
习素慢肾: Caffe是目前深度学习比较优秀好用的一个开源库,采样c++和CUDA实现,具有速度快,模型定义方便等优点.学习了几天过后,发现也有一个不方便的地方,就是在我的程序中调用Caffe做图像分类没有直接的接口.Caffe的数据层可以从数据库
霸州市19148097433: windows怎么配置深度学习的环境 - ?
习素慢肾: 说真干事别自手种机器装起挺累找供应商搞定且Titan X排装起高负载散热怕需要额外特别处理(暴力扇架做间隔水冷均)
霸州市19148097433: 如何通过ARM Compute Library写深度学习模型 - ?
习素慢肾: AlphaGo依靠精确的专家评估系统(value network):专家系统是一个智能计算机程序系统,其内部含有大量的某个领域专家水平的知识与经验,能够利用人类专家的知识和解决问题的方法来处理该领域问题.基于海量数据的深度神经网络(...
霸州市19148097433: 深度学习可以用FPGA实现吗 - ?
习素慢肾: 深度学习要用VB来实现.目前主流的编程软件VisualBasic的版本是VisualBasic 6.0专业版.我们所使用的操作系统是Windows10. 先把VisualBasic 6.0的安装光盘放入电脑的光盘驱动器中,通常电脑能够自动运行光盘上的安装程序.在安装...
霸州市19148097433: T1000显卡是什么级别的显卡? - ?
习素慢肾: T1000显卡是一款性能出色、适用于各种计算需求的显卡.首先,T1000显卡采用了先进的图形处理单元(GPU),能够高效处理各种复杂的图形任务.其高效的渲染能力使得它能够快速完成高质量的图像渲染,适用于各种需要图形加速的应用...
霸州市19148097433: deep dream怎样制作 - ?
习素慢肾: SVM方面,首选的肯定是libsvm这个库,应该是应用最广的机器学习库了. 下面主要推荐一些DeepLearning的GitHub项目吧! 1. convnetjs - star:2200+ 实现了卷积神经网络,可以用来做分类,回归,强化学习等. 2. DeepLearn Toolbox - star:...