机器学习依赖于算法、统计模型和神经网络
而深度学习是机器学习的一个子领域,专注于神经网络。

任何神经网络的关键组成部分都是激活函数
但确切地理解它们为何对任何神经网络系统都是至关主要的,是一个常见的问题,也可能是一个难以回答的问题。

本文重点阐明为什么激活函数是必需的,以大略的办法和类最近解释。

通过理解这一点,您将理解到AI模型思维的过程。

AI模型的思维办法激活函数的关键浸染及代码示例

在此之前,我们将磋商AI中的神经网络。
我们还将磋商最常用的激活函数。

我们还将剖析一个非常大略的PyTorch神经网络代码示例的每一行。

(本文视频讲解:java567.com)

本文将磋商以下内容:人工智能与深度学习的崛起理解激活函数:简化神经网络机制大略类比:激活函数的必要性没有激活函数会发生什么?PyTorch激活函数代码示例结论:AI神经网络的默默英雄

本文不涵盖辍学或其他正则化技能、超参数优化、繁芜架构如CNNs,或者梯度低落变体的详细差异。

我只想展示为什么须要激活函数以及当它们未运用到神经网络时会发生什么。

人工智能与深度学习的兴起人工智能中的深度学习是什么?

显示社会与人工智能之间联系的图像

深度学习是人工智能的一个子领域。
它利用神经网络来处理繁芜的模式,就像体育团队为赢得比赛而采取的策略一样。

神经网络越大,就越能够做出令人惊叹的事情 - 就像ChatGPT一样,它利用自然措辞处理来回答问题并与用户交互。

要真正理解神经网络的根本知识 - 每个单独的人工智能模型都具有的共同点,使其能够事情 - 我们须要理解激活层。

深度学习 = 演习神经网络

大略神经网络

深度学习的核心是演习神经网络。

这基本上意味着利用数据来得到精确的权重值,以便能够预测我们想要的内容。

神经网络由组织在层中的神经元构成。
每一层从数据中提取独特的特色。

这种分层构造使得深度学习模型能够剖析和解释繁芜的数据。

理解激活函数:简化神经网络机制

Leaky ReLU激活函数

激活函数帮助神经网络处理繁芜的数据。
它们根据吸收到的数据改变神经元的值。

险些每个神经元在将其值发送到下一个神经元之前都有一个类似的过滤器。

本色上,激活函数掌握神经网络的信息流 - 它们决定哪些数据是干系的,哪些是不干系的。

这有助于防止梯度消逝,以确保网络精确学习。

梯度消逝问题发生在神经网络的学习旗子暗记太弱以至于权重值不变时。
这使得从数据中学习变得非常困难。

大略类比:激活函数为什么必要

足球运动员思考

在足球比赛中,球员决定是传球、运球还是射门。

这些决定基于当前的比赛情形,就像神经网络中的神经元处理数据一样。

在这种情形下,激活函数在决策过程中起到这样的浸染。

如果没有它们,神经元将会毫无选择性地通报数据 - 就像球员毫无思考地踢球,不管比赛背景如何。

这样,激活函数引入了繁芜性到神经网络中,使其能够学习繁芜的模式。

没有激活函数会发生什么?

球员奔跑

为了理解没有激活函数会发生什么,让我们首先想一想如果在足球比赛中球员毫无考虑地踢球会发生什么情形。

他们很可能会输掉比赛,由于没有团队决策过程。
球还是会被踢到某个地方 - 但大部分韶光它不会飞往预期的地方。

这与没有激活函数的神经网络所发生的情形相似:神经网络不会做出良好的预测,由于神经元只是随机地向彼此通报数据。

我们仍旧会得到一个预测结果。
只是不是我们想要的,或者不是有用的。

这严重限定了足球队和神经网络的能力。

对激活函数的直不雅观阐明

现在让我们看一个例子,以便您可以直不雅观地理解这一点。

ReLU激活函数

让我们从深度学习中最广泛利用的激活函数开始(它也是最大略的之一)。

这是一个ReLU激活函数。
它基本上充当了神经元发送值到其下一个神经元之前的过滤器。

这个过滤器基本上包含两个条件:

如果权重值为负,它变为0如果权重值为正,它不改变任何值

通过这样做,我们为每个神经元增加了一个决策过程。
它决定发送哪些数据,哪些不发送。

现在让我们看一些其他激活函数的例子。

Sigmoid激活函数

这个激活函数将输入值转换为0到1之间的值。
Sigmoid在末了一个神经元中的二元分类问题中广泛利用。

Sigmoid激活函数

不过,Sigmoid激活函数存在问题。
考虑给定线性变换的输出值:

0.000000030.999999920.000002470.99993320

我们可以讯问这些值的一些问题:

