其实有些东西已经在sklearn的那个里面讲过了,这边补充点没讲过的吧
3.5 向量化实现的解释
以下面这个前向传播为例:
此时,W[1]就是一个矩阵,而x(i)都是列向量,那么就转化成了矩阵与向量的数学运算:
从上述例子不难看出,运用了向量算法就可以不通过循环来对多样本数据进行计算;
3.6 激活函数
常见的有这几种:
- sigmoid函数:
- tanh函数:
值域变成了(-1,1)
通过比较(在哪)发现,tanh比sigmoid要好用。例外:在二分类问题中,输出层的值为0/1,所以就得用sigmoid函数。除此以外的情况一般都是用tanh函数了;
共同缺点:在z特别大/小的情况下,导数就会一直趋近于0,降低了梯度下降的速度;
-
Relu函数:a = max(0,z)。这个函数现在用的最多;
选激活函数的经验法则:如果输出是 0、1 值(二分类问题),则输出层选择 sigmoid 函数,然后其它的所有单元都选择Relu函数;
Relu函数的优点:当𝑧是负值的时候,导数等于 0;
Leaky Relu:当𝑧是负值时,这个函数的值不是等于 0,而是轻微的倾斜。公式:𝑎 = 𝑚𝑎𝑥(0.01𝑧, 𝑧);
他们四个的图像如下图所示:
快速概括:
sigmoid 激活函数:除了输出层是一个二分类问题基本不会用它;
tanh 激活函数:tanh 是非常优秀的,几乎适合所有场合;
ReLu 激活函数:最常用的默认函数,,如果不确定用哪个激活函数,就使用 ReLu 或者Leaky ReLu;
3.9 神经网络的梯度下降
定义:其实就是通过导数找最低点从而找到最优点;
单隐层神经网络会有𝑊[1],𝑏[1],𝑊[2],𝑏[2]这些参数,还有个𝑛𝑥表示输入特征的个数,𝑛[1]表示隐藏单元个数,𝑛[2]表示输出单元个数;
训练参数需要做梯度下降,在训练神经网络的时候,随机初始化参数很重要,而不是初始化成全零。当你参数初始化成某些值后,每次梯度下降就是不断求导然后求解最优值;
-
正向传播:计算𝑧[1],𝑎[1],再计算𝑧[2],𝑎[2],最后得到 loss function;
-
反向传播:向后推算出𝑑𝑎[2],然后推算出𝑑𝑧[2],接着推算出𝑑𝑎[1],然后推算出𝑑𝑧[1]。我们不需要对𝑥求导,因为𝑥是固定的,我们也不是想优化x;
这些都是针对所有样本进行过向量化,𝑌是1 × 𝑚的矩阵;这里 np.sum 是 python 的 numpy 命令,axis=1 表示水平相加求和,keepdims 是防止python 输出那些古怪的秩数(𝑛, ),加上这个确保阵矩阵𝑑𝑏[2]这个向量输出的维度为(𝑛, 1)这样标准的形式;
其实向后推算出𝑑𝑎,z[2]的步骤可以合为:
3.11 随机初始化
通过随机初始化来解决参数w可能为0的情况:把 𝑊[1]设为np.random.randn(2,2)(生成高斯/正态分布),通常再乘上一个小的数,比如 0.01,这样把它初始化为很小的随机数;
𝑊[1] = 𝑛𝑝. 𝑟𝑎𝑛𝑑𝑜𝑚. 𝑟𝑎𝑛𝑑𝑛(2,2) ∗ 0.01
𝑏[1] = 𝑛𝑝. 𝑧𝑒𝑟𝑜𝑠((2,1))
𝑊[2] = 𝑛𝑝. 𝑟𝑎𝑛𝑑𝑜𝑚. 𝑟𝑎𝑛𝑑𝑛(2,2) ∗ 0.01
𝑏[2] = 0
选取0.01是为了防止其对应的激活函数的值在梯度很小的地方(两端),从而导致其无法进行优化
注意:当训练一个个非常非常深的神经网络时,会有比0.01更好的常数,在下一章讲;