激活函数(Activation Function)及十大常见激活函数

news2024/11/17 5:51:04

目录

1 激活函数的概念和作用

1.1 激活函数的概念

1.2 激活函数的作用

1.3 通俗地理解一下激活函数(图文结合)

1.3.1 无激活函数的神经网络

1.3.2 带激活函数的神经网络

2 神经网络梯度消失与梯度爆炸

2.1 简介梯度消失与梯度爆炸

2.2 梯度不稳定问题 

2.3 产生梯度消失的根本原因

2.4 产生梯度爆炸的根本原因

2.5 当激活函数为sigmoid时,梯度消失和梯度爆炸哪个更容易发生

2.6 如何解决梯度消失和梯度爆炸

3 激活函数的比较

3.1 Sigmoid

3.1.1 公式

3.1.2 在什么情况下适合使用Sigmoid激活函数?

3.1.3 缺点

3.2 tanh函数

3.3 ReLU

3.4 Leaky ReLU

3.5 ELU函数

3.6 PReLU

3.7 Softmax

3.8 Swish

3.9 Maxout

3.10 Softplus

4 应用中如何选择合适的激活函数


1 激活函数的概念和作用

1.1 激活函数的概念

    激活函数(Activation Function)是一种添加到人工神经网络中的函数,旨在帮助网络学习数据中的复杂模式。类似于人类大脑中基于神经元的模型,激活函数最终决定了要发射给下一个神经元的内容。

    在人工神经网络中,一个节点的激活函数定义了该节点在给定的输入或输入集合下的输出。标准的计算机芯片电路可以看作是根据输入得到开(1)或关(0)输出的数字电路激活函数。因此,激活函数是确定神经网络输出的数学方程式。

    首先我们来了解一下人工神经元的工作原理,大致如下:

    上述过程的数学可视化过程如下图所示:

1.2 激活函数的作用

    关于神经网络中的激活函数的作用,通常都是这样解释:不使用激活函数的话,神经网络的每层都只是做线性变换,多层输入叠加后也还是线性变换。因为线性模型的表达能力通常不够,所以这时候就体现了激活函数的作用了,激活函数可以引入非线性因素。疑问就来了,激活函数是如何引入非线性因素呢?

1.3 通俗地理解一下激活函数(图文结合)

    为了解释激活函数如何引入非线性因素,接下来让我们以神经网络分割平面空间作为例子。

1.3.1 无激活函数的神经网络

    神经网络最简单的结构就是单输出的单层感知机,单层感知机只有输入层和输出层,分别代表了神经感受器和神经中枢。下图是一个只有两个输入单元和一个输出单元的简单单层感知机。图中x1,x2代表神经网络的输入神经元受到的刺激,w1,w2代表输入神经元和输出神经元间链接的紧密程度,b代表输出神经元的兴奋阈值,y为输出神经元的输出。我们使用该单层感知机划出一条线将平面分隔开,如图所示:

    同理,我们也可以将多个感知机(注意,不是多层感知机)进行组合获得更强的平面分类能力,如图所示:

    再看一看包含一个隐层的多层感知机的情况,如图所示: 

    通过对比可以发现,上面三种没有激励函数的神经网络的输出都是线性方程,其都是在用复杂的线性组合来试图逼近曲线。 

1.3.2 带激活函数的神经网络

    让我们在神经网络每一层神经元做完线性变换以后,加上一个非线性激活函数对线性变换的结果进行转换,结果显而易见,输出立马变成一个不折不扣的非线性函数了。

    拓展到多层神经网络的情况,和刚刚一样的结构,加非线性激活函数之后,输出就变成了一个复杂的非线性函数了,如图所示:

    总结:加入非线性激活函数后,神经网络就有可能学习到平滑的曲线来分割平面,而不是用复杂的线性组合逼近平滑曲线来分割平面,使神经网络的表示能力更强了,能够更好的拟合目标函数。这就是为什么我们要有非线性的激活函数的原因。。如下图所示说明加入非线性激活函数后的差异,上图为用线性组合逼近平滑曲线来分割平面,下图为平滑的曲线来分割平面:

2 神经网络梯度消失与梯度爆炸

