日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

pytorch checkpoint_pytorch的两种部署方式 web部署与c++部署

發布時間:2024/9/15 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pytorch checkpoint_pytorch的两种部署方式 web部署与c++部署 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

知乎地址: ?https://zhuanlan.zhihu.com/c_1101089619118026752?

作者: ? 小哲?

github: ?https://github.com/lxztju/notes?

微信公眾號: 小哲AI

近期看到了一篇威信公眾號推送,研究了一下這兩種pytorch模型的部署方式,一種為web部署,一種是c++部署

完整代碼:

https://github.com/lxztju/pytorch_classification/tree/master/deployment

  • 1. web部署

    • 1. Redis安裝,配置

    • 2. server端

    • 3. Redis服務器端

    • 4. 調用測試

  • 2. c++模型部署

    • 1. 安裝libtorch

    • 2. 將模型轉換為torch腳本

    • 3. torch腳本序列化為文件

    • 4. 在c++中調用模型

    • 一個問題

1. web部署

web部署就是采用REST API的形式進行接口調用。

web部署的方式采用flask+ redis的方法進行模型部署,pytorch為模型的框架,flask為后端框架,redis是采用鍵值的形式存儲圖像的數據庫。

各package包的版本:

pytorch 1.2.0flask 1.0.2 Redis 3.0.6

1. Redis安裝,配置

ubuntu Redis的安裝,下載地址:https://redis.io/download

安裝教程: https://www.jianshu.com/p/bc84b2b71c1c

wget http://download.redis.io/releases/redis-6.0.6.tar.gz# 拷貝到/usr/local目錄下cp redis-3.0.0.rar.gz /usr/local# 解壓tar xzf redis-6.0.6.tar.gzcd /usr/local/redis-6.0.6# 安裝至指定的目錄下make PREFIX=/usr/local/redis install

Redis配置:

# redis.conf是redis的配置文件,redis.conf在redis源碼目錄。# 拷貝配置文件到安裝目錄下# 進入源碼目錄,里面有一份配置文件 redis.conf,然后將其拷貝到安裝路徑下cd /usr/local/rediscp /usr/local/redis-3.0.0/redis.conf /usr/local/redis/bin

此時在/usr/local/redis/bin目錄下,有如下文件:

redis-benchmark redis性能測試工具redis-check-aof AOF文件修復工具redis-check-rdb RDB文件修復工具redis-cli redis命令行客戶端redis.conf redis配置文件redis-sentinal redis集群管理工具redis-server redis服務進程

Redis服務開啟:

# 這是以前端方式啟動,關閉終端,服務停止./redis-server# 后臺方式啟動#修改redis.conf配置文件, daemonize yes 以后端模式啟動cd /usr/local/redis./bin/redis-server ./redis.conf

連接Redis

/usr/local/redis/bin/redis-cli

關閉Redis

cd /usr/local/redis./bin/redis-cli shutdown

強行中止Redis,(可能會丟失持久化數據)

pkill redis-server

2. server端

@app.route('/predict', methods=['POST'])def predict(): data = {'Success': False} if request.files.get('image'): now = time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time())) image = request.files['image'].read() image = Image.open(io.BytesIO(image)) image = image_transform(InputSize)(image).numpy() # 將數組以C語言存儲順序存儲 image = image.copy(order="C") # 生成圖像ID k = str(uuid.uuid4()) d = {"id": k, "image": base64_encode_image(image)} # print(d) db.rpush(ImageQueue, json.dumps(d)) # 運行服務 while True: # 獲取輸出結果 output = db.get(k) # print(output) if output is not None: output = output.decode("utf-8") data["predictions"] = json.loads(output) db.delete(k) break time.sleep(ClientSleep) data["success"] = True return jsonify(data)if __name__ == '__main__': app.run(host='127.0.0.1', port =5000,debug=True )

3. Redis服務器端

def classify_process(filepath): # 導入模型 print("* Loading model...") model = load_checkpoint(filepath) print("* Model loaded") while True: # 從數據庫中創建預測圖像隊列 queue = db.lrange(ImageQueue, 0, BatchSize - 1) imageIDs = [] batch = None # 遍歷隊列 for q in queue: # 獲取隊列中的圖像并反序列化解碼 q = json.loads(q.decode("utf-8")) image = base64_decode_image(q["image"], ImageType, (1, InputSize[0], InputSize[1], Channel)) # 檢查batch列表是否為空 if batch is None: batch = image # 合并batch else: batch = np.vstack([batch, image]) # 更新圖像ID imageIDs.append(q["id"]) # print(imageIDs) if len(imageIDs) > 0: print("* Batch size: {}".format(batch.shape)) preds = model(torch.from_numpy(batch.transpose([0, 3,1,2]))) results = decode_predictions(preds) # 遍歷圖像ID和預測結果并打印 for (imageID, resultSet) in zip(imageIDs, results): # initialize the list of output predictions output = [] # loop over the results and add them to the list of # output predictions print(resultSet) for label in resultSet: prob = label.item() r = {"label": label.item(), "probability": float(prob)} output.append(r) # 保存結果到數據庫 db.set(imageID, json.dumps(output)) # 從隊列中刪除已預測過的圖像 db.ltrim(ImageQueue, len(imageIDs), -1) time.sleep(ServeSleep)def load_checkpoint(filepath): checkpoint = torch.load(filepath, map_location='cpu') model = checkpoint['model'] # 提取網絡結構 model.load_state_dict(checkpoint['model_state_dict']) # 加載網絡權重參數 for parameter in model.parameters(): parameter.requires_grad = False model.eval() return modelif __name__ == '__main__': filepath = '../c/resnext101_32x8.pth' classify_process(filepath)

4. 調用測試

curl -X POST -F image=@test.jpg 'http://127.0.0.1:5000/predict'from threading import Threadimport requestsimport time# 請求的URLREST_API_URL = "http://127.0.0.1:5000/predict"# 測試圖片IMAGE_PATH = "./test.jpg"# 并發數NUM_REQUESTS = 500# 請求間隔SLEEP_COUNT = 0.05def call_predict_endpoint(n): # 上傳圖像 image = open(IMAGE_PATH, "rb").read() payload = {"image": image} # 提交請求 r = requests.post(REST_API_URL, files=payload).json() # 確認請求是否成功 if r["success"]: print("[INFO] thread {} OK".format(n)) else: print("[INFO] thread {} FAILED".format(n))# 多線程進行for i in range(0, NUM_REQUESTS): # 創建線程來調用api t = Thread(target=call_predict_endpoint, args=(i,)) t.daemon = True t.start() time.sleep(SLEEP_COUNT)time.sleep(300)

2. c++模型部署

教程:https://pytorch.apachecn.org/docs/1.2/beginner/Intro_to_TorchScript_tutorial.html

利用TorchScript進行模型c++部署,

業界與學術界最大的區別在于工業界的模型需要落地部署,學界更多的是關心模型的精度要求,而不太在意模型的部署性能。一般來說,我們用深度學習框架訓練出一個模型之后,使用Python就足以實現一個簡單的推理演示了。但在生產環境下,Python的可移植性和速度性能遠不如C++。所以對于深度學習算法工程師而言,Python通常用來做idea的快速實現以及模型訓練,而用C++作為模型的生產工具。目前PyTorch能夠完美的將二者結合在一起。實現PyTorch模型部署的核心技術組件就是TorchScript和libtorch。

所以基于PyTorch的深度學習算法工程化流程大體如下圖所示:

img

1. 安裝libtorch

pytorch官網 下載libtorch

解壓到指定的位置,我這里直接解壓到/home/xxx/.

2. 將模型轉換為torch腳本

定義一個python文件,載入模型文件pth,然后將其轉換為torch腳本.

import torchdef load_checkpoint(filepath): checkpoint = torch.load(filepath, map_location='cpu') model = checkpoint['model'] # 提取網絡結構 model.load_state_dict(checkpoint['model_state_dict']) # 加載網絡權重參數 for parameter in model.parameters(): parameter.requires_grad = False model.eval() return modelmodel = load_checkpoint('./resnext101_32x8.pth')# 這里如果保存采用gpu模型,就必須將example轉換為cuda類型example = torch.rand(1, 3, 224, 224)# 轉換為torch腳本# 這里有兩種方式,另一種方式為script,如果模型中存在if的分支結構,使用trace不行的,使用script# 參考鏈接: https://pytorch.apachecn.org/docs/1.2/beginner/Intro_to_TorchScript_tutorial.htmltraced_script_module = torch.jit.trace(model, example)# 測試轉換是否正確output = traced_script_module(torch.ones(1, 3, 224, 224))print(output)

3. torch腳本序列化為文件

將上文轉換完成的腳本序列化為pt模型文件

