神经网络实践之初始化权重参数

2019-10-18  本文已影响0人  此间不留白

前言

机器学习的应用层面中,已经了解了神经网络中的一些有关实践层面的一些参数包括方差,偏差,权重初始化,几种正则化的方法,和梯度检验等相关知识,本篇文章是深度学习课程的配套作业,将会通过代码实现深度学习应用层面的一些参数配置,提高神经网络的性能。

初始化权重参数

神经网络的第一项任务就是初始化权重参数,一些好的初始化权重参数有利于提高网络性能和加快网络训练速度。
利用python实现初始化权重的过程如下所示:

import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
# 绘图的一些默认参数
%matplotlib inline
plt.rcParams['figure.figsize'] = (7.0, 4.0) #设置图片m默认大小
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
def load_dataset():
    np.random.seed(1)
    train_X, train_Y = sklearn.datasets.make_circles(n_samples=300, noise=.05)
    np.random.seed(2)
    test_X, test_Y = sklearn.datasets.make_circles(n_samples=100, noise=.05)
    # 可视化数据
    plt.scatter(train_X[:, 0], train_X[:, 1], c=train_Y, s=40, cmap=plt.cm.Spectral);
    train_X = train_X.T
    train_Y = train_Y.reshape((1, train_Y.shape[0]))
    test_X = test_X.T
    test_Y = test_Y.reshape((1, test_Y.shape[0]))
    return train_X, train_Y, test_X, test_Y

对于神经网络模型,将会利用三种不同的方式实现权重参数的随机初始化,并比较这三种初始化方式的优劣,具体如下所示:

搭建神经网络模型

在完成参数初始化之前,首先完成整个网络模型的搭建。整个网络模型的结构是一个三层的神经网络,整个神经网络模型的实现过程,在一步步构建一个神经网络中有详细的介绍,在此不再多做说明。只考虑每次设置不同的权重参数初始化方式,比较模型性能。

def model(X, Y, learning_rate = 0.01, num_iterations = 15000, print_cost = True, initialization = "he"):
    """
   三层神经网络的模型结构: LINEAR->RELU->LINEAR->RELU->LINEAR->SIGMOID.
    
    参数:
    X -- 输入数据 矩阵形状是(2, 样本数量)
    Y -- 输出标签,1代表红点,0代表蓝点,向量形状 (1, 样本数量)
    learning_rate -- 梯度下降的学习率
    num_iterations -- 运行梯度下降的迭代次数
    print_cost -- 打印出每1000次迭代之后的损失
    initialization -- 初始化权重参数的方式选择
 ("zeros","random" or "he")
    
  返回值:模型学习的参数
    """
        
    grads = {}
    costs = [] # to keep track of the loss
    m = X.shape[1] # number of examples
    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):

        # 前向传播: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID.
        a3, cache = forward_propagation(X, parameters)
        
        # 计算损失
        cost = compute_loss(a3, Y)

        # 反向传播.
        grads = backward_propagation(X, Y, cache)
        
        # 参数更新
        parameters = update_parameters(parameters, grads, learning_rate)
        
        # 打印出每1000次迭代的损失
        if print_cost and i % 1000 == 0:
            print("Cost after iteration {}: {}".format(i, cost))
            costs.append(cost)
            
    # 绘制模型损失图像
    plt.plot(costs)
    plt.ylabel('cost')
    plt.xlabel('iterations (per hundreds)')
    plt.title("Learning rate =" + str(learning_rate))
    plt.show()
    
    return parameters

0初始化

0初始化,也就是将所有的权重参数设为0,具体实现代码如下所示:

def initialize_parameters_zeros(layers_dims):
    """
   参数说明:
    layer_dims -- 神经网络的层数,一个列表,其中的值代表这一层的单元数量,长度代表神经网络的层数
    Returns:
    返回一个存储参数的python字典
              
    WL -- 权重矩阵的形状 (layers_dims[L], layers_dims[L-1])
    bL -- 偏置向量的形状 (layers_dims[L], 1)
    """
    
    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

运行以上代码后,输出结果如下所示:


采用参数0初始化之后的梯度下降过程如下所示,可以看出,将初始化参数全部设为0之后,运行多次梯度下降算法之后,损失值一直保持不变,训练集和测试集的输出全是0,分类精度只有0.5,说明权重参数0初始化并不是一种可行的办法。

随机初始化

权重参数的随机初始化即是将每一层的权重参数w^{[l]}初始化为随机高斯分布(取值范围为(-1,1)),并将其乘以10,偏置参数b^{[l]}初始化为0,具体的实现代码如下所示:


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[l],1))
      

    return parameters

运行一下代码,并输出模型损失和性能如下所示:

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.83和0.86

输出集和测试集的输出分别如下所示:


运行以下代码,绘制出决策边界如下所示:

plt.title("Model with large random 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初始化

He初始化是2015年以它的发明者命名的,这种初始化方法采用了对权重使用比例因为的方法,也就是对权重参数w^{[l]}乘以比例因子\frac{1}{\sqrt{(n^{[l-1]})}}的方法,具体实现方式如下所示:


def initialize_parameters_he(layers_dims):
   
    np.random.seed(3)
    parameters = {}
    L = len(layers_dims) - 1 
     
    for l in range(1, L + 1):
      
        parameters['W' + str(l)] = np.random.randn(layers_dims[l],layers_dims[l-1])*np.sqrt(1/layers_dims[l-1])
        parameters['b' + str(l)] = np.zeros((layers_dims[l],1))
     
        
    return parameters

输出结果如下所示:

梯度下降过程中的迭代如下所示,随着迭代次数的增加,损失一直在降低,并且训练集和测试集的精度分别达到了99%和93%:


最后,绘制决策边界如下所示:

上一篇下一篇

猜你喜欢

热点阅读