2.1 简介梯度消失与梯度爆炸

    层数较多的神经网络模型在训练的时候会出现梯度消失(gradient vanishing problem)和梯度爆炸(gradient exploding problem)问题。梯度消失问题和梯度爆炸问题一般会随着网络层数的增加变得越来越明显。

    例如,对于下图所示的含有三个隐藏层的神经网络:

    →梯度消失问题发生时,靠近输出层的hidden layer3的权值更新相对正常,但是靠近输入层的hidden layer1的权值更新会变得很慢,导致靠近输入层的隐藏层权值几乎不变,仍接近于初始化的权值。这就导致hidden layer1相当于只是一个映射层,对所有的输入做了一个函数映射,这时此深度神经网络的学习就等价于只有后几层的隐藏层网络在学习。

    →梯度爆炸的情况是:当初始的权值过大,靠近输入层的hidden layer1的权值变化比靠近输出层的hidden layer3的权值变化更快,就会引起梯度爆炸的问题。

2.2 梯度不稳定问题 

    在深度神经网络中的梯度是不稳定的,在靠近输入层的隐藏层中或会消失,或会爆炸。这种不稳定性才是深度神经网络中基于梯度学习的根本问题。

    梯度不稳定的原因:前面层上的梯度是来自后面层上梯度的乘积。当存在过多的层时,就会出现梯度不稳定场景,比如梯度消失和梯度爆炸。

2.3 产生梯度消失的根本原因

    我们以图2的反向传播为例,假设每一层只有一个神经元且对于每一层都可以用公式1表示,其中\sigma为sigmoid函数,C表示的是代价函数,前一层的输出和后一层的输入关系如公式1所示。我们可以推导出公式2。

    而sigmoid函数的导数{\sigma }'(x)如下图右图所示。 

    可见, {\sigma }'(x)的最大值为1/4,而我们一般会使用标准方法来初始化网络权重,即使用一个均值为0标准差为1的高斯分布。因此,初始化的网络权值通常都小于1,从而有\left |{\sigma }'(z)\omega \right | \leq \frac{1}{4}。对于2式的链式求导,层数越多,求导结果越小,最终导致梯度消失的情况出现。

    对于上图,\frac{\partial C}{\partial b_{1}}和 \frac{\partial C}{\partial b_{3}}有共同的求导项。可以看出,前面的网络层比后面的网络层梯度变化更小,故权值变化缓慢,从而引起了梯度消失问题。

2.4 产生梯度爆炸的根本原因

    当\left |{\sigma }'(z)\omega \right | > 1,也就是W比较大的情况。则前面的网络层比后面的网络层梯度变化更快,引起了梯度爆炸的问题。

2.5 当激活函数为sigmoid时,梯度消失和梯度爆炸哪个更容易发生

    结论:梯度爆炸问题在使用sigmoid激活函数时,出现的情况较少,不容易发生。

    量化分析梯度爆炸时x的取值范围:因导数最大为0.25,故\left | w \right | > 4,才可能出现\left |{\sigma }'(z)\omega \right | > 1;按照\left |{\sigma }'(wx + b)\omega \right | > 1可计算出x的数值变化范围很窄,仅在公式3范围内,才会出现梯度爆炸。画图如5所示,可见x的数值变化范围很小;最大数值范围也仅仅0.45,当\left | w \right | = 6.9时出现。因此仅仅在此很窄的范围内会出现梯度爆炸的问题。

2.6 如何解决梯度消失和梯度爆炸

    梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。对于更普遍的梯度消失问题,可以考虑以下三种方案解决:

1、用ReLU、Leaky-ReLU、P-ReLU、R-ReLU、Maxout等替代sigmod函数。

2、用Batch Normalization。

3、LSTM的结构设计也可以改善RNN中的梯度消失问题。

3 激活函数的比较

    反之,不满足以上条件的函数则称为非饱和激活函数。

    sigmoid和tanh是“饱和激活函数”,而ReLU及其变体则是“非饱和激活函数”。使用“非饱和激活函数”的优势在于两点:(1)“非饱和激活函数”能解决所谓的“梯度消失”问题。(2)它能加快收敛速度。

    →Sigmoid函数将一个实值输入压缩至[0,1]的范围---------σ(x) = 1 / (1 + exp(−x))

    →tanh函数将一个实值输入压缩至 [-1, 1]的范围---------tanh(x) = 2σ(2x) − 1

    由于使用sigmoid激活函数会造成神经网络的梯度消失和梯度爆炸的问题,所以许多人提出了一些改进的激活函数,如:tanh、ReLU、LeakyReLU、PReLU、RReLU、ELU、Maxout。

