当前位置: 首页 > news >正文

神经网络系列---激活函数


文章目录

    • 激活函数
      • Sigmoid 激活函数
      • Tanh激活函数
      • ReLU激活函数
      • Leaky ReLU激活函数
      • Parametric ReLU激活函数 (自适应Leaky ReLU激活函数)
      • ELU激活函数
      • SeLU激活函数
      • Softmax 激活函数
      • Swish 激活函数
      • Maxout激活函数
      • Softplus激活函数


激活函数

在这里插入图片描述

一般来说,在神经元中,激活函数是很重要的一部分,为了增强网络的表示能力和学习能力,神经网络的激活函数都是非线性的,通常具有以下几点性质:

  • 连续并可导(允许少数点上不可导),可导的激活函数可以直接利用数值优化的方法来学习网络参数;
  • 激活函数及其导数要尽可能简单一些,太复杂不利于提高网络计算率;
  • 激活函数的导函数值域要在一个合适的区间内,不能太大也不能太小,否则会影响训练的效率和稳定性。

Sigmoid 激活函数

Sigmoid函数,也称为Logistic函数,是一种常用的激活函数之一。它将输入值映射到一个介于0和1之间的连续输出值。

Sigmoid函数的数学表达式为:

数学推导:
对Sigmoid函数f(x) = 1 / (1 + exp(-x)),我们可以通过链式法则对其求导。首先,我们计算Sigmoid函数的导数f'(x):
f'(x) = d/dx(1 / (1 + exp(-x)))接下来,我们将求导式进行变形,以便更方便地计算:
f'(x) = 1 / (1 + exp(-x))^2 * exp(-x)因此,Sigmoid函数的导数f'(x)的表达式为:
f'(x) = f(x) * (1 - f(x))这个表达式可以用于计算任意输入x处的Sigmoid函数的导数。

在这里插入图片描述

C++实现Sigmoid函数的示例代码:

#include <cmath>// Sigmoid函数的实现
double sigmoid(double x) {return 1.0 / (1.0 + exp(-x));
}// Sigmoid函数的导数实现
double sigmoidDerivative(double x) {double fx = sigmoid(x);return fx * (1.0 - fx);
}int main() {double x = 2.0; // 示例输入值// 调用Sigmoid函数计算输出double result = sigmoid(x);// 调用Sigmoid函数的导数计算输出double derivative = sigmoidDerivative(x);// 输出结果printf("Sigmoid(%f) = %f\n", x, result);printf("Sigmoid的导数(%f) = %f\n", x, derivative);return 0;
}

其中,exp表示自然常数e(约等于2.71828)的指数函数。

Sigmoid函数的特点是在输入值较大或较小时,输出接近于1或0,而在输入值接近0时,输出接近于0.5。这种S型曲线形状使得Sigmoid函数在二分类问题中常被用作输出层的激活函数,将输出解释为概率值,表示正类的概率。

Sigmoid函数具有以下优点和缺点:

优点:

  1. 可以将输入映射到介于0和1之间的概率值,适用于二分类问题中将输出解释为概率的情况。
  2. Sigmoid函数在输入接近0时,输出接近于0.5,具有平滑的、连续的特性。
  3. Sigmoid函数具有可导性,这对于使用梯度下降等基于梯度的优化算法进行模型训练是重要的。

缺点:

  1. Sigmoid函数在输入较大或较小的情况下,输出接近于0或1,导致梯度饱和,使得反向传播时梯度变得非常小,造成梯度消失的问题。这限制了Sigmoid函数在深度神经网络中的应用。
  2. Sigmoid函数的指数计算较为复杂,相比于其他激活函数,计算代价较高。
  3. Sigmoid函数输出的值不是以0为中心的,即其输出均值不为0,这可能导致网络在训练过程中的收敛速度变慢。

综上所述,尽管Sigmoid函数在过去被广泛应用于神经网络中,但随着深度学习的发展,人们更倾向于使用其他激活函数,如ReLU及其变种,因为它们能够缓解梯度消失问题并提供更好的性能。然而,在某些特定情况下,Sigmoid函数仍然可以有所用处,例如需要将输出解释为概率的二分类问题。

Tanh激活函数

Tanh函数(双曲正切函数)是一种常用的激活函数,它将输入值映射到一个介于-1和1之间的连续输出值。

Tanh函数的数学表达式为:

数学推导:
Tanh函数的数学表达式为:f(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))我们可以通过对Tanh函数进行求导,得到其导数的数学表达式。首先,我们令y = Tanh(x),则Tanh函数可以表示为:y = (exp(x) - exp(-x)) / (exp(x) + exp(-x))对y求导,即计算dy/dx。使用除法的求导法则和指数函数的求导法则,我们可以得到:dy/dx = [(exp(x) + exp(-x))(exp(x) + exp(-x)) - (exp(x) - exp(-x))(exp(x) - exp(-x))] / (exp(x) + exp(-x))^2化简上述表达式,我们可以得到Tanh函数的导数的数学表达式:dy/dx = 1 - (Tanh(x))^2因此,Tanh函数的导数为 1 减去其本身的平方。

在这里插入图片描述
Tanh函数可以看作是Sigmoid函数的变种,它具有Sigmoid函数的S型曲线形状,但输出范围更广,从-1到1。

Tanh函数的特点包括:

  1. 在输入接近0时,输出接近于0,具有零中心化的特性。
  2. Tanh函数的输出在输入为负时接近于-1,在输入为正时接近于1。
  3. Tanh函数是可导的,对于使用梯度下降等基于梯度的优化算法进行模型训练是可行的。

以下是使用C++实现Tanh函数的示例代码:

#include <cmath>// Tanh函数的实现
double tanh(double x) {return (exp(x) - exp(-x)) / (exp(x) + exp(-x));
}// Tanh函数的导数实现
double tanh_derivative(double x) {double tanh_x = tanh(x);return 1 - tanh_x * tanh_x;
}int main() {double x = 2.0; // 示例输入值// 调用Tanh函数计算输出double result = tanh(x);// 调用Tanh函数的导数计算输出double derivative = tanh_derivative(x);// 输出结果printf("Tanh(%f) = %f\n", x, result);printf("Tanh Derivative(%f) = %f\n", x, derivative);return 0;
}

Tanh函数(双曲正切函数)具有以下优点和缺点:

优点:

  1. Tanh函数的输出范围是介于-1和1之间,相比于Sigmoid函数,Tanh函数的输出具有零中心化的特性,使得数据在处理时更接近原点。
  2. Tanh函数在输入接近0时,输出接近于0,可以将数据映射到更接近原点的区域,有助于模型的收敛。
  3. Tanh函数是可导的,对于使用梯度下降等基于梯度的优化算法进行模型训练是可行的。

缺点:

  1. Tanh函数在输入较大或较小的情况下,输出接近于1或-1,导致梯度饱和,使得反向传播时梯度变得非常小,造成梯度消失的问题,尤其在深度神经网络中。
  2. Tanh函数的指数计算较为复杂,相比于其他激活函数,计算代价较高。
  3. Tanh函数的输出值域为[-1, 1],这使得它对于某些任务而言,可能不是最优的激活函数选择。

