目录
习题4-2
试设计一个前馈神经网络来解决XOR问题,要求该前馈神经网络具有两个隐藏层和一个输出神经元,并使用ReLU 作为激活函数
XOR问题:即异或问题,可以看成单位正方形的四个角,输入模式为(0,0),(0,1),(1,1),(1,0)。\n\n输入模式(0,0)和(1,1)是单位正方形的两个相对的角,但它们产生相同的结果是0。另一方面,输入模式(0,1)和(1,0)是单位正方形另一对相对的角,但是它们属于类1。很显然,无法找出一条直线作为决策边界可以使(0,0)和(1,1)在一个区域,而(1,0)和(0,1)在另一个区域。
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)
习题4-3
试举例说明“死亡ReLU问题”,并提出解决方法
“死亡ReLU问题”是指参数再一次不恰当的更新后,使得隐藏层神经元的输入全部为负数,ReLU函数无法对其激活,那么神经元自身参数的梯度永远都是0,以后的训练过程中永远都不会被激活。
举例:以二分类问题为例,同时采用交叉熵作为Loss Function:
是真实值 是预测值
当与
不同时,一个0一个1,L为无穷大
当与
相同时,L为0
当遇到负例时,应该变小,所以
应该变小,此时,若Learning Rate 设置过大,则会导致
突然变得非常小,以至于输出
为负数,结果ReLU激活函数后无法激活,后续将不会得到更新,导致了死亡结点。
解决方法:使用Leaky ReLU、PReLU、ELU、Softplus等激活函数代替ReLU
习题4-7
为什么在神经网络模型的的结构化风险函数中不能对偏置b进行正则化?
正则化主要是为了防止过拟合,而过拟合一般表现为模型对于输入的微小改变产生了输出的较大差异,这主要是由于有些参数 w 过大的关系,通过对 ||w|| 进行惩罚,可以缓解这种问题。而如果对 ||b|| 进行惩罚,其实是没有作用的,因为在对输出结果的贡献中,参数b对于输入的改变是不敏感的,不管输入改变是大还是小,参数b的贡献就只是加个偏置而已。
或者说,模型对于输入的微小改变产生了输出的较大差异,这是因为模型的“曲率”太大,而模型的曲率是由 w 决定的, b 不贡献曲率(对输入进行求导, b 是直接约掉的)。
习题4-8
为什么在用反向传播算法进行参数学习是要采用随机参数初始化的方式而不是直接令W=0,b=0?
反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w 对总的损失函数的影响,即损失函数对每个w 的偏导。根据w 的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。当直接令w =0,b=0时,会让下一层神经网络中所有神经元进行着相同的计算,具有同样的梯度,同样权重更新。
习题4-9
梯度消失问题是否可以通过增加学习率来缓解?
梯度消失问题是由于激活函数为类似于sigmoid与tanh,其值太大或太小时导数都趋于0;并且在深层神经网络中,误差反向传播时,传播到前几层时梯度信息也会很小。问题是可否通过增大学习率来增大梯度,以至于梯度信息可以在更新时变大。
梯度消失问题不可以通过增加学习率来缓解,增大学习率带来的缺陷会比梯度消失问题更加严重,学习率变大时,很容易使得参数跳过最优值点,然后梯度方向改变,导致参数优化时无法收敛。
ref:
https://blog.csdn.net/weixin_43650749/article/details/106109163
为什么Relu会导致死亡节点_u014296502的专栏-CSDN博客
Why can't we handle vanishing gradient problem in neural nets using large step sizes?
总结:
通过从此实验最大的收货是对死亡ReLU问题有了更深的了解,通过查阅资料知道了死亡节点产生的原因 追本溯源通过改变激活函数来解决Dead ReLU现象