3.1 Sigmoid

3.1.1 公式

    Sigmoid(s形)是常用的非线性的激活函数,它的数学公式如下:

    特点:它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的实数,那么输出就是0;如果是非常大的正数,输出就是1。

    Sigmoid函数是深度学习领域开始时使用频率最高的activation function。它是便于求导的平滑函数。

3.1.2 在什么情况下适合使用Sigmoid激活函数?

1、Sigmoid函数的输出范围是0到1,。由于输出值限定在0到1,因此它对每个神经元的输出进行了归一化。

2、用于将预测概率作为输出的模型。由于概率的取值范围是0到1,因此Sigmoid函数非常适合。

3、梯度平滑,避免跳跃的输出值。

4、函数是可微的,这意味着可以找到任意两个点的Sigmoid曲线的斜率。

5、明确的预测,即非常接近1或0。

3.1.3 缺点

1、容易出现梯度消失。

2、函数输出并不是zero-centered。

3、幂运算相对来讲比较耗时。

(1)梯度消失

    优化神经网络的方法是反向传播,即导数的后向传递:先计算输出层对应的loss,然后将loss以导数的形式不断向上一层神经网络传递,修正相应的参数,达到降低loss的目的。Sigmoid函数在深度网络中常常会导致导数逐渐变为0,使得参数无法被更新,神经网络无法被优化,原因在于两点:

    1、在上图中容易看出,当\sigma (x)中x较大或较小时,导数接近0,而向后传递的数学依据是微积分求导的链式法则,当前层的导数需要之前各层导数的乘积,几个小数的相乘,结果会很接近0。

    2、Simoid导数的最大值是0.25,这意味着导数在每一层至少会被压缩为原来的1/4,通过两层之后变为1/16,.... , 通过10层以后为1/1048576.请注意这里是“至少”,导数达到最大值这种情况还是很少见的。

(2)输出不是zero-centered

    Sigmoid函数的输出值恒大于0,这会导致模型训练的收敛速度变慢。举例来讲,对

来讲,如果所有xi均为正数或负数,那么其对wi的导数总是正数或负数,这会导致如下图红色箭头所示的阶梯式更新,这显然并非一个好的优化路径。深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以总体来讲,训练深度学习网络尽量使用zero-centered数据(可以经过数据预处理实现)和zero-centered输出。

    不是zero-centered产生的一个结果就是:如果数据进入神经元的时候是正的,那么w计算出的梯度也会始终是正的。当然了,如果你是按batch去训练,那么batch可能得到不同的信号,所以这个问题还是可以缓解一下的。因此,非0均值这个问题虽然会产生一些不好的影响,不过跟上面提到的kill gradients问题相比还是要好很多的。 

(3)幂运算相对耗时

    相对于前两项,这其实并不是一个大问题,我们目前是具备相应计算能力的,但面对深度学习中庞大的计算量,最好是能省就省。之后我们会看到,在R额LU函数中,需要做的仅仅是一个thresholding,相对于幂运算来讲会快很多。

3.2 tanh函数

    tanh激活函数的图像也是s形,表达式如下:

    tanh读作Hyperbolic Tangent(双曲正切),如上图所示,它解决了zero-centered的输出问题,然而梯度消失的问题和幂运算的问题仍然存在。

    tanh是一个双曲正切函数。tanh函数和sigmoid函数的曲线相对相似,但是它比sigmoid函数更有一些优势。 

图片

    1、首先,在输入较大或较小时,输出几乎是平滑的并且梯度较小,这不利于权重更新。二者的区别在于输出间隔,tanh的输出间隔为1(x>=0 y∈[0,1)),并且整个函数以0为中心,比sigmoid函数更好。

    2、在tanh图中,负输入将被强映射为负,而零输入被映射为接近零。

    注意:在一般的二元分类问题中,tanh函数用于隐藏层,而sigmoid函数用于输出层,但这都不是固定的,需要根据特定问题进行调整。 

