[论文笔记]GAUSSIAN ERROR LINEAR UNITS (GELUS)

引言

今天来看一下GELU的原始论文。

作者提出了GELU(Gaussian Error Linear Unit,高斯误差线性单元)非线性激活函数: GELU = x Φ ( x ) \text{GELU}= x\Phi(x) GELU=xΦ(x),其中 Φ ( x ) \Phi(x) Φ(x)​是标准高斯累积分布函数。与ReLU激活函数通过输入的符号进行门控不同,GELU非线性激活函数通过输入的数值进行加权。

Tags

#ActivateFunction#

总体介绍

随着网络变得更深,使用sigmoid激活函数进行训练的效果不如非平滑、非概率性的ReLU,后者基于输入的符号进行硬门控决策。ReLU通常比sigmoid激活函数能够实现更快更好的收敛性。在ReLU的成功基础上,最近的一种修改称为ELU允许ReLU-like的非线性激活函数输出负值,这有时可以提高训练速度。总之,激活函数选择对于神经网络仍然是一个必要的架构决策,否则网络将成为一个深度线性分类器。

深度非线性分类器能够很好地拟合数据,以至于网络设计者通常需要选择是否包含随机正则化器,例如在隐藏层添加噪声或应用dropout,而这个选择与激活函数是相互独立的。因此,非线性和dropout共同决定了神经元的输出,但这两个创新仍然是不同的。此外,由于流行的随机正则化器不考虑输入,而非线性受到这些正则化器的帮助,因此两者都不会取代对方。

在这篇工作中,作者引入了一种新称为GELU的激活函数。它与随机正则化器有关,因为它是自适应dropout修改的期望。这表明了对神经元输出的更概率性的观点。

补充知识

正态分布与误差函数

本节介绍一些相关知识,以便更好地理解这篇论文。正态分布的概率密度函数为:
f ( x ) = 1 2 π σ exp ⁡ ( − ( x − μ ) 2 2 σ 2 ) (p1) f(x) = \frac{1}{\sqrt{2\pi} \sigma} \exp\left( -\frac{(x-\mu)^2}{2\sigma^2} \right) \tag{p1} f(x)=2π σ1exp(2σ2(xμ)2)(p1)
假设 X X X是随机变量,累积分布函数是概率 P ( X ≤ x ) P(X \leq x) P(Xx),用概率密度函数可以表示为:
F ( x ; μ , σ ) = 1 2 π σ ∫ − ∞ x exp ⁡ ( − ( t − μ ) 2 2 σ 2 ) d t (p2) F(x;\mu,\sigma) = \frac{1}{\sqrt{2\pi} \sigma} \int_{-\infty}^x \exp\left( -\frac{(t-\mu)^2}{2\sigma^2} \right)dt \tag{p2} F(x;μ,σ)=2π σ1xexp(2σ2(tμ)2)dt(p2)
正态分布可记为 N ( μ , σ 2 ) N(\mu,\sigma^2) N(μ,σ2),其中 μ \mu μ σ 2 \sigma^2 σ2分别代表均值和方差。当 μ = 0 , σ = 1 \mu=0,\sigma=1 μ=0,σ=1时称为标准正态分布。

下图是一些不同取值的概率密度函数图像(左)和累积分布函数图像(右):

image-20240427161126069

误差函数(Error function, erf \text{erf} erf)的定义如下:
erf ( x ) = 1 π ∫ − x x e − t 2 d t = 2 π ∫ 0 x e − t 2 d t (p3) \text{erf}(x) = \frac{1}{\sqrt \pi} \int_{-x}^x e^{-t^2} dt = \frac{2}{\sqrt \pi} \int_0^x e^{-t^2} dt \tag{p3} erf(x)=π 1xxet2dt=π 20xet2dt(p3)
互补误差函数( erfc \text{erfc} erfc),在误差函数的基础上定义:
erfc = 1 − erf ( x ) = 2 π ∫ x ∞ e − t 2 d t (p4) \text{erfc} = 1 - \text{erf}(x) = \frac{2}{\sqrt \pi} \int_x^\infty e^{-t^2} dt \tag{p4} erfc=1erf(x)=π 2xet2dt(p4)
为什么要介绍误差函数,因为它和正态分布式有关系的,重点是作者也引入了它。