综上所述,尽管Tanh函数具有一些优点,但在深度神经网络中,它容易出现梯度消失的问题,因此在实践中,ReLU及其变种等激活函数更常用。然而,Tanh函数仍然可以在特定情况下使用,例如需要将输出值范围控制在[-1, 1]之间的任务,或者在某些循环神经网络(RNN)的隐藏层中使用。

ReLU激活函数

ReLU(Rectified Linear Unit)函数是一种常用的激活函数,它在深度学习中广泛使用,特别是在卷积神经网络(CNN)中。

ReLU函数的定义很简单:

ReLU函数的数学表达式为:f(x) = max(0, x)ReLU函数在输入大于0时的导数为1,在输入小于等于0时的导数为0。数学推导如下:当 x > 0 时,ReLU函数为 f(x) = x。其导数为:f'(x) = 1当 x <= 0 时,ReLU函数为 f(x) = 0。其导数为:f'(x) = 0

在这里插入图片描述

以下是使用C++实现ReLU激活函数的示例代码:

// ReLU函数的实现
double relu(double x) {return (x > 0) ? x : 0;
}// ReLU函数的导数实现
double relu_derivative(double x) {return (x > 0) ? 1 : 0;
}

在这个示例代码中,relu()函数接受一个double类型的输入值x,并返回计算得到的ReLU函数的输出值。在函数内部,使用条件运算符(三元运算符)判断x是否大于0,如果是,则返回x,否则返回0。

main()函数中,我们提供一个示例输入值x,然后调用relu()函数计算输出结果,并使用printf()函数打印结果。

这只是一个简单的示例代码,您可以根据自己的需求进行扩展和修改。

即,对于输入x,如果x大于0,则输出x,否则输出0。

ReLU函数优缺点:
优点:

  1. 简单有效:ReLU函数的计算非常简单,只需比较输入和0的大小并取最大值。这使得ReLU函数的计算速度非常快,尤其对于大规模深度神经网络而言,具有重要意义。
  2. 解决梯度消失问题:相对于Sigmoid和Tanh等传统激活函数,ReLU函数在正区间(输入大于0)上具有线性特性,梯度恒定为1,不会出现梯度消失问题。这有助于有效传播梯度,促进模型的收敛。
  3. 增强稀疏性:ReLU函数在负区间(输入小于0)上的输出值为0,这种“激活稀疏性”可以使得神经网络中的许多神经元处于非激活状态,从而减少参数冗余和计算负载,提高模型的效率和泛化能力。

缺点:

  1. Dead ReLU问题:当输入小于等于0时,ReLU函数的输出恒为0,这时该神经元对应的权重无法更新,可能会导致神经元“死亡”,不再对任何输入产生响应。这一问题在训练过程中需要特别注意,可以通过使用Leaky ReLU或其他变种来缓解。
  2. 不是零中心化:ReLU函数的输出范围是从0开始的正半轴,不是以0为中心的。这可能导致某些优化算法对权重的更新过程受到一定影响。

综上所述,ReLU函数由于其简单性、解决梯度消失问题的能力和稀疏性增强的特性,成为了深度学习中最常用的激活函数之一。然而,在使用ReLU函数时,需要注意Dead ReLU问题和零中心化的影响,可能需要采取一些技巧和变种来处理这些问题。

Leaky ReLU激活函数

Leaky ReLU (Rectified Linear Unit) 是一种常用的激活函数,它是对传统的 ReLU 函数的改进。ReLU 函数在输入为负数时输出为零,这可能导致神经元的死亡,即该神经元在训练过程中不再激活。

为了解决这个问题,Leaky ReLU 引入了一个小的斜率(slope)参数,当输入为负数时,它会乘以这个斜率而不是输出零。这样,Leaky ReLU 允许一小部分负值通过,并给神经元提供了一个非零的输出。

Leaky ReLU 函数的数学定义如下:f(x) = max(ax, x)其中,a是一个小于1的正数,用来控制负值区域的斜率。为了计算Leaky ReLU函数的导数,需要分别考虑两个区域:x > 0 和 x <= 0。当 x > 0 时,函数的导数为1,即 f'(x) = 1。当 x <= 0 时,函数的导数为 a,即 f'(x) = a。因此,Leaky ReLU函数的导数可以表示为:f'(x) = 1, if x > 0a, if x <= 0

在这里插入图片描述

其中,a 是一个小的正数,通常取较小的值,如0.01。当 a = 0 时,Leaky ReLU 退化为传统的 ReLU 函数。

Leaky ReLU 的主要优点是它在解决梯度消失问题方面比传统的 ReLU 函数更有效。由于在负值区域存在斜率,Leaky ReLU 可以传播梯度,使得神经网络的训练更稳定。此外,Leaky ReLU 保留了大部分的稀疏激活性质,即只有少数神经元被激活,这有助于减少模型的复杂性。

然而,Leaky ReLU 也存在一些缺点。由于负值区域的斜率是一个固定的超参数,它需要手动选择,并且可能会对模型的性能产生一定的影响。此外,Leaky ReLU 在解决梯度死亡问题方面仍然不如一些其他激活函数,如 ELU (Exponential Linear Unit) 或 SELU (Scaled Exponential Linear Unit)。

在实践中,Leaky ReLU 经常被用作默认的激活函数之一,并在很多深度学习模型中取得了良好的效果。

Leaky ReLU 的优缺点:
优点包括:

  1. 解决了梯度消失问题:相对于传统的 ReLU 函数,Leaky ReLU 具有非零的负斜率,这使得它能够传播梯度,有效地缓解了梯度消失的问题。

  2. 保留稀疏激活性质:Leaky ReLU 仍然保留了传统 ReLU 的稀疏激活性质,即只有少数神经元被激活,从而减少了模型的复杂性。

  3. 实现简单:Leaky ReLU 的计算简单,只需在传统的 ReLU 函数中引入一个小的斜率参数即可。

缺点:

  1. 需要手动选择超参数:Leaky ReLU 的性能依赖于负斜率参数的选择,这需要手动调整。选择不当的斜率参数可能会导致模型的性能下降。

  2. 可能存在神经元死亡问题:尽管 Leaky ReLU 解决了传统 ReLU 中负输入值输出为零的问题,但仍然可能存在神经元死亡问题。当斜率参数选择得过小时,仍有一部分神经元在训练过程中不会被激活。

  3. 不是最优选择:虽然 Leaky ReLU 在某些情况下表现良好,但并不是最优的激活函数选择。一些其他激活函数,如 ELU 或 SELU,可以在解决梯度消失问题方面更有效,并提供更平滑的激活函数曲线。

以下是使用C++实现Leaky ReLU激活函数的示例代码:

// Leaky ReLU函数的实现
double leakyRelu(double x, double alpha) {return (x > 0) ? x : alpha * x;
}// Leaky ReLU函数的导数实现
double leakyReluDerivative(double x, double alpha) {return (x > 0) ? 1 : alpha;
}int main() {double x = -2.0; // 示例输入值double alpha = 0.1; // Leaky ReLU的负斜率// 调用Leaky ReLU函数计算输出double result = leakyRelu(x, alpha);// 输出结果printf("Leaky ReLU(%f) = %f\n", x, result);return 0;
}

Parametric ReLU激活函数 (自适应Leaky ReLU激活函数)

Parametric ReLU (PReLU) 是一种激活函数,它是对传统的 ReLU 函数的改进。与 Leaky ReLU 不同,PReLU 的负斜率不是固定的超参数,而是可以通过学习得到的可训练参数。

