吴恩达深度学习笔记:深度学习的 实践层面 (Practical aspects of Deep Learning)1.6-1.8

目录

  • 第一门课:第二门课 改善深层神经网络:超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)
    • 第一周:深度学习的 实践层面 (Practical aspects of Deep Learning)
      • 1.6 dropout 正则化(Dropout Regularization)
      • 1.7 理解 dropout(Understanding Dropout)
      • 1.8 其他正则化方法(Other regularization methods)

第一门课:第二门课 改善深层神经网络:超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)

第一周:深度学习的 实践层面 (Practical aspects of Deep Learning)

1.6 dropout 正则化(Dropout Regularization)

除了𝐿2正则化,还有一个非常实用的正则化方法——“Dropout(随机失活)”,我们来看看它的工作原理。
在这里插入图片描述
假设你在训练上图这样的神经网络,它存在过拟合,这就是 dropout 所要处理的,我们复制这个神经网络,dropout 会遍历网络的每一层,并设置消除神经网络中节点的概率。假设网络中的每一层,每个节点都以抛硬币的方式设置概率,每个节点得以保留和消除的概率都是 0.5,设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用 backprop 方法进行训练。

在这里插入图片描述
这是网络节点精简后的一个样本,对于其它样本,我们照旧以抛硬币的方式设置概率,保留一类节点集合,删除其它类型的节点集合。对于每个训练样本,我们都将采用一个精简后神经网络来训练它,这种方法似乎有点怪,单纯遍历节点,编码也是随机的,可它真的有效。不过可想而知,我们针对每个训练样本训练规模极小的网络,最后你可能会认识到为什么要正则化网络,因为我们在训练极小的网络。
在这里插入图片描述

如何实施 dropout 呢?方法有几种,接下来我要讲的是最常用的方法,即 inverted dropout(反向随机失活),出于完整性考虑,我们用一个三层(𝑙 = 3)网络来举例说明。编码中会有很多涉及到 3 的地方。我只举例说明如何在某一层中实施 dropout。首先要定义向量𝑑,𝑑[3]表示一个三层的 dropout 向量:

d3 = np.random.rand(a3.shape[0],a3.shape[1])

然后看它是否小于某数,我们称之为 keep-prob,keep-prob 是一个具体数字,上个示例中它是 0.5,而本例中它是 0.8,它表示保留某个隐藏单元的概率,此处 keep-prob 等于 0.8,它意味着消除任意一个隐藏单元的概率是 0.2,它的作用就是生成随机矩阵,如果对 a [ 3 ] a^{[3]} a[3]进行
因子分解,效果也是一样的。 d [ 3 ] d^{[3]} d[3]是一个矩阵,每个样本和每个隐藏单元,其中 d [ 3 ] d^{[3]} d[3]中的对应值为 1 的概率都是 0.8,对应为 0 的概率是 0.2,随机数字小于 0.8。它等于 1 的概率是 0.8,等于 0 的概率是 0.2。

接下来要做的就是从第三层中获取激活函数,这里我们叫它 a [ 3 ] a^{[3]} a[3] a [ 3 ] a^{[3]} a[3]含有要计算的激活函数, a [ 3 ] a^{[3]} a[3]等于上面的 a [ 3 ] a^{[3]} a[3]乘以 d [ 3 ] d^{[3]} d[3],a3 =np.multiply(a3,d3),这里是元素相乘,也可写为𝑎3 ∗= 𝑑3,它的作用就是让 d [ 3 ] d^{[3]} d[3]中所有等于 0 的元素(输出),而各个元素等于 0 的概率只有 20%,乘法运算最终把 d [ 3 ] d^{[3]} d[3]中相应元素输出,即让 d [ 3 ] d^{[3]} d[3]中 0 元素与 a [ 3 ] a^{[3]} a[3]中相对元素归零。
在这里插入图片描述
如果用 python 实现该算法的话, d [ 3 ] d^{[3]} d[3]则是一个布尔型数组,值为 true 和 false,而不是1 和 0,乘法运算依然有效,python 会把 true 和 false 翻译为 1 和 0,大家可以用 python 尝试一下。最后,我们向外扩展𝑎[3],用它除以 0.8,或者除以 keep-prob 参数。