误差函数本质上与标准正态累积分布函数 Φ \Phi Φ(将 μ = 0 , σ = 1 \mu=0,\sigma=1 μ=0,σ=1代入式p2)是等价的:
Φ ( x ) = 1 2 π ∫ − ∞ x exp ⁡ ( − t 2 2 ) d t = 1 2 [ 1 + erf ( x 2 ) ] = 1 2 erfc ( − x 2 ) (p5) \Phi(x) =\frac{1}{\sqrt{2\pi}} \int_{-\infty}^x \exp\left( -\frac{t^2}{2} \right)dt = \frac{1}{2}\left[1+ \text{erf}\left( \frac{x}{\sqrt 2}\right) \right ] = \frac{1}{2} \text{erfc} \left(-\frac{x}{\sqrt 2} \right)\tag{p5} Φ(x)=2π 1xexp(2t2)dt=21[1+erf(2 x)]=21erfc(2 x)(p5)
可整理为如下形式:
erf ( x ) = 2 Φ ( x 2 ) − 1 erfc ( x ) = 2 Φ ( − x 2 ) = 2 ( 1 − Φ ( x 2 ) ) \begin{aligned} \text{erf}(x) &= 2\Phi(x\sqrt 2) -1 \\ \text{erfc}(x) &= 2\Phi(-x\sqrt 2) = 2(1-\Phi(x\sqrt 2)) \end{aligned} erf(x)erfc(x)=(x2 )1=(x2 )=2(1Φ(x2 ))

关于泰勒展开可以参考——人工智能数学基础之高等数学。

误差函数泰勒展开收敛:
erf ( z ) = 2 π ∑ n = 0 ∞ ( − 1 ) n z 2 n + 1 n ! ( 2 n + 1 ) = 2 π ( z − z 3 3 + z 5 10 − z 7 42 + z 9 216 − ⋯ ) (p6) \text{erf}(z) = \frac{2}{\sqrt \pi} \sum_{n=0}^\infty \frac{(-1)^n z^{2n+1}}{n!(2n+1)} =\frac{2}{\sqrt \pi} \left(z - \frac{z^3}{3} + \frac{z^5}{10} - \frac{z^7}{42} + \frac{z^9}{216} - \cdots \right) \tag{p6} erf(z)=π 2n=0n!(2n+1)(1)nz2n+1=π 2(z3z3+10z542z7+216z9)(p6)
误差函数和 tanh ⁡ \tanh tanh的关系:
erf ( x ) ≈ tanh ⁡ ( 2 π ( x + 11 123 x 3 ) ) (p7) \text{erf}(x) \approx \tanh\left(\frac{2}{\sqrt \pi} \left(x +\frac{11}{123}x^3 \right) \right) \tag{p7} erf(x)tanh(π 2(x+12311x3))(p7)

import numpy as np
import matplotlib.pyplot as plt
import scipy.specialx = np.linspace(-3, 3, 100)y1 = scipy.special.erf(x)y2 = np.tanh(2/np.sqrt(np.pi)*(x + 11/123 * x**3))plt.figure()
plt.plot(x, y1, label='erf(x)')
plt.plot(x, y2, label='tanh(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Plot of erf(x) and tanh(x)')
plt.legend()
plt.grid(True)
plt.show()

image-20240428075759147

当通常如上代码画图,这两个函数的图几乎重叠。

伯努利分布

伯努利分布(Bernoulli distribution),又称为两点分布或0-1分布,是一个离散型概率分布。若伯努利试验成功,则伯努利随机变量取值为1,否则伯努利试验失败,伯努利随机变量取值为0。即其成功概率为 p ( 0 ≤ p ≤ 1 ) p( 0 \leq p \leq 1) p(0p1),失败概率为 q = 1 − p q= 1-p q=1p