PReLU 的数学定义如下:
f(x) = max(ax, x)其中a是一个可学习的参数,可以根据数据进行训练得到。当a为0时,PReLU函数退化为普通的ReLU函数。PReLU函数的导数在正区间(x>0)上为1,而在负区间(x<0)上为a。下面我们来推导PReLU函数的导数。对于x>0,PReLU函数的导数为1:
f'(x) = 1,(x > 0)对于x<0,PReLU函数的导数为a:
f'(x) = a,(x < 0)在x=0的位置,PReLU函数的导数存在争议,通常会将其定义为左导数和右导数的平均值,即:
f'(x) = (1 + a) / 2,(x = 0)这样,PReLU函数的导数就可以在所有实数范围内连续定义。

其中,a 是一个可训练的参数,它可以根据数据进行学习和调整。当 a = 0 时,PReLU 退化为传统的 ReLU 函数。

Parametric ReLU优缺点:
优点:

  1. 自适应负斜率:PReLU 允许负斜率参数根据数据进行学习,这使得激活函数能够自适应地调整负值区域的斜率。这提供了更大的灵活性和表达能力,适应不同类型的数据分布和模型复杂度。

  2. 解决了梯度消失问题:与传统的 ReLU 类似,PReLU 仍然能够缓解梯度消失问题,通过保留正值输入的激活性。

缺点:

  1. 参数学习的复杂性:与固定斜率的 Leaky ReLU 不同,PReLU 需要学习一个额外的参数,这增加了模型的复杂性。参数的学习过程需要更多的计算和存储资源,并且可能需要更多的数据和训练时间。

  2. 过拟合的风险:PReLU 具有更高的模型灵活性,这也可能导致过拟合的风险增加。过度学习负斜率参数可能使模型对训练数据过度拟合,从而影响泛化能力。

在实践中,PReLU 可以作为一种有效的激活函数,特别适用于深层神经网络和大规模数据集。然而,由于其参数学习的复杂性,需要在具体问题和实验中进行评估和比较,以确定是否使用 PReLU 和如何设置参数。

以下是使用C++实现PReLU激活函数及其导数的示例代码:

#include <cmath>// PReLU函数的实现
double prelu(double x, double a) {return (x > 0) ? x : a * x;
}// PReLU函数的导数实现
double preluDerivative(double x, double a) {return (x > 0) ? 1 : a;
}

ELU激活函数

ELU (Exponential Linear Unit) 是一种激活函数,它在负输入值区域具有非零斜率,且输出值有指数级的下降。ELU 在解决梯度消失问题的同时,还能够处理负输入值的情况,避免了神经元的死亡现象。

ELU 的数学定义如下:

ELU函数的定义如下:
f(x) = x,                  if x >= 0alpha * (exp(x) - 1), if x < 0其中,alpha是一个超参数,用于控制负值区域的斜率。通常情况下,alpha取一个较小的正数,如0.10.2。ELU函数的导数计算如下:
f'(x) = 1,                if x >= 0f(x) + alpha,     if x < 0接下来,我们将对ELU函数的导数进行数学推导。假设y = f(x)是ELU函数的输出,其中x表示输入值,y表示输出值。1. 对于x >= 0的情况,ELU函数的导数为1。这是因为在x >= 0时,ELU函数是线性的,导数恒定为12. 对于x < 0的情况,我们将f(x) = alpha * (exp(x) - 1)代入导数的定义式中,得到:f'(x) = d/dx (alpha * (exp(x) - 1))= alpha * d/dx (exp(x) - 1)根据指数函数的导数性质,d/dx (exp(x)) = exp(x),则:f'(x) = alpha * exp(x)因此,当x < 0时,ELU函数的导数为f(x) + alpha。这样,我们得到了ELU函数的导数公式。

在这里插入图片描述

其中,alpha 是一个超参数,控制负输入值区域的斜率。通常,alpha 的值设置为一个小的正数,如 0.01。

ELU 的优点包括:

  1. 解决梯度消失问题:ELU 具有非零斜率,可以传播梯度,有效地解决梯度消失的问题。

  2. 平滑的曲线:ELU 在负输入值区域具有平滑的曲线,相对于 Leaky ReLU 和 PReLU,它更平滑并且具有更好的连续性。

  3. 处理负输入值:ELU 可以处理负输入值,并且在该区域具有非零斜率。这可以避免神经元的死亡问题,并允许网络学习更多的特征。

  4. 激活值的范围:ELU 的输出范围是 (-∞, +∞),相比于其他激活函数,如 sigmoid 和 tanh,ELU 不会导致输出值饱和,更有利于模型的学习。

缺点:

  1. 计算复杂性:ELU 函数的计算相对于传统的激活函数来说较为复杂,特别是在负输入值区域需要进行指数计算,这可能会增加模型的计算成本。

  2. 非单调性:ELU 在整个输入范围内都是单调递增的,这可能导致网络的收敛速度较慢,特别是在某些优化算法中。

在实践中,ELU 通常被认为是一种有效的激活函数,尤其适用于解决梯度消失问题和处理负输入值的情况。然而,对于特定的任务和数据集,需要根据实验和模型的性能来选择和调整激活函数。

下面是使用C++实现ELU函数及其导数的示例代码:

#include <cmath>// ELU函数的实现
double elu(double x, double alpha) {return (x >= 0) ? x : alpha * (exp(x) - 1);
}// ELU函数的导数实现
double elu_derivative(double x, double alpha) {return (x >= 0) ? 1 : elu(x, alpha) + alpha;
}int main() {double x = -2.0; // 示例输入值double alpha = 0.1; // ELU的alpha值// 调用ELU函数计算输出double result = elu(x, alpha);// 调用ELU函数的导数计算double derivative = elu_derivative(x, alpha);// 输出结果printf("ELU(%f) = %f\n", x, result);printf("ELU的导数(%f) = %f\n", x, derivative);return 0;
}

SeLU激活函数

SeLU (Scaled Exponential Linear Unit) 是一种激活函数,它在负输入值区域具有非零斜率,并且在正输入值区域具有一个大于1的缩放因子。SeLU 在解决梯度消失问题的同时,还能够使得每个神经元的输出接近零均值和单位方差,从而提高神经网络的稳定性和表示能力。

SeLU 的数学定义如下:

f(x) = { scale * x,                           if x > 0,scale * alpha * (exp(x) - 1),        if x <= 0 }

其中,scalealpha是可调节的超参数,通常设置为scale = 1.0507alpha = 1.6733。SeLU函数在输入小于0时,具有指数增长的形式,有助于处理负值。而在输入大于0时,与线性函数相似。

现在,我们将对SeLU激活函数的导数进行推导。

首先,我们计算SeLU函数的一阶导数:


f'(x) = { scale * 1,                           if x > 0,scale * alpha * exp(x) ,        if x <= 0 }

根据SeLU函数的定义,我们可以将输入分为两个区域讨论:

  1. x > 0 时,导数为1,因为在这个区域,SeLU函数的形式与线性函数相似。
  2. x <= 0 时,导数为 alpha * exp(x),因为在这个区域,SeLU函数的形式是指数增长的。

对于SeLU函数的导数,我们可以进一步计算二阶导数:


f''(x) = { scale * 0,                           if x > 0,scale * alpha * exp(x) ,        if x <= 0 }