𝑎3/= 𝑘𝑒𝑒𝑝 − 𝑝𝑟𝑜𝑏

下面我解释一下为什么要这么做,为方便起见,我们假设第三隐藏层上有 50 个单元或50 个神经元,在一维上 a [ 3 ] a^{[3]} a[3]是 50,我们通过因子分解将它拆分成50 × 𝑚维的,保留和删除它们的概率分别为 80%和 20%,这意味着最后被删除或归零的单元平均有 10(50×20%=10)个,现在我们看下 z [ 4 ] z^{[4]} z[4] z [ 4 ] = w [ 4 ] a [ 3 ] + b [ 4 ] z^{[4]} = w^{[4]}a^{[3]} + b^{[4]} z[4]=w[4]a[3]+b[4],我们的预期是,𝑎[3]减少 20%,也就是说 a [ 3 ] a^{[3]} a[3]中有 20%的元素被归零,为了不影响 z [ 4 ] z^{[4]} z[4]的期望值,我们需要用 w [ 4 ] a [ 3 ] / 0.8 w^{[4]}a^{[3]}/0.8 w[4]a[3]/0.8,它将会修正或弥补我们所需的那 20%, a [ 3 ] a^{[3]} a[3]的期望值不会变,划线部分就是所谓的 dropout 方法。

在这里插入图片描述
它的功能是,不论 keep-prop 的值是多少 0.8,0.9 甚至是 1,如果 keep-prop 设置为 1,那么就不存在 dropout,因为它会保留所有节点。反向随机失活(inverted dropout)方法通过除以 keep-prob,确保 a [ 3 ] a^{[3]} a[3]的期望值不变。

事实证明,在测试阶段,当我们评估一个神经网络时,也就是用绿线框标注的反向随机失活方法,使测试阶段变得更容易,因为它的数据扩展问题变少,我们将在下节课讨论。

据我了解,目前实施 dropout 最常用的方法就是 Inverted dropout,建议大家动手实践一下。Dropout 早期的迭代版本都没有除以 keep-prob,所以在测试阶段,平均值会变得越来越复杂,不过那些版本已经不再使用了。

现在你使用的是𝑑向量,你会发现,不同的训练样本,清除不同的隐藏单元也不同。实际上,如果你通过相同训练集多次传递数据,每次训练数据的梯度不同,则随机对不同隐藏单元归零,有时却并非如此。比如,需要将相同隐藏单元归零,第一次迭代梯度下降时,把一些隐藏单元归零,第二次迭代梯度下降时,也就是第二次遍历训练集时,对不同类型的隐藏层单元归零。向量d或 d [ 3 ] d^{[3]} d[3]用来决定第三层中哪些单元归零,无论用 foreprop 还是 backprop,这里我们只介绍了 foreprob。

如何在测试阶段训练算法,在测试阶段,我们已经给出了𝑥,或是想预测的变量,用的是标准计数法。我用 a [ 0 ] a^{[0]} a[0],第 0 层的激活函数标注为测试样本𝑥,我们在测试阶段不使用dropout 函数,尤其是像下列情况:

z [ 1 ] = w [ 1 ] a [ 0 ] + b [ 1 ] z^{[1]} = w^{[1]}a^{[0]} + b^{[1]} z[1]=w[1]a[0]+b[1]
a [ 1 ] = g [ 1 ] ( z [ 1 ] ) a^{[1]} = g^{[1]}(z^{[1]}) a[1]=g[1](z[1])
z [ 2 ] = w [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]} = w^{[2]}a^{[1]} + b^{[2]} z[2]=w[2]a[1]+b[2]
a [ 2 ] = ⋯ a^{[2]} = ⋯ a[2]=

以此类推直到最后一层,预测值为 y ^ \hat{y} y^
在这里插入图片描述

