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

前言

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

初始化权重参数

神经网络的第一项任务就是初始化权重参数,一些好的初始化权重参数有利于提高网络性能和加快网络训练速度。
利用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'
  • 加载数据集并可视化
    这些数据集是通过调用sklearn库生成的一些随机数据,这些随机数据按照颜色分为两类的二维随机数据,这些训练数据分为训练集和测试集,在二维图形中大致按照圆形分布,具体实现如下代码所示:
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)

注意:

  • 可以看出,刚开始迭代时,损失非常高,达到了正无穷,这是因为刚开始设置的权重参数非常大,对于sigmoid函数来说,很容易导致输出接近0或者1,从而导致最后的损失函数中的log(a^{[3]}) = log(0) =- inf

  • 初始化参数过大或者过小可能会导致梯度爆炸或者梯度消失,可能会导致训练速度减慢。

  • 如果对该网络进行更长时间的训练,训练精度可能会更高,但是会花费更长的时间。

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%:


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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容