同样地,在 x > 0 的区域,二阶导数为0。而在 x <= 0 的区域,二阶导数为 alpha * exp(x)

综上所述,SeLU激活函数在 x > 0 的区域具有导数为1的线性形式,在 x <= 0 的区域具有指数增长的形式。

在这里插入图片描述

其中,scale 和 alpha 是两个超参数,用于缩放和调整激活函数。通常,scale 的值设置为 1.0507,alpha 的值设置为 1.6733。

SeLU 的优点包括:

  1. 解决梯度消失问题:SeLU 具有非零斜率,在负输入值区域能够传播梯度,有效地解决梯度消失的问题。

  2. 零均值和单位方差:SeLU 的设计使得每个神经元的输出在训练过程中接近零均值和单位方差,从而提高神经网络的稳定性和表示能力。

  3. 自适应性质:SeLU 的缩放因子可以自适应地调整输出值的范围,使得神经网络在不同的数据分布和模型复杂度下都能表现良好。

缺点:

  1. 不适用于所有情况:SeLU 的设计基于假设输入数据具有零均值和单位方差,因此在某些情况下可能不适用。如果输入数据具有不同的分布特征,可能需要考虑其他激活函数。

  2. 计算复杂性:SeLU 的计算相对于传统的激活函数来说较为复杂,特别是在负输入值区域需要进行指数计算。这可能会增加模型的计算成本。

在实践中,SeLU 通常被认为是一种有效的激活函数,尤其适用于深层神经网络和大规模数据集。然而,需要根据具体问题和实验进行评估和比较,以确定是否使用 SeLU 和如何设置超参数。

下面是使用C++实现SeLU激活函数及其一阶导数的示例代码:

#include <cmath>// SeLU激活函数的实现
double selu(double x, double scale = 1.0507, double alpha = 1.6733) {return (x > 0) ? (scale * x) : (scale * alpha * (exp(x) - 1));
}// SeLU激活函数的一阶导数实现
double selu_derivative(double x, double scale = 1.0507, double alpha = 1.6733) {return (x > 0) ? scale : (scale * alpha * exp(x));
}int main() {double x = 2.0; // 示例输入值// 调用SeLU函数计算输出double result = selu(x);// 调用SeLU函数的一阶导数计算输出double derivative = selu_derivative(x);// 输出结果printf("SeLU(%f) = %f\n", x, result);printf("SeLU derivative(%f) = %f\n", x, derivative);return 0;
}

在这个示例代码中,selu()函数接受一个double类型的输入值x,并返回计算得到的SeLU函数的输出值。selu_derivative()函数计算SeLU函数的一阶导数。scalealpha分别是SeLU函数的超参数,可以根据需要进行调整。

main()函数中,我们提供一个示例输入值x,然后调用selu()函数和selu_derivative()函数分别计算输出结果和导数,并使用printf()函数打印结果。

这只是一个简单的示例代码,您可以根据自己的需求进行扩展和修改。

Softmax 激活函数

Softmax 是一种常用的激活函数,它常用于多类别分类任务中。Softmax 函数将一组实数转换为表示概率分布的向量,使得所有元素的和等于 1,并将每个元素映射到一个 [0, 1] 的范围内。

Softmax 函数的数学定义如下:

softmax(x_i) = exp(x_i) / sum(exp(x_j))

在这里插入图片描述

其中,x_i 表示输入向量的第 i 个元素,exp 表示指数函数,sum 表示对所有元素的指数函数求和。

Softmax 函数的输出可以解释为输入向量中每个元素对应的概率分布,因此在多类别分类任务中非常有用。最大的输出值对应概率最高的类别。

Softmax 函数的优点包括:

  1. 输出概率分布:Softmax 函数将输入映射到概率分布,使得每个元素都表示了一个类别的概率。这对于多类别分类问题非常有用,可以得到对不同类别的置信度估计。

  2. 可导性:Softmax 函数是可导的,这意味着可以使用梯度下降等优化算法来训练使用 Softmax 函数的神经网络。

缺点:

  1. 敏感性:Softmax 函数对输入的绝对大小非常敏感,这可能导致数值不稳定性。在输入中存在很大的差异时,Softmax 可能会输出接近于 0 或接近于 1 的值,使得梯度下降算法更难以收敛。

  2. 多类别不平衡:在多类别分类问题中,如果存在类别不平衡,Softmax 可能倾向于预测数量较多的类别。

在实践中,Softmax 函数通常与交叉熵损失函数结合使用,用于多类别分类任务中。它在神经网络中广泛应用,并且经常作为输出层的激活函数。
在 C++ 中实现 Softmax 激活函数时,我们可以使用以下代码示例:

在这里插入图片描述

当Softmax函数遇到非常大的数值时,可能会导致数值不稳定的问题。这主要是因为Softmax函数的定义涉及指数运算,如果输入值很大,那么指数函数的输出可能会迅速增加到超过计算机可以表示的范围。

Softmax函数的定义如下:

Softmax ( x ) i = e x i ∑ j e x j \text{Softmax}(x)_i = \frac{e^{x_i}}{\sum_j e^{x_j}} Softmax(x)i=jexjexi

其中 x x x是输入向量。

为了解决这个问题,可以从输入向量中减去其最大值,然后再应用Softmax。这样做不会改变Softmax的输出,因为分子和分母都被同一个数值除以。但是,通过减去最大值,指数运算的输入范围会减小,从而避免了数值溢出的问题。

下面是应用这种技巧后的Softmax函数定义:

Softmax ( x ) i = e x i − max ⁡ ( x ) ∑ j e x j − max ⁡ ( x ) \text{Softmax}(x)_i = \frac{e^{x_i - \max(x)}}{\sum_j e^{x_j - \max(x)}} Softmax(x)i=jexjmax(x)eximax(x)

对不起,我之前的回答未涉及减去最大值后的Softmax梯度。这里是经过修改的Softmax函数(减去最大值)的梯度推导。

假设我们先计算了减去最大值后的输入向量:

y i = x i − max ⁡ ( x ) y_i = x_i - \max(x) yi=ximax(x)

然后我们计算Softmax:

s i = e y i ∑ j e y j s_i = \frac{e^{y_i}}{\sum_j e^{y_j}} si=jeyjeyi

关于原始输入( x )的梯度可以由以下推导得到:

对于 i = j i = j i=j

∂ s i ∂ x i = s i ⋅ ( 1 − s i ) \frac{\partial s_i}{\partial x_i} = s_i \cdot (1 - s_i) xisi=si(1si)

对于 i ≠ j i \neq j i=j

∂ s i ∂ x j = − s i ⋅ s j \frac{\partial s_i}{\partial x_j} = -s_i \cdot s_j xjsi=sisj

通过减去最大值,我们不会改变Softmax梯度的形式,因为我们只是从输入中减去了一个常数(最大值),并没有改变Softmax函数相对于其输入的梯度。所以,无论是否减去最大值,Softmax梯度的形式都是一样的。

在这里插入图片描述