显然在测试阶段,我们并未使用 dropout,自然也就不用抛硬币来决定失活概率,以及要消除哪些隐藏单元了,因为在测试阶段进行预测时,我们不期望输出结果是随机的,如果测试阶段应用 dropout 函数,预测会受到干扰。理论上,你只需要多次运行预测处理过程,每一次,不同的隐藏单元会被随机归零,预测处理遍历它们,但计算效率低,得出的结果也几乎相同,与这个不同程序产生的结果极为相似。

Inverted dropout 函数在除以 keep-prob 时可以记住上一步的操作,目的是确保即使在测试阶段不执行 dropout 来调整数值范围,激活函数的预期结果也不会发生变化,所以没必要在测试阶段额外添加尺度参数,这与训练阶段不同。

l = k e e p − p r o b l = keep − prob l=keepprob
这就是 dropout,大家可以通过本周的编程练习来执行这个函数,亲身实践一下。
为什么 dropout 会起作用呢?下节课我们将更加直观地了解 dropout 的具体功能。

1.7 理解 dropout(Understanding Dropout)

Dropout 可以随机删除网络中的神经单元,他为什么可以通过正则化发挥如此大的作用呢?

直观上理解:不要依赖于任何一个特征,因为该单元的输入可能随时被清除,因此该单元通过这种方式传播下去,并为单元的四个输入增加一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和之前讲的L2正则化类似;实施 dropout 的结果实它会压缩权重,并完成一些预防过拟合的外层正则化;L2对不同权重的衰减是不同的,它取决于激活函数倍增的大小。

总结一下,dropout 的功能类似于L2正则化,与L2正则化不同的是应用方式不同会带来一点点小变化,甚至更适用于不同的输入范围。

在这里插入图片描述
第二个直观认识是,我们从单个神经元入手,如图,这个单元的工作就是输入并生成一些有意义的输出。通过 dropout,该单元的输入几乎被消除,有时这两个单元会被删除,有时会删除其它单元,就是说,我用紫色圈起来的这个单元,它不能依靠任何特征,因为特征都有可能被随机清除,或者说该单元的输入也都可能被随机清除。我不愿意把所有赌注都放在一个节点上,不愿意给任何一个输入加上太多权重,因为它可能会被删除,因此该单元将通过这种方式积极地传播开,并为单元的四个输入增加一点权重,通过传播所有权重,dropout 将产生收缩权重的平方范数的效果,和我们之前讲过的𝐿2正则化类似,实施 dropout的结果是它会压缩权重,并完成一些预防过拟合的外层正则化。

事实证明,dropout 被正式地作为一种正则化的替代形式,𝐿2对不同权重的衰减是不同的,它取决于倍增的激活函数的大小。

总结一下,dropout 的功能类似于𝐿2正则化,与𝐿2正则化不同的是,被应用的方式不同,dropout 也会有所不同,甚至更适用于不同的输入范围。

在这里插入图片描述
实施 dropout 的另一个细节是,这是一个拥有三个输入特征的网络,其中一个要选择的参数是 keep-prob,它代表每一层上保留单元的概率。所以不同层的 keep-prob 也可以变化。第一层,矩阵 W [ 1 ] W^{[1]} W[1]是 7×3,第二个权重矩阵 W [ 2 ] W^{[2]} W[2]是 7×7,第三个权重矩阵 W [ 3 ] W^{[3]} W[3]是 3×7,以此类推, W [ 2 ] W^{[2]} W[2]是最大的权重矩阵,因为 W [ 2 ] W^{[2]} W[2]拥有最大参数集,即 7×7,为了预防矩阵的过拟合,对于这一层,我认为这是第二层,它的 keep-prob 值应该相对较低,假设是 0.5。对于其它层,过拟合的程度可能没那么严重,它们的 keep-prob 值可能高一些,可能是 0.7,这里是0.7。如果在某一层,我们不必担心其过拟合的问题,那么 keep-prob 可以为 1,为了表达清除,我用紫色线笔把它们圈出来,每层 keep-prob 的值可能不同。
在这里插入图片描述
注意 keep-prob 的值是 1,意味着保留所有单元,并且不在这一层使用 dropout,对于有可能出现过拟合,且含有诸多参数的层,我们可以把 keep-prob 设置成比较小的值,以便应用更强大的 dropout,有点像在处理𝐿2正则化的正则化参数𝜆,我们尝试对某些层施行更多正则化,从技术上讲,我们也可以对输入层应用 dropout,我们有机会删除一个或多个输入特征,虽然现实中我们通常不这么做,keep-prob 的值为 1,是非常常用的输入值,也可以用更大的值,或许是 0.9。但是消除一半的输入特征是不太可能的,如果我们遵守这个准则,keep-prob 会接近于 1,即使你对输入层应用 dropout。

