深度学习模型部署概述


一般地,当我们在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