traced_script_module.save('./trace_resnext101_32x8.pt')

4. 在c++中調用模型

1. CMakeLists.txt

# 指定 cmake 最低編譯版本cmake_minimum_required(VERSION 3.0 FATAL_ERROR)# 指定project的名稱project(c)#添加需要的庫set(CMAKE_PREFIX_PATH /home/lxztju/libtorch_cpu /home/lxztju/opencv_3.4.3/build)find_package(Torch REQUIRED)find_package(OpenCV REQUIRED)#添加可執行文件add_executable(c main.cpp)#外部庫依賴target_link_libraries(c ${TORCH_LIBRARIES} ${OpenCV_LIBS})# 編譯語言set_property(TARGET c PROPERTY CXX_STANDARD 14)

opencv安裝

由于使用了opencv這里記錄opencv的安裝(ubuntu)

下載地址:https://opencv.org/releases/

然后解壓在指定文件夾下,這里解壓在/home/lxztju下.

cd /home/lxztju/opencv-3.4.3mkdir buildcd buildsudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..sudo make -j8sudo make install

配置環境

sudo gedit /etc/ld.so.conf# 添加一行 include /usr/loacal/lib# 其中/usr/local是makefile中指定的路徑sudo gedit /etc/bash.bashrc

在末尾添加如下內容

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfigexport PKG_CONFIG_PATHsource /etc/bash.bashrc# 查看是否安裝成功pkg-config opencv --modversion

2. cpp文件

//頭文件#include #include #include #include #include #include # include #include using namespace std;//https://pytorch.org/tutorials/advanced/cpp_export.html//存儲測試圖像的文件夾string image_path ( "/home/lxztju/git/model_deployment/c/image");//獲取一個文件夾下的所有圖像,存入files著發餓vector中.void getFiles( string path, vector& files ){ struct dirent *ptr; DIR *dir; dir = opendir(path.c_str()); while ((ptr = readdir(dir)) != NULL) { //跳過'.'和'..'兩個目錄 if(ptr->d_name[0] == '.') continue; files.push_back(ptr->d_name); }}int main(int argc, const char* argv[]){ //載入模型 torch::jit::script::Module module = torch::jit::load("/home/luxiangzhe/git/model_deployment/c/trace_resnext101_32x8.pt"); cout << "ok\n"; vector files; char * filePath = "/home/luxiangzhe/git/model_deployment/c/image";獲取該路徑下的所有文件 getFiles(filePath, files ); int size = files.size();// for (int i = 0;i < size;i++)// {// cout<// } clock_t start, end; double totle_time; for (int i = 0; i < files.size(); i++) { // 輸入圖像 auto image = cv::imread(image_path + '/' + files[i], cv::ImreadModes::IMREAD_COLOR); cv::Mat image_transformed; cv::resize(image, image_transformed, cv::Size(224, 224)); cv::cvtColor(image_transformed, image_transformed, cv::COLOR_BGR2RGB); //圖像轉換為tensor torch::Tensor image_tensor = torch::from_blob(image_transformed.data, {image_transformed.rows, image_transformed.cols, 3}, torch::kByte); image_tensor = image_tensor.permute({2, 0, 1}); image_tensor = image_tensor.toType(torch::kFloat); image_tensor = image_tensor.div(255); image_tensor = image_tensor.unsqueeze(0); //這里如果采用gpu版本的libtorch模型,需要將測試圖像轉換為cuda //image_tensor = image_tensor.to(at::kCUDA); //start = clock(); //前向傳播 at::Tensor output = module.forward({image_tensor}).toTensor(); //end = clock(); //totle_time = (double)(end-start) /CLOCKS_PER_SEC; //cout << "totle time: " << totle_time < auto max_result = output.max(1, true); auto max_index = std::get<1>(max_result).item(); cout < } return 0;}

3. 編譯鏈接

首先在c++ 項目中建立文件夾

mkdir buildcd build

編譯鏈接

cmake ..make

執行生成的可執行文件

./project_name

一個問題

這里我對比了pytorch與libtorch模型的推理速度,發現采用c++與libtorch的結合速度要慢很多,這個我看了github上的一些回答,也沒有發現合理的解釋,不知道怎么回事,可能采用c++并發會很大程度上加快整體的運行速度,也不清楚怎么回事.還希望看到的大佬能夠解答一下.

總結

以上是生活随笔為你收集整理的pytorch checkpoint_pytorch的两种部署方式 web部署与c++部署的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。