总结一下,如果你担心某些层比其它层更容易发生过拟合,可以把某些层的 keep-prob值设置得比其它层更低,缺点是为了使用交叉验证,你要搜索更多的超级参数,另一种方案是在一些层上应用 dropout,而有些层不用 dropout,应用 dropout 的层只含有一个超级参数,就是 keep-prob。

结束前分享两个实施过程中的技巧,实施 dropout,在计算机视觉领域有很多成功的第一次。计算视觉中的输入量非常大,输入太多像素,以至于没有足够的数据,所以 dropout在计算机视觉中应用得比较频繁,有些计算机视觉研究人员非常喜欢用它,几乎成了默认的选择,但要牢记一点,dropout 是一种正则化方法,它有助于预防过拟合,因此除非算法过拟合,不然我是不会使用 dropout 的,所以它在其它领域应用得比较少,主要存在于计算机视觉领域,因为我们通常没有足够的数据,所以一直存在过拟合,这就是有些计算机视觉研究人员如此钟情于 dropout 函数的原因。直观上我认为不能概括其它学科。

在这里插入图片描述
dropout 一大缺点就是代价函数𝐽不再被明确定义,每次迭代,都会随机移除一些节点,如果再三检查梯度下降的性能,实际上是很难进行复查的。定义明确的代价函数𝐽每次迭代后都会下降,因为我们所优化的代价函数 J 实际上并没有明确定义,或者说在某种程度上很难计算,所以我们失去了调试工具来绘制这样的图片。我通常会关闭 dropout 函数,将 keepprob 的值设为 1,运行代码,确保𝐽函数单调递减。然后打开 dropout 函数,希望在 dropout过程中,代码并未引入 bug。我觉得你也可以尝试其它方法,虽然我们并没有关于这些方法性能的数据统计,但你可以把它们与 dropout 方法一起使用。

1.8 其他正则化方法(Other regularization methods)

除了𝐿2正则化和随机失活(dropout)正则化,还有几种方法可以减少神经网络中的过拟合:
在这里插入图片描述
一.数据扩增
假设你正在拟合猫咪图片分类器,如果你想通过扩增训练数据来解决过拟合,但扩增数据代价高,而且有时候我们无法扩增数据,但我们可以通过添加这类图片来增加训练集。例如,水平翻转图片,并把它添加到训练集。所以现在训练集中有原图,还有翻转后的这张图片,所以通过水平翻转图片,训练集则可以增大一倍,因为训练集有冗余,这虽然不如我们额外收集一组新图片那么好,但这样做节省了获取更多猫咪图片的花费。

除了水平翻转图片,你也可以随意裁剪图片,这张图是把原图旋转并随意放大后裁剪的,仍能辨别出图片中的猫咪。

通过随意翻转和裁剪图片,我们可以增大数据集,额外生成假训练数据。和全新的,独立的猫咪图片数据相比,这些额外的假的数据无法包含像全新数据那么多的信息,但我们这么做基本没有花费,代价几乎为零,除了一些对抗性代价。以这种方式扩增算法数据,进而正则化数据集,减少过拟合比较廉价。