3.3 ReLU

    近年来,ReLU函数变得越来越受欢迎。全称是Rectified Linear Unit(修正线性单元)。ReLU是Krizhevsky、Hinton等人在2012年《ImageNet Classification with Deep Convolutional Neural Networks》论文中提出的一种线性且不饱和的激活函数。它的数学表达式:

    ReLU函数其实就是一个取最大值函数,注意这并不是全区间可导的,但是我们可以取sub-gradient,如上图所示。ReLU虽然简单,但却是这几年的重要成果,有以下几大优点:

1、解决了gradient vanishing问题(在正区间上)。

2、 Sigmoid和tanh激活函数均需要计算指数,复杂度高,而ReLU只需要一个阈值即可得到激活值。ReLU函数中只存在线性关系,因此它的计算速度比Sigmoid和tanh更快。计算速度非常快,只需要判断输入是否大于0。

3、收敛速度远快于sigmoid和tanh。

4、ReLU的非饱和性可以有效地解决梯度消失的问题,提供相对宽的激活边界。

5、ReLU的单侧抑制提供了网络的稀疏表达能力。

    ReLU也有几个需要特别注意的问题:

1、ReLU函数的输出为0或正数,不是zero-centered。

2、Dead ReLU Problem,指的是某些神经元可能永远都不会被激活,导致相应的参数永远不能被更新。这是由于函数f(x) = max(0,z),导致负梯度在经过ReLU单元时被设置为0,且在之后也不被任何数据激活,即流经该神经元的梯度永远为0,不对任何数据产生影响。当输入为负时,ReLU完全失效,在正向传播过程中,这不是问题。有些区域很敏感,有些则不敏感。但是在反向传播过程中,如果输入负数,则梯度完全为0,sigmoid函数和tanh函数也具有相同的问题。有两个主要原因可能导致这种情况产生:(1)非常不幸的参数初始化,这种情况比较少见(2)learning rate太高导致在训练过程中参数更新太大,会导致超过一定比例的神经元不可逆死亡,进而参数梯度无法更新,整个训练过程失败。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或者使用adagrad等自动调节learning rate的算法。

    尽管存在这两个问题,ReLU目前仍然是最常用的activation function,在搭建人工神经网络的时候推荐优先尝试!

3.4 Leaky ReLU

    人们为了解决Dead ReLU Problem, 提出了将ReLU的前半段设为0.01而非0。注意看,在负区间上不等于0。

    为什么Leaky ReLU比ReLU更好?

1、Leaky ReLU通过把x非常小的线性分量给予负输入(0.01x)来调整负值的零梯度(zero gradients)问题。

2、leak有利于扩大ReLU函数的范围,通常a的值为0.01左右。

3、Leaky ReLU的函数范围是(负无穷到正无穷)

    但另一方面,a值的选择增加了问题难度,需要较强的人工经验或多次重复训练以确定合适的参数值。

    注意:从理论上讲,Leaky ReLU具有ReLU的所有优点,而且Dead ReLU不会有任何问题,但在实际操作中,尚未完全证明Leaky ReLU总是比ReLU更好。

3.5 ELU函数

    ELU(Exponential Linear Units)指数线性单位的提出也解决了ReLU的问题。与ReLU相比,ELU有负值,这会使激活的平均值接近零。均值激活接近于零可以使学习更快,因为它们使梯度更接近自然梯度。

    显然,ELU具有ReLU的所有优点,并且:

1、没有Dead ReLU问题,输出的平均值接近0,以0为中心。

2、ELU通过减少偏置偏移的影响,使正常梯度更接近于自然单位梯度,从而使均值像0加速学习。

3、ELU在较小的输入下会饱和至负值,从而减少前向传播的变异和信息。

    一个小问题是它的计算强度更高。与Leaky ReLU类似,尽管理论上比ReLU更好,但目前在实践中没有充分的证据表明ELU总是比ReLU好。 

3.6 PReLU

    PReLU也是ReLU的改进版本,想法是基于参数的方法,即Parametric ReLU: ,其中\alpha可由back propagation学出来。

    Kaiming He的论文《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》指出,不仅可以训练,而且效果更好。

    看一下PReLU的公式:参数\alpha通常为0到1之间的数字,并且通常相对较小。

