习题4-2 试设计一个前馈神经网络来解决 XOR 问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用 ReLU 作为激活函数.
两个隐藏层神经元不容易成功,三个改改初始化的参数范围为mean=4,std=0.1必要容易成功
import torch
import torch.nn.functional as F
from torch.autograd import Variable
import matplotlib.pyplot as plt
from torch.nn.init import constant_, normal_, uniform_
#数据集:
torch.manual_seed(1)
x = torch.tensor([[1, 0], [0, 1],
[1, 1], [0, 0]]).type(torch.FloatTensor)
y = torch.tensor([1,1,0,0]).type(torch.LongTensor)
x, y = Variable(x), Variable(y)
#其实就是四个点对角为同一类
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0)
plt.show()
#定义单隐藏层类型
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output,mean_init=4.0, std_init=0.1, b_init=3.0):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
normal_(tensor=self.hidden.weight, mean=mean_init, std=std_init)
constant_(tensor=self.hidden.bias, val=b_init)
self.out = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.sigmoid(self.hidden(x))
x = self.out(x)
return x
#输入输出都为2,中间为三个神经元
net = Net(n_feature=2, n_hidden=3, n_output=2)
#打印网络初始化的参数和网络结构
for name, parms in net.named_parameters():
print('-->name:', name, ' -->grad_value:', parms.grad)
print(net)
#优化器和损失函数
optimizer = torch.optim.Adam(net.parameters(), lr=0.01, betas=(0.9, 0.99))
loss_func = torch.nn.CrossEntropyLoss()
#训练
for t in range(3000):
for name, parms in net.named_parameters():
print('-->name:', name, ' -->grad_value:', parms.grad)
print('输入:',x)
out = net.forward(x)
loss = loss_func(out, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if t % 10 == 0 or t in [3, 6]:
_, prediction = torch.max(F.softmax(out, dim=1), 1)
print('输出:',prediction)
pred_y = prediction.data.numpy().squeeze()
target_y = y.data.numpy()
accuracy = sum(pred_y == target_y) / 4.
print('Accuracy=%.2f' % accuracy)
if t == 1000: #以上参数在450第一次accuracy=1
print(t)
break
for i in range(0,30):
for j in range(0,30):
outt=net.forward(torch.tensor([i/30,j/30]))
_, pre = torch.max(F.softmax(outt),dim=0)
if pre.item()==0:
plt.scatter(i,j,c='r',s=1)
else:
plt.scatter(i,j,c='b',s=1)
plt.show()
-->name: hidden.weight -->grad_value: tensor([[-3.0028e-06, -2.8242e-06],
[-3.1055e-06, -2.5827e-06],
[-5.3309e-04, -5.1687e-04]])
-->name: hidden.bias -->grad_value: tensor([7.1569e-05, 7.2469e-05, 4.4869e-03])
-->name: out.weight -->grad_value: tensor([[ 1.6258e-05, 1.5901e-05, -2.3893e-03],
[-1.6230e-05, -1.5873e-05, 2.3893e-03]])
-->name: out.bias -->grad_value: tensor([-7.1432e-05, 7.1456e-05])
输入: tensor([[1., 0.],
[0., 1.],
[1., 1.],
[0., 0.]])
输出: tensor([1, 1, 0, 0])
Accuracy=1.00
450
习题4-3 试举例说明“死亡ReLU问题”,并提出解决方法.
实验里有说明将初值初始化为负值就很容易参数全迭代为零,因为容易在参数值为零和复数的时候停止更新出现参数值都为零的情况。初始化参数的时候将参数设置为远离零的正数。或者改用别的激活函数似使得激活函数在参数小于零的时候更加容易
习题4-7 为什么在神经网络模型的结构化风险函数中不对偏置b进行正则化?
资料上基本都是说对系数的正则能减少过拟合,仅仅是因为“缩放”比平移更容易导致过拟合么,正则化类似罚函数法是将约束问题变为了无约束问题,但是这种约束是先验的及人们认为w参数过大会带来问题,为什么?
form : https://towardsdatascience.com/regularization-techniques-for-neural-networks-379f5b4c9ac3
其主要意思是因为接近0的时候网络的非线性被从权重和激活函数的非线性区间的使用上被减少了,所以更加简单,
在这一点上看对偏置的正则化确实用处不大
习题 4-8 为什么在用反向传播算法进行参数学习时要采用随机参数初始化的方式而不是直接令 w= 0, 𝒃 = 0?
因为backWord的时候在反向传播的是用到中间变量的,并不是计算的导函数进行带入,中间变量为零导致导数为零无法更新。
习题4-9 梯度消失问题是否可以通过增加学习率来缓解?
一般上是不行,但是你要是说说增加某些层的学习率或者随机神经元的不好说,但是也不是用来解决梯度消失的,其实这种变化是算在梯度的计算还是学习率上不好说。因为参数更新的方法是(学习率和梯度的多元函数)学习率不是问题,梯度才是,梯度并不是消失了而是超出了小数的表达范围,而单纯增加学习率基本无用。