其概率质量函数(probability mass function, pmf)为:
f X ( x ) = p x ( 1 − p ) 1 − x = { p if x = 1 q if x = 0 f_X(x) = p^x (1-p)^{1-x} = \begin{cases} p & \text{if x = 1}\\ q & \text{if x = 0} \end{cases} fX(x)=px(1p)1x={pqif x = 1if x = 0
概率质量函数是离散型随机变量在各特定取值上的概率,和概率密度函数的一个不同之处在于:概率质量函数是对离散随机变量定义的,本身代表该值的概率;概率密度函数本身不是概率,只有对连续随机变量的概率密度函数必须在某一个区间内被积分后才能产生出概率。

不同成功概率下的概率质量函数图像:

image-20240427170444091

其期望为:
E [ X ] = ∑ i = 0 1 x i f X ( x ) = 0 + p = p (p6) E[X] = \sum_{i=0}^1 x_i f_X(x) = 0 + p = p \tag {p6} E[X]=i=01xifX(x)=0+p=p(p6)

GELU公式

作者通过结合dropout、zoneout和ReLU的特性来激发出这个激活函数。

首先要注意的是,ReLU和dropout都可以确定地将神经元的输出乘零或一,而dropout则是随机地将其乘零。此外,一种新的RNN正则化器称为zoneout可以通过乘一来随机地乘输入。

作者通过将输入乘零或一来合并这种功能,但是这个零一掩码的值是随机确定的,同时也依赖于输入。具体来说,将神经元的输入 x x x m ∼ Bernoulli ( Φ ( x ) ) m ∼ \text{Bernoulli}(\Phi(x)) mBernoulli(Φ(x)),其中 Φ ( x ) = P ( X ≤ x ) \Phi(x) = P(X ≤ x) Φ(x)=P(Xx) X ∼ N ( 0 , 1 ) X ∼ N(0, 1) XN(0,1)​​​是标准正态分布的累积分布函数。

选择这个分布是因为神经元的输入往往遵循正态分布,尤其是在批归一化的情况下。在这种情况下,随着 x x x的减小,输入“被丢弃”的概率更高,因此应用于 x x x​​的转换是随机的,但取决于输入。

以这种方式屏蔽输入保留了非确定性,但仍然依赖于输入值。随机选择的掩码相当于对输入进行随机的恒等映射(不变)和置零映射。这非常类似于自适应dropout,但自适应dropout与非线性一起使用,并使用逻辑斯蒂分布而不是标准正态分布。作者发现,只使用这种随机正则化器就可以训练出具有竞争力的网络,而不需要使用任何非线性。

我们通常希望神经网络做出确定性的决策,所以激活函数的输出应该是确定的,不能是随机的。为了移除这个随机性,我们可以计算期望:
E [ m x ] = x E [ m ] = x Φ ( x ) E[mx] = x E[m] = x\Phi(x) E[mx]=xE[m]=xΦ(x)
因为 m m m是伯努利分布,根据(p6)我们知道该伯努利分布的期望为 Φ ( x ) \Phi(x) Φ(x)

由于高斯分布的累积分布函数通常使用误差函数计算,因此作者将GELU定义为:
GELU ( x ) = x P ( X ≤ x ) = x Φ ( x ) = x ⋅ 1 2 [ 1 + erf ( x / 2 ) ] \text{GELU} (x) = x P(X \leq x) = x\Phi(x) = x \cdot \frac{1}{2} \left[1 + \text{erf}(x / \sqrt 2) \right] GELU(x)=xP(Xx)=xΦ(x)=x21[1+erf(x/2 )]
这里可以参考(p5)。

image-20240427172743948

其对应的函数图像可以参考上图的蓝线。从其图像可以看出,在负值区域,不像 ReLU \text{ReLU} ReLU全为0,并且是光滑地、处处可导的。

在HuggingFace的transformers库中的实现为如下:

class GELUActivation(nn.Module):"""Original Implementation of the GELU activation function in Google BERT repo when initially created. Forinformation: OpenAI GPT's GELU is slightly different (and gives slightly different results): 0.5 * x * (1 +torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))) This is now written in C in nn.functionalAlso see the Gaussian Error Linear Units paper: https://arxiv.org/abs/1606.08415"""def __init__(self, use_gelu_python: bool = False):super().__init__()if use_gelu_python:self.act = self._gelu_pythonelse:self.act = nn.functional.geludef _gelu_python(self, input: Tensor) -> Tensor:return input * 0.5 * (1.0 + torch.erf(input / math.sqrt(2.0)))def forward(self, input: Tensor) -> Tensor:return self.act(input)

可以看到这里提供了两种实现,一种是直接通过上面的公式实现——_gelu_python();从注释中可以看出,还有一种是基于0.5 * x * (1 +torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3))))的近似实现,通过C来实现,默认是采用这种方式。

后者是为了加速计算,第一种实现时精确求解。作者有指出可以近似GELU为
0.5 x ( 1 + tanh ⁡ [ 2 / π ( x + 0.044715 x 3 ) ] ) 0.5 x(1+ \tanh[\sqrt{2/\pi} (x + 0.044715x^3)]) 0.5x(1+tanh[2/π (x+0.044715x3)])


x σ ( 1.702 x ) x\sigma(1.702 x) xσ(1.702x)
甚至如果更快的前馈网络速度的价值超过了准确性的代价,还可以使用不同的累积分布函数。例如,我们可以使用逻辑斯蒂分布的累积分布函数 σ ( x ) σ(x) σ(x)来得到所谓的Sigmoid线性单元(Sigmoid Linear Unit, SiLU):
SiLU = x σ ( x ) \text{SiLU} = x\sigma(x) SiLU=xσ(x)
也可以使用 N ( μ , σ 2 ) N(\mu, σ^2) N(μ,σ2)的累积分布函数,并让µ和σ成为可学习的超参数,但在这项工作中,只简单地让 μ = 0 \mu= 0 μ=0 σ = 1 σ = 1 σ=1​。

近似推导

从补充知识中我们看到了 erf ( x ) ≈ tanh ⁡ ( 2 π ( x + 11 123 x 3 ) ) \text{erf}(x) \approx \tanh\left(\frac{2}{\sqrt \pi} \left(x +\frac{11}{123}x^3 \right) \right) erf(x)tanh(π 2(x+12311x3))​。下面我们利用泰勒展开证明一下。

tanh ⁡ x \tanh x tanhx的泰勒展开为:
tanh ⁡ x = ∑ n = 1 ∞ 2 2 n ( 2 2 n − 1 ) B 2 n x 2 n − 1 ( 2 n ) ! = x − x 3 3 + 2 x 5 15 − 17 x 7 315 + ⋯ \tanh x = \sum^{\infty}_{n=1} \frac{2^{2n}(2^{2n}-1)B_{2n}x^{2n-1}}{(2n)!}= x -\frac{x^3}{3} + \frac{2x^5}{15} - \frac{17x^7}{315} + \cdots tanhx=n=1(2n)!22n(22n1)B2nx2n1=x3x3+152x531517x7+
假设我们不知道式(p7)中的具体数值。我们考虑近似形式 tanh ⁡ ( a x + b x 3 ) \tanh (ax+bx^3) tanh(ax+bx3)以及 GELU \text{GELU} GELU中的形式,在 x = 0 x=0 x=0​处展开

考虑 tanh ⁡ ( a x + b x 3 ) \tanh (ax+bx^3) tanh(ax+bx3)的泰勒展开:
a x + b x 3 − ( a 3 3 x 3 + b 3 x 6 3 ) + ⋯ ax + bx^3 - (\frac{a^3}{3}x^3 + \frac{b^3x^6}{3}) + \cdots ax+bx3(3a3x3+3b3x6)+
我们仅考虑前两项,即令同幂次前的系数相等:
erf ( x 2 ) − tanh ⁡ ( a x + b x 3 ) = ( 2 π − a ) x + ( a 3 3 − b − 1 3 2 π ) x 3 \text{erf}(\frac{x}{\sqrt 2}) - \tanh(ax+bx^3) = \left( \sqrt \frac{ 2}{ \pi} -a \right)x +\left(\frac{a^3}{3} -b -\frac{1}{3\sqrt {2\pi}} \right)x^3 erf(2 x)tanh(ax+bx3)=(π2 a)x+(3a3b32π 1)x3
得到两个方程,求解得到

a = 2 π , b = 4 − π 3 2 π 3 / 2 a = \sqrt \frac{2}{\pi},\quad b=\frac{4-\pi}{3\sqrt 2\pi^{3/2}} a=π2 ,b=32 π3/24π

代入GELU中的 x Φ ( x ) x\Phi(x) xΦ(x),得到

x Φ ( x ) ≈ 1 2 x [ 1 + tanh ⁡ ( 2 π ( x + 0.0455399 x 3 ) ) ] \begin{equation}x\Phi(x)\approx \frac{1}{2} x\left[1 + \tanh\left(\sqrt{\frac{2}{\pi}}\left(x + 0.0455399 x^3\right)\right)\right]\end{equation} xΦ(x)21x[1+tanh(π2 (x+0.0455399x3))]

