C++builder中的人工智能(15):C++高斯误差线性单元(GELU)

部署运行你感兴趣的模型镜像

在这篇文章中,我们将探索高斯误差线性单元(GELU:Gaussian Error Linear Unit)是什么,它是如何在人工神经网络(ANN)中工作的,以及GELU可以应用于哪些AI技术。通过学习C++中的高斯误差线性单元,你将能够使用C++ IDE构建C++应用程序。

什么是激活函数?

激活函数(phi()),也称为转移函数或阈值函数,它根据净输入函数的给定值(sum)确定激活值(a = phi(sum))。在这里,sum是它们权重中的信号之和,激活函数是这个和的新值,具有给定的函数或条件。换句话说,激活函数是将所有加权信号的和转换为该信号的新激活值的方法。有不同类型的激活函数,通常使用的是线性(恒等)、双极性和逻辑(sigmoid)函数。

在C++(以及大多数编程语言)中,你可以创建自己的激活函数。注意,sum是净输入函数的结果,它计算所有加权信号的和。我们将使用这些作为输入函数的结果。在这里,人工神经元(输出值)的激活值可以通过激活函数如下所示,

什么是高斯误差线性单元(GELU)?

高斯误差线性单元(GELU)是ReLU、ELU函数的替代品,由Dan Hendrycks和Kevin Gimpel在2016年定义和发布。它用于平滑ReLU和ELU激活(全文可以在这里找到https://arxiv.org/pdf/1606.08415

GELU是一种高性能的神经网络激活函数。GELU激活函数是xΦ(x),其中Φ(x)是标准高斯累积分布函数。GELU非线性通过它们的值加权输入,而不是像ReLUs(x>0)那样通过它们的符号门控输入。对GELU非线性与ReLU和ELU激活的实证评估已应用于所有考虑的计算机视觉、自然语言处理和语音任务,并有性能提升。

GELU函数可以写成

我们可以用以下方式近似GELU,

或者如果更大的前馈速度值得牺牲精确性,我们可以使用以下近似,

我们可以使用不同的CDFs,即我们可以使用逻辑函数(Logistic Function),累积分布函数(Cumulative Distribution Function )CDF σ(x)来获得激活值,这称为Sigmoid Linear Unit(SiLU) xσ(x)。

根据第二个公式,我们可以用GELU编写我们的phi()激活函数如下,

double sqrt_2divPI = std::sqrt(2.0/M_PI);
double phi(double sum) {
    return(0.5*sum*(1+std::tanh(sqrt_2divPI*(sum+0.044715*std::pow(sum,3)))); // GeLU Function
}

根据第三个公式,我们可以使用sigmoid函数,并编写我们的phi()激活函数如下,

double sigmoid(double x) {
    return(1/(1+std::exp(-1*x)));
}
double phi2(double sum) {
    return(sum*sigmoid(1.702*sum)); // GeLU Function
}

这些公式都可以在以下示例中进行测试,

#include <iostream>
double sqrt_2divPI = std::sqrt(2.0/M_PI);
double phi(double sum) {
    return(0.5*sum*(1+std::tanh(sqrt_2divPI*(sum+0.044715*std::pow(sum,3)))); // GeLU Function
}
double sigmoid(double x) {
    return(1/(1+std::exp(-1*x)));
}
double phi2(double sum) {
    return(sum*sigmoid(1.702*sum)); // GeLU Function
}
int main() {
    std::cout << phi(0.5) << '\n';
    std::cout << phi2(0.5) << '\n';
    getchar();
    return 0;
}

有没有一个简单的C++ ANN示例,使用GELU激活函数?

#include <iostream>
#define NN 2   // 神经元数量
double sqrt_2divPI = std::sqrt(2.0/M_PI);
class Tneuron { // 神经元类
public:
    double a;       // 每个神经元的活动值
    double w[NN+1]; // 神经元之间连接的权重
    Tneuron() {
        a = 0;
        for (int i = 0; i <= NN; i++) w[i] = -1;  // 如果权重是负数,则表示没有连接
    }
    // 定义输出神经元的激活函数(或阈值)
    double activation_function(double sum) {
        return(0.5*sum*(1+std::tanh(sqrt_2divPI*(sum+0.044715*pow(sum,3)))); // GeLU Function
    }
};
Tneuron ne[NN+1]; // 神经元对象
void fire(int nn) {
    double sum = 0;
    for (int j = 0; j <= NN; j++) {
        if (ne[j].w[nn] >= 0) sum += ne[j].a * ne[j].w[nn];
    }
    ne[nn].a = ne[nn].activation_function(sum);
}
int main() {
    // 定义两个输入神经元(a0, a1)和一个输出神经元(a2)的活动值
    ne[0].a = 0.0;
    ne[1].a = 1.0;
    ne[2].a = 0;
    // 定义来自两个输入神经元到输出神经元(0到2和1到2)的信号权重
    ne[0].w[2] = 0.3;
    ne[1].w[2] = 0.2;
    // 激发我们的人工神经元活动,输出将是
    fire(2);
    printf("%10.6f\n", ne[2].a);
    getchar();
    return 0;
}

这个示例展示了如何在C++中使用GELU激活函数来模拟一个简单的人工神经网络。通过这种方式,你可以构建更复杂的神经网络模型,并在C++应用中实现深度学习技术。

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.9

TensorFlow-v2.9

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

### 结合线性层、Layer Normalization 和 GELU实现 在深度学习框架中,结合线性层(Fully Connected Layer)、Layer Normalization (LN)GELU 激活函数是一种常见的做法。这种组合能够有效增强模型的稳定性并改善其收敛性能。 #### 实现过程描述 1. **线性变换** 首先通过一个线性变换计算隐藏状态 \(z\),即 \(z = xW_1 + b_1\),其中 \(W_1\) 是权重矩阵,\(b_1\) 是偏置向量[^1]。 2. **Layer Normalization** 接下来应用 Layer Normalization 对线性变换的结果进行标准化处理。Layer Normalization 可以减少梯度消失或爆炸现象的发生,并加速训练过程。假设输入为 \(z\),则 LN 计算如下: \[ z_{\text{norm}} = \frac{z - \mu}{\sigma} * \gamma + \beta \] 其中,\(\mu\) 表示均值,\(\sigma\) 表示标准差,而 \(\gamma, \beta\) 则是可学习参数[^3]。 3. **GELU 激活函数** 经过 LN 处理后的张量再传递给 GELU 激活函数。Gaussian Error Linear Unit (GELU) 定义为: \[ \text{GELU}(x) = x \cdot P(X \leq x) = x \cdot \Phi(x) \] 或者近似形式: \[ \text{GELU}_{\text{approx}}(x) = 0.5x(1 + \tanh[\sqrt{\frac{2}{\pi}}(x + 0.044715x^3)]) \] 这种激活函数相较于传统的 ReLU 能够提供更平滑的非线性映射[^4]。 4. **后续操作** 最终经过上述三个步骤得到的新特征表示可以作为下一层网络的输入或者进一步参与残差连接等结构设计。 以下是基于 PyTorch 的具体代码实现: ```python import torch import torch.nn as nn class FNNWithLNGELU(nn.Module): def __init__(self, input_dim, hidden_dim): super(FNNWithLNGELU, self).__init__() self.linear = nn.Linear(input_dim, hidden_dim) # 线性层 self.ln = nn.LayerNorm(hidden_dim) # 层归一化 self.activation = nn.GELU() # GELU 激活函数 def forward(self, x): out = self.linear(x) # 应用线性变换 out = self.ln(out) # 应用层归一化 out = self.activation(out) # 应用 GELU 激活函数 return out ``` 此模块定义了一个简单的前馈神经网络单元,它依次执行了线性变换、层归一化以及 GELU 激活的操作序列[^5]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caridle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值