如何计算神经网络的参数量以及创建多隐藏层网络(总参数量接近)

计算神经网络的参数量

对于全连接层来说,其单层的参数量为 (输入维度 + 1) * 该层神经元个数。这是因为全连接层的每个神经元都需要一个 权重向量 和一个 偏置值 来计算其输出,权重向量 的长度就是 输入维度偏置值 是一个标量。

若当前 networkhidden_layershidden layer,其中每层 hidden_layerhidden_dim 维,则有:

T o t a l _ p a r a m s = ( i n p u t _ d i m + 1 ) ∗ h i d d e n _ d i m + ( h i d d e n _ d i m + 1 ) ∗ h i d d e n _ d i m ∗ ( h i d d e n _ l a y e r s − 1 ) + ( h i d d e n _ d i m + 1 ) ∗ o u t p u t _ d i m Total\_params = (input\_dim + 1) * hidden\_dim + (hidden\_dim + 1) * hidden\_dim * (hidden\_layers - 1) + (hidden\_dim + 1) * output\_dim Total_params=(input_dim+1)hidden_dim+(hidden_dim+1)hidden_dim(hidden_layers1)+(hidden_dim+1)output_dim

对于一个神经网络来说,其总参数量就是所有全连接层的参数量之和。例如,如果我们有一个神经网络,它有一个输入层(输入维度为 4),一个隐藏层(隐藏层神经元个数为 5),和一个输出层(输出维度为 3),那么它的总参数量就是:

输入层到隐藏层的全连接层: ( 4 + 1 ) ∗ 5 = 25 (4 + 1) * 5 = 25 (4+1)5=25
隐藏层到输出层的全连接层: ( 5 + 1 ) ∗ 3 = 18 (5 + 1) * 3 = 18 (5+1)3=18
总参数量: 25 + 18 = 43 25 + 18 = 43 25+18=43

图源自《动手学深度学习》

创建多隐藏层的网络

那么该如何创建多隐藏层的网络,顺便打印参数量呢?
这里举个例子说明:

import torch.nn as nn

input_dim = 8
hidden_dim = 16
hidden_layers = 2
output_dim = 8

# 为了简洁,舍去了 Relu()
network = nn.Sequential(
            nn.Linear(input_dim, hidden_dim),
            # 在函数的调用中,一个 * 表示将一个序列展开为单独的位置参数,这一行代码是列表推导,最终的表现是重复生成多个 hidden layer
            *[nn.Linear(hidden_dim, hidden_dim) for _ in range(hidden_layers-1)], 
            nn.Linear(hidden_dim, output_dim)
        )
# 打印总参数量
total_params = (
    (input_dim+1) * hidden_dim +
    (hidden_dim + 1) * hidden_dim * (hidden_layers - 1) +
    (hidden_dim + 1) * output_dim
)
print(f'Total params: {total_params}')
>> Total params: 552

当然,实际上你可以直接使用 pytorch 中的函数进行打印

total_params = sum(param.numel() for param in network.parameters())
print(f'Total params: {total_params}')
>> Total params: 552

进一步的,如果你想查看各层分别的参数量,你可以使用以下代码

for name, param in network.named_parameters():
    print(name, param.numel())
0.weight 128
0.bias 16
1.weight 256
1.bias 16
2.weight 128
2.bias 8

其中 weight 对应的是权重,bias是偏差。

构建总参数量接近的神经网络

这个视频片段能够让你更好的了解 Deep Network 和 Shallow network 的差异:Why Deep Learning?

已知神经网络的总参数量由下式给出:
T o t a l _ p a r a m s = ( i n p u t _ d i m + 1 ) ∗ h i d d e n _ d i m + ( h i d d e n _ d i m + 1 ) ∗ h i d d e n _ d i m ∗ ( h i d d e n _ l a y e r s − 1 ) + ( h i d d e n _ d i m + 1 ) ∗ o u t p u t _ d i m Total\_params = (input\_dim + 1) * hidden\_dim + (hidden\_dim + 1) * hidden\_dim * (hidden\_layers - 1) + (hidden\_dim + 1) * output\_dim Total_params=(input_dim+1)hidden_dim+(hidden_dim+1)hidden_dim(hidden_layers1)+(hidden_dim+1)output_dim

为了符号简便,做以下简写:

  • i = i n p u t _ d i m i = input\_dim i=input_dim
  • o = o u t p u t _ d i m o = output\_dim o=output_dim
  • l = h i d d e n _ l a y e r s l = hidden\_layers l=hidden_layers
  • d = h i d d e n _ d i m d = hidden\_dim d=hidden_dim

有:
T o t a l _ p a r a m s = ( i + 1 ) ∗ d + ( d + 1 ) ∗ d ∗ ( l − 1 ) + ( d + 1 ) ∗ o Total\_params = (i + 1) * d + (d + 1) * d * (l - 1) + (d + 1) * o Total_params=(i+1)d+(d+1)d(l1)+(d+1)o

进一步的,将其化成一元二次方程的形式,其中 d d d 为自变量:
T o t a l _ p a r a m s = ( l − 1 ) ∗ d 2 + ( i + o + l ) ∗ d + o Total\_params = (l - 1) * d^2 + (i + o + l) * d + o Total_params=(l1)d2+(i+o+l)d+o

