Функция torch.nn.ReLU в PyTorch
Справочное руководство PyTorch torch.nn
torch.nn.ReLUЭто одна из наиболее часто используемых функций активации в PyTorch. Она поэлементно выполняет операцию rectified linear unit (ReLU) над входным тензором.
ReLU — одна из самых успешных функций активации в глубоком обучении, поскольку она вычислительно проста, быстро сходится и эффективно смягчает проблему затухающего градиента.
Определение функции
torch.nn.ReLU(inplace=False)
Описание параметров:
inplace(bool): если установлено вTrue, она будет напрямую изменять входной тензор на месте, экономя память. По умолчанию —False。
Математический принцип
nn.ReLUФормула расчета выглядит следующим образом:
f(x) = max(0, x)
То есть для каждого элемента входных данных, если значение больше 0, оно остаётся неизменным; если значение меньше или равно 0, выход равен 0.
Это простое нелинейное преобразование позволяет сети изучать сложные закономерности, сохраняя поток градиентов.
Примеры использования
Пример 1: Базовое использование
Создайте слой активации ReLU и примените активацию к входу:
Пример
import torch.nn as nn
# Создать слой активации ReLU
relu = nn.ReLU()
# Создать входной тензор, содержащий отрицательные значения
input_tensor = torch.tensor([[-1.0, 2.0, -3.0], [4.0, -5.0, 6.0]])
# Прямое распространение
output = relu(input_tensor)
print("Input:\n", input_tensor)
print("Вывод:\n", output)
Результат вывода:
输入:
tensor([[-1., 2., -3.],
[ 4., -5., 6.]])
输出:
tensor([[0., 2., 0.],
[4., 0., 6.]])
Как видите, все отрицательные значения устанавливаются в 0, а положительные остаются неизменными.
Пример 2: Операция на месте
Использование параметра inplace позволяет экономить память:
Пример
import torch.nn as nn
# Создать ReLU с включённой операцией на месте
relu_inplace = nn.ReLU(inplace=True)
# Создать входной тензор
input_tensor = torch.randn(2, 4)
original_id = id(input_tensor)
# Изменить на месте
output = relu_inplace(input_tensor)
# Проверить, был ли изменён исходный тензор
print("Был ли изменён исходный тензор:", id(output) == original_id)
print("Вход/Выход:\n", input_tensor)
Результат вывода:
是否修改了原张量: True
输入/输出:
tensor([[0.0000, 0.0000, 1.2345, 0.0000],
[0.5432, 0.0000, 0.0000, 2.3456]])
Примечание: операции на месте могут экономить память, но в некоторых случаях они могут влиять на вычисление градиентов. На ранних этапах обучения или когда необходимо сохранить промежуточные значения активаций, рекомендуется использовать режим по умолчанию
inplace=False。
Пример 3: Использование в нейронных сетях
В свёрточных нейронных сетях ReLU обычно следует за свёрточным слоем:
Пример
import torch.nn as nn
# Определить простую свёрточную нейронную сеть
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
# Свёрточный слой: вход 3 канала, выход 32 канала, ядро 3x3
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
# активация ReLU
self.relu1 = nn.ReLU()
# Второй сверточный слой
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.relu2 = nn.ReLU()
# Слой пулинга
self.pool = nn.MaxPool2d(2, 2)
def forward(self, x):
x = self.conv1(x)
x = self.relu1(x)
x = self.pool(x)
x = self.conv2(x)
x = self.relu2(x)
x = self.pool(x)
return x
# Создание модели
model = SimpleCNN()
# Вывести структуру модели
print("Структура модели:")
print(model)
# Проверка прямого распространения
# Смоделировать цветное изображение 3x32x32
input_image = torch.randn(1, 3, 32, 32)
output = model(input_image)
print("\nФорма входных данных:", input_image.shape)
print("Форма выхода:", output.shape)
Результат вывода:
模型结构: SimpleCNN( (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (relu1): ReLU() (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (relu2): ReLU() (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) 输入形状: torch.Size([1, 3, 32, 32]) 输出形状: torch.Size([1, 64, 8, 8])
Пример 4: Использование nn.functional.relu
PyTorch также предоставляет функциональный интерфейсtorch.nn.functional.relu:
Пример
import torch.nn.functional as F
# Использование функционального интерфейса
input_tensor = torch.randn(1, 5, 5)
# Способ 1: Использование функционального интерфейса
output1 = F.relu(input_tensor)
# Способ 2: Использование in-place версии функции
F.relu_(input_tensor)
print("Output:\n", output1)
Различия между ними:
nn.ReLUЯвляется классом модуля, который можно использовать в определениях моделей и который сохраняет параметры.F.reluЯвляется функциональным интерфейсом, обычно используется в методе forward или в случаях, когда нет обучаемых параметров.F.relu_Является функцией с подчёркиванием для in-place версии.
Сравнение с другими функциями активации
| Функция активации | Формула | Характеристики | Применимые сценарии |
|---|---|---|---|
nn.ReLU |
max(0, x) | Простое вычисление, разреженная активация | Общее глубокое обучение (выбор по умолчанию) |
nn.LeakyReLU |
x > 0 ? x : 0.01x | Малый градиент на отрицательной полуоси | Предотвращает "отмирание нейронов" | nn.GELU |
x * Φ(x) | Гладкая аппроксимация, выбор по умолчанию для Transformer | Transformer, BERT и т. д. |
nn.Sigmoid |
1/(1+e^(-x)) | Выход 0-1, насыщение градиента | Выходной слой, бинарная классификация |
nn.Tanh |
(e^x - e^(-x))/(e^x + e^(-x)) | Выход от -1 до 1, центрирован относительно нуля | RNN、LSTM |
Часто задаваемые вопросы
Q1: Почему ReLU вызывает проблему "отмирающих нейронов"?
Когда вход остаётся отрицательным, выход ReLU всегда равен 0, и градиент также равен 0, из-за чего эти нейроны не могут дальше обучаться.
Решения:
- Используйте
nn.LeakyReLUилиnn.ELUчтобы заменить - Используйте меньшую начальную скорость обучения
- Примените пакетную нормализацию
Q2: Подходит ли ReLU для выходного слоя?
Обычно не подходит. В выходном слое чаще используетсяSigmoid(для классификации) или тождественная функция (для регрессии), потому что выход ReLU не ограничен.
Сценарии использования
nn.ReLUЭто наиболее часто используемая функция активации в глубоком обучении. Основные сценарии применения включают:
- Свёрточные нейронные сети: добавление нелинейности после свёрточных слоёв или полносвязных слоёв.
- Многослойный перцептрон: в качестве функции активации для скрытых слоёв.
- Transformer: в качестве функции активации в FFN (сеть прямого распространения) (хотя сейчас чаще используется GELU).
- Генеративные состязательные сети: в качестве функции активации для генератора.
Совет: если нет особых требований, при проектировании нейронных сетей ReLU является первым выбором для функций активации скрытых слоёв.
Другие расширения