像0.00000003和0.000002这样的值真的主要吗?它们不能只是0,这样我们就少了要在打算机上运行的东西吗?请记住,在本日的许多模型中,我们有数百万个权重。
数百万的0.00000003和0.000002不能是0吗?如果它是一个正值,它如何区分大值和非常大值?例如,在0.99993320和0.99999992中,输入值像7和137和55在哪里?0.99993320和0.99999992并没有准确地描述它们的输入值。

我们如何区分输出中眇小差异,以保持准确性?

这便是ReLU激活函数办理的问题:将负数设为零,同时保持正数可以增强神经网络的打算效率。

Tanh(双曲正切)激活函数

tanh激活函数

这些激活函数的输出值在-1和1之间,与Sigmoid类似。

它们常日用于循环神经网络(RNNs)和是非期影象网络(LSTMs)。

Tanh也被利用是由于它因此零为中央的。
这意味着输出值的均匀值大约为零。
这种特性有助于处理梯度消逝问题。

Leaky ReLU

Leaky ReLU激活函数

Leaky ReLU激活函数不是忽略负值,而是会有一个小的负值。

这样,当演习神经网络时,负值也会被利用。

利用ReLU激活函数时,带有负值的神经元是不生动的,并且不会对学习过程做出贡献。

利用Leaky ReLU激活函数时,带有负值的神经元是生动的,并且对学习过程有所贡献。

这种决策过程是由激活函数实现的。
如果没有它,它将大略地将数据发送给下一个神经元(就像球员毫无思考地踢球)。

激活函数的数学阐明

数学变换的力量

神经元做两件事情:

它们利用以前神经元的权重值进行线性变换它们利用激活函数来过滤某些值以有选择地通报值。

如果没有激活函数,神经网络只做一件事情:线性变换。

如果它只做线性变换,它便是一个线性系统。

如果它是一个线性系统,大略地说而不太技能性地说,叠加定理见告我们,两个或更多线性变换的任何稠浊都可以简化为一个单一的变换。

基本上,这意味着,没有激活函数,这个繁芜的神经网络:

没有激活函数的长神经网络

与这个大略的神经网络相同:

没有激活函数的短神经网络

这是由于每一层在矩阵形式中都是前一层的线性变换的乘积。

根据定理,由于任何两个或更多线性变换的稠浊可以简化为一个单一的变换,那么神经网络中隐蔽层(即神经元的输入和输出之间的层)的任何稠浊都可以简化为只有一个层。

这统统意味着什么?

这意味着它只能以线性办法对数据进行建模。
但在现实生活中,利用真实数据,每个别系都是非线性的。
以是我们须要激活函数。

我们引入非线性到神经网络中,以便它学习非线性模式。

PyTorch激活函数代码示例

在本节中,我们将演习以下神经网络:

大略的前馈神经网络

这是一个大略的神经网络AI模型,具有四层:

输入层有10个神经元两个隐蔽层,每层有18个神经元一个隐蔽层有18个神经元一个输出层有1个神经元

在代码中,我们可以选择本教程中提到的四种激活函数中的任意一种。

下面是完全的代码 - 我们将逐步谈论:

import torchimport torch.nn as nnimport torch.optim as optim# 在代码中选择要利用的激活函数defined_activation_function = 'relu'activation_functions = { 'relu': nn.ReLU(), 'sigmoid': nn.Sigmoid(), 'tanh': nn.Tanh(), 'leaky_relu': nn.LeakyReLU()}# 初始化超参数num_samples = 100batch_size = 10num_epochs = 150learning_rate = 0.001# 定义一个大略的合成数据集def generate_data(num_samples): X = torch.randn(num_samples, 10) y = torch.randn(num_samples, 1) return X, y# 天生合成数据X, y = generate_data(num_samples)class SimpleModel(nn.Module): def __init__(self, activation=defined_activation_function): super(SimpleModel, self).__init__() self.fc1 = nn.Linear(in_features=10, out_features=18) self.fc2 = nn.Linear(in_features=18, out_features=18) self.fc3 = nn.Linear(in_features=18, out_features=4) self.fc4 = nn.Linear(in_features=4, out_features=1) self.activation = activation_functions[activation] def forward(self, x): x = self.fc1(x) x = self.activation(x) x = self.fc2(x) x = self.activation(x) x = self.fc3(x) x = self.activation(x) x = self.fc4(x) return x# 初始化模型,定义丢失函数和优化器model = SimpleModel(activation=defined_activation_function)criterion = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=learning_rate)# 演习循环for epoch in range(num_epochs): for i in range(0, num_samples, batch_size): # 获取小批量数据 inputs = X[i:i+batch_size] labels = y[i:i+batch_size] # 梯度清零 optimizer.zero_grad() # 前向传播 outputs = model(inputs) # 打算丢失 loss = criterion(outputs, labels) # 反向传播和优化 loss.backward() optimizer.step() print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss}')print("演习完成。
")