像这样人工合成数据的话,我们要通过算法验证,图片中的猫经过水平翻转之后依然是猫。大家注意,我并没有垂直翻转,因为我们不想上下颠倒图片,也可以随机选取放大后的部分图片,猫可能还在上面。

对于光学字符识别,我们还可以通过添加数字,随意旋转或扭曲数字来扩增数据,把这些数字添加到训练集,它们仍然是数字。为了方便说明,我对字符做了强变形处理,所以数字 4 看起来是波形的,其实不用对数字 4 做这么夸张的扭曲,只要轻微的变形就好,我做成这样是为了让大家看的更清楚。实际操作的时候,我们通常对字符做更轻微的变形处理。因为这几个 4 看起来有点扭曲。所以,数据扩增可作为正则化方法使用,实际功能上也与正则化相似。

二.early stopping

还有另外一种常用的方法叫作 early stopping,运行梯度下降时,我们可以绘制训练误差,或只绘制代价函数𝐽的优化过程,在训练集上用 0-1 记录分类误差次数。呈单调下降趋势,如图。

在这里插入图片描述
因为在训练过程中,我们希望训练误差,代价函数𝐽都在下降,通过 early stopping,我们不但可以绘制上面这些内容,还可以绘制验证集误差,它可以是验证集上的分类误差,或验证集上的代价函数,逻辑损失和对数损失等,你会发现,验证集误差通常会先呈下降趋势,然后在某个节点处开始上升,early stopping 的作用是,你会说,神经网络已经在这个迭代过程中表现得很好了,我们在此停止训练吧,得到验证集误差,它是怎么发挥作用的?

在这里插入图片描述
当你还未在神经网络上运行太多迭代过程的时候,参数𝑤接近 0,因为随机初始化𝑤值时,它的值可能都是较小的随机值,所以在你长期训练神经网络之前𝑤依然很小,在迭代过程和训练过程中𝑤的值会变得越来越大,比如在这儿,神经网络中参数𝑤的值已经非常大了,所以 early stopping 要做就是在中间点停止迭代过程,我们得到一个𝑤值中等大小的弗罗贝尼乌斯范数,与𝐿2正则化相似,选择参数𝑤范数较小的神经网络,但愿你的神经网络过度拟合不严重。

术语 early stopping 代表提早停止训练神经网络,训练神经网络时,我有时会用到 early stopping,但是它也有一个缺点,我们来了解一下。

我认为机器学习过程包括几个步骤,其中一步是选择一个算法来优化代价函数𝐽,我们有很多种工具来解决这个问题,如梯度下降,后面我会介绍其它算法,例如 Momentum,RMSprop 和 Adam 等等,但是优化代价函数𝐽之后,我也不想发生过拟合,也有一些工具可以解决该问题,比如正则化,扩增数据等等。

在机器学习中,超级参数激增,选出可行的算法也变得越来越复杂。我发现,如果我们用一组工具优化代价函数𝐽,机器学习就会变得更简单,在重点优化代价函数𝐽时,你只需要留意𝑤和𝑏,𝐽(𝑤, 𝑏)的值越小越好,你只需要想办法减小这个值,其它的不用关注。然后,预防过拟合还有其他任务,换句话说就是减少方差,这一步我们用另外一套工具来实现,这个原理有时被称为“正交化”。思路就是在一个时间做一个任务,后面课上我会具体介绍正交化,如果你还不了解这个概念,不用担心。

但对我来说 early stopping 的主要缺点就是你不能独立地处理这两个问题,因为提早停止梯度下降,也就是停止了优化代价函数𝐽,因为现在你不再尝试降低代价函数𝐽,所以代价函数𝐽的值可能不够小,同时你又希望不出现过拟合,你没有采取不同的方式来解决这两个问题,而是用一种方法同时解决两个问题,这样做的结果是我要考虑的东西变得更复杂。

如果不用 early stopping,另一种方法就是𝐿2正则化,训练神经网络的时间就可能很长。我发现,这导致超级参数搜索空间更容易分解,也更容易搜索,但是缺点在于,你必须尝试很多正则化参数𝜆的值,这也导致搜索大量𝜆值的计算代价太高。