1、如果a_i = 0, 则f变为ReLU。

2、如果a_i > 0, 则f变为leaky ReLU。

3、如果a_i是可学习的参数,则f变为PReLU。 

    PReLU的优点如下:

1、在负值域,PReLU的斜率较小,这样也可以避免Dead ReLU问题。

2、与ELU相比,PReLU在负值域是线性运算,尽管斜率很小,但不会趋于0。

3.7 Softmax

    Softmax是用于多分类问题的激活函数,在多类分类问题中,超过两个类标签则需要类成员关系。对于长度为k的任意实向量,Softmax可以将其压缩为长度为k,值在(0,1)范围内,并且向量中元素的总和为1的实向量。

    Softmax与正常的max函数不同:max函数仅输出最大值,但Softmax确保较小的值具有较小的概率,并且不会直接丢弃。我们可以认为它是argmax函数的概率版本或[soft]版本。

    Softmax函数的分母结合了原始输出值的所有因子,这意味着Softmax函数获得各种概率彼此相关。

    Softmax函数的主要缺点是:

1、在零点不可微

2、负输入的梯度为0,这意味着对于该区域的激活,权重不会在反向传播期间更新,因此会产生永不激活的死亡神经。

3.8 Swish

    函数表达式:y = x * sigmoid(x)

    Swish的设计受到了LSTM和高速网络中gating的sigmoid函数使用的启发。我们使用相同的gating值来简化gating机制,这称为self-gating。

    self-gating的优点在于它只需要简单的标量输入,而普通的gating则需要多个标量输入。这使得诸如Swish之类的self-gated激活函数能够轻松替换以单个标量为输入的激活函数(例如ReLU),而无需更改隐藏容量或参数数量。

    Swish激活函数的主要优点如下:

1、无界性:有助于防止慢速训练期间,梯度逐渐接近0并导致饱和(同时,有界性也是有优势的,因为有界激活函数可以具有很强的正则化,并且较大的负输入问题也能解决)。

2、导数恒大于0。

3、平滑度在优化和泛化中起了重要作用。 

3.9 Maxout

    这个函数可以参考论文《maxout networks》,Maxout是深度学习网络中的一层网络,就像池化层、卷积层一样等,我们可以把maxout看出是网络的激活函数层,我们假设网络某一层的输入特征向量为:X = (x1,x2,..., xd), 也就是我们输入是d个神经元。Maxout隐藏层每个神经元的计算公式如下:

    上面的公式就是maxout隐藏层神经元i的计算公式。其中k就是maxout层所需要的参数了,由我们人为设定大小。就像dropout一样,也有自己的参数p(每个神经元dropout概率),maxout的参数是k。公式中z的计算公式为:

    权重w是一个大小为(d,m,k)三维矩阵,b是一个大小为(m,k)的二维矩阵,这两个就是我们需要学习的参数。如果我们设定参数k = 1, 那么这个时候,网络就类似于以前我们所学普通的MLP网络。

    我们可以这么理解,本来传统的MLP算法在第i层到第i+1层,参数只有一组,然而现在我们不这么干了,我们在这一层同时训练n组的w,b参数,然后选择激活值z最大的作为下一层神经元的激活值,这个max(z)函数即充当了激活函数。 

    在Maxout层,激活函数是输入的最大值,因此只有2个maxout节点的多层感知机就可以拟合任意的凸函数。

    单个Maxout节点可以解释为对一个实值函数进行分段线性近似(PWL),其中函数图上任意两点之间的线段位于图(凸函数)的上方。

    Maxout也可以对d维向量(V)实现:

    假设两个凸函数h_1(x)和h_2(x),由两个Maxout节点近似化,函数g(x)是连续的PWL函数。

    因此,由两个Maxout节点组成的Maxout层可以很好地近似任何连续函数。

3.10 Softplus

    Softplus 函数:f(x)= ln(1 + exp x),Softplus 的导数为:f ′(x)=exp(x) / ( 1+exp⁡ x ) = 1/ (1 +exp(−x )),也称为 logistic / sigmoid 函数。Softplus 函数类似于 ReLU 函数,但是相对较平滑,像 ReLU 一样是单侧抑制。它的接受范围很广:(0, + inf)。

