龙空技术网

「pytorch」 落地模型的必要步骤:层层核对

老师明明可以靠颜值 79

前言:

而今大家对“c语言打印二进制用什么”大致比较珍视,小伙伴们都需要分析一些“c语言打印二进制用什么”的相关内容。那么小编同时在网上网罗了一些有关“c语言打印二进制用什么””的相关知识,希望各位老铁们能喜欢,朋友们快快来了解一下吧!

最近在写一个用c语言落地神经网络的落地库,模型的前向计算写完以后,就需要读入一张图片,逐层地核对模型的前向计算过程了。

我先使用pytorch训练了一个lenet模型,在mnist上。

我这里需要使用pytorch把每一层的详细予以显示,并将c语言的输出结果与其核对。

所以,我需要将修改pytorch的相关代码,用以显示各层中间结果,或者能够完成我自己逐层检查,修改后的代码如下:

51行--56行的 forward layer实现了单独运行某一层。

其中x是输入的feature map,out是输出的feature map

i表示层序号,flag表示使用self.conv还是self.fc.

当 i=0,flag=0时,就表示使用self.conv中的第一个层nn.Conv2d进行计算

当 i=0,flag=0时,就表示使用了self.conv中的第一个层nn.relu进行计算

有了这个函数, 我们就可以随时调用网络中的每一层进行测试了。

现读入一张mnist测试集中的图片img,如下:

c中读出的图片

从其大概的形状可以看出,这是一个数字7.

pytorch中读出的图片。

然后使用:

output_1=model.forward_layer(img,0,0)

来使用self.conv中的第一个层nn.Conv2d对图片进行卷积。

结果:

28x28的矩阵,我们得到了6个channel。

矩阵的元素有点多,为了验证方便,我们只查看每个feature map的第6行的数据。

output_1[:,0,:,:].flatten()[28*5:28*6]

channel=0的第6行数据

channel=1的第6行

channel=5的第6行

这些数据放在这里待用。

我们再继续运行模型后面的所有层:

第二个层relu:

output_1_relu=model.forward_layer(output_1,1,0)

第三个层maxpool2d:

output_1_maxpool2d=model.forward_layer(output_1_relu,2,0)

第四个层conv2d:

output_2=model.forward_layer(output_1_maxpool2d,3,0)

第五个层relu:

 output_2_relu=model.forward_layer(output_2,4,0)

第六个层maxpool2d:

output_2_maxpool2d=model.forward_layer(output_2_relu,5,0)

第七个层fc:

output_2_maxpool2d_flat=output_2_maxpooling.view(output_2_maxpool2d.size(0), -1)fc1=model.forward_layer(output_2_maxpool2d_flat,0,1)

这里先把output_2_maxpool2d的维度进行变换:

然后再输入到fc层中进行计算。注意要,我们访问self.fc的第一个层nn.Linear(400,120),所以令flag=1,index=0.

第八个层fc:

 fc2=model.forward_layer(fc1,1,1)

第九个层fc:

 fc3=model.forward_layer(fc2,2,1)

这个代码中,3个fc层连起来用,作用相当于一个fc层,应该在fc之后,加上激活函数层的。

这样,我们就得到了8个层的输出featuremap了,分别存储在fc3,fc2,fc1,output_2_maxpool2d,output_2_relu,output_2,output_1_mampool2d,output_1_relu,output_1里。

我们可以随时查看每一层计算的输出结果了。

比如:

第8层的输出结果为:

而我c代码的前向计算过程的第八层的输出结果为:

可以看到,两者结果一模一样。

这说明,我c代码中实现的卷积层,全连接层,relu层等都是正确的。

将这些层组合成网络时,在第八层之前,其中的网络参数,比如层的连接方式,每个卷积层的padding,stride等参数也都是正确无误的。

我们再看最有一层的输出:

pytorch:

c:

观察一下,发现数值对,但是顺序不对。这是因为我c语言中做了排序。

到这里,这个c语言的落地代码实现了。并且验证一个简单的模型后,证明代码基本正确

继续验证几张图片看看:

indexes_result的最大需要为1,也就是将图片识别为1.

img矩阵看起来,也就是1了,说明识别正确。

这个是0,但是有点显示不出来。稍微改一下显示方式,就容易看出来了。

用sign函数处理一下显示问题

处理后:

再看二张:

看起来,测试结果还行,随便找了测试库中的图片进行识别,都是正确的。

后续的工作做一些优化了,比如指令集优化,调用一些加速库实现速度优化。加速库包括gpu的矩阵计算包,mkl等。

当然,一旦调用加速包,就有依赖了,移植起来就比较麻烦了。

所以,不用任何加速库写的前向计算库,还是比较有价值的:容易加速,容易修改,容易扩展。

这个c的部署库,再完善一段时间就可以开源。

c语言部署库的价值在于:移植方便,成本低,无论什么平台上,哪怕你算力单薄如单片机,哪怕你发展迅速如web前端,都很容调用c的二进制库。

更别说:python,lua,c++,php等语言了。

标签: #c语言打印二进制用什么

上一篇Golang 入门之指针(三)

下一篇没有了