Функция torch.nn.ReLU в PyTorch

PyTorch torch.nn 参考手册Справочное руководство 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
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
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
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
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 является первым выбором для функций активации скрытых слоёв.


PyTorch torch.nn 参考手册Справочное руководство PyTorch torch.nn

Другие расширения