成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手把手:我的深度學習模型訓練好了,然后要做啥?

開發 開發工具
本文講的是如何快速而不求完美地部署一個訓練好的機器學習模型并應用到實際中。

[[219745]]

大數據文摘作品

編譯:姜范波、云舟

本文講的是如何快速而不求***地部署一個訓練好的機器學習模型并應用到實際中。如果你已經成功地使用諸如Tensorflow或Caffe這樣的框架訓練好了一個機器學習模型,現在你正在試圖讓這個模型能夠快速的演示,那么讀這篇文章就對了。

使用前檢查清單

  • 檢查tensorflow的安裝
  • 從 stdin 運行在線分類
  • 在本地運行分類
  • 把分類器放到硬編碼(hardcoded)的代理
  • 把分類器放到有服務發現(service discovery)的代理
  • 用一個偽DNS調用分類器

機器學習的實際應用

當我們***次進入Hive的機器學習空間時,針對我們的實際應用場景,我們已經擁有了數百萬張準確標記的圖像,這些圖像使我們能夠在一周之內,從頭開始訓練***進的深度卷積神經網絡圖像分類模型(即隨機權重)。然而,在更典型的應用場景中,圖像的數量級通常只有數百幅,這種情況下,我建議微調現有的模型。比如,

https://www.tensorflow.org/tutorials/image_retraining有一個關于如何微調Imagenet模型(在1.2M圖像上訓練1000個類別)以對花進行分類的樣本數據集(3647個圖像, 5個類別)。

上面的Tensorflow教程簡要而言,是在安裝bazel和tensorflow之后,需要運行以下代碼,用大約30分鐘的來建模,5分鐘來訓練:

  1. cd "$HOME" && \ 
  2. curl -O http://download.tensorflow.org/example_images/flower_photos.tgz && \ 
  3. tar xzf flower_photos.tgz ; 
  4. ) && \ 
  5. bazel build tensorflow/examples/image_retraining:retrain \ 
  6.           tensorflow/examples/image_retraining:label_image \ 
  7. && \ 
  8. bazel-bin/tensorflow/examples/image_retraining/retrain \ 
  9.   --image_dir "$HOME"/flower_photos \ 
  10.   --how_many_training_steps=200 
  11. && \ 
  12. bazel-bin/tensorflow/examples/image_retraining/label_image \ 
  13.   --graph=/tmp/output_graph.pb \ 
  14.   --labels=/tmp/output_labels.txt \ 
  15.   --output_layer=final_result:0 \ 
  16.   --image=$HOME/flower_photos/daisy/21652746_cc379e0eea_m.jpg 

或者,如果你安裝了Docker,則可以使用以下預構建的Docker鏡像:

  1. sudo docker run -it --net=host liubowei/simple-ml-serving:latest /bin/bash 
  2.  
  3. >>> cat test.sh && bash test.sh 

這將進入容器內部的交互式shell中并運行上述命令; 如果你愿意的話,也可以按照容器內的其余部分進行操作。

現在,tensorflow已經將模型信息保存到/tmp/output_graph.pb和/tmp/output_labels.txt中,這些作為命令行參數傳遞給label_image.py腳本。Google的image_recognition教程也鏈接到另一個腳本,但是這里我們仍將使用label_image.py。

將本地運行轉換為在線運行(Tensorflow)

如果我們只想接受來自標準輸入的文件名,每行一個,我們就可以很容易地進行“在線”運行:

  1. while read line ; do 
  2. bazel-bin/tensorflow/examples/image_retraining/label_image \ 
  3. --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt \ 
  4. --output_layer=final_result:0 \ 
  5. --image="$line" ; 
  6. done 

然而,從性能的角度來看這樣糟糕透了—— 每一個輸入都要重新加載神經網絡,權重,整個Tensorflow框架和python本身!

當然可以改進。先修改label_image.py 腳本。對我而言,這個腳本的位置在:

  1. in bazel-bin/tensorflow/examples/image_retraining/label_image.runfiles/org_tensorflow/tensorflow/examples/image_retraining/label_image.py. 

修改如下:

  1. 141:  run_graph(image_data, labels, FLAGS.input_layer, FLAGS.output_layer, 
  2. 142:        FLAGS.num_top_predictions)141:  for line in sys.stdin: 

修改后馬上快了很多,但這還不是***。

  1. 141:  run_graph(image_data, labels, FLAGS.input_layer, FLAGS.output_layer, 
  2. 142:        FLAGS.num_top_predictions)141:  for line in sys.stdin: 