Early stopping 的优点是,只运行一次梯度下降,你可以找出𝑤的较小值,中间值和较大值,而无需尝试𝐿2正则化超级参数𝜆的很多值。

如果你还不能完全理解这个概念,没关系,下节课我们会详细讲解正交化,这样会更好理解。

虽然𝐿2正则化有缺点,可还是有很多人愿意用它。吴恩达老师个人更倾向于使用𝐿2正则化,尝试许多不同的𝜆值,假设你可以负担大量计算的代价。而使用 early stopping 也能得到相似结果,还不用尝试这么多𝜆值。

这节课我们讲了如何使用数据扩增,以及如何使用 early stopping 降低神经网络中的方差或预防过拟合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/3775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

knife4j 空指针异常

knife4j 空指针异常 一开始正常访问,但是改着改着,就无法访问了,百度了一圈没找到原因,最后对比了之前版本的区别发现这里有问题。最后把这个注解去掉就好了。 只是我本人遇到的问题是这样的,仅供参考

C++对象的初始化和处理

生活中我们买的电子产品都基本会有出厂设置!在某一天我们不用时候也会删除一些自己信息数据保证安全。 C中的面向对象来源于生活,每个对象也都会有初始设置以及对象销毁前的清理数据的设置。 构造函数和析构函数 对象的初始化和清理也是两个非常重要的安全问题 一…

Android Studio布局

文章目录 LinearLayout线性布局排列方向排列位置行列权重 LinearLayout线性布局 从行开始,顶格 排列方向 android:orientation“horizontal”android:orientation“vertical”排列位置 注意layout_width和layout_height的值是match_parent还是wrap_content&…

03_Scala变量和数据类型

文章目录 [toc] **变量和数据类型****1.注释****2.变量和常量****3. 标识符的命名规范****4.scala的字符串****5.键盘输入****5.1 StdIn.readLine()****5.2 从文件中读取数据****5.3 Scala向外写数据** 变量和数据类型 1.注释 和Java完全一样 ** ** 2.变量和常量 var name…

Shell脚本学习记录

0.理解Linux文件权限 0.1 Linux安全性 用户的权限是通过创建用户时分配的用户ID(UID)来追踪的,UID是个数值,每个用户都有一个唯一的UID 0.1.1 /etc/passwd文件 Linux系统使用一个专门的文件/etc/passwd来匹配登录名与对应的UID值,该文件包…

力扣37题:回溯算法之解数独

编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) 数独部分空…

R基本的数据管理

一&#xff0c;创建变量 创建一个数据框 > myData<-data.frame(x1c(1,2,3,4,5,6),x2c(6,5,67,8,9,0)) > myDatax1 x2 1 1 6 2 2 5 3 3 67 4 4 8 5 5 9 6 6 0增加一列为两者的和 > myData$sum<-myData$x1myData$x2 > myDatax1 x2 sum 1 1 6 …

Python浅谈清朝秋海棠叶版图

1、清朝疆域概述&#xff1a; 清朝是我国最后一个封建王朝&#xff0c;其始于1616年建州女真部努尔哈赤建立后金&#xff0c;此后统一女真各部、东北地区。后又降服漠南蒙古&#xff0c;1644年入关打败农民起义军、灭南明&#xff0c;削三藩&#xff0c;复台湾。后又收外蒙&am…

Visual Studio 2022 Professional、Enterprise安装教程

Visual Studio 2022 Professional、Enterprise安装教程 下载安装包安装 我是电脑已经有VS2019&#xff0c;现在加装一个VS2022。 下载安装包 首先下载安装包&#xff0c;进入官网进行下载&#xff0c;VS官网下载地址。 进入之后&#xff0c;会显示如下界面&#xff0c;选择Pro…

安卓NetworkStatsManager使用及demo

