【深度学习:进阶篇】--2.3.深度学习正则化

article/2025/8/22 23:58:58

学习目标

  • 目标
    • 了解偏差与方差的意义
    • 知道L2正则化与L1正则化的数学意义
    • 知道Droupout正则化的方法
    • 了解早停止法、数据增强法的其它正则化方式
  • 应用

目录

学习目标

1 偏差与方差

1.1 数据集划分

1.2 偏差与方差

1.3 解决方法(过拟合)

2 正则化(Regularization)

2.1 逻辑回归的L1与L2正则化

2.2 正则化项的理解

2.3 神经网络中的正则化

2.4 正则化为什么能够防止过拟合

3 Droupout正则化

3.1 Inverted droupout

3.2 droupout为什么有效总结

4 其它正则化方法

4.1 早停止法(Early Stopping)

4.2 数据增强

5 实现代码


1 偏差与方差

1.1 数据集划分

首先我们对机器学习当中涉及到的数据集划分进行一个简单的复习

  • 训练集(train set):用训练集对算法或模型进行训练过程;
  • 验证集(development set):利用验证集(又称为简单交叉验证集,hold-out cross validation set)进行交叉验证选择出最好的模型
  • 测试集(test set):最后利用测试集对模型进行测试,对学习方法进行评估。

小数据量的时代,如 100、1000、10000 的数据量大小,可以将数据集按照以下比例进行划分:

  • 无验证集的情况:70% / 30%
  • 有验证集的情况:60% / 20% / 20%

而在如今的大数据时代,拥有的数据集的规模可能是百万级别的,所以验证集和测试集所占的比重会趋向于变得更小。

  • 100 万数据量:98% / 1% / 1%
  • 超百万数据量:99.5% / 0.25% / 0.25%

以上这些比例可以根据数据集情况选择。

1.2 偏差与方差

“偏差-方差分解”(bias-variance decomposition)是解释学习算法泛化性能的一种重要工具。

泛化误差可分解为偏差、方差与噪声,泛化性能是由学习算法的能力数据的充分性以及学习任务本身的难度所共同决定的。

  • 偏差:度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力

  • 方差:度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响

  • 噪声:表达了在当前任务上任何学习算法所能够达到的期望泛化误差的下界,即刻画了学习问题本身的难度

那么偏差、方差与我们的数据集划分到底有什么关系呢?

  • 1、训练集的错误率较小,而验证集/测试集的错误率较大,说明模型存在较大方差,可能出现了过拟合
  • 2、训练集和测试集的错误率都较大,且两者相近,说明模型存在较大偏差,可能出现了欠拟合
  • 3、训练集和测试集的错误率都较小,且两者相近,说明方差和偏差都较小,这个模型效果比较好。

所以我们最终总结,方差一般指的是数据模型得出来了,能不能对未知数据的扰动预测准确。而偏差说明在训练集当中就已经误差较大了,基本上在测试集中没有好的效果。

所以如果我们的模型出现了较大的方差或者同时也有较大的偏差,该怎么去解决?

1.3 解决方法(过拟合)

对于高方差,有以下几种方式:(过拟合)

  • 获取更多的数据,使得训练能够包含所有可能出现的情况
  • 正则化(Regularization)
  • 寻找更合适的网络结构

对于高偏差,有以下几种方式:(欠拟合)

  • 扩大网络规模,如添加隐藏层或者神经元数量
  • 寻找合适的网络架构,使用更大的网络结构,如AlexNet
  • 训练时间更长一些

不断尝试,直到找到低偏差、低方差的框架。

2 正则化(Regularization)

正则化即在成本函数中加入一个正则化项(惩罚项),惩罚模型的复杂度,防止网络过拟合

2.1 逻辑回归的L1与L2正则化

逻辑回归的参数W数量根据特征的数量而定,那么正则化如下

  • 逻辑回归的损失函数中增加L2正则化

其中的L2范数可以理解:

解释:所有w参数的平方和的结果

  • 逻辑回归的损失函数中增加L1正则化

注:其中,λ 为正则化因子,是超参数。由于 L1 正则化最后得到 w 向量中将存在大量的 0,使模型变得稀疏化,因此 L2 正则化更加常用。

2.2 正则化项的理解

在损失函数中增加一项,那么其实梯度下降是要减少损失函数的大小,对于L2或者L1来讲都是要去减少这个正则项的大小,那么也就是会减少W权重的大小。这是我们一个直观上的感受。

  • 接下来我们通过方向传播来理解这个其中的L2,对于损失函数我们要反向传播求参数梯度:

所以每次更新的时候都会让,这个系数永远小于1,所以我们通常称L2范数为权重衰减

2.3 神经网络中的正则化