原因在于用with tf.Session()構建對話。Tensorflow本質上是在每次調用run_graph時將所有的計算加載到內存中。一旦開始嘗試在GPU上進行運算,這一點就會變得很明顯——可以看到GPU內存使用隨著Tensorflow加載和卸載GPU的模型參數而上下波動。據我所知,這種結構并不存在于Caffe或Pytorch框架中。

解決方法是把with命令去掉,傳遞一個sess變量到run_graph:

  1. def run_graph(image_data, labels, input_layer_name, output_layer_name, 
  2.               num_top_predictions, sess): 
  3.     # Feed the image_data as input to the graph. 
  4.     #   predictions will contain a two-dimensional array, where one 
  5.     #   dimension represents the input image count, and the other has 
  6.     #   predictions per class 
  7.     softmax_tensor = sess.graph.get_tensor_by_name(output_layer_name) 
  8.     predictions, = sess.run(softmax_tensor, {input_layer_name: image_data}) 
  9.     # Sort to show labels in order of confidence 
  10.     top_k = predictions.argsort()[-num_top_predictions:][::-1] 
  11.     for node_id in top_k: 
  12.       human_string = labels[node_id] 
  13.       score = predictions[node_id] 
  14.       print('%s (score = %.5f)' % (human_string, score)) 
  15.     return [ (labels[node_id], predictions[node_id].item()) for node_id in top_k ] # numpy floats are not json serializable, have to run item 
  16.  
  17. ... 
  18.  
  19.   with tf.Session() as sess: 
  20.     for line in sys.stdin: 
  21.       run_graph(load_image(line), labels, FLAGS.input_layer, FLAGS.output_layer, 
  22.           FLAGS.num_top_predictions, sess) 

如果你運行完這一段,你會發現每張圖只需要大約0.1秒,對于在線應用來說已經夠快了。

將本地運行轉換為在線運行(其他ML框架)

Caffe使用net.forward代碼,很容易被放入一個可調用的框架中:

see http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb

Mxnet也是非常獨特的:它實際上已經準備好了面向大眾的服務器代碼。

部署

我們的計劃是,將這些代碼包裝到一個Flask應用程序中。如果你沒有聽說Flask,簡單解釋一下,Flask是一個非常輕量級的Python Web框架,它允許你以最少的工作啟動一個http api服務器。