看起来有点多,不是吗?别担心 - 我们会一步步来阐明。

1: 导入库并定义激活函数

import torchimport torch.nn as nnimport torch.optim as optim# 在代码中选择要利用的激活函数defined_activation_function = 'relu'activation_functions = { 'relu': nn.ReLU(), 'sigmoid': nn.Sigmoid(), 'tanh': nn.Tanh(), 'leaky_relu': nn.LeakyReLU()}

导入库并定义包含激活函数的字典

在这段代码中:

import torch:导入PyTorch库。
import torch.nn as nn:从PyTorch导着迷经网络模块。
import torch.optim as optim:从PyTorch导入优化模块。

上述变量和字典帮助您轻松地为这个深度学习模型定义要利用的激活函数。

2: 定义超参数并天生数据集

# 初始化超参数num_samples = 100batch_size = 10num_epochs = 150learning_rate = 0.001# 定义一个大略的合成数据集def generate_data(num_samples): X = torch.randn(num_samples, 10) y = torch.randn(num_samples, 1) return X, y# 天生合成数据X, y = generate_data(num_samples)

初始化超参数并利用函数创建合成数据集

在这段代码中:

num_samples 是合成数据集中的样本数量。
batch_size 是演习过程中每个小批量的大小。
num_epochs 是在演习期间对全体数据集进行迭代的次数。
learning_rate 是优化算法利用的学习率。

此外,我们定义了一个 generate_data 函数来创建两个具有随机值的张量。
然后调用该函数,为 X 和 y 天生具有随机值的两个张量。

3: 创建深度学习模型

class SimpleModel(nn.Module): def __init__(self, activation=defined_activation_function): super(SimpleModel, self).__init__() self.fc1 = nn.Linear(in_features=10, out_features=18) self.fc2 = nn.Linear(in_features=18, out_features=18) self.fc3 = nn.Linear(in_features=18, out_features=4) self.fc4 = nn.Linear(in_features=4, out_features=1) self.activation = activation_functions[activation] def forward(self, x): x = self.fc1(x) x = self.activation(x) x = self.fc2(x) x = self.activation(x) x = self.fc3(x) x = self.activation(x) x = self.fc4(x) return x

一个大略的前馈神经网络深度学习模型

SimpleModel 类中的 __init__ 方法初始化了神经网络架构。
它初始化了四个全连接层,并定义了我们将要利用的激活函数。

我们利用 nn.Linear 创建每一层,而 forward 方法定义了数据在神经网络中的流动办法。

4: 初始化模型并定义丢失函数和优化器

model = SimpleModel(activation=defined_activation_function)criterion = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=learning_rate)

定义激活函数、丢失函数和要利用的梯度低落变体

在这段代码中:

model = SimpleModel(activation=defined_activation_function) 创建了一个带有指定激活函数的神经网络模型。
criterion = nn.MSELoss() 定义了均方偏差(MSE)丢失函数。
optimizer = optim.Adam(model.parameters(), lr=learning_rate) 设置了Adam优化器,用于在演习期间更新模型参数,并指定了学习率。
5: 演习深度学习模型

for epoch in range(num_epochs): for i in range(0, num_samples, batch_size): # 获取小批量数据 inputs = X[i:i+batch_size] labels = y[i:i+batch_size] # 梯度清零 optimizer.zero_grad() # 前向传播 outputs = model(inputs) # 打算丢失 loss = criterion(outputs, labels) # 反向传播和优化 loss.backward() optimizer.step() print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss}')

演习模型

外循环基于 num_epochs(迭代次数)掌握全体数据集的处理次数。
内循环利用 range 函数将数据集分成小批量。

在每个小循环中:

利用输入和标签,我们获取要处理的小批量数据。
我们利用 optimizer.zero_grad() 肃清上一个小批量迭代的梯度 - 这很主要,以防止在小批量之间稠浊梯度信息。
通过前向传播得到模型预测值(outputs),并利用指定的丢失函数(criterion)打算丢失。
利用 loss.backward() 打算权重的梯度。
末了,optimizer.step() 基于这些梯度更新模型的权重,以最小化丢失函数。

这是在非常大略的数据集上演习非常大略的深度学习模型的完全代码。

它没有更高等的内容,比如卷积神经网络。

结论:AI神经网络的默默英雄

激活函数就像守门员一样。
通过限定信息的流动,神经网络可以更好地学习。

激活函数就像人们学习时或足球运动员决定如何处理球时一样。

这些函数授予了神经网络学习和精确预测的能力。

从数学上讲,激活函数是神经网络中精确逼近任何线性或非线性函数的关键。
没有它们,神经网络只能逼近线性函数。

(本文视频讲解:java567.com)