假设 i , o , l , d i, o, l, d i,o,l,d 均为已知量,现在需要求:在输入输出维度不变的情况下,当 d e s t _ h i d d e n _ l a y e r s dest\_hidden\_layers dest_hidden_layers 给定时,隐藏层的维数等于多少才能让两个网络的总参数量接近?( d e s t dest dest 代指我们要计算的目标网络)

同样的,做以下简写:

  • l d = d e s t _ h i d d e n _ l a y e r s l_d = dest\_hidden\_layers ld=dest_hidden_layers
  • d d = d e s t _ h i d d e n _ d i m d_d = dest\_hidden\_dim dd=dest_hidden_dim

则有:
d e s t _ T o t a l _ p a r a m s = ( l d − 1 ) ∗ d d 2 + ( i + o + l d ) ∗ d d + o dest\_Total\_params = (l_d - 1) * d_d^2 + (i + o + l_d) * d_d + o dest_Total_params=(ld1)dd2+(i+o+ld)dd+o

d e s t _ T o t a l _ p a r a m s = T o t a l _ p a r a m s dest\_Total\_params = Total\_params dest_Total_params=Total_params
( l d − 1 ) ∗ d d 2 + ( i + o + l d ) ∗ d d + o = ( l − 1 ) ∗ d 2 + ( i + o + l ) ∗ d + o ⇓ ( l d − 1 ) ∗ d d 2 + ( i + o + l d ) ∗ d d − ( l − 1 ) ∗ d 2 − ( i + o + l ) ∗ d = 0 (l_d - 1) * d_d^2 + (i + o + l_d) * d_d + o = (l - 1) * d^2 + (i + o + l) * d + o\\\Downarrow\\ (l_d - 1) * d_d^2 + (i + o + l_d) * d_d - (l - 1) * d^2 - (i + o + l) * d = 0 (ld1)dd2+(i+o+ld)dd+o=(l1)d2+(i+o+l)d+o(ld1)dd2+(i+o+ld)dd(l1)d2(i+o+l)d=0

这实际上是一个一元二次方程,其中 d d d_d dd 为自变量,其余均已知,可当作常数看待。令
a = l d − 1 , b = i + o + l d , c = − ( l − 1 ) ∗ d 2 − ( i + o + l ) ∗ d a = l_d - 1,\\ b = i + o + l_d,\\ c = - (l - 1) * d^2 - (i + o + l) * d a=ld1b=i+o+ldc=(l1)d2(i+o+l)d
则上式可化成 a ∗ d d 2 + b ∗ d d + c = 0 a * d_d^2 + b *d_d + c = 0 add2+bdd+c=0
由一元二次方程的求根公式
y = − b ± b 2 − 4 a c 2 a y = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} y=2ab±b24ac

d d = − ( i + o + l d ) ± ( i + o + l d ) 2 − 4 ( l d − l ) ( − ( ( l − 1 ) ∗ d 2 − ( i + o + l ) ∗ d ) ) 2 ( l d − l ) d_d = \frac{-(i+o+l_d) \pm \sqrt{(i+o+l_d)^2 - 4(l_d-l)(-((l - 1) * d^2 - (i + o + l) * d))}}{2(l_d-l)} dd=2(ldl)(i+o+ld)±(i+o+ld)24(ldl)(((l1)d2(i+o+l)d))

你可以通过调用下方代码中的 get_dest_dim() 获取目标网络隐藏层应该设置的维度。

def get_dest_dim(input_dim, output_dim, hidden_layers, dest_hidden_layers, hidden_dim):
	'''获取目标网络隐藏层的维度(总参数量接近于原网络)'''
    # 计算一元二次方程的系数 a,b,c
    a = dest_hidden_layers - 1  # a = l_d - 1
    b = input_dim + output_dim + dest_hidden_layers  #  b = i + o + l_d
    c = - (hidden_layers - 1) * (hidden_dim ** 2) - (input_dim + output_dim + hidden_layers) * hidden_dim  # c = - (l - 1) * (d ** 2) - (i + o + l) * d
    
    # 计算分子中的平方根部分,即 b^2-4ac
    sqrt_part = (b ** 2) - 4 * a * c
    
    # 计算两个解,一个是加号,一个是减号,即(-b±√(b^2-4ac))/(2a)
    d_d_plus = (-b + sqrt_part**(0.5)) / (2 * a)
    d_d_minus = (-b - sqrt_part**(0.5)) / (2 * a)
    
    # 返回两个解的元组
    return (d_d_plus, d_d_minus)

# 设置你想要的目标网络隐藏层数量
dest_hidden_layers = 2

# 获取对应的维数
dest_hidden_dim, _ = get_dest_dim(input_dim, output_dim, hidden_layers, dest_hidden_layers, hidden_dim)
print(f"若将隐藏层网络层数改为: {dest_hidden_layers},则维数应当改为: {round(dest_hidden_dim)}",)

参考链接:
图源自《动手学深度学习》
HW02 的 Sample code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hoper.J

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值