作為一個快速參考,這里是一個Flask應用程序,它接收包含多部分表單數據的POST請求:

  1. #!/usr/bin/env python 
  2. # usage: python echo.py to launch the server ; and then in another session, do 
  3. # curl -v -XPOST 127.0.0.1:12480 -F "data=@./image.jpg" 
  4. from flask import Flask, request 
  5. app = Flask(__name__) 
  6. @app.route('/', methods=['POST']) 
  7. def classify(): 
  8.     try: 
  9.         data = request.files.get('data').read() 
  10.         print repr(data)[:1000] 
  11.         return data, 200 
  12.     except Exception as e: 
  13.         return repr(e), 500 
  14. app.run(host='127.0.0.1',port=12480

這里是如何將相應的FLASK應用程序連接到上面的run_graph:

  1. And here is the corresponding flask app hooked up to run_graph above: 
  2.  
  3. #!/usr/bin/env python 
  4. # usage: bash tf_classify_server.sh 
  5. from flask import Flask, request 
  6. import tensorflow as tf 
  7. import label_image as tf_classify 
  8. import json 
  9. app = Flask(__name__) 
  10. FLAGS, unparsed = tf_classify.parser.parse_known_args() 
  11. labels = tf_classify.load_labels(FLAGS.labels) 
  12. tf_classify.load_graph(FLAGS.graph) 
  13. sess = tf.Session() 
  14. @app.route('/', methods=['POST']) 
  15. def classify(): 
  16.     try: 
  17.         data = request.files.get('data').read() 
  18.         result = tf_classify.run_graph(data, labels, FLAGS.input_layer, FLAGS.output_layer, FLAGS.num_top_predictions, sess) 
  19.         return json.dumps(result), 200 
  20.     except Exception as e: 
  21.         return repr(e), 500 
  22. app.run(host='127.0.0.1',port=12480

模型部署至此看起來還是相當不錯的。除了一點——需要FlASK和Tensorflow完全同步——Flask按照接收的順序一次處理一個請求,并且Tensorflow在進行圖像分類時完全占用線程。

速度瓶頸可能還是在實際的計算工作中,所以升級Flask包裝代碼沒有太多的意義。現在,也許這個代碼足以處理你的負載。

有兩種顯而易見的方法可以擴大請求的通量:通過增加工人數量來橫向放大,這在下一節將會介紹,或者通過使用GPU和批處理邏輯來縱向擴展。實現后者需要一個能夠一次處理多個待處理請求的web服務器,并決定是否繼續等待更大的批處理或將其發送到Tensorflow圖形線程進行分類,對于這個Flask應用程序是非常不適合的。有兩種可能性:使用Twisted + Klein來保留Python代碼,或者如果你更喜歡***的事件循環支持,并且能夠連接到非Python ML框架(如Torch),則可以使用Node.js + ZeroMQ。

擴展:負載平衡和服務發現

那么,假設現在你只有一臺服務器來部署模型,由于它太慢了,或者我們的負載變得太高了,此時你想要啟動更多服務器——如何在每個服務器上分配請求?

常規的方法是添加一個代理層,也許是haproxy或nginx,它能夠平衡后端服務器之間的負載,同時向客戶端呈現一個統一的接口。為了在本節稍后使用,以下是運行基本Node.js負載均衡器http代理的一些示例代碼:

  1. // Usage : node basic_proxy.js WORKER_PORT_0,WORKER_PORT_1,... 
  2. const worker_ports = process.argv[2].split(',') 
  3. if (worker_ports.length === 0) { console.err('missing worker ports') ; process.exit(1) } 
  4.  
  5. const proxy = require('http-proxy').createProxyServer({}) 
  6. proxy.on('error', () => console.log('proxy error')) 
  7.  
  8. let i = 0 
  9. require('http').createServer((req, res) => { 
  10.   proxy.web(req,res, {target: 'http://localhost:' + worker_ports[ (i++) % worker_ports.length ]}) 
  11. }).listen(12480) 
  12. console.log(`Proxying localhost:${12480} to [${worker_ports.toString()}]`) 
  13.  
  14. // spin up the ML workers 
  15. const { exec } = require('child_process') 
  16. worker_ports.map(port => exec(`/bin/bash ./tf_classify_server.sh ${port}`)) 

為了自動檢測后端服務器的數量和位置,人們通常使用“服務發現”工具,該工具可能與負載平衡器捆綁在一起,或者是分開的。一些知名例子的是Consul和Zookeeper。設置和學習使用它們不在本文的討論范圍之內,所以我使用了一個非?;镜?,通過node.js服務發現包seport實現的代理。

Proxy代碼:

  1. // Usage : node seaport_proxy.js 
  2. const seaportServer = require('seaport').createServer() 
  3. seaportServer.listen(12481) 
  4. const proxy = require('http-proxy').createProxyServer({}) 
  5. proxy.on('error', () => console.log('proxy error')) 
  6.  
  7. let i = 0 
  8. require('http').createServer((req, res) => { 
  9.   seaportServer.get('tf_classify_server', worker_ports => { 
  10.     const this_port = worker_ports[ (i++) % worker_ports.length ].port 
  11.     proxy.web(req,res, {target: 'http://localhost:' + this_port }) 
  12.   }) 
  13. }).listen(12480) 
  14. console.log(`Seaport proxy listening on ${12480} to '${'tf_classify_server'}' servers registered to ${12481}`) 

Worker代碼:

  1. // Usage : node tf_classify_server.js 
  2. const port = require('seaport').connect(12481).register('tf_classify_server') 
  3. console.log(`Launching tf classify worker on ${port}`) 
  4. require('child_process').exec(`/bin/bash ./tf_classify_server.sh ${port}`) 

然而,當應用于機器學習時,這個設置遇到了帶寬問題。

每秒幾十到幾百張圖像,這個系統就會成為網絡帶寬的瓶頸。在目前的設置中,所有的數據都必須通過我們的單個seaport 主節點,這也是呈現給客戶端的端點。

為了解決這個問題,我們需要我們的客戶端不要訪問http://127.0.0.1:12480這個端點,而是要在后端服務器之間通過自動輪換來訪問。如果你懂網絡,一定會想:這不就是DNS干的活嘛!

但是,設置自定義的DNS服務器已經超出了本文的范圍。相反,通過更改客戶端以遵循兩步“手動DNS”協議,我們可以重新使用我們的基礎版的seaport 代理來實現客戶端直接連接到其服務器的“點對點”協議:

Proxy代碼:

  1. // Usage : node p2p_proxy.js 
  2. const seaportServer = require('seaport').createServer() 
  3. seaportServer.listen(12481) 
  4.  
  5. let i = 0 
  6. require('http').createServer((req, res) => { 
  7.   seaportServer.get('tf_classify_server', worker_ports => { 
  8.     const this_port = worker_ports[ (i++) % worker_ports.length ].port 
  9.     res.end(`${this_port} 
  10. `) 
  11.   }) 
  12. }).listen(12480) 
  13. console.log(`P2P seaport proxy listening on ${12480} to 'tf_classify_server' servers registered to ${12481}`)(Worker 代碼同上) 

Client代碼:

  1. curl -v -XPOST localhost:`curl localhost:12480` -F"data=@$HOME/flower_photos/daisy/21652746_cc379e0eea_m.jpg" 

結論和進一步閱讀

至此你的系統應該可以進入實際應用了,但它總是要發展的。本指南中未涉及幾個重要的主題:

1. 新硬件上的自動部署和設置。

  • 值得注意的工具包括Openstack / VMware(如果您使用的是自己的硬件),Chef / Puppet(用于安裝Docker并處理網絡路由)以及Docker(用于安裝Tensorflow,Python等)。
  • 如果你在云端,Kubernetes或Marathon / Mesos也很棒

2. 模型版本管理

  • 一開始手動管理不難。
  • Tensorflow Serving是一個很好的工具,可以非常徹底地處理這個問題,以及批處理和整體部署。 缺點是設置和編寫客戶端代碼有點難,另外不支持Caffe / PyTorch。

3. 如何將機器學習代碼從Matlab中遷移出來。

  • 在生產階段不要用Matlab

4. GPU驅動,Cuda,CUDNN

  • 使用nvidia-docker,試試其它的在線Dockfiles。

5. 后處理層。

  • 一旦你在生產中得到了一些不同的ML模型,你可能會開始想要混合和匹配不同的用例——只有在模型B不確定的情況下才運行模型A,在Caffe中運行模型C并將結果傳遞給模型D在Tensorflow 等等。

來源:

https://thehive.ai/blog/simple-ml-serving?utm_campaign=Revue%20newsletter&utm_medium=Newsletter&utm_source=The%20Wild%20Week%20in%20AI

【本文是51CTO專欄機構大數據文摘的原創譯文,微信公眾號“大數據文摘( id: BigDataDigest)”】

     大數據文摘二維碼

 

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2021-04-09 14:49:02

人工智能機器學習

2017-10-18 09:48:13

深度學習TensorFlow入門篇

2019-11-13 14:39:56

EdgeBoard

2022-05-10 10:19:04

AI深度學習模型

2024-08-20 15:05:42

機器學習多任務多標簽模型

2016-04-27 09:49:16

用戶模型產品總結

2017-02-09 18:50:42

深度學習機器計算機

2020-11-27 07:38:43

MongoDB

2011-01-10 14:41:26

2011-05-03 15:59:00

黑盒打印機

2025-05-07 00:31:30

2018-02-25 19:02:45

Python機器學習算法

2021-07-14 09:00:00

JavaFX開發應用

2011-02-22 13:46:27

微軟SQL.NET

2021-02-26 11:54:38

MyBatis 插件接口

2021-12-28 08:38:26

Linux 中斷喚醒系統Linux 系統

2021-09-26 16:08:23

CC++clang_forma

2020-09-27 06:59:59

IO系統Linux

2019-11-21 15:35:28

機器學習人工智能計算機

2023-04-26 12:46:43

DockerSpringKubernetes
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线播放国产视频 | 免费激情av| 欧美日韩网站 | 欧美国产日韩精品 | 国产乱xxav | 日韩成人av在线 | 国产精品国产精品国产专区不片 | 国产xxxx岁13xxxxhd | 男女羞羞的网站 | 亚洲91精品 | 精品国产一区二区三区性色av | 久久精品国产99国产精品 | 国产视频一区二区三区四区五区 | 免费小视频在线观看 | 免费av手机在线观看 | 久久久久久久久久一区 | 精品国产一区二区三区免费 | 日韩在线精品视频 | 在线视频亚洲 | 国产乱码精品一区二区三区五月婷 | 亚洲国产aⅴ精品 | 在线看成人av| 色婷婷av777 av免费网站在线 | 免费的色网站 | 欧美成人一区二免费视频软件 | 国产免费观看一区 | 欧美精品乱码久久久久久按摩 | 一级黄大片 | 亚洲国产视频一区 | 欧美电影大全 | 久久国产精品网站 | 夜夜爽99久久国产综合精品女不卡 | 亚洲精品 在线播放 | 免费99精品国产自在在线 | 国产四区 | 国产精品一区在线观看 | 日韩国产黄色片 | 欧美国产日韩在线观看 | www.日韩免费 | 91精品国产综合久久香蕉922 | 亚洲精品不卡 |