4 应用中如何选择合适的激活函数

    这个问题目前没有确定的方法,凭一些经验吧。

1、深度学习往往需要大量时间来处理数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量选择输出具有zero-centered数据(可以经过数据预处理实现)和zero-centered输出。所以要尽量选择输出具有zero-centered特点的激活函数以加快模型的收敛速度。

2、如果使用ReLU,那么一定要小心设置learning rate, 而且要注意不要让网络出现很多“dead”神经元,如果这个问题不好解决,可以试试Leaky ReLU、PReLU或者Maxout。

3、最好不要使用sigmoid,你可以试试tanh,不过可以预期它的效果会比不上ReLU和Maxout。

本文参考:激活函数(Activation Function)_意念回复的博客-CSDN博客

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

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

相关文章

asp.net+C#房地产销售系统文献综述和开题报告+Lw

本系统使用了B/S模式,使用ASP.NET语言和SQL Server来设计开发的。首先把所有人分为了用户和管理员2个部分,一般的用户可以对系统的前台进行访问,对一般的信息进行查看,而注册用户就可以通过登录来完成对房屋信息的查看和对房屋的…

动态通讯录——C语言【详解+全部码源】

作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏:进阶C语言,本专栏主要讲解数据存储,进阶指针,动态内存管理&a…

企业数据安全能力建设思路

在现代社会,企业数据安全已经成为一个非常重要的话题。企业数据安全能力的建设是每个企业都必须面对和解决的问题。企业数据安全能力建设思路包括以下几个方面: 1. 建立完善的安全管理制度 企业要建立完善的安全管理制度,包括信息安全政策、…

[入门必看]数据结构5.1:树的基本概念

[入门必看]数据结构5.1:树的基本概念 第五章 树与二叉树5.1 树的基本概念知识总览5.1.15.1.2 树的定义和基本术语5.1.3 树的性质 5.1.15.1.2 树的定义和基本术语树的基本概念树形逻辑结构的应用结点之间的关系描述结点、树的属性描述有序树 V.S 无序树树 V.S 森林 5…

软考 软件设计师上午题uml

