版权为吴恩达老师所有,参考Koala_Tree的博客,部分根据自己实践添加
使用google翻译,部分手工翻译
你可能需要的参考资料https://pan.baidu.com/s/1ndJoW3dGyRDwJbAcjYWUxg
第1部分:初始化
精心选择的初始化可以:
- 加速梯度下降的收敛
- 增加梯度下降收敛到较低训练(和泛化)误差的几率
要开始,请运行以下单元格以加载要尝试分类的包和平面数据集。
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
from init_utils import sigmoid,relu,compute_loss,forward_propagation,backward_propagation
from init_utils import update_parameters,predict,load_dataset,plot_decision_boundary,predict_dec
plt.rcParams['figure.figsize'] = (7.0, 4.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
train_X,train_Y,test_X,test_Y=load_dataset()
1 - 神经网络模型
您将使用3层神经网络(已经为您实现)。以下是您将要试验的初始化方法:
- 零初始化 - initialization = "zeros"
在输入参数中进行设置。
- 随机初始化 - initialization = "random"
在输入参数中设置。这会将权重初始化为大的随机值。
- 初始化 - initialization = "he"
在输入参数中设置。这将权重初始化为根据He等人,2015年的论文缩放的随机值。
说明:请快速阅读下面的代码,然后运行它。在下一部分中,您将实现此model()
调用的三个初始化方法。
def model(X,Y,learning_rate=0.01,num_iterations=15000,print_cost=True,initialization="he"):
grads={}
costs=[]
m=X.shape[1]
layers_dims=[X.shape[0],10,5,1]
if initialization == "zeros":
parameters=initialize_parameters_zeros(layers_dims)
elif initialization == "random":
parameters=initialize_parameters_random(layers_dims)
elif initialization == "he":
parameters=initialize_parameters_he(layers_dims)
for i in range(0,num_iterations):
A3,cache=forward_propagation(X,parameters)
cost=compute_loss(A3,Y)
grads=backward_propagation(X,Y,cache)
parameters=update_parameters(parameters,grads,learning_rate)
if print_cost and i%1000 == 0:
print("Cost after iteration {}: {}".format(i,cost))
costs.append(cost)
plt.close()
plt.plot(costs)
plt.ylabel("cost")
plt.xlabel("iterations (per hundreds)")
plt.title("Learning rate ="+str(learning_rate))
plt.show()
return parameters
2 - 零初始化
在神经网络中初始化有两种类型的参数:
- 权重矩阵
- bias向量
练习:实现以下函数将所有参数初始化为零。稍后你会看到它不能很好地工作,因为它无法“破坏对称性”,但我们无论如何都要尝试它,看看会发生什么。使用具有正确形状的np.zeros((..,..))。
def initialize_parameters_zeros(layers_dims):
parameters={}
L=len(layers_dims)
for l in range(1,L):
parameters["W"+str(l)]=np.zeros((layers_dims[l],layers_dims[l-1]))
parameters["b"+str(l)]=np.zeros((layers_dims[l],1))
return parameters
parameters = initialize_parameters_zeros([3,2,1])
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
train_X,train_Y,test_X,test_Y=load_dataset()
运行以下代码,使用零初始化在15,000次迭代中训练模型。
parameters = model(train_X, train_Y, initialization = "zeros")
print ("On the train set:")
predictions_train = predict(train_X, train_Y, parameters)
print ("On the test set:")
predictions_test = predict(test_X, test_Y, parameters)
性能非常糟糕,成本并没有真正降低,算法的表现并不比随机猜测好。为什么?让我们看一下预测的细节和决策边界:
print ("predictions_train = " + str(predictions_train))
print ("predictions_test = " + str(predictions_test))
每个例子的模型预测为0。
通常,将所有权重初始化为零会导致网络无法破坏对称性。这意味着每层中的每个神经元都会学到同样的东西,对于每一层你也可以用训练神经网络,网络并不比线性分类器(如逻辑回归)更好。
你应该记住的:
- 权重应该随机初始化以打破对称性。
- 然而,初始化偏差是可以为零的。只要被随机初始化对称性就会被打破 。
3 - 随机初始化
要打破对称性,请随机初始化权重。在随机初始化之后,每个神经元然后可以继续学习其输入的不同功能。在本练习中,您将看到如果权重是随机初始化会发生的情况,但会看到非常大的值。
练习:实现以下函数将权重初始化为大的随机值(按* 10缩放),将偏差初始化为零。使用np.random.randn(..,..) * 10
的权重和np.zeros((.., ..))
的偏见。我们使用一个固定的np.random.seed(..)
来确保你的“随机”权重与我们的相匹配,所以不要担心如果运行几次你的代码总是为参数提供相同的初始值。
def initialize_parameters_random(layers_dims):
np.random.seed(3)
parameters={}
L=len(layers_dims)
for l in range(1,L):
parameters["W"+str(l)]=np.random.randn(layers_dims[l],layers_dims[l-1])*10
parameters["b"+str(l)]=np.zeros((layers_dims[1],1))
return parameters
parameters = initialize_parameters_random([3, 2, 1])
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
运行以下代码,使用随机初始化在15,000次迭代中训练模型。
parameters = model(train_X, train_Y, initialization = "random")
print ("On the train set:")
predictions_train = predict(train_X, train_Y, parameters)
print ("On the test set:")
predictions_test = predict(test_X, test_Y, parameters)
如果在迭代0之后看到“inf”作为成本,这是因为数值舍入; 一个更加数字复杂的实现将解决这个问题。但这对我们的目的来说并不值得担心。
无论如何,看起来你已经破坏了对称性,这会产生更好的结果。比以前该模型不再输出全0。
print (predictions_train)
print (predictions_test)
观察:
- 成本开始很高。这是因为对于大的随机值权重,最后一次激活(sigmoid)输出的结果非常接近0或1,对于某些示例,当它得到该示例错误时,它会导致该示例的非常高的损失。确实,当,损失变为无穷大。
- 初始化不良会导致梯度消失/爆炸,这也会降低优化算法的速度。
- 如果您训练此网络的时间越长,您就会看到更好的结果,但使用过大的随机数进行初始化会降低优化速度。
总结:
- 将权重初始化为非常大的随机值不能很好地工作。
- 希望使用小的随机值进行初始化会更好。重要的问题是:这些随机值应该多小?让我们在下一部分找到!
4 - He初始化
最后,尝试“He初始化”; 这是以第一作者He (et al., 2015)命名的。(如果您听说过“Xavier初始化”,这是类似的,除了Xavier初始化使用权重的缩放因子sqrt(1./layers_dims[l-1])
,He初始化使用sqrt(2./layers_dims[l-1])
。)
练习:使用He初始化实现以下函数来初始化参数。
提示:此功能与之前的功能类似initialize_parameters_random(...)
。唯一的区别是,不是将np.random.randn(..,..)乘
10,而是乘以,这是He初始化的建议对于使用ReLU激活的图层
def initialize_parameters_he(layers_dims):
np.random.seed(3)
parameters={}
L=len(layers_dims)
for l in range(1,L):
parameters["W"+str(l)]=np.random.randn(layers_dims[l],layers_dims[l-1])*np.sqrt(2.0/layers_dims[l-1])
parameters["b"+str(l)]=np.zeros((layers_dims[l],1))
return parameters
parameters = initialize_parameters_he([2, 4, 1])
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
运行以下代码,使用He初始化在15,000次迭代中训练模型。
parameters = model(train_X, train_Y, initialization = "he")
print ("On the train set:")
predictions_train = predict(train_X, train_Y, parameters)
print ("On the test set:")
predictions_test = predict(test_X, test_Y, parameters)
plt.title("Model with He initialization")
axes = plt.gca()
axes.set_xlim([-1.5,1.5])
axes.set_ylim([-1.5,1.5])
plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y)
观察:
- 具有He初始化的模型在少量迭代中非常好地分离蓝色和红色点。
5。结论
您已经看到了三种不同类型的初始化。对于相同数量的迭代和相同的超参数,比较是:
**模型** | **训练准确度** | **问题/评论** |
具有零初始化的3层NN | 50% | 未能破坏对称性 |
具有大量随机初始化的3层NN | 83% | 权值太大了 |
He初始化的3层NN | 99% | 推荐的方法 |
你应该记住:
- 不同的初始化导致不同的结果
- 随机初始化用于打破对称性并确保不同的隐藏单元可以学习不同的东西
- 不要初始化为太大的值
- He的初始化对于ReLU激活的网络具有很好的效果。