《神经网络与深度学习》(邱锡鹏):
https://nndl.github.io/
《神经网络与深度学习》官方课后习题交流:
https://github.com/nndl/solutions
习题4-1 对于一个神经元 σ ( w T x + b ) \sigma(w^Tx+b) σ(wTx+b),并使用梯度下降优化参数 w w w时,如果输入恒大于0,其收敛速度会比零均值化的输入更慢.
习题 4-2 试设计一个前馈神经网络来解决 XOR问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用ReLU作为激活函数.
习题4-3 试举例说明“死亡ReLU问题”,并提出解决方法.
习题4-4 计算Swish函数和GELU函数的导数. 参见第4.1.3节.
习题 4-5 如果限制一个神经网络的总神经元数量(不考虑输入层)为 + 1,输入层大小为 M 0 M_0 M0,输出层大小为 1,隐藏层的层数为 ,每个隐藏层的神经元数量为 N L \dfrac{N}{L} LN ,试分析参数数量和隐藏层层数的关系.
习题 4-6 证明通用近似定理对于具有线性输出层和至少一个使用 ReLU 激活函数的隐藏层组成的前馈神经网络,也都是适用的. 参见定理4.1.
习题4-7 为什么在神经网络模型的结构化风险函数中不对偏置进行正则化?
习题 4-8 为什么在用反向传播算法进行参数学习时要采用随机参数初始化的方式而不是直接令 w w w= 0, = 0?
习题4-9 梯度消失问题是否可以通过增加学习率来缓解
4-1:
零均值化的输入,使得神经元在0附近,sigmoid函数在零点处的导数最大,所有收敛速度最快。当输入为非零均值化的时候, w w w的梯度要么大于0要么小于0,权重更新发生抖动,影响梯度下降速度。所以输入x恒大于0,其收敛速度比零均值化的输入更慢。
4-2:
X O R 问 题 XOR问题 XOR问题
x 1 x1 x1 | x 2 x2 x2 | Output |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
import numpy as np
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
#input and output
X=np.array([[0,0],[0,1],[1,0],[1,1]])
Y=np.array([[0],[1],[1],[0]])
x=tf.placeholder(dtype=tf.float32,shape=[None,2])
y=tf.placeholder(dtype=tf.float32,shape=[None,1])
#weight
w1=tf.Variable(tf.random_normal([2,2]))
w2=tf.Variable(tf.random_normal([2,1]))
#bias
b1=tf.Variable([0.1,0.1])
b2=tf.Variable(0.1)
#relu activation function
h=tf.nn.relu(tf.matmul(x,w1)+b1)
output=tf.matmul(h,w2)+b2
#loss and Adam optimizer
loss=tf.reduce_mean(tf.square(output-y))
train=tf.train.AdamOptimizer(0.05).minimize(loss)
with tf.Session() as session:
session.run(tf.global_variables_initializer())
for i in range(2000):
session.run(train,feed_dict={
x:X,y:Y})
loss_=session.run(loss,feed_dict={
x:X,y:Y})
if i%50 == 0:
print("step:%d,loss:%.3f"%(i,loss_))
print("X:%r"%X)
print("Pred:%r"%session.run(output,feed_dict={
x:X}))
运行结果:
step:0,loss:1.112
step:50,loss:0.144
step:100,loss:0.011
step:150,loss:0.000
step:200,loss:0.000
step:250,loss:0.000
step:300,loss:0.000
step:350,loss:0.000
step:400,loss:0.000
step:450,loss:0.000
step:500,loss:0.000
step:550,loss:0.000
step:600,loss:0.000
step:650,loss:0.000
step:700,loss:0.000
step:750,loss:0.000
step:800,loss:0.000
step:850,loss:0.000
step:900,loss:0.000
step:950,loss:0.000
step:1000,loss:0.000
step:1050,loss:0.000
step:1100,loss:0.000
step:1150,loss:0.000
step:1200,loss:0.000
step:1250,loss:0.000
step:1300,loss:0.000
step:1350,loss:0.000
step:1400,loss:0.000
step:1450,loss:0.000
step:1500,loss:0.000
step:1550,loss:0.000
step:1600,loss:0.000
step:1650,loss:0.000
step:1700,loss:0.000
step:1750,loss:0.000
step:1800,loss:0.000
step:1850,loss:0.000
step:1900,loss:0.000
step:1950,loss:0.000
X:array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
Pred:array([[-1.3168901e-06],
[ 9.9999815e-01],
[ 9.9999756e-01],
[-6.3823536e-06]], dtype=float32)
参考链接:《ML–XOR问题》https://blog.csdn.net/V_lq6h/article/details/88928592?utm_source=app
4-3:
在反向传播过程中,如果学习率比较大,一个很大的梯度经过ReLU神经元,可能会导致ReLU神经元更新后的偏置和权重是负数,进而导致下一轮正向传播过程中ReLU神经元的输入是负数,输出是0。由于ReLU神经元的输出为0,在后续迭代的反向过程中,该处的梯度一直为0,相关参数不再变化,从而导致ReLU神经元的输入始终是负数,输出始终为0。即为“死亡ReLU问题”
解决方法:
使用Leaky ReLU/PReLU、ELU函数或者Softplus函数替换。
4-4:Swish函数的导数:
d S w i s h ( x ) d x = d x e − β x + 1 d x = ( 1 + e − β x ) − x ( 1 + e − β x ) ( e − β x + 1 ) 2 \frac {dSwish(x)} {dx}= \frac{d \frac {x}{ e^{-\beta x }+1}} {dx}=\frac{(1+e^{-\beta x})-x(1+e^{-\beta x})} { {(e^{-\beta x} +1)}^2} dxdSwish(x)=dxde−βx+1x=(e−βx+1)2(1+e−βx)−x(1+e−βx)
= ( x + 1 ) e − β x + 1 ( e − β x + 1 ) 2 =\frac {(x+1){e^{-\beta x}}+1} { {(e^{-\beta x}+1)}^2} =(e−βx+1)2(x+1)e−βx+1
GELU函数导数:
d G E L U ( x ) d x = x d P ( X ⩽ x ) d x + P ( X ⩽ x ) \frac {dGELU(x)} {dx}=\frac {xdP(X \leqslant x)} {dx}+P(X\leqslant x) dxdGELU(x)=dxxdP(X⩽x)+P(X⩽x)
= x e − x 2 2 2 π + ϕ ( x ) = \frac {xe^{-{\frac { {x^2}} 2}}} {\sqrt{2\pi}}+\phi(x) =2πxe−2x2+ϕ(x)
4-5:
参数数量与与隐藏层数L的关系为:
p a r a m s = ( N + 1 ) + ( L − 1 ) ( N L ) 2 + M ∗ N L + N L params=(N+1)+(L-1)(\frac NL)^2+\frac {M*N}L+\frac NL params=(N+1)+(L−1)(LN)2+LM∗N+LN
参考代码:
from tensorflow import keras
from tensorflow.keras import layers
L=3
N=18
M=3
network=keras.Sequential([])
for _ in range(L):
network.add(layers.Dense(N/L))
network.add(layers.ReLU())
network.add(layers.Dense(1))
network.build(input_shape=(None,M))
network.count_params()
输出结果为115个参数
参考链接:https://github.com/nndl/solutions/issues/12
4-6:
通用近似定理(Universal Approximation Theorem)告诉我们:一个仅有单隐藏层的神经网络。在神经元个数足够多的情况下,通过非线性的激活函数,足以拟合任意函数。这使得我们在思考神经网络的问题的时候,不需要考虑:我的函数是否能够用神经网络拟合,因为它永远可以做到——只需要考虑如何用神经网络做到更好的拟合。
发现了一个博客在这里写的很好:
https://blog.csdn.net/zpcxh95/article/details/69952020
这里给出了可视化的证明:
http://neuralnetworksanddeeplearning.com/chap4.html
以及原文地址:
http://www.dartmouth.edu/~gvc/Cybenko_MCSS.pdf
4-7:
在神经网络模型的结构化风险函数中加入正则化项,可以避免过拟合,对于偏置 b b b进行正则化对于防止过拟合没有什么影响。
4-8:
反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个 w w w对总的损失函数的影响,即损失函数对每个 w w w的偏导。根据 w w w的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。当直接令 w w w=0,b=0时,会让下一层神经网络中所有神经元进行着相同的计算,具有同样的梯度,同样权重更新。
参考资料:《智能计算系统》
4-9:
在一定程度上可以缓解。适当增大学习率可以使学习率与导数相乘结果变大,缓解梯度消失;过大学习率可能梯度巨大,导致梯度爆炸。
本文仅供参考互相学习交流,水平有限,如果发现错误欢迎您的指正!谢谢!部分答案来源于网络,如有侵权,请联系我删除!
参考资料:
【1】通用近似定理问题:https://blog.csdn.net/zpcxh95/article/details/69952020
【2】XOR问题:https://blog.csdn.net/V_lq6h/article/details/88928592?utm_source=app
【3】《智能计算系统》(陈云霁,李玲,李威,郭崎,杜子东 ,2020)
【4】参数与隐藏层数问题:https://github.com/nndl/solutions/issues/12
(etc.)