UML uml事物依赖关系关联聚合组合关系泛化关系实现关系关联多重度UML类图UML 类图的概念对象图用例图包含关系扩展关系泛化关系用例图概念交互图通信图![在这里插入图片描述](https://img-blog.csdnimg.cn/d62c6f00d57a48949e3306461f3fbe25.png)通信图例子状态图状态图的状态和…

# 生成器

生成器 生成器是什么? 生成器(generator)是一种用来生成数据的对象。它们是普通函数的一种特殊形式,可以用来控制数据的生成过程。 生成器有什么优势? 使用生成器的优势在于它们可以在生成数据的同时控制数据的生成过程…

android ContentObserver实时监测媒体图片增删改,java(1)

android ContentObserver实时监测媒体图片增删改,java&#xff08;1&#xff09; <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.READ_MEDIA_IMAGES" /> impl…

七、JS07使用 jQuery 操作 DOM

七、使用 jQuery 操作 DOM 7.1 DOM 操作 7.1.1 DOM 操作分类 使用 JavaScript 操作 DOM 时分为三类——DOM Core(核心)、HTML-DOM 和 CSS-DOMjQuery 操作也同样分为这三类下面主要回顾以下 JavaScript 中的 DOM 操作 JavaScript 中的 getElementById()、getElementByTagName…

c++内联函数inline

目录 内联函数的概念&#xff1a; 内联函数的用法&#xff1a; 内联的优点&#xff1a; 内联的缺点&#xff1a; 内联的使用场景 内联注意事项&#xff1a; 内联函数的概念&#xff1a; C中内联&#xff08;inline&#xff09;是一种关键字&#xff0c;用于告诉编译器把函…

以太网和DNS

以太网 数据链路层考虑的是相邻俩个节点之间的传输(通过网线/光纤/无线直接相连的设备),数据链路层中最典型的协议就说"以太网" 以太网协议规定了数据链路层,也规定了物理层的内容,我们使用的网线,也叫做"以太网线"(遵守以太网协议的网线) 以太网帧格式…

使用RecyclerView开发TabView

github链接 demo代码 效果图 这个功能是使用RecyclerView开发的&#xff0c;需要解决下面这些问题 单个item滚动的问题&#xff1a;左边的view需要固定、手指松开之后&#xff0c;惯性的处理滑动布局子View事件分发冲突的解决多个item联合滚动滚动header解决itemView与Recycl…

【MYSQL】表的增删改查(进阶)

文章目录 &#x1f337; 1. 数据库约束⭐ 1.1 约束类型⭐ 1.2 NULL约束⭐ 1.3 UNIQUE&#xff1a;唯一约束⭐ 1.4 DEFAULT&#xff1a;默认值约束⭐ 1.5 PRIMARY KEY&#xff1a;主键约束⭐ 1.6 FOREIGN KEY&#xff1a;外键约束⭐ 1.7 CHECK约束&#xff08;了解&#xff09; …

实在智能创意沙画引爆第25届“海博会”,数字员工为电商超自动化转型加“数”

4月18日&#xff0c;由中国纺织工业联合会、中国服装协会、中国服装设计师协会、台湾纺织业拓展会主办&#xff0c;石狮市人民政府指导的第二十五届海峡两岸纺织服装博览会暨科技成果交易会&#xff08;下称“海博会”&#xff09;在石狮市举行。本届海博会以“融合创新、共享时…

Android Jetpack 应用指南 - Navigation

前言 在Android开发的过去几年中&#xff0c;在公司的项目中一直没有机会尝试单Activity多Fragment的开发模式&#xff0c;随着Google推出Navigation组件&#xff0c;我意识到&#xff0c;终于有机会学习一种全新的开发模式了。 与上一篇文章相同&#xff0c;本篇同样是Navig…

Lenovo IdeaPad S540-14IML 电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。&#xff08;下载请直接百度黑果魏叔&#xff09; 硬件型号驱动情况 主板Lenovo IdeaPad S540-14IML 2019 (Type 81NF) 处理器Intel Core i5-10210U / i7-10510U已驱动 内存Internal 4GB 2666 Changeable 8GB 2666 memo…

Android进程间通信

在操作系统中&#xff0c;每个进程都有一块独立的内存空间。为了保证程序的的安全性&#xff0c;操作系统都会有一套严格的安全机制来禁止进程间的非法访问&#xff0c;但是&#xff0c;很多情况下进程间也是需要相互通信的 进程间通信&#xff08;Inter-process communication…

嵌入式学习笔记——SPI通信的应用

SPI通信的应用 前言屏幕分类1.3OLED概述驱动芯片框图原理图通信时序显示的方式页地址、列地址初始化指令 程序设计初始化代码初始化写数据与写命令清屏函数 初始化代码字符显示函数 总结 前言 上一篇中介绍了STM32的SPI通信&#xff0c;并根据框图和寄存器进行了SPI通信的初始…

轻松掌握k8s(使用docker)安装知识点

1、介绍 kubernetes具有以下特性&#xff1a; 服务发现和负载均衡 Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器&#xff0c;如果进入容器的流量很大&#xff0c; Kubernetes 可以负载均衡并分配网络流量&#xff0c;从而使部署稳定。存储编排 Kubernetes 允许你自…

【数据库】— 无损连接、Chase算法、保持函数依赖

【数据库】— 无损连接、Chase算法 Chase算法Chase算法举例一种简便方法&#xff1a;分解为两个模式时无损连接和函数依赖的一个简单例子 Chase算法 形式化定义&#xff1a; 构造一个 k k k行 n n n列的表格&#xff0c;每行对应一个模式 R i ( 1 ≤ i ≤ k ) Ri (1≤i ≤ k)…

计算机组成原理汇总

提示&#xff1a;日落归山海&#xff0c;山海藏深情 文章目录 1.1 计算机的发展1.2 计算机硬件的基本组成1.3 计算机的性能指标2.1.1 进位计数制2.1.2 BCD码2.1.3 无符号整数的表示和运算2.1.4 带符号整数的表示和运算(原反补)2.1.5原反补码的特性对比2.1.6 移码2.1.7 定点小数…