目录 一、TrafficStats类简介二、demo示例 一、TrafficStats类简介 TrafficStats Android API 8提供了android.net.TrafficStats类。 通过此类能获取设备重启以来网络信息&#xff0c;部分函数如下所示&#xff1a; static long getMobileRxBytes() //获取通过移动数据网络…

开放式激光振镜运动控制器的视觉校正振镜精度解决方案

市场应用背景 激光振镜控制系统因具有惯量小、低负载、响应速度极快等优点&#xff0c;非常适合高速微加工应用&#xff0c;如激光标刻、焊接、3D打印和精密切割等应用。 激光振镜控制系统主要涵盖了激光振镜控制和图形校正等两个技术层面&#xff0c;来共同控制激光在加工过…

【自动化测试入门】Selenium基础(建议收藏)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

【Android】 四大组件详解之广播接收器、内容提供器

目录 前言广播机制简介系统广播动态注册实现监听网络变化静态注册实现开机自启动 自定义广播发送标准广播发送有序广播 本地广播 内容提供器简介运行时权限访问其他程序中的数据ContentResolver的基本用法读取系统联系人 创建自己的内容提供器创建内容提供器的步骤 跨程序数据共…

vivado 创建和运行链路清扫

创建和运行链路清扫 要分析给定链路的裕度 &#xff0c; 利用不同 MGT 设置来多次运行链路扫描是很有效的。这样有助于判定最佳设置。 Vivado Serial I/O Analyzer 功能支持您定义、运行、保存和重新调用链路清扫 &#xff0c; 链路清扫是由多次链路扫描集合而成的。 每条…

HTML中的文档声明

前言 什么是<!DOCTYPE>&#xff1f;是否需要在 HTML5 中使用&#xff1f;什么是严格模式与混杂模式&#xff1f; 文档声明概念 HTML 文档通常以文档声明开始&#xff0c;该声明的作用是帮助浏览器确定其尝试解析和显示的 HTML 文档类型。 <!DOCTYPE html>文档声…

Allure精通指南(05)定制化报告内容(环境信息、图标、缺陷类别)

文章目录 Allure 自定义测试环境信息Allure 自定义缺陷类别信息Allure 自定义图标步骤一步骤二步骤三 Allure 自定义测试环境信息 步骤 1&#xff1a;创建 environment.properties 文件 在项目根目录或任何其他不会被--clean-alluredir参数影响的目录下创建 environment.proper…

【链表】Leetcode K个一组翻转链表

题目讲解 25. K 个一组翻转链表 算法讲解 虽然这道题是一道困难题&#xff0c;但是从代码层面很简单&#xff0c;只是一道简单的模拟&#xff1a;我们要先求出总共需要翻转的链表有多少组&#xff08;链表的长度 / k&#xff09;&#xff0c;接下来就是翻转k的链表最链接的问…

Tomcat安装步骤及详细配置教程(2022最新版)

网上的tomcat安装及配置教程一大堆&#xff0c;但是好多都过时了&#xff0c;根本不适用现在的版本&#xff0c;今天凯歌整理一篇Tomcat安装步骤及详细配置教程&#xff0c;2022年最新版~ Tomcat安装及配置教程主要分为四步&#xff1a; 步骤一&#xff1a;首先确认自己是否已…

【C++进阶之路】C++11(下) —— 线程库

序言 本篇文章主要是填之前C11留下的坑以及了解与熟悉线程库&#xff0c;有读者感兴趣之前的内容的话可见「C进阶之路」专栏中标题为「C11」的内容&#xff0c;废话不多说&#xff0c;先来概括一下本文的内容&#xff0c;首先我们会从历史的角度分别谈及Linux以及Windows下的线…

JavaEE 初阶篇-深入了解 I/O 高级流(缓冲流、交换流、数据流和序列化流)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 缓冲流概述 1.1 缓冲流的工作原理 1.2 使用缓冲流的步骤 1.3 字节缓冲流于字符缓冲流的区别 1.4 字节缓冲流的实例 1.5 字符缓冲流的实例 2.0 转换流概述 2.1 字符…