这个值很接近 0.044715 0.044715 0.044715,因为我们仅做了前两项的近似,所以得到的这个值与真实值存在误差,注意的是作者提出的也是一种近似,也存在误差。这种做法仅考虑局部误差,即在 x = 0 x=0 x=0的局部会比较精确。

因此我们还需要考虑全局误差。

我们固定 a = 2 π a=\sqrt{\frac{2}{\pi}} a=π2 ,这个 a a a是一阶局部近似,我们希望保留在这个近似。同时希望 b b b尽可能帮我们减少全局误差。所以我们可以求解:
min ⁡ b max ⁡ x ∣ erf ( x 2 ) − tanh ⁡ ( a x + b x 3 ) ∣ \begin{equation}\min_{b} \max_x \left|\text{erf}\left(\frac{x}{\sqrt{2}}\right)-\tanh\left(a x + b x^3\right)\right|\end{equation} bminxmax erf(2 x)tanh(ax+bx3)
通过参考2中给出的代码来求解:

import numpy as np
from scipy.special import erf
from scipy.optimize import minimize
# 增加设置显示精度
np.set_printoptions(precision=20)def f(x, b):a = np.sqrt(2 / np.pi)return np.abs(erf(x / np.sqrt(2)) - np.tanh(a * x + b * x**3))def g(b):return np.max([f(x, b) for x in np.arange(0, 4, 0.001)])options = {'xtol': 1e-10, 'ftol': 1e-10, 'maxiter': 100000}
result = minimize(g, 0, method='Powell', options=options)
print(result.x)
[0.035677337314877496]

代入 x Φ ( x ) x\Phi(x) xΦ(x),得到:

x Φ ( x ) ≈ 1 2 x [ 1 + tanh ⁡ ( 2 π ( x + 0.04471491123850979 x 3 ) ) ] \begin{equation}x\Phi(x)\approx \frac{1}{2} x\left[1 + \tanh\left(\sqrt{\frac{2}{\pi}}\left(x + 0.04471491123850979 x^3\right)\right)\right]\end{equation} xΦ(x)21x[1+tanh(π2 (x+0.04471491123850979x3))]

怎么代入呢,因为上式提出了一个 2 π \sqrt{\frac{2}{\pi}} π2 ,所以让 0.035677337314877496 × π 2 0.035677337314877496 \times \sqrt \frac{\pi}{2} 0.035677337314877496×2π 即可:

import mathmath.sqrt(math.pi /2) * 0.035677337314877496
0.04471491123850979

此时得到的结果比论文中的 0.044715 0.044715 0.044715更加精确。

本篇工作中还提出了一种近似,即 x σ ( 1.702 x ) x\sigma(1.702 x) xσ(1.702x),它是直接用 σ ( b x ) \sigma(bx) σ(bx)全局逼近 Φ ( x ) \Phi(x) Φ(x)的结果,即
min ⁡ λ max ⁡ x ∣ Φ ( x ) − σ ( b x ) ∣ \begin{equation}\min_{\lambda}\max_{x}\left|\Phi(x) - \sigma(b x)\right|\end{equation} λminxmaxΦ(x)σ(bx)
修改下上面的代码:

import numpy as np
from scipy.special import erf
from scipy.optimize import minimize
from scipy.special import expitnp.set_printoptions(precision=20)def f(x, b):return np.abs(0.5*(1+erf(x / np.sqrt(2))) - 1/(1 + np.exp(-b*x)))def g(b):return np.max([f(x, b) for x in np.arange(0, 4, 0.001)])options = {'xtol': 1e-10, 'ftol': 1e-10, 'maxiter': 100000}
result = minimize(g, 0, method='Powell', options=options)
print(result.x)
[1.7017449256323682]


Φ ( x ) ≈ σ ( 1.7017449256323682 x ) \begin{equation}\Phi(x)\approx \sigma(1.7017449256323682 x)\end{equation} Φ(x)σ(1.7017449256323682x)

实验

讨论

通过实验证明,GELU表现优于先前的非线性激活函数,但在其他方面与ReLU和ELU相似。例如,当 σ → 0 σ → 0 σ0 μ = 0 \mu = 0 μ=0时,GELU变成了ReLU。此外,ReLU和GELU在渐进上是相等的。实际上,可以将GELU视为平滑ReLU的一种方式。

