Функция PyTorch torch.nn.Linear
Справочное руководство 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.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.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.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.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.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.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.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.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.
Другие расширения