神经网络中的正则化与逻辑回归相似,只不过参数W变多了,每一层都有若干个权重,可以理解成一个矩阵

对于矩阵的L2范数,有个专业名称叫弗罗贝尼乌斯范数(Frobenius Norm)

2.4 正则化为什么能够防止过拟合

正则化因子设置的足够大的情况下,为了使成本函数最小化,权重矩阵 W 就会被设置为接近于 0 的值,直观上相当于消除了很多神经元的影响,那么大的神经网络就会变成一个较小的网络。

在加入正则化项后,当λ增大,导致W​[​​l]减小,Z[l]=W[l]a[l−1]+b[l]​​便会减小。由上图可知,在 z 较小(接近于 0)的区域里,函数近似线性,所以每层的函数就近似线性函数,整个网络就成为一个简单的近似线性的网络,因此不会发生过拟合。

3 Droupout正则化

Droupout论文地址:http://jmlr.org/papers/volume15/srivastava14a.old/srivastava14a.pdf

Droupout:随机的对神经网络每一层进行丢弃部分神经元操作。

对于网络的每一层会进行设置保留概率,即keep_prob。假设keep_prob为0.8,那么也就是在每一层所有神经元有20% 的概率直接失效,可以理解为0.

3.1 Inverted droupout

这种方式会对每层进行如下代码操作

# 假设设置神经元保留概率
keep_prob = 0.8
# 随机建立一个标记1 or 0的矩阵,表示随机失活的单元,占比20%
dl = np.random.rand(al.shape[0], al.shape[1]) < keep_prob
# 让a1对应d1的为0地方结果为0
al = np.multiply(al, dl)# 为了测试的时候,每一个单元都参与进来
al /= keep_prob

  • 训练练的时候只有占比为p的隐藏层单元参与训练。

  • 增加最后一行代码的原因,在预测的时候,所有的隐藏层单元都需要参与进来,就需要测试的时候将输出结果除以以p使下一层的输入规模保持不变。

假设keep_prob=p=0.8

注:原始:(1+1+1+1+1+1+1+1+1+1)/10 = 1,现在其中20%失效,则平均值为0.8,所以0.8 * (10/8) = 1. 相当于其中8个神经元参数增大了(10/8)倍

3.2 droupout为什么有效总结

加入了 dropout 后,输入的特征都存在被随机清除的可能,所以该神经元不会再特别依赖于任何一个输入特征,也就是不会给任何一个输入特征设置太大的权重。通过传播过程,dropout 将产生和 L2 正则化相同的收缩权重的效果。

  • 对于不同的层,设置的keep_prob大小也不一致,神经元较少的层,会设keep_prob为 1.0,而神经元多的层则会设置比较小的keep_prob

  • 通常被使用在计算机视觉领域,图像拥有更多的特征,场景容易过拟合,效果被实验人员证明是很不错的。

调试时候使用技巧:

  • dropout 的缺点是成本函数无法被明确定义,因为每次会随机消除一部分神经元,所以参数也无法确定具体哪一些,在反向传播的时候带来计算上的麻烦,也就无法保证当前网络是否损失函数下降的。如果要使用droupout,会先关闭这个参数,保证损失函数是单调下降的,确定网络没有问题,再次打开droupout才会有效。

4 其它正则化方法

  • 早停止法(Early Stopping)
  • 数据增强

4.1 早停止法(Early Stopping)

通常我们在训练验证的时候,发现过拟合。可以得到下面这张损失图

通常不断训练之后,损失越来越小。但是到了一定之后,模型学到的过于复杂(过于拟合训练集上的数据的特征)造成测试集开始损失较小,后来又变大。模型的w参数会越来越大,那么可以在测试集损失减小一定程度之后停止训练。

但是这种方法治标不治本,得从根本上解决数据或者网络的问题。

4.2 数据增强

  • 数据增强

指通过剪切、旋转/反射/翻转变换、缩放变换、平移变换、尺度变换、对比度变换、噪声扰动、颜色变换等一种或多种组合数据增强变换的方式来增加数据集的大小

即使卷积神经网络被放在不同方向上,卷积神经网络对平移、视角、尺寸或照度(或以上组合)保持不变性,都会认为是一个物体。

  • 为什么这样做?

假设数据集中的两个类。左边的代表品牌A(福特),右边的代表品牌B(雪佛兰)。

假设完成了训练,并且输入下面的图像(品牌A),但是你的神经网络输出认为它是品牌B的汽车!

为什么会发生这种现象? 因为算法可能会寻找区分一个类和另一个类的最明显特征。在这个例子中 ,这个特征就是所有品牌A的汽车朝向左边,所有品牌B的汽车朝向右边。神经网络的好坏取决于输入的数据。

