pytorch设置每一层网络的数据类型为float32 pytorch 网络参数量_conv2d参数


我们都知道,卷积神经网络的参数统计是很重要的,关于一个网络的容量大小与性能评价。pytorch的参数统计与层结构的打印可以用torchsummary 来统计,但是前几天在写网络的时候遇到了共享参数问题,再用torchsummary的时候就出现了问题,经过进一步实验,终于找到了正确统计参数的规律。

先以实例进行讲解:

case1: 无参数共享(最常见)


# -*- coding: utf-8 -*-


输出:


----------------------------------------------------------------


首先说一下 count_parameters(model) 函数的意思:


return


其中model.parameters()是取得模型的参数,if p.requires_grad 是可求导参数的情况下。其实在定义网络的时候基本上都是可求导参数,包括卷积层参数,BN层参数,所以我们统计可求导参数。然后numel()是统计numpy数组里面的元素的个数。这样一来就很明显了,我们定义了两个3x3卷积层,而且没有bias,所以参数个数是3x3x2=18个,网络结构是两层。到这里都对!然后我们再看看case2.

case2: 参数共享


# -*- coding: utf-8 -*-


输出:


----------------------------------------------------------------


看看出现了什么?,parameter_count统计的是9个参数,而torchsummary统计的是18个参数,为什么会出现这种问题?要想找到原因肯定是要先了解我们的网络是怎么构建的,从网络构建可以看出,我们只初始化了一个卷积层对象——conv1,然后在网络构建时(forward里面),重复调用了conv1,这样做是因为:根据pytorch官方的教程,这样可以实现参数共享,也就是Conv2d-1 和Conv2d-2 层共享了conv1的参数。也就是其实我们只用了一个卷积层的参数,所以parameters_count 计算的是对的,但是torchsummary为什么计算成了18? 那是因为torchsummary 计算时是先把层结构打印下来,然后再统计对各个层的参数求和,这样一来,它不会区分conv2d-1和conv2d-2里面的参数是否相同,只是根据结构都打印且统计了出来。所以在遇到参数共享的时候,torchsummary统计的是不正确的!但是parameter_count 统计的就一定正确吗?并不是!请看下面的例子。

case3: 初始化了层,却没有调用


# -*- coding: utf-8 -*-


输出:


----------------------------------------------------------------


可以看到,我们构建网络的时候和case2是相同的,都是共享conv1的参数,但是与case2不同的是我们也初始化了一个conv2的卷积层对象,但是没有用来构建网络,就放在了那里,这个时候parameters_count也出现了错误,错误的计算成了18,那是因为你在BaseNet类里多初始化了conv2,即使你没有在forward里面调用,但是它也算在你的model.parameters()里面,所以总参数变成了18,这个时候torchsummary的18 和parameters_count的18是不同的意思,但是都是错的,对于你本来想构建的网络来说。如果不信的话可以看看下面这个例子,case3,case4做一下对比就知道了!

case4:


# -*- coding: utf-8 -*-


输出:


----------------------------------------------------------------


总结:

如果没有共享参数的情况出现尽量用torchsummary来计算,如果出现了共享参数的情况,那就用parameters_count的计算方式,这个时候要注意尽量将没有用到的层对象注释干净,这样才能计算出正确的参数来!