深度學習模型部署概述


一般地,當我們在python框架(eg:pytorch,tensorflow等)中訓練好模型,需要部署到C/C++環境,有以下方案:

  • CPU方案:Libtorch、OpenCV-DNN、OpenVINO、ONNX(有個runtime可以調)
  • GPU方案:TensorRT、OpenCV-DNN(需要重新編譯,帶上CUDA)

注:OpenCV、OpenVINO都是intel的開源框架庫,OpenCV的DNN模塊其實調用的也就是OpenVINO,另外OpenvVINO在硬件加速方面使用了intel自家CPU的集成顯卡。

 

模型部署的時候,我們僅需要實現數據處理、前向傳播就行,不需要去管反向傳播。網絡架構是一定要讀懂的,舉個例子:

 

假設現有大小為32 x 32的圖片樣本,輸入樣本的channels為1,該圖片可能屬於10個類中的某一類。CNN框架定義如下:

 1 class CNN(nn.Module):
 2     def __init__(self):
 3         nn.Model.__init__(self)
 4  
 5         self.conv1 = nn.Conv2d(1, 6, 5)  # 輸入通道數為1,輸出通道數為6
 6         self.conv2 = nn.Conv2d(6, 16, 5)  # 輸入通道數為6,輸出通道數為16
 7         self.fc1 = nn.Linear(5 * 5 * 16, 120)
 8         self.fc2 = nn.Linear(120, 84)
 9         self.fc3 = nn.Linear(84, 10)
10 
11     def forward(self,x):
12         # 輸入x -> conv1 -> relu -> 2x2窗口的最大池化
13         x = self.conv1(x)
14         x = F.relu(x)
15         x = F.max_pool2d(x, 2)
16         # 輸入x -> conv2 -> relu -> 2x2窗口的最大池化
17         x = self.conv2(x)
18         x = F.relu(x)
19         x = F.max_pool2d(x, 2)
20         # view函數將張量x變形成一維向量形式,總特征數不變,為全連接層做准備
21         x = x.view(x.size()[0], -1)
22         x = F.relu(self.fc1(x))
23         x = F.relu(self.fc2(x))
24         x = self.fc3(x)
25         return x

要用libtorch實現上述python代碼,首先得弄個清楚網絡中每一層的數據維度變換,如下圖,我都注釋了:

 1 # 詳細注釋    
 2 # reference:https://www.jianshu.com/p/45a26d278473    
 3 #************************************************************************************************
 4 class CNN(nn.Module):
 5     def __init__(self):
 6         nn.Model.__init__(self)
 7  
 8         self.conv1 = nn.Conv2d(1, 6, 5)  # 輸入通道數為1,輸出通道數為6
 9         self.conv2 = nn.Conv2d(6, 16, 5)  # 輸入通道數為6,輸出通道數為16
10         self.fc1 = nn.Linear(5 * 5 * 16, 120)
11         self.fc2 = nn.Linear(120, 84)
12         self.fc3 = nn.Linear(84, 10)
13 
14     #網絡整體結構:[conv + relu + pooling] * 2 + FC * 3
15     #原始輸入樣本的大小:32 x 32 x 1
16     def forward(self,x):
17         # 第一次卷積:使用6個大小為5 x 5的卷積核,故卷積核的規模為(5 x 5) x 6;
18         #卷積操作的stride參數默認值為1 x 1,32 - 5 + 1 = 28,並且使用ReLU對
19         #第一次卷積后的結果進行非線性處理,輸出大小為28 x 28 x 6;
20         x = self.conv1(x)
21         
22         # 第一次卷積后池化:kernel_size為2 x 2,輸出大小變為14 x 14 x 6;
23         x = F.relu(x)
24         x = F.max_pool2d(x, 2)
25         
26         # 第二次卷積:使用16個卷積核,故卷積核的規模為(5 x 5 x 6) x 16;
27         # 使用ReLU對第二次卷積后的結果進行非線性處理,14 - 5 + 1 = 10,
28         # 故輸出大小為10 x 10 x 16;
29         x = self.conv2(x)
30         
31         # 第二次卷積后池化:kernel_size同樣為2 x 2,輸出大小變為5 x 5 x 16;
32         x = F.relu(x)
33         x = F.max_pool2d(x, 2)
34         
35         # view函數將張量x變形成一維向量形式,總特征數不變,為全連接層做准備
36         x = x.view(x.size()[0], -1)
37         
38         #第一次全連接:將上一步得到的結果鋪平成一維向量形式,5 x 5 x 16 = 400,
39         #即輸入大小為400 x 1,W大小為120 x 400,輸出大小為120 x 1;
40         x = F.relu(self.fc1(x))
41         
42         # 第二次全連接,W大小為84 x 120,輸入大小為120 x 1,輸出大小為84 x 1;
43         x = F.relu(self.fc2(x))
44         
45         # 第三次全連接:W大小為10 x 84,輸入大小為84 x 1,輸出大小為10 x 1,即分別預測為10
46         x = self.fc3(x)
47         return x

網絡結構圖如下,

 

 對於其他網絡,在訓練完畢之后,一般的,也可以使用Netron可視化一下。

 

 

reference:

https://www.jianshu.com/p/45a26d278473    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM