深度学习 - 2019年2月2日

激活函数,数据预处理,权重初始化,内存计算

想法

快过年了,小更一下,这么久没更有点不安心,也祝大家新年快乐。

感觉对于机器学习来说,还是要多动笔算。

笔记

激活函数

Sigmoid的三个问题:

  • 饱和的神经元会让梯度消失;
  • 输出不是中心对称的,全都大于等于0,如果输入是全正或全负,就会限制梯度的更新方向(例如在二维上,梯度更新方向被限制为第一象限和第三象限,如果梯度的正确方向是第四象限,就会出现zig zag path)。这也是为什么要让输入中心化;
  • 计算复杂(不是主要原因,因为点乘占用大部分时间)。

tanh的问题:

  • 输出是中心化了,但是在神经元饱和时仍然会让梯度消失。

ReLu的问题:

  • 不会饱和,收敛速度比上述两个快6倍,但输出不是中心化的;
  • 在负半轴被称为”dead ReLU”(实践中有10%~20%的神经元都是死的,但对训练网络没有太大影响);
  • 有的人尝试初始化正的bias(e.g. 0.01)让ReLU刚开始的时候能激活更多的神经元,但在实践中不常用。

ReLU的变体:

  • Leaky ReLU f(x)=max(0.01x, x);
  • PReLU f(x)=max(αx, x);
  • ELU f(x)=max(α(exp(x)-1), x) 对输入噪音有更好的鲁棒性。

其他:

  • Maxout神经元 max(W1X+b, W2X+b),泛化了ReLU和Leaky ReLU,不常用,会让参数加倍。

数据预处理

对于图像数据只要中心化就可以了,AlexNet使用的是单张图像均值,VGGNet使用的是单通道均值。

权重初始化

如果只是使用 W = 0.01 * np.random.randn(D, H),会让权值和梯度消失的很快(因为逐层乘以很小的数,shrink的非常快);

如果用较大的权重初始化,神经元很快就会饱和,使用tanh激活函数的话,梯度还是会消失;

用Xavier初始化 W = np.random.randn(fan_in, fan_out) / np.sqrt(fan_in) 可以解决问题,但如果使用ReLU激活函数,实际上会使数据的方差减半(每层的输入减半),所以要改成除以 np.sqrt(fan_in / 2)

内存计算

VGGNet内存计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
INPUT: [224x224x3]        memory:  224*224*3=150K   weights: 0
CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*3)*64 = 1,728
CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*64)*64 = 36,864
POOL2: [112x112x64] memory: 112*112*64=800K weights: 0
CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*64)*128 = 73,728
CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*128)*128 = 147,456
POOL2: [56x56x128] memory: 56*56*128=400K weights: 0
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*128)*256 = 294,912
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824
POOL2: [28x28x256] memory: 28*28*256=200K weights: 0
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*256)*512 = 1,179,648
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296
POOL2: [14x14x512] memory: 14*14*512=100K weights: 0
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
POOL2: [7x7x512] memory: 7*7*512=25K weights: 0
FC: [1x1x4096] memory: 4096 weights: 7*7*512*4096 = 102,760,448
FC: [1x1x4096] memory: 4096 weights: 4096*4096 = 16,777,216
FC: [1x1x1000] memory: 1000 weights: 4096*1000 = 4,096,000

TOTAL memory: 24M * 4 bytes ~= 93MB / image (only forward! ~*2 for bwd)
TOTAL params: 138M parameters