Функция PyTorch torch.nn.Linear

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


torch.nn.Linearявляется модулем в PyTorch, используемым для создания полносвязного слоя (также называемого линейным слоем или аффинным преобразованием).

Это один из самых базовых и часто используемых слоёв в нейронных сетях, отвечающий за линейное преобразование входных признаков в выходное пространство признаков.

Определение функции

torch.nn.Linear(in_features, out_features, bias=True)

Описание параметров:

  • in_features(int): Размерность входных признаков, т.е. число признаков, выводимых предыдущим слоем.
  • out_features(int): Размерность выходных признаков, т.е. число признаков, выводимых этим слоем.
  • bias(bool): указывает, добавлять ли член смещения. По умолчанию —True. Если установлено вFalse, то этот слой не будет обучать параметры смещения.

Атрибуты:

  • weight(Tensor): Обучаемая матрица весов с размером (out_features, in_features).
  • bias(Tensor): Обучаемый вектор смещения с размером (out_features,). Еслиbias=False, то этот атрибут не существует.

Математический принцип

nn.LinearФормула расчета выглядит следующим образом:

y = xA^T + b

где:

  • x— входной тензор с формой (..., in_features)
  • A— матрица весов с формой (out_features, in_features)
  • b— вектор смещения с формой (out_features)
  • y— выходной тензор с формой (..., out_features)

Символ...указывает, что вход может быть тензором любой размерности, а линейное преобразование применяется к последней размерности.


Примеры использования

Пример 1: Базовое использование

Создайте простой полносвязный слой, который отображает 10-мерный вход в 5-мерный выход:

Пример

import torch
import torch.nn as nn

# Создать линейный слой: вход 10 измерений, выход 5 измерений
linear_layer = nn.Linear(in_features=10, out_features=5, bias=True)

# Вывести формы веса и смещения
print("Форма веса:", linear_layer.weight.shape)  # torch.Size([5, 10])
print("Форма смещения:", linear_layer.bias.shape)   # torch.Size([5])

# Создаём входной тензор: batch_size=3, размер признаков=10
input_tensor = torch.randn(3, 10)

# Прямое распространение
output = linear_layer(input_tensor)

print("Форма входных данных:", input_tensor.shape)  # torch.Size([3, 10])
print("Форма выходных данных:", output.shape)        # torch.Size([3, 5])
print("Выходные данные:\n", output)

Результат вывода:

权重形状: torch.Size([5, 10])
偏置形状: torch.Size([5])
输入形状: torch.Size([3, 10])
输出形状: torch.Size([3, 5])
输出数据:
 tensor([[-0.1838,  0.0607, -0.4879,  0.8981, -0.2098],
        [ 0.1513, -0.1873,  0.1866, -0.2448, -0.6012],
        [ 0.2915,  0.3053,  0.2532, -0.3372, -0.3968]],
       grad_fn=<AddmmBackward0>)

В этом примере мы создали полносвязный слой с входом 10 и выходом 5. Форма входного тензора — (3, 10), где 3 — размер батча, а 10 — размер признаков. Форма выходного тензора — (3, 5).

Пример 2: Без смещения

Создайте линейный слой без члена смещения:

Пример

import torch
import torch.nn as nn

# Создаём линейный слой без смещения
linear_no_bias = nn.Linear(in_features=10, out_features=5, bias=False)

# Проверить, существует ли смещение
print("Смещение существует:", linear_no_bias.bias is None)  # True

# Прямое распространение
input_tensor = torch.randn(3, 10)
output = linear_no_bias(input_tensor)

print("Форма выходных данных:", output.shape)  # torch.Size([3, 5])
print("Вывод:\n", output)

Результат вывода:

偏置是否存在: True
输出形状: torch.Size([3, 5])
输出:
 tensor([[-0.3312, -0.4113,  0.0257, -0.4876,  0.0780],
        [ 0.1513,  0.2459, -0.2983,  0.2456, -0.0727],
        [-0.0143,  0.3053,  0.1866, -0.3372,  0.2532]],
       grad_fn=<MmBackward>)

Пример 3: Многомерный вход

nn.LinearОн может обрабатывать входные данные произвольной размерности и преобразует только последнее измерение:

Пример

import torch
import torch.nn as nn

# Создать линейный слой
linear = nn.Linear(in_features=10, out_features=5)

# Обработать 2D-вход (батч, признаки)
input_2d = torch.randn(8, 10)
output_2d = linear(input_2d)
print("2D вход -> выход:", input_2d.shape, "->", output_2d.shape)

# Обработка 3D-входа (батч, последовательность, признаки)
input_3d = torch.randn(4, 6, 10)
output_3d = linear(input_3d)
print("3D вход -> выход:", input_3d.shape, "->", output_3d.shape)

# Обработка 4D-входа (батч, каналы, высота, ширина)
input_4d = torch.randn(2, 3, 4, 10)
output_4d = linear(input_4d)
print("4D вход -> выход:", input_4d.shape, "->", output_4d.shape)