当然,以下是使用C++实现Softmax函数(包括减去最大值以提高数值稳定性)及其梯度的代码:```cpp
#include <vector>
#include <cmath>
#include <algorithm>// Softmax function
std::vector<double> softmax(const std::vector<double>& x) {std::vector<double> result(x.size());double maxVal = *std::max_element(x.begin(), x.end());double sum = 0.0;for (int i = 0; i < x.size(); ++i) {result[i] = std::exp(x[i] - maxVal);sum += result[i];}for (int i = 0; i < x.size(); ++i) {result[i] /= sum;}return result;
}// Softmax gradient
std::vector<std::vector<double>> softmax_gradient(const std::vector<double>& x) {std::vector<double> s = softmax(x);std::vector<std::vector<double>> gradient(x.size(), std::vector<double>(x.size(), 0.0));for (int i = 0; i < x.size(); ++i) {for (int j = 0; j < x.size(); ++j) {if (i == j) {gradient[i][j] = s[i] * (1 - s[i]);} else {gradient[i][j] = -s[i] * s[j];}}}return gradient;
}

在这个代码中,softmax函数接受一个包含原始输入的向量,并返回Softmax函数的输出。softmax_gradient函数接受同样的输入,并返回一个包含关于输入的Softmax梯度的二维向量。

请注意,这段代码对于实际应用来说可能还需要进一步优化和测试。在将其用于重要项目之前,请确保进行了充分的验证和测试。


在这个示例代码中,`softmaxDerivative()`函数接受一个`std::vector<double>`类型的Softmax输出向量`softmaxOutput`,并返回计算得到的Softmax函数的导数向量。函数首先计算每个元素的指数值,然后计算所有指数值的总和`sumExp`。接下来,对于每个元素,计算其导数值并进行归一化,得到最终的导数向量。在这个示例中,我们定义了一个名为 `softmax` 的函数,它接受一个输入向量 `input`,并返回一个经过 Softmax 函数处理的输出向量。在函数内部,我们首先计算输入向量中每个元素的指数值,并累加求和。然后,我们将指数值除以总和,以得到归一化的输出向量。在 `main` 函数中,我们给定了一个输入向量 `{1.0, 2.0, 3.0}`,然后调用 `softmax` 函数计算输出向量,并将结果打印到控制台上。

Swish 激活函数

Swish 是一种激活函数,它结合了 Sigmoid 函数和线性函数。Swish 函数在接近零时具有 Sigmoid 函数的饱和性质,并在正无穷时趋近于线性函数。Swish 函数在一些深度学习任务中表现出了很好的性能,并被认为比一些传统激活函数更有效。

Swish 函数的数学定义如下:

f(x) = x * (1.0 / (1.0 + exp(-beta * x)))  ==  Swish(x) = x * sigmoid(-beta * x)

Swish激活函数是一种近年来提出的激活函数,其数学表达式为:

Swish(x) = x * sigmoid(beta * x)

其中,sigmoid函数是常见的Sigmoid函数,beta是一个可调节的参数。

为了计算Swish函数的导数,我们首先计算Swish函数的导数对x的求导:

Swish’(x) = sigmoid(beta * x) + x * sigmoid(beta * x) * (1 - sigmoid(beta * x))

然后,我们可以将Swish函数的导数写为Swish函数本身的形式,得到一个更简洁的表示:

Swish’(x) = Swish(x) + sigmoid(beta * x) * (1 - Swish(x))

这个公式表示了Swish函数对输入x的导数。在实际编程中,可以使用这个公式来计算Swish函数的导数。

在这里插入图片描述

其中,sigmoid(x) 表示 Sigmoid 函数,即 1 / (1 + exp(-beta*x))。
在这里插入图片描述

Swish 函数的优点包括:

  1. 平滑性质:Swish 函数具有平滑的曲线,相比于一些分段线性函数,Swish 更连续并具有更好的可导性。

  2. 饱和性质:Swish 在接近零时具有 Sigmoid 函数的饱和性质,这可以缓解梯度消失问题。

  3. 自适应性:Swish 函数具有自适应性质,即在不同的数据分布和模型复杂度下都能表现良好。

然而,Swish 函数也存在一些限制:

  1. 计算复杂性:Swish 函数的计算相对于一些简单的激活函数来说较为复杂,特别是涉及到 Sigmoid 函数的计算。

  2. 对梯度消失问题的处理:虽然 Swish 函数可以缓解梯度消失问题,但并没有完全解决。在某些情况下,仍可能存在梯度消失或梯度爆炸的问题。

在实践中,Swish 函数通常用作激活函数应用于神经网络的隐藏层。它可以提供较好的非线性建模能力,并在一些任务中获得较好的性能。然而,对于特定的问题和模型,仍需要根据实验和评估来选择和调整激活函数。

以下是使用C++实现Swish激活函数的示例代码:

#include <cmath>// Swish激活函数的实现
double swish(double x, double beta) {return x * (1.0 / (1.0 + exp(-beta * x)));
}// Swish激活函数的导数实现
double swishDerivative(double x, double beta) {double sw = swish(x, beta);return sw + (1.0 - sw) * (1.0 / (1.0 + exp(-beta * x)));
}int main() {double x = 2.0; // 示例输入值double beta = 1.0; // Swish函数的参数// 调用Swish函数计算输出double result = swish(x, beta);// 调用Swish函数的导数计算输出double derivative = swishDerivative(x, beta);// 输出结果printf("Swish(%f) = %f\n", x, result);printf("Swish'(%f) = %f\n", x, derivative);return 0;
}

Maxout激活函数

Maxout 是一种激活函数,它通过比较多个线性函数的输出并选择最大的那个来进行非线性建模。Maxout 可以学习多个线性函数的参数,从而增强神经网络的表达能力。

Maxout 函数的数学定义如下:

f(x) = max(w_1 * x + b_1, w_2 * x + b_2, ..., w_k * x + b_k)

其中,w_i 和 b_i 是 Maxout 函数中第 i 个线性函数的权重和偏置,k 是线性函数的个数。Maxout 函数通过选择产生最大输出的线性函数来提供非线性特性。

Maxout 函数的优点包括:

  1. 多线性函数:Maxout 函数可以学习多个线性函数的参数,从而增强了神经网络的表达能力。每个线性函数可以捕捉不同的特征和模式。

  2. 非线性性质:Maxout 函数通过选择最大输出来提供非线性特性。这使得神经网络能够更好地适应复杂的数据分布和模式。

  3. 梯度传播:Maxout 函数在正向传播和反向传播过程中能够有效地传播梯度,从而促进模型的训练和收敛。

缺点:

  1. 参数量增加:Maxout 函数的参数量随着线性函数的个数增加而增加。这可能导致模型的复杂性增加,需要更多的计算和存储资源。

  2. 计算复杂性:Maxout 函数的计算相对于一些简单的激活函数来说较为复杂,特别是当线性函数的个数较多时。

在实践中,Maxout 函数通常用作激活函数应用于神经网络的隐藏层。它可以提供较强的非线性建模能力,并在一些任务中获得较好的性能。然而,对于特定的问题和模型,仍需要根据实验和评估来选择和调整激活函数。

Maxout 激活函数在 C++ 中的实现可以如下所示:

#include <iostream>
#include <vector>
#include <algorithm>double maxout(const std::vector<double>& input, const std::vector<double>& weights, const std::vector<double>& biases) {std::vector<double> max_values;//  计算每个线性函数的值for (size_t i = 0; i < weights.size(); ++i) {double value = weights[i] * input[i] + biases[i];max_values.push_back(value);}// 选择最大值double max_output = *std::max_element(max_values.begin(), max_values.end());return max_output;
}
// Maxout激活函数的导数实现
double maxout_derivative(double x1, double x2) {return (x1 > x2) ? 1 : 0;
}
int main() {std::vector<double> input = {1.0, 2.0, 3.0};std::vector<double> weights = {0.5, 0.8, 1.2};std::vector<double> biases = {-0.2, 0.1, 0.5};double output = maxout(input, weights, biases);std::cout << "Input: ";for (double val : input) {std::cout << val << " ";}std::cout << std::endl;std::cout << "Output: " << output << std::endl;return 0;
}

在上面的代码中,我们定义了一个名为 maxout 的函数,它接受输入向量 input、权重向量 weights 和偏置向量 biases,并返回 Maxout 函数的输出。在函数内部,我们计算了每个线性函数的输出值,并将它们保存在 max_values 向量中。然后,我们选择 max_values 中的最大值作为 Maxout 函数的输出。

main 函数中,我们给定了一个输入向量 {1.0, 2.0, 3.0},以及对应的权重向量和偏置向量。然后调用 maxout 函数计算输出值,并将结果打印到控制台上。

Softplus激活函数

Softplus 是一种平滑的激活函数,它在正输入值区域具有非线性特性,并且在负输入值区域趋近于零。Softplus 函数常用于神经网络的隐藏层,可以提供一种非线性建模能力。

Softplus 函数的数学定义如下:

Softplus函数是一种平滑的激活函数,其定义为:
f(x) = log(1 + exp(x))要计算Softplus函数的导数,我们需要对其进行求导。首先,我们将Softplus函数表示为指数函数的形式:
f(x) = log(1 + exp(x)) = log(exp(0) + exp(x))然后,我们可以使用链式法则对其进行求导。设g(x) = exp(x),则:
f(x) = log(g(0) + g(x))对f(x)进行求导,可以得到:
f'(x) = (g'(0) + g'(x)) / (g(0) + g(x))其中,g'(x)表示指数函数的导数,即g'(x) = exp(x)。代入g(0) = exp(0) = 1,g'(0) = exp(0) = 1,得到:
f'(x) = (1 + exp(x)) / (1 + exp(0)) = (1 + exp(x)) / 2因此,Softplus函数的导数为:
f'(x) = (1 + exp(x)) / 2

在这里插入图片描述

其中,exp 表示指数函数,log 表示自然对数函数。

Softplus 函数的优点包括:

  1. 非线性性质:Softplus 函数在正输入值区域具有非线性特性,使得神经网络能够对复杂的数据分布进行建模。

  2. 平滑性质:Softplus 函数是平滑的,具有连续的导数,这有助于优化算法在训练过程中更好地进行梯度传播和参数更新。

  3. 输出范围:Softplus 函数的输出范围是 (0, +∞),这使得它适用于需要非负输出的任务。

然而,Softplus 函数也存在一些限制:

  1. 梯度饱和:在输入值非常大的情况下,Softplus 函数的梯度可能会接近于零,导致梯度消失问题。

  2. 对负输入值的处理:Softplus 函数在负输入值区域趋近于零,可能无法处理负输入值的情况。

在实践中,Softplus 函数通常用作神经网络的隐藏层激活函数。然而,对于特定的问题和模型,仍需要根据实验和评估来选择和调整激活函数。

在 C++ 中实现 Softplus 激活函数,可以使用以下代码示例:

#include <iostream>
#include <cmath>// Softplus函数的实现
double softplus(double x) {return log(1 + exp(x));
}// Softplus函数的导数实现
double softplusDerivative(double x) {return (1 + exp(x)) / 2;
}int main() {double x = 2.0; // 示例输入值// 调用Softplus函数计算输出double result = softplus(x);// 输出结果printf("Softplus(%f) = %f\n", x, result);// 调用Softplus函数的导数计算输出double derivative = softplusDerivative(x);// 输出导数结果printf("Softplus Derivative(%f) = %f\n", x, derivative);return 0;
}

相关文章:

神经网络系列---激活函数

文章目录 激活函数Sigmoid 激活函数Tanh激活函数ReLU激活函数Leaky ReLU激活函数Parametric ReLU激活函数 &#xff08;自适应Leaky ReLU激活函数&#xff09;ELU激活函数SeLU激活函数Softmax 激活函数Swish 激活函数Maxout激活函数Softplus激活函数 激活函数 一般来说&#xf…...

python中continue的对比理解

# 使用while循环&#xff0c;输入1-10之间的数字&#xff0c;除7之外。 以下为代码对比&#xff1a; # 使用while循环&#xff0c;输入1-10之间的数字&#xff0c;除7之外。 # 第一种方式 num 0 while num < 10:num num 1if num 7:print("")else:print(num)…...

Amazon Generative AI | 基于 Amazon 扩散模型原理的代码实践之采样篇

以前通过论文介绍 Amazon 生成式 AI 和大语言模型&#xff08;LLMs&#xff09;的主要原理之外&#xff0c;在代码实践环节主要还是局限于是引入预训练模型、在预训练模型基础上做微调、使用 API 等等。很多开发人员觉得还不过瘾&#xff0c;希望内容可以更加深入。因此&#x…...

[服务器-数据库]MongoDBv7.0.4不支持ipv6访问

文章目录 MongoDBv7.0.4不支持ipv6访问错误描述问题分析错误原因解决方式 MongoDBv7.0.4不支持ipv6访问 错误描述 报错如下描述 Cannot connect to MongoDB.No suitable servers found: serverSelectionTimeoutMS expired: [failed to resolve 2408]问题分析 首先确定其是…...

【b站咸虾米】chapter5_uniapp-API_新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握

课程地址&#xff1a;【新课uniapp零基础入门到项目打包&#xff08;微信小程序/H5/vue/安卓apk&#xff09;全掌握】 https://www.bilibili.com/video/BV1mT411K7nW/?p12&share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 5 API 5.1 页面和路…...

自学Python第十八天-自动化测试框架(二):DrissionPage、appium

自学Python第十八天-自动化测试框架&#xff08;二&#xff09;&#xff1a;DrissionPage、appium DrissionPage环境和安装配置准备工作简单的使用示例控制浏览器收发数据包模式切换 浏览器模式创建浏览器对象访问页面加载模式none 模式技巧 获取页面信息页面交互查找元素ele()…...

云尚办公-0.3.0

5. controller层 import pers.beiluo.yunshangoffice.model.system.SysRole; import pers.beiluo.yunshangoffice.service.SysRoleService;import java.util.List;//RestController&#xff1a;1.该类是控制器&#xff1b;2.方法返回值会被写进响应报文的报文体&#xff0c;而…...

汇编英文全称

mov move mvn Mov Negative ldr LoaD Register str Store Register lsl Logic Shift Left lsr Logic Shift Right asr Arithmetic Shift Right 算数右移 ror Rotate right 循环右移…...

基于虚拟力优化的无线传感器网络覆盖率matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 虚拟力优化算法 4.2 覆盖覆盖率计算 5.完整程序 1.程序功能描述 基于虚拟力优化的无线传感器网络覆盖率&#xff0c;仿真输出优化前后的网络覆盖率&#xff0c;覆盖率优化收敛迭代曲线…...

阿里云-系统盘-磁盘扩容

阿里云系统磁盘扩容 之前是测试环境磁盘用的默认的有 40G&#xff0c;后面升级到正式的 磁盘怕不够用打算升级到 100G&#xff0c; 系统镜像&#xff1a; Alibaba Cloud Linux 3.2104 LTS 64 位 磁盘 ESSD 40G 升级步骤&#xff1a; 扩容与创建快照 在阿里云后台首先去扩容…...

libmmd.dll修复

libmmd.dll 是与Intel Math Kernel Library (MKL) 相关的动态链接库文件&#xff0c;通常用于数学和科学计算。 最常出现的错误信息是&#xff1a; 程序无法启动&#xff0c;因为您的计算机缺少 libmmd.dll 。尝试重新安装程序来解决这个问题。 启动 libmmd.dll 发生错误。无法…...

大数据时代的明星助手:数据可视化引领新风潮

在大数据时代的浪潮中&#xff0c;数据可视化如一位巧夺天工的画师&#xff0c;为我们描绘出庞大而丰富的信息画卷&#xff0c;为我们提供了直观、清晰、高效的数据呈现方式。下面我就以可视化从业者的角度&#xff0c;来简单聊聊这个话题。 数据可视化首先在信息管理和理解方面…...

设计模式--享元模式和组合模式

享元模式 享元模式&#xff08;Flyweight Pattern&#xff09;又称为轻量模式&#xff0c;是对象池的一种实现。类似于线程池&#xff0c;线程池可以避免不停的创建和销毁多个对象&#xff0c;销毁性能。提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒…...

基于Java springmvc+mybatis酒店信息管理系统设计和实现

基于Java springmvcmybatis酒店信息管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获…...

leetcode-找不同

389. 找不同 题解&#xff1a; 从题意我们可以知道&#xff0c;虽然 t 是由 s组成&#xff0c;但是 t中又随机添加了一个字符&#xff0c;也就是相当于 t 包含 s,我们使用字典&#xff0c;将 t 转换成字典对应关系t_map&#xff0c;然后遍历 s 中的字符&#xff0c;若存在&am…...

笔记本hp6930p安装Android-x86避坑日记

一、序言 农历癸卯年前大扫除&#xff0c;翻出老机hp6930p&#xff0c;闲来无事&#xff0c;便安装Android-x86玩玩&#xff0c;期间多次入坑&#xff0c;随手记之以避坑。 笔记本配置&#xff1a;T9600,4G内存&#xff0c;120G固态160G机械硬盘 二、Android-x86系统简介 官…...

zabbix监控业务数据

前言 监控系统除了监控os和数据库性能相关的指标外&#xff0c;业务数据也是重点监控的对象。 一线驻场的运维同学应该深有体会&#xff0c;每天需要向甲方或者公司反馈现场的数据情况&#xff0c;正常情况下一天巡检两次&#xff0c;早上上班后和下午下班前各一次。监控项目…...

access数据库泄露与IIS短文件名利用

access数据库 Microsoft Office Access是微软把 数据库引擎 的图形用户界面和 软件开发工具 结合在一起的一个 数据库管理系统 它的数据库是没有库名的&#xff0c;都是表名。 (借用别的up的图)是不是感觉有点像excel access数据库的后缀是.mdb access数据库泄露漏洞 如果…...

MySQL 篇-深入了解 DDL 语言(一)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 MySQL 说明 2.0 DDL 语言 2.1 DDL 语言 - 定义数据库 2.1.1 创建数据库操作 2.1.2 查看数据库操作 2.1.3 使用数据库操作 2.1.4 删除数据库操作 2.2 DDL 语言 …...

MT8788|MTK8788安卓核心板参数_4G联发科MTK模块

MT8788核心板是一款功能强大的4G全网通安卓智能模块。该模块采用了联发科AIOT芯片平台&#xff0c;具有长达8年的生命周期。MT8788模块内置了12nm制程的八核处理器&#xff0c;包括4个Cortex A73和4个Coretex A53&#xff0c;主频最高可达2.0GHZ。标配内存为4GB64GB&#xff0c…...

EXCEL 在列不同单元格之间插入N个空行

1、第一步数据&#xff0c;要求在每个数字之间之间插入3个空格 2、拿数据个数*&#xff08;要插入空格数1&#xff09; 19*4 3、填充 4、复制数据到D列 5、下拉数据&#xff0c;选择复制填充这样1-19就会重复4次 6、全选数据D列排序&#xff0c;这样即完成了插入空格 以…...

Linux快速修改ip地址

Linux修改IP配置 一 、查找ip配置文件 ifcfg-ens33二、编辑 vi ifcfg-ens33文件三、重启网络或者重启系统 一 、查找ip配置文件 ifcfg-ens33 cd /etc/sysconfig/network-scripts/ls //查看network-scripts文件夹下面的文件二、编辑 vi ifcfg-ens33文件 vi ifcfg-ens33注意&…...

采用遗传算法搜索MAC效率最高的矩阵乘规模

如何采用遗传算法搜索MAC效率最高的矩阵乘规模 具体实现MAC效率评估代码(eval.py)遗传算法实现 本文介绍了采用遗传算法搜索MAC效率最高的矩阵乘规模 需求背景: 一些AI加速卡在做矩阵乘时,因硬件或软件的约束,并不是规模越大MAC效率越高在测试AI加卡的实际算力时,采用MAC效率最…...

流计算之Flink

文章目录 概要有界无界流集群JobManagerTaskManagersTasks 和算子链Task Slots 和资源 小结 概要 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模…...

【Linux基础】Linux自动化构建工具make/makefile

背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪些文件需要后…...

问题慢慢解决-通过android emulator调试android kernel-内核条件断点遇到的问题和临时解决方案

起因 在摸索到这个方案之后&#xff0c;mac m1调试aarch64 android kernel最终方案&#xff0c;就准备调试内核了&#xff0c;预备下断点的地方是 b binder_poll b ep_ptable_queue_proc b remove_wait_queue但是由于是android系统&#xff0c;上面三个函数会被频繁的触发&am…...

社区发现之标签传播算法(LPA)

在Graph领域,社区发现(Community detection)是一个非常热门且广泛的话题,后面会写一个系列,该问题实际上是从子图分割的问题演变而来,在真实的社交网络中,有些用户之间连接非常紧密,有些用户之间的连接较为稀疏,连接紧密的用户群体可以看做一个社区,在风控问题中,可…...

【前端素材】推荐优质后台管理系统Dashy平台模板(附源码)

一、需求分析 后台管理系统&#xff08;或称作管理后台、管理系统、后台管理平台&#xff09;是一种专门用于管理网站、应用程序或系统后台运营的软件系统。它通常由一系列功能模块组成&#xff0c;为管理员提供了管理、监控和控制网站或应用程序的各个方面的工具和界面。以下…...

MFC 配置Halcon

1.新建一个MFC 工程&#xff0c;Halcon 为64位&#xff0c;所以先将工程改为x64 > VC 目录设置包含目录和库目录 包含目录 库目录 c/c ->常规 链接器 ->常规 > 链接器输入 在窗口中添加头文件 #include "HalconCpp.h" #include "Halcon.h"…...

xss-跨站脚本攻击漏洞

前备知识&#xff1a; Cookie和Session是Web开发中用于维持用户状态、跟踪用户会话的核心技术&#xff0c;它们的主要目的是在无状态的HTTP协议基础上实现有状态的用户交互。 **Cookie**&#xff1a; - Cookie是一种由服务器发送到客户端&#xff08;通常是用户的浏览器&#x…...

在MFC对话框中嵌入web网页时事件失效问题

2010-04-20 日志 在MFC对话框中嵌入web网页时&#xff0c;网页初始化中添加事件无效 document.body.onkeydown function () {//onkeydown"keydownbody()" 不能激发alert(event.keyCode);if(event.keyCode 27)//VK_ESCAPE //String.fromcharcode(A);{if (external…...

【Leetcode】235. 二叉搜索树的最近公共祖先

文章目录 题目思路代码结果 题目 题目链接 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度…...

python 基础语法及保留字

编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码&#xff1a; # -*- coding: cp-1252 -*-上述定义允许在源文件中使用 Windows-1252 字符集中的字符编码&#xff0c;对应适合语…...

Parade Series - NVR Stat

获取文件夹占用空间信息 DIR %NVRHOME% /W /SDIR %NVRHOME% /s | tail -n2 | sed s/,//g | awk {if(NR1){key"Used";}else{key"Free";};sum$3/(1024*1024);unit"MB";if(sum^>1024){sumsum/1024;unit"GB";}printf("{\"Ty…...

【shell脚本实战学习笔记】#2

场景描述 你负责一个Web应用的运维工作&#xff0c;该应用部署在一组Linux服务器上。你需要编写一个Shell脚本来自动化以下任务&#xff1a; 检查Web服务器进程&#xff1a; 确保Web服务器&#xff08;例如Apache或Nginx&#xff09;正常运行。如果没有运行&#xff0c;则尝试…...

docker 安装nacos 一脚shell脚本

要创建一个用于安装Nacos的Docker的Shell脚本&#xff0c;你可以按照以下步骤进行。这个脚本会执行以下操作&#xff1a; 拉取Nacos的Docker镜像。创建一个Docker容器并映射必要的端口。设置Nacos的环境变量。如果需要&#xff0c;可以持久化存储数据到本地目录。 以下是一个…...

mysql的隔离级别,和实现

参考链接 https://xiaolincoding.com/mysql/transaction/mvcc.html#%E4%BA%8B%E5%8A%A1%E7%9A%84%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E6%9C%89%E5%93%AA%E4%BA%9B 事务特性&#xff08;ACID&#xff09; 原子性&#xff08;Atomicity&#xff09;&#xff1a; 事务是原子的&…...

Linux的信号

Linux的信号是一种用于进程之间通信的机制。它们用于向进程发送通知&#xff0c;告知进程发生了某种事件或请求进程执行某个操作。信号可以由内核、其他进程或进程自身发送。 信号的作用有以下几个方面&#xff1a; 通知进程某个事件的发生&#xff0c;如进程的终止、挂起、恢…...

Spring数据脱敏实现

在当今的数字化时代&#xff0c;数据安全和个人隐私保护变得日益重要。为了遵守各种数据保护法规&#xff0c;如欧盟的GDPR&#xff08;通用数据保护条例&#xff09;&#xff0c;企业在处理敏感信息时需要格外小心。数据脱敏是一种常见的技术手段&#xff0c;用于隐藏敏感数据…...

Java核心-核心类与API(4)

话接上回&#xff0c;继续核心类与API的学习&#xff0c;最后介绍一下Object类以及与数学、日期/时间有关的类&#xff0c;就结束该部分的学习了&#xff0c;其他的根据需要自行了解。 一、Object类 1、概述 Object 是 Java 类库中的一个特殊类&#xff0c;也是所有类的父类…...

【C语言】详解计算机二级c语言程序题

文章目录 前言资料相关程序题 一&#xff08;字符串&#xff09;程序题 二&#xff08;数组&#xff09;程序题 三&#xff08;基础&#xff09;程序题 四&#xff08;结构体&#xff09;程序题 五&#xff08;结构体&#xff09;程序题 六&#xff08;基础&#xff09; 前言 …...

限流算法

下面对常见的限流算法进行讨论。目前&#xff0c;常用的限流算法主要有三种&#xff1a;计数器法、滑动窗口算法、漏桶算法和令牌桶算法。下面分别介绍其原理。 1. 计数器法 计数器法是通过计数对到来的请求进行选择性处理。如系统限制一秒内最多有X个请求&#xff0c;则在该…...

备战蓝桥杯 Day10(背包dp)

01背包问题 1267&#xff1a;【例9.11】01背包问题 【题目描述】 一个旅行者有一个最多能装 M&#xfffd; 公斤的背包&#xff0c;现在有 n&#xfffd; 件物品&#xff0c;它们的重量分别是W1&#xff0c;W2&#xff0c;...,Wn&#xfffd;1&#xff0c;&#xfffd;2&#…...

Sora 使用教程,新手小白可用

Sora 使用教程&#xff0c;新手小白可用 参考文章&#xff1a;Sora 使用教程&#xff0c;OpenAI 的文生视频模型 为了在激烈的行业竞争中保持领先地位&#xff0c;OpenAI 在 2024 年 2 月 15 日发布了其革命性的文本至视频转换模型——Sora。这个先进的工具能够将文本描述转化…...

【洛谷千题详解】P1031 均分纸牌

目录 题目描述 思路点拨 AC代码 题目描述 题目网址&#xff1a;[NOIP2002 提高组] 均分纸牌 - 洛谷 有 N 堆纸牌&#xff0c;编号分别为 1,2,……,N。每堆上有若干张&#xff0c;但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌&#xff0c;然后移动。 移牌规则为&a…...

基于文本提示和语义分割的快速抠图

基于文本提示和语义分割的快速抠图 1. 介绍2. 效果展示3. 安装模型4. 命令行调用5. 代码调用5.1 模型加载5.2 可视化函数定义5.3 图像语义分割 6. 参考资料7. 结语服务 1. 介绍 传统的图像语义分割模型通常固定类别进行分割&#xff0c;而基于文本提示的语义分割模型则具有更高…...

什么是媒体发稿?发稿媒体分类及发稿流程

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体发稿是一种企业推广和宣传的手段&#xff0c;通过媒体渠道传递企业信息和形象。 媒体发稿的含义在于&#xff0c;当企业有新闻、事件或其他消息需要对外公布时&#xff0c;可以选择…...

安全测试自学手册之软件安全测试基础

安全测试的概念 定义&#xff1a;指有关验证应用程序的安全等级和识别潜在安全性缺陷的过程。】 应用软件的安全性测试&#xff1a;软件自身设计中存在的安全隐患&#xff0c;并检查软件对非法入侵的防御能力。系统级别的安全性测试&#xff1a;确保只有具备系统平台访问权限…...

【LeetCode】升级打怪之路 Day 04:链表 part 2

今日题目&#xff1a; 24. 两两交换链表中的节点19. 删除链表的倒数第 N 个结点160. 相交链表142. 环形链表 II 目录 LeetCode 24. 两两交换链表中的节点 【易错】LeetCode 19. 删除链表的倒数第 N 个结点 【还行】LeetCode 160. 相交链表&#xff08;两个链表是否相交&#xf…...

JAVA编程题系列——涵盖几乎所有java内容

自己定义一个类&#xff0c;有static属性和构造方法&#xff0c;有构造方法重载&#xff0c;有其他方法&#xff08;方法有对String类型操作&#xff09; public class MyClass {// 静态属性public static String staticProperty "Static Property";// 成员变量priv…...