前言:
而今大家对“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,如下:
从其大概的形状可以看出,这是一个数字7.
然后使用:
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]
这些数据放在这里待用。
我们再继续运行模型后面的所有层:
第二个层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,但是有点显示不出来。稍微改一下显示方式,就容易看出来了。
处理后:
再看二张:
看起来,测试结果还行,随便找了测试库中的图片进行识别,都是正确的。
后续的工作做一些优化了,比如指令集优化,调用一些加速库实现速度优化。加速库包括gpu的矩阵计算包,mkl等。
当然,一旦调用加速包,就有依赖了,移植起来就比较麻烦了。
所以,不用任何加速库写的前向计算库,还是比较有价值的:容易加速,容易修改,容易扩展。
这个c的部署库,再完善一段时间就可以开源。
c语言部署库的价值在于:移植方便,成本低,无论什么平台上,哪怕你算力单薄如单片机,哪怕你发展迅速如web前端,都很容调用c的二进制库。
更别说:python,lua,c++,php等语言了。
标签: #c语言打印二进制用什么