GELU和之前的激活函数比有几个显著的区别。这个非凸非单调函数在正域不是线性的,并且在所有点上都表现出曲率。而ReLU和ELU是凸函数和单调激活函数,在正域中是线性的,因此可能缺乏曲率。因此,增加曲率和非单调性可能使GELU比ReLU或ELU更容易逼近复杂的函数。此外,由于 ReLU ( x ) = x 1 ( x > 0 ) \text{ReLU}(x) = x\Bbb 1(x > 0) ReLU(x)=x1(x>0) GELU ( x ) = x Φ ( x ) \text{GELU}(x) = x\Phi(x) GELU(x)=xΦ(x),如果 μ = 0 , σ = 1 \mu = 0,σ = 1 μ=0σ=1​,我们可以看到ReLU根据输入的符号对其进行门控,而GELU根据其相对于其他输入的大小对其进行加权。此外,重要的是指出,GELU具有概率解释,因为它是随机正则化器的期望。

结论

本篇工作评估了大量的数据集,证明GELU超越了ELU和ReLU的准确率。

总结

⭐ 作者提出了一种新的激活函数——GELU,根据输入相对于其他输入的大小对其进行加权。即随着输入 x x x的减小,输入“被丢弃”的概率更高,因此应用于 x x x的置零或置一变换是随机的,但取决于输入。

参考

  1. 维基百科
  2. 苏剑林. (Mar. 26, 2020). 《GELU的两个初等函数近似是怎么来的 》[Blog post]. Retrieved from https://kexue.fm/archives/7309

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

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

相关文章

网盘—上传文件

本文主要讲解网盘里面关于文件操作部分的上传文件,具体步骤如下 目录 1、实施步骤: 2、代码实现 2.1、添加上传文件协议 2.2、添加上传文件槽函数 2.3、添加槽函数定义 2.4、关联上传槽函数 2.5、服务器端 2.6、在服务器端添加上传文件请求的ca…

算法学习(5)-图的遍历

目录 什么是深度和广度优先 图的深度优先遍历-城市地图 图的广度优先遍历-最少转机 什么是深度和广度优先 使用深度优先搜索来遍历这个图的过程具体是: 首先从一个未走到过的顶点作为起始顶点, 比如以1号顶点作为起点。沿1号顶点的边去尝试访问其它未…

提升编码技能:学习如何使用 C# 和 Fizzler 获取特价机票

引言 五一假期作为中国的传统节日,也是旅游热门的时段之一,特价机票往往成为人们关注的焦点。在这个数字化时代,利用爬虫技术获取特价机票信息已成为一种常见的策略。通过结合C#和Fizzler库,我们可以更加高效地实现这一目标&…

2024年---蓝桥杯网络安全赛道部分WP

一、题目名称:packet 1、下载附件是一个流量包 2、用wireshark分析,看到了一个cat flag的字样 3、追踪http数据流,在下面一行看到了base64编码。 4、解码之后得到flag 二、题目名称:cc 1、下载附件,打开是一个html …

Docker构建LNMP部署WordPress

前言 使用容器化技术如 Docker 可以极大地简化应用程序的部署和管理过程,本文将介绍如何利用 Docker 构建 LNMP 环境,并通过部署 WordPress 来展示这一过程。 目录 一、环境准备 1. 项目需求 2. 安装包下载 3. 服务器环境 4. 规划工作目录 5. 创…

CAPS Wizard for Mac:打字输入辅助应用

CAPS Wizard for Mac是一款专为Mac用户设计的打字输入辅助应用,以其简洁、高效的功能,为用户带来了全新的打字体验。 CAPS Wizard for Mac v5.3激活版下载 该软件能够智能预测用户的输入内容,实现快速切换和自动大写锁定,从而大大…

OmniReader Pro for Mac:强大且全面的阅读工具

OmniReader Pro for Mac是一款专为Mac用户设计的强大且全面的阅读工具,它集阅读、编辑、管理等多种功能于一身,为用户提供了卓越的阅读体验。 OmniReader Pro for Mac v2.9.5激活版下载 该软件支持多种文件格式的阅读,包括PDF、Word、Excel、…

pycharm配置wsl开发环境(conda)

背景 在研究qanything项目的过程中,为了进行二次开发,需要在本地搭建开发环境。然后根据文档说明发现该项目并不能直接运行在windows开发环境,但可以运行在wsl环境中。于是我需要先创建wsl环境并配置pycharm。 wsl环境创建 WSL是“Windows Su…

新时代写作与互动:《一本书讲透 Elasticsearch》读者群的创新之路

1、《一本书讲透 Elasticsearch》销售最近进展汇报 给大家同步一下《一本书讲透 Elasticsearch》图书的进展情况,本周五(2024年4月26日),出版社编辑老师反馈图书相关销量进展: 预计全网销量 1000 册,发货量…

OpenHarmony语言基础类库【@ohos.xml (xml解析与生成)】

将XML文本转换为JavaScript对象、以及XML文件生成和解析的一系列接口。 说明: 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 导入模块 import xml from ohos.xml; XmlSerializer XmlSerializer接口…

FPGA实现图像处理之【直方图均衡-寄存器版】

FPGA实现直方图统计 一、图像直方图统计原理 直方图的全称为灰度直方图,是对图像每一灰度间隔内像素个数的统计。即对一张图片中每隔二灰度值的像素数量做统计,然后以直方图的形式展现出来。图下的亮暗分布在直方图中就可以一目了然,直方图…

Spark核心名词解释与编程

Spark核心概念 名词解释 1)ClusterManager:在Standalone(上述安装的模式,也就是依托于spark集群本身)模式中即为Master(主节点),控制整个集群,监控Worker。在YARN模式中为资源管理器ResourceManager(国内…

paddlehub的简单应用

1、下载安装 pip install paddlehub -i https://pypi.tuna.tsinghua.edu.cn/simple 报错&#xff1a; Collecting onnx<1.9.0 (from paddle2onnx>0.5.1->paddlehub)Using cached https://pypi.tuna.tsinghua.edu.cn/packages/73/e9/5b953497c0e36df589fc60cc6c6b35…

Redux数据流架构

Redux的难点是理解它对于数据修改的规则, 下图动态展示了在整个数据的修改中&#xff0c;数据的流向 Redux代码被分为三个核心的概念&#xff0c;三个概念分别是: state: 一个对象 存放着我们管理的数据action: 一个对象 用来描述你想怎么改数据reducer: 一个函数 根据action的…

万兆以太网MAC设计(11)完整UDP协议栈仿真

文章目录 前言一、模块接口二、IP模块与ARP模块之间的联系三、整体协议栈仿真总结&#xff1a; 前言 目前除了巨帧处理逻辑之外&#xff0c;所有的准备工作都已经结束了&#xff0c;先进行整体的功能验证。 一、模块接口 所有模块接口皆采用AXIS数据流的形式&#xff0c;其中…

用Jenkins实现cherry-pick多个未入库的gerrit编译Android固件

背景: 在做Android固件开发的时候,通常我们可以利用gerrit-trigger插件,开发者提交一笔的时候自动触发jenkins编译,如果提交的这一笔的编译依赖其他gerrit才能编译过,我们可以在commit message中加入特殊字段,让jenkins在编译此笔patch的时候同时抓取依赖的gerrit代码下…

java后端项目:视积分抽奖平台

一、项目背景: 本次抽奖系统实现是在视频中内置一个线上活动抽奖系统,奖品是在一个时间段区间内均匀发布,用户可以在这个时间段内参与抽奖。 二、项目架构 活动抽奖平台采用微服务架构来完成,在功能上实现拆分为用户、网关、以及抽奖微服务,其中用户、网关是后台项目通…

三. TensorRT基础入门-TensorRT内部的优化模块

目录 前言0. 简述1.TensorRT的优化策略2. Layer Fusion3. Kernel Auto-Tuning4. Quantization总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习课程第三章—TensorRT 基础入…

C++ | 类和对象(上)

目录 什么是类 类的介绍 struct在两种语言中的有何区别 私有变量命名注意点 类的作用域 类的声明定义分离 类的访问限定符 封装 类的实例化 类对象的存储 this指针 一道this指针相关的王炸题&#xff1a; 结语 什么是类 类的介绍 我们举一个日常生活中的例子&…

罗宾斯《管理学》第15版笔记/课后习题/考研真题答案

第Ⅰ篇 管理导论 第1章 工作场所中的管理者和你 1.1 知识结构导图 1.2 考点难点归纳 1.3 课后习题详解 1.4 考研真题详解 附加模块一 管理史 知识结构导图 考点难点归纳 课后习题详解 考研真题详解 第2章 决 策 2.1 知识结构导图 2.2 考点难点归纳 2.3 课后习题详解…