Результат вывода:

二维输入 -> 输出: torch.Size([8, 10]) -> torch.Size([8, 5])
三维输入 -> 输出: torch.Size([4, 6, 10]) -> torch.Size([4, 6, 5])
四维输入 -> 输出: torch.Size([2, 3, 4, 10]) -> torch.Size([2, 3, 4, 5])

Пример 4: Использование в нейронной сети

В реальной нейронной сети,nn.Linearобычно он используется в сочетании с другими слоями:

Пример

import torch
import torch.nn as nn

# Определить многослойный перцептрон (MLP)
class MLP(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(MLP, self).__init__()
        # Первый слой: вход -> скрытый слой
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        # Функция активации
        self.relu = nn.ReLU()
        # Второй слой: скрытый слой -> выход
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# Создание модели
model = MLP(input_dim=784, hidden_dim=256, output_dim=10)

# Вывести структуру модели
print("Структура модели:")
print(model)

# Проверка прямого распространения
input_tensor = torch.randn(32, 784)  # batch_size=32, 28x28=784
output = model(input_tensor)

print("\nФорма входных данных:", input_tensor.shape)  # torch.Size([32, 784])
print("Форма выхода:", output.shape)        # torch.Size([32, 10])

Результат вывода:

模型结构:
MLP(
  (fc1): Linear(in_features=784, out_features=256, bias=True)
  (relu): ReLU()
  (fc2): Linear(in_features=256, out_features=10, bias=True)
)

输入形状: torch.Size([32, 784])
输出形状: torch.Size([32, 10])

Инициализация весов

По умолчанию,nn.Linearиспользует стратегию инициализации PyTorch по умолчанию.

Вы также можете инициализировать веса вручную:

Пример

import torch
import torch.nn as nn

# Создать линейный слой
linear = nn.Linear(10, 5)

# Использовать инициализацию Xavier для весов
nn.init.xavier_uniform_(linear.weight)
# Инициализировать смещение нулём
nn.init.zeros_(linear.bias)

# Просмотреть инициализированные веса
print("Вес:\n", linear.weight.data)
print("Смещение:", linear.bias.data)

Отличие от nn.functional.linear

PyTorch также предоставляет функциональный интерфейсtorch.nn.functional.linear:

Пример

import torch
import torch.nn as nn
import torch.nn.functional as F

# Метод 1: Использование nn.Module
linear_module = nn.Linear(10, 5)
output1 = linear_module(torch.randn(3, 10))

# Метод 2: Использование функционального интерфейса
weight = torch.randn(5, 10)
bias = torch.randn(5)
output2 = F.linear(torch.randn(3, 10), weight, bias)

print("Форма вывода nn.Module:", output1.shape)
print("Форма вывода nn.functional:", output2.shape)

Разница между ними:

  • nn.Linear— это класс модуля, который сохраняет параметры weight и bias, что делает его удобным для обучения и сохранения моделей.
  • F.linear— это функция, которая требует ручной передачи весов и смещений, часто используется в ситуациях без обучаемых параметров.

Примечание: хотя математические операции у обоих одинаковы, при построении нейронных сетей мы обычно используемnn.Linear, потому что он автоматически регистрирует параметры, что делает удобным их обновление оптимизаторами.


Часто задаваемые вопросы

Вопрос 1: Как посмотреть количество параметров в слое Linear?

Для линейного слоя с (in_features, out_features):

  • Количество параметров весов: in_features * out_features
  • Количество параметров смещения: out_features (если bias=True)

Пример

import torch
import torch.nn as nn

linear = nn.Linear(100, 50)
print("Общее количество параметров:", sum(p.numel() for p in linear.parameters()))
print("Параметры весов:", linear.weight.numel())
print("Параметры смещения:", linear.bias.numel())

Вопрос 2: Как заморозить параметры слоя Linear?

Если вы хотите зафиксировать определённые слои, чтобы они не участвовали в обучении, можно установитьrequires_grad=False:

Пример

import torch
import torch.nn as nn

linear = nn.Linear(10, 5)

# Заморозить веса, чтобы они не участвовали в вычислении градиента
linear.weight.requires_grad = False
# Заморозить смещение
linear.bias.requires_grad = False

# Проверка
print("Weight requires_grad:", linear.weight.requires_grad)
print("Bias requires_grad:", linear.bias.requires_grad)

Сценарии использования

nn.Linearявляется одним из наиболее часто используемых слоёв в нейронных сетях. Основные сценарии применения включают:

  • Многослойный перцептрон (MLP): Как полносвязный слой, отображает признаки в новое признаковое пространство.
  • Классификатор: В конце или рекуррентных сетей используйте полносвязный слой для классификации.
  • Преобразование признаков: Примените линейное преобразование, чтобы уменьшить или увеличить размерность.
  • Механизм внимания: В Transformer для генерации матриц Q, V.

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

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