怎么解决这个问题?

我们需要减少数据集中不相关特征的数量。对上面的汽车类型分类器来说,你只需要将现有的数据集中的照片水平翻转,使汽车朝向另一侧。现在,用新的数据集训练神经网络,通过过增强数据集,可以防止神经网络学习到不相关的模式,提升效果。(在没有采集更多的图片前提下)

  • 数据增强类别

那么我们应该在机器学习过程中的什么位置进行数据增强?在向模型输入数据之前增强数据集。

  • 离线增强。预先进行所有必要的变换,从根本上增加数据集的规模(例如,通过翻转所有图像,保存后数据集数量会增加2倍)。
  • 在线增强,或称为动态增强。可通过对即将输入模型的小批量数据的执行相应的变化,这样同一张图片每次训练被随机执行一些变化操作,相当于不同的数据集了。

那么我们的代码中也是进行这种在线增强。

  • 数据增强技术

下面一些方法基础但功能强大的增强技术,目前被广泛应用。

  • 翻转:tf.image.random_flip_left_right
    • 你可以水平或垂直翻转图像。一些架构并不支持垂直翻转图像。但,垂直翻转等价于将图片旋转180再水平翻转。下面就是图像翻转的例子。

                  从左侧开始分别是:原始图像,水平翻转图像,垂直翻转图像
  • 旋转:rotate

                                      从左到右,图像相对于前一个图像顺时针旋转90度
  • 剪裁:random_crop
    • 随机从原始图像中采样一部分,然后将这部分图像调整为原始图像大小。这个方法更流行的叫法是随机裁剪。

从左侧开始分别为:原始图像,从左上角裁剪出一个正方形部分,然后从右下角裁剪出一个正方形部分。剪裁的部分被调整为原始图像大小。
  • 平移、缩放等等方法

数据增强的效果是非常好的,比如下面的例子,绿色和粉色表示没有数据增强之前的损失和准确率效果,红色和蓝色表示数据增强之后的损失和准确率结果,可以看到学习效果也改善较快。

那么TensorFlow 官方源码都是基于 vgg与inception论文的图像增强介绍,全部通过tf.image相关API来预处理图像。并且提供了各种封装过tf.image之后的API。那么TensorFlow 官网也给我们提供了一些模型的数据增强过程。


5 实现代码

问题陈述:假如法国足球公司招聘AI专家。他们希望你推荐法国队的守门员应该踢球的位置,以便法国队的球员可以用他们的头来击球。

守门员将球踢到空中,每支球队的球员都在用头撞击球。我们提供了法国过去10场比赛位置数据集。

每个点对应于足球场上的位置,在法国守门员从足球场的左侧射球之后,足球运动员用他/她的头击球。

  • 如果点是蓝色,则意味着法国球员设法用他们的头击球
  • 如果点是红色,则表示其他球队的球员用他们的头击球

分类目的:使用深度学习模型找到守门员应该踢球的场地位置。

代码:

utils.py:基础功能(前向传播、反向传播...)

import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
import sklearn.linear_model
import scipy.iodef sigmoid(x):"""Compute the sigmoid of xArguments:x -- A scalar or numpy array of any size.Return:s -- sigmoid(x)"""s = 1 / (1 + np.exp(-x))return sdef relu(x):"""Compute the relu of xArguments:x -- A scalar or numpy array of any size.Return:s -- relu(x)"""s = np.maximum(0, x)return sdef initialize_parameters(layer_dims):"""Arguments:layer_dims -- python array (list) containing the dimensions of each layer in our networkReturns:parameters -- python dictionary containing your parameters "W1", "b1", ..., "WL", "bL":W1 -- weight matrix of shape (layer_dims[l], layer_dims[l-1])b1 -- bias vector of shape (layer_dims[l], 1)Wl -- weight matrix of shape (layer_dims[l-1], layer_dims[l])bl -- bias vector of shape (1, layer_dims[l])Tips:- For example: the layer_dims for the "Planar Data classification model" would have been [2,2,1]. This means W1's shape was (2,2), b1 was (1,2), W2 was (2,1) and b2 was (1,1). Now you have to generalize it!- In the for loop, use parameters['W' + str(l)] to access Wl, where l is the iterative integer."""np.random.seed(3)parameters = {}L = len(layer_dims) # number of layers in the networkfor l in range(1, L):parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) / np.sqrt(layer_dims[l-1])parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))assert(parameters['W' + str(l)].shape == layer_dims[l], layer_dims[l-1])assert(parameters['W' + str(l)].shape == layer_dims[l], 1)return parametersdef forward_propagation(X, parameters):"""Implements the forward propagation (and computes the loss) presented in Figure 2.Arguments:X -- input dataset, of shape (input size, number of examples)parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2", "W3", "b3":W1 -- weight matrix of shape ()b1 -- bias vector of shape ()W2 -- weight matrix of shape ()b2 -- bias vector of shape ()W3 -- weight matrix of shape ()b3 -- bias vector of shape ()Returns:loss -- the loss function (vanilla logistic loss)"""# retrieve parametersW1 = parameters["W1"]b1 = parameters["b1"]W2 = parameters["W2"]b2 = parameters["b2"]W3 = parameters["W3"]b3 = parameters["b3"]# LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOIDZ1 = np.dot(W1, X) + b1A1 = relu(Z1)Z2 = np.dot(W2, A1) + b2A2 = relu(Z2)Z3 = np.dot(W3, A2) + b3A3 = sigmoid(Z3)cache = (Z1, A1, W1, b1, Z2, A2, W2, b2, Z3, A3, W3, b3)return A3, cachedef backward_propagation(X, Y, cache):"""Implement the backward propagation presented in figure 2.Arguments:X -- input dataset, of shape (input size, number of examples)Y -- true "label" vector (containing 0 if cat, 1 if non-cat)cache -- cache output from forward_propagation()Returns:gradients -- A dictionary with the gradients with respect to each parameter, activation and pre-activation variables"""m = X.shape[1](Z1, A1, W1, b1, Z2, A2, W2, b2, Z3, A3, W3, b3) = cachedZ3 = A3 - YdW3 = 1./m * np.dot(dZ3, A2.T)db3 = 1./m * np.sum(dZ3, axis=1, keepdims = True)dA2 = np.dot(W3.T, dZ3)dZ2 = np.multiply(dA2, np.int64(A2 > 0))dW2 = 1./m * np.dot(dZ2, A1.T)db2 = 1./m * np.sum(dZ2, axis=1, keepdims = True)dA1 = np.dot(W2.T, dZ2)dZ1 = np.multiply(dA1, np.int64(A1 > 0))dW1 = 1./m * np.dot(dZ1, X.T)db1 = 1./m * np.sum(dZ1, axis=1, keepdims = True)gradients = {"dZ3": dZ3, "dW3": dW3, "db3": db3,"dA2": dA2, "dZ2": dZ2, "dW2": dW2, "db2": db2,"dA1": dA1, "dZ1": dZ1, "dW1": dW1, "db1": db1}return gradientsdef update_parameters(parameters, grads, learning_rate):"""Update parameters using gradient descentArguments:parameters -- python dictionary containing your parameters:parameters['W' + str(i)] = Wiparameters['b' + str(i)] = bigrads -- python dictionary containing your gradients for each parameters:grads['dW' + str(i)] = dWigrads['db' + str(i)] = dbilearning_rate -- the learning rate, scalar.Returns:parameters -- python dictionary containing your updated parameters """n = len(parameters) // 2 # number of layers in the neural networks# Update rule for each parameterfor k in range(n):parameters["W" + str(k+1)] = parameters["W" + str(k+1)] - learning_rate * grads["dW" + str(k+1)]parameters["b" + str(k+1)] = parameters["b" + str(k+1)] - learning_rate * grads["db" + str(k+1)]return parametersdef predict(X, y, parameters):"""This function is used to predict the results of a  n-layer neural network.Arguments:X -- data set of examples you would like to labelparameters -- parameters of the trained modelReturns:p -- predictions for the given dataset X"""m = X.shape[1]p = np.zeros((1,m), dtype = int)# Forward propagationa3, caches = forward_propagation(X, parameters)# convert probas to 0/1 predictionsfor i in range(0, a3.shape[1]):if a3[0,i] > 0.5:p[0,i] = 1else:p[0,i] = 0# print results#print ("predictions: " + str(p[0,:]))#print ("true labels: " + str(y[0,:]))print("Accuracy: "  + str(np.mean((p[0,:] == y[0,:]))))return pdef compute_cost(a3, Y):"""Implement the cost functionArguments:a3 -- post-activation, output of forward propagationY -- "true" labels vector, same shape as a3Returns:cost - value of the cost function"""m = Y.shape[1]logprobs = np.multiply(-np.log(a3),Y) + np.multiply(-np.log(1 - a3), 1 - Y)cost = 1./m * np.nansum(logprobs)return costdef load_dataset():data = scipy.io.loadmat('datasets/data.mat')train_X = data['X'].Ttrain_Y = data['y'].Ttest_X = data['Xval'].Ttest_Y = data['yval'].T# plt.scatter(train_X[0, :], train_X[1, :], c=train_Y, s=40, cmap=plt.cm.Spectral);return train_X, train_Y, test_X, test_Y
  • 自带有L2正则化的网络,λ=0.7
def compute_cost_with_regularization(A3, Y, parameters, lambd):"""损失函数中增加L2正则化"""m = Y.shape[1]W1 = parameters["W1"]W2 = parameters["W2"]W3 = parameters["W3"]# 计算交叉熵损失cross_entropy_cost = compute_cost(A3, Y)# 开始L2_regularization_cost = (1. / m) * (lambd / 2) * \(np.sum(np.square(W1)) + np.sum(np.square(W2)) + np.sum(np.square(W3)))cost = cross_entropy_cost + L2_regularization_cost# 结束return cost
  • 自实现带有Droupout的网络, keep_prob=0.86

def forward_propagation_with_dropout(X, parameters, keep_prob=0.5):"""带有dropout的前向传播"""np.random.seed(1)W1 = parameters["W1"]b1 = parameters["b1"]W2 = parameters["W2"]b2 = parameters["b2"]W3 = parameters["W3"]b3 = parameters["b3"]# LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID# 计算第一层输出Z1 = np.dot(W1, X) + b1A1 = relu(Z1)# 开始# 初始化一个矩阵D1 = np.random.rand(A1.shape[0], A1.shape[1])# 标记为0和1D1 = D1 < keep_prob# 对于A1中的部分结果丢弃A1 = np.multiply(A1, D1)# 保持原来的期望值A1 /= keep_prob# 结束# 计算第二层输出Z2 = np.dot(W2, A1) + b2A2 = relu(Z2)# 开始D2 = np.random.rand(A2.shape[0], A2.shape[1])D2 = D2 < keep_probA2 = np.multiply(A2, D2)A2 /= keep_prob# 结束# 最后一层输出Z3 = np.dot(W3, A2) + b3A3 = sigmoid(Z3)cache = (Z1, D1, A1, W1, b1, Z2, D2, A2, W2, b2, Z3, A3, W3, b3)return A3, cachedef backward_propagation_with_dropout(X, Y, cache, keep_prob):"""droupout的反向传播"""m = X.shape[1](Z1, D1, A1, W1, b1, Z2, D2, A2, W2, b2, Z3, A3, W3, b3) = cachedZ3 = A3 - YdW3 = 1. / m * np.dot(dZ3, A2.T)db3 = 1. / m * np.sum(dZ3, axis=1, keepdims=True)dA2 = np.dot(W3.T, dZ3)dA2 = np.multiply(dA2, D2)dA2 /= keep_probdZ2 = np.multiply(dA2, np.int64(A2 > 0))dW2 = 1. / m * np.dot(dZ2, A1.T)db2 = 1. / m * np.sum(dZ2, axis=1, keepdims=True)dA1 = np.dot(W2.T, dZ2)dA1 = np.multiply(dA1, D1)dA1 /= keep_probdZ1 = np.multiply(dA1, np.int64(A1 > 0))dW1 = 1. / m * np.dot(dZ1, X.T)db1 = 1. / m * np.sum(dZ1, axis=1, keepdims=True)gradients = {"dZ3": dZ3, "dW3": dW3, "db3": db3, "dA2": dA2,"dZ2": dZ2, "dW2": dW2, "db2": db2, "dA1": dA1,"dZ1": dZ1, "dW1": dW1, "db1": db1}return gradients

完整代码:

import numpy as np
import matplotlib.pyplot as pltfrom utils import initialize_parameters, compute_cost, forward_propagation, backward_propagation, update_parameters
from utils import load_dataset, predict, sigmoid, relu# -------
# 1、带有正则化的计算损失函数
# 2、正则化后的反向传播计算
# -------
def compute_cost_with_regularization(A3, Y, parameters, lambd):"""损失函数中增加L2正则化"""m = Y.shape[1]W1 = parameters["W1"]W2 = parameters["W2"]W3 = parameters["W3"]# 计算交叉熵损失cross_entropy_cost = compute_cost(A3, Y)# 开始L2_regularization_cost = (1. / m) * (lambd / 2) * \(np.sum(np.square(W1)) + np.sum(np.square(W2)) + np.sum(np.square(W3)))cost = cross_entropy_cost + L2_regularization_cost# 结束return costdef backward_propagation_with_regularization(X, Y, cache, lambd):"""对增加了L2正则化后的损失函数进行反向传播计算"""m = X.shape[1](Z1, A1, W1, b1, Z2, A2, W2, b2, Z3, A3, W3, b3) = cachedZ3 = A3 - YdW3 = 1. / m * (np.dot(dZ3, A2.T) + lambd * W3)db3 = 1. / m * np.sum(dZ3, axis=1, keepdims=True)dA2 = np.dot(W3.T, dZ3)dZ2 = np.multiply(dA2, np.int64(A2 > 0))dW2 = 1. / m * (np.dot(dZ2, A1.T) + lambd * W2)db2 = 1. / m * np.sum(dZ2, axis=1, keepdims=True)dA1 = np.dot(W2.T, dZ2)dZ1 = np.multiply(dA1, np.int64(A1 > 0))dW1 = 1. / m * (np.dot(dZ1, X.T) + lambd * W1)db1 = 1. / m * np.sum(dZ1, axis=1, keepdims=True)gradients = {"dZ3": dZ3, "dW3": dW3, "db3": db3, "dA2": dA2,"dZ2": dZ2, "dW2": dW2, "db2": db2, "dA1": dA1,"dZ1": dZ1, "dW1": dW1, "db1": db1}return gradients# ----------
# 1、droupout前向传播过程
# 2、droupout反向传播过程
# ----------def forward_propagation_with_dropout(X, parameters, keep_prob=0.5):"""带有dropout的前向传播"""np.random.seed(1)W1 = parameters["W1"]b1 = parameters["b1"]W2 = parameters["W2"]b2 = parameters["b2"]W3 = parameters["W3"]b3 = parameters["b3"]# LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID# 计算第一层输出Z1 = np.dot(W1, X) + b1A1 = relu(Z1)# 开始# 初始化一个矩阵D1 = np.random.rand(A1.shape[0], A1.shape[1])# 标记为0和1D1 = D1 < keep_prob# 对于A1中的部分结果丢弃A1 = np.multiply(A1, D1)# 保持原来的期望值A1 /= keep_prob# 结束# 计算第二层输出Z2 = np.dot(W2, A1) + b2A2 = relu(Z2)# 开始D2 = np.random.rand(A2.shape[0], A2.shape[1])D2 = D2 < keep_probA2 = np.multiply(A2, D2)A2 /= keep_prob# 结束# 最后一层输出Z3 = np.dot(W3, A2) + b3A3 = sigmoid(Z3)cache = (Z1, D1, A1, W1, b1, Z2, D2, A2, W2, b2, Z3, A3, W3, b3)return A3, cachedef backward_propagation_with_dropout(X, Y, cache, keep_prob):"""droupout的反向传播"""m = X.shape[1](Z1, D1, A1, W1, b1, Z2, D2, A2, W2, b2, Z3, A3, W3, b3) = cachedZ3 = A3 - YdW3 = 1. / m * np.dot(dZ3, A2.T)db3 = 1. / m * np.sum(dZ3, axis=1, keepdims=True)dA2 = np.dot(W3.T, dZ3)dA2 = np.multiply(dA2, D2)dA2 /= keep_probdZ2 = np.multiply(dA2, np.int64(A2 > 0))dW2 = 1. / m * np.dot(dZ2, A1.T)db2 = 1. / m * np.sum(dZ2, axis=1, keepdims=True)dA1 = np.dot(W2.T, dZ2)dA1 = np.multiply(dA1, D1)dA1 /= keep_probdZ1 = np.multiply(dA1, np.int64(A1 > 0))dW1 = 1. / m * np.dot(dZ1, X.T)db1 = 1. / m * np.sum(dZ1, axis=1, keepdims=True)gradients = {"dZ3": dZ3, "dW3": dW3, "db3": db3, "dA2": dA2,"dZ2": dZ2, "dW2": dW2, "db2": db2, "dA1": dA1,"dZ1": dZ1, "dW1": dW1, "db1": db1}return gradientsdef model(X, Y, learning_rate=0.3, num_iterations=30000, lambd=0, keep_prob=1):"""使用三层网络,激活函数为:LINEAR->RELU->LINEAR->RELU->LINEAR->SIGMOID.第一个隐层:20个神经元第二个隐层:3个神经元输出层:1个神经元"""grads = {}costs = []m = X.shape[1]layers_dims = [X.shape[0], 20, 3, 1]# 初始化网络参数parameters = initialize_parameters(layers_dims)# 梯度下降循环逻辑for i in range(0, num_iterations):# 前向传播计算# LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID.# 如果keep_prob=1,进行正常前向传播# 如果keep_prob<1,说明需要进行droupout计算if keep_prob == 1:a3, cache = forward_propagation(X, parameters)elif keep_prob < 1:a3, cache = forward_propagation_with_dropout(X, parameters, keep_prob)# 计算损失# 如果传入lambd不为0,判断加入正则化if lambd == 0:cost = compute_cost(a3, Y)else:cost = compute_cost_with_regularization(a3, Y, parameters, lambd)# 只允许选择一个,要么L2正则化,要么Droupoutassert (lambd == 0 or keep_prob == 1)if lambd == 0 and keep_prob == 1:grads = backward_propagation(X, Y, cache)elif lambd != 0:grads = backward_propagation_with_regularization(X, Y, cache, lambd)elif keep_prob < 1:grads = backward_propagation_with_dropout(X, Y, cache, keep_prob)# 更新参数parameters = update_parameters(parameters, grads, learning_rate)# 每10000词打印损失结果if i % 10000 == 0:print("迭代次数为 {}: 损失结果大小:{}".format(i, cost))costs.append(cost)# 画出损失变化结果图plt.plot(costs)plt.ylabel('损失')plt.xlabel('迭代次数')plt.title("损失变化图,学习率为" + str(learning_rate))plt.show()return parametersif __name__ == '__main__':train_X, train_Y, test_X, test_Y = load_dataset()# parameters = model(train_X, train_Y, keep_prob=0.86)#使用droupout正则化parameters = model(train_X, train_Y, lambd=0.7)#使用L2正则化print("训练集的准确率:")predictions_train = predict(train_X, train_Y, parameters)print("测试集的准确率:")predictions_test = predict(test_X, test_Y, parameters)

L2: 

droupout:

 

 


http://www.hkcw.cn/article/KheXbDlsuF.shtml

相关文章

解决报错error: ‘void_t’ is not a member of ‘std’

解决报错error: ‘void_t’ is not a member of ‘std’ 博主是在编译ceres库时遇到的此报错。 解决方式很简单&#xff0c;将编译使用的c标准设定为c17即可。 例如&#xff0c;在VS2022中&#xff0c;右键单击项目-属性&#xff1a;

【达梦数据库】会话sp_close关闭不掉

背景 一个纯查询的语句&#xff0c;执行了很久&#xff0c;sp_close关闭不掉 排查方法 1、会话sp_close关闭不掉&#xff0c;sp_cance后再执行sp_close依旧关闭不了&#xff1b; sp_close_session(sess_id)sp_cancel_session_operation(sess_id)2、通过分析事务视图v$trx的…

澳门向永久居民每人发1万澳门元 新计划细节公布

澳门特区行政会今日完成讨论《2025年度现金分享计划》行政法规草案。该法规对2025年度的现金分享发放资格及申请手续进行了规范。根据规定,符合身份条件和在澳条件的居民可获得现金分享,其中永久性居民每人一万澳门元,非永久性居民每人六千澳门元。身份条件是指在2024年12月…

接口测试之文件上传(全)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 在日常工作中&#xff0c;经常有上传文件功能的测试场景&#xff0c;因此&#xff0c;本文介绍两种主流编写上传文件接口测试脚本的方法。 首先&#xff0c;要知道…

数十家超市曝出食品安全问题 供应链隐患凸显

近日,全国多地超市接连曝出食品安全问题,涉及蔬菜、肉类、包装食品等多个品类。永辉、麦德龙、山姆会员店、小象超市、盒马、中百、朴朴、沃尔玛、奥乐齐和大润发等多家超市被点名。在12315、黑猫和消费保等投诉平台上,可以看到山姆永辉等超市因食品安全问题遭到消费者投诉。…

canvas 实现全屏倾斜重复水印

​ 参考&#xff1a; html、js、canvas实现水印_html页面使用canvas绘制重复水印-CSDN博客 效果 ​​​​ 不求水印显示完全。 实现代码 <template><div class"watermark" ref"waterMark"></div></template><script lang&q…

Android Studio 2022.2.1.20 汉化教程

查看Android Studio 版本 Android Studio Flamingo | 2022.2.1 Patch 2 下载&#xff1a;https://plugins.jetbrains.com/plugin/13710-chinese-simplified-language-pack----/versions/stable

一根开价10万 年轻人迷上文玩玉米,风靡年轻圈

一根开价10万年轻人迷上文玩玉米。“文玩玉米风靡年轻圈,单根标价10万仍抢手!特殊培育的琥珀纹路、蜜蜡颗粒,经直播带货引爆市场,产业链从云南育种到百倍溢价,争议中见证新消费魔力。”文玩,这个曾被贴上“中老年专属”标签的传统爱好,如今正以意想不到的方式在年轻人中…

如何在Qt中绘制一个带有动画的弧形进度条?

如何在Qt中绘制一个弧形的进度条 在图形用户界面开发中&#xff0c;进度指示控件&#xff08;Progress Widget&#xff09;是非常常见且实用的组件。CCArcProgressWidget 是一个继承自 QWidget 的自定义控件&#xff0c;用于绘制圆弧形进度条。当然&#xff0c;笔者看了眼公开…

体育平台数据服务解决方案:从痛点到落地的全栈技术支持

一、体育平台开发的数据痛点解析 在体育平台开发领域&#xff0c;数据层建设往往成为技术团队的核心挑战&#xff1a; 实时数据获取难自建实时数据采集系统需解决赛事方反爬机制、多源数据同步&#xff08;如比分 / 球员位置 / 赔率&#xff09;、毫秒级延迟控制等问题&#…

去寺庙减脂的人胖了11斤 素食诱惑难抵挡

去寺庙减脂的人胖了11斤!一群原本希望通过吃减脂餐修身养性的打工人和中年人,在体验后第一批人竟胖了11斤,这反转实在惊人。当下生活节奏飞快,很多人被亚健康困扰,身体各种不适。于是大家开始注重养生,寺庙因宁静祥和且素食养生概念深入人心,被不少人视为减脂圣地。人们…

printf 输出格式总结(C语言)和C 中的类型提升规则、默认整型提升

类型格式符示例输出说明十进制整数%d12345输出有符号十进制&#xff08;int 类型&#xff09;十进制整数%u12345输出无符号十进制&#xff08;unsigned int&#xff09;十六进制%x3fa2小写十六进制&#xff08;无前缀&#xff09;十六进制%X3FA2大写十六进制&#xff08;无前缀…

Flutter下的一点实践

目录 1、背景2、refena创世纪代码3、localsend里refena的刷新3.1 初始状态3.2 发起设备扫描流程3.3 扫描过程3.3 刷新界面 4.localsend的设备扫描流程4.1 UDP广播设备注册流程4.2 TCP/HTTP设备注册流程4.3 localsend的服务器初始化工作4.4总结 1、背景 在很久以前&#xff0c;…

英国利物浦汽车冲撞人群事件嫌疑人身份公布

英国利物浦汽车冲撞人群事件嫌疑人身份公布 警方通报调查进展英国默西赛德郡警方发言人当地时间5月29日说,日前在利物浦市中心驾车冲撞球迷的男子面临7项指控,将于30日在利物浦地方法院出庭。据英国媒体报道,默西-柴郡地区皇家检察署授权默西赛德郡警方正式对53岁的嫌疑人保…

「动态规划::状压DP」网格图递推 / AcWing 292|327(C++)

目录 概述 相邻行递推 思路 算法过程 优化方案 空间优化 返回值优化 Code 复杂度 相邻两行递推 思路 算法过程 Code 复杂度 特殊优化&#xff1a;编译期计算 总结 概述 如果我们有一张地图&#xff0c;要求是在符合某类条件的前提在地图上放置最优解&#xff…

深圳海关查获超18公斤摇头丸 科技助力精准打击

近日,深圳邮局海关在跨境转运货物的监管过程中查获了一批伪报为“有机蜡溶香草”的包裹,实际上是摇头丸,总重量达18433.3克。目前,该案件已正式移交至海关缉私部门,进行更深入的调查和追溯。事件起因是海关关员对一批申报品名为“有机蜡溶香草”的转运货物进行例行检查时,…

一根网线连接两台电脑组建局域网

用一根网线分别插在网络端口&#xff0c;修改网络IP地址&#xff0c;假如有A和B&#xff0c;设置A:IP地址192.168.1.1,B&#xff1a;192.168.1.2 接着把网络防火墙关闭&#xff0c;步骤如下&#xff1a; 后面接着右键点击我的电脑&#xff0c;选择属性&#xff0c;打开远程控制…

丰巢回应快递柜消失市民取件扑空!

丰巢回应快递柜消失市民取件扑空。5月27日,上海普陀。市民发帖称包裹被存放在丰巢快递柜,过去取件时快递柜却消失不见了。5月29日,该包裹快递员告诉《正在新闻》,昨天在该小区的66号楼快递柜发生同样事件。对于快递柜搬走的原因,他表示不清楚,快递柜管理人员并没有告知他…

树型表查询方法 —— SQL递归

目录 引言&#xff1a; 自链接查询&#xff1a; 递归查询&#xff1a; 编写service接口实现&#xff1a; 引言&#xff1a; 看下图&#xff0c;这是 course_category 课程分类表的结构&#xff1a; 这张表是一个树型结构&#xff0c;通过父结点id将各元素组成一个树。 我…

高校大数据采集平台产品特色

大数据采集平台是专为高校大数据相关专业打造的智能化数据采集教学与实训工具。平台具有以下核心优势&#xff1a;采用可视化图形界面&#xff0c;无需编程基础&#xff0c;通过简单配置即可快速抓取网页中的文本、链接、图片、视频及文档等全类型数据&#xff0c;并自动存储至…