Función PyTorch torch.nn.Linear
Manual de referencia de PyTorch torch.nn
torch.nn.LinearEs un módulo de PyTorch utilizado para crear capas totalmente conectadas (también conocidas como capas lineales o transformaciones afines).
Es una de las capas más básicas y más utilizadas en las redes neuronales; se encarga de transformar linealmente las características de entrada al espacio de características de salida.
Definición de la función
torch.nn.Linear(in_features, out_features, bias=True)
Descripción de parámetros:
in_features(int): dimensión de las características de entrada, es decir, el número de características de salida de la capa anterior.out_features(int): dimensión de las características de salida, es decir, el número de características que emite esta capa.bias(bool): si se añade el término de sesgo. El valor predeterminado esTrue. Si se establece enFalse, esta capa no aprenderá los parámetros de sesgo.
Atributos:
weight(Tensor): matriz de pesos aprendible de forma (out_features, in_features).bias(Tensor): vector de sesgo aprendible de forma (out_features,). Sibias=False, este atributo no existe.
Principios matemáticos
nn.LinearLa fórmula de cálculo ejecutada es la siguiente:
y = xA^T + b
Donde:
xes el tensor de entrada, con forma (..., in_features)Aes la matriz de pesos, con forma (out_features, in_features)bes el vector de sesgo, con forma (out_features)yes el tensor de salida, con forma (..., out_features)
El símbolo ......indica que la entrada puede ser un tensor de cualquier dimensión; la transformación lineal se aplica a la última dimensión.
Ejemplos de uso
Ejemplo 1: Uso básico
Crea una capa totalmente conectada simple que mapea una entrada de 10 dimensiones a una salida de 5 dimensiones:
Ejemplo
import torch.nn as nn
# Crea la capa lineal: entrada de 10 dimensiones, salida de 5 dimensiones
linear_layer = nn.Linear(in_features=10, out_features=5, bias=True)
# Imprime la forma de los pesos y el sesgo
print(Forma del peso:, linear_layer.weight.shape) # torch.Size([5, 10])
print(Forma del sesgo:, linear_layer.bias.shape) # torch.Size([5])
# Crea el tensor de entrada: batch_size=3, dimensión de características=10
input_tensor = torch.randn(3, 10)
# Propagación hacia adelante
output = linear_layer(input_tensor)
print(Forma de entrada:, input_tensor.shape) # torch.Size([3, 10])
print(Forma de salida:, output.shape) # torch.Size([3, 5])
print(Datos de salida:\n, output)
El resultado es:
权重形状: 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>)
En este ejemplo, creamos una capa totalmente conectada con entrada de 10 dimensiones y salida de 5 dimensiones. La forma del tensor de entrada es (3, 10), donde 3 es el tamaño del lote (batch size) y 10 es la dimensión de las características. La forma del tensor de salida es (3, 5).
Ejemplo 2: Sin sesgo
Crea una capa lineal sin término de sesgo:
Ejemplo
import torch.nn as nn
# Crea una capa lineal sin sesgo
linear_no_bias = nn.Linear(in_features=10, out_features=5, bias=False)
# Comprueba si el sesgo existe
print(¿Existe el sesgo?:, linear_no_bias.bias is None) # True
# Propagación hacia adelante
input_tensor = torch.randn(3, 10)
output = linear_no_bias(input_tensor)
print(Forma de salida:, output.shape) # torch.Size([3, 5])
print(Salida:\n, output)
El resultado es:
偏置是否存在: 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>)
Ejemplo 3: Entrada multidimensional
nn.LinearPuede manejar entradas de cualquier dimensión, transformando solo la última dimensión:
Ejemplo
import torch.nn as nn
# Crea la capa lineal
linear = nn.Linear(in_features=10, out_features=5)
# Procesa entrada bidimensional (batch, features)
input_2d = torch.randn(8, 10)
output_2d = linear(input_2d)
print(Entrada bidimensional -> Salida:, input_2d.shape, "->", output_2d.shape)
# Procesa entrada tridimensional (batch, seq, features)
input_3d = torch.randn(4, 6, 10)
output_3d = linear(input_3d)
print(Entrada tridimensional -> Salida:, input_3d.shape, "->", output_3d.shape)
# Procesa entrada de cuatro dimensiones (batch, channels, height, width)
input_4d = torch.randn(2, 3, 4, 10)
output_4d = linear(input_4d)
print(Entrada de cuatro dimensiones -> Salida:, input_4d.shape, "->", output_4d.shape)
El resultado es:
二维输入 -> 输出: 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])
Ejemplo 4: Uso en una red neuronal
En una red neuronal real,nn.Linearnormalmente se combina con otras capas:
Ejemplo
import torch.nn as nn
# Define un perceptrón multicapa (MLP)
class MLP(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(MLP, self).__init__()
# Primera capa: entrada -> capa oculta
self.fc1 = nn.Linear(input_dim, hidden_dim)
# Función de activación
self.relu = nn.ReLU()
# Segunda capa: capa oculta -> salida
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
# Crea el modelo
model = MLP(input_dim=784, hidden_dim=256, output_dim=10)
# Imprime la estructura del modelo
print(Estructura del modelo:)
print(model)
# Prueba la propagación hacia adelante
input_tensor = torch.randn(32, 784) # batch_size=32, 28x28=784
output = model(input_tensor)
print(\nForma de entrada:, input_tensor.shape) # torch.Size([32, 784])
print(Forma de salida:, output.shape) # torch.Size([32, 10])
El resultado es:
模型结构: 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])
Inicialización de pesos
Por defecto,nn.Linearse utiliza la estrategia de inicialización predeterminada de PyTorch.
También puedes inicializar los pesos manualmente:
Ejemplo
import torch.nn as nn
# Crea la capa lineal
linear = nn.Linear(10, 5)
# Inicializa los pesos usando Xavier
nn.init.xavier_uniform_(linear.weight)
# Inicializa el sesgo a cero
nn.init.zeros_(linear.bias)
# Muestra los pesos después de la inicialización
print(Pesos:\n, linear.weight.data)
print(Sesgo:, linear.bias.data)
Diferencias con nn.functional.linear
PyTorch también proporciona una interfaz funcionaltorch.nn.functional.linear:
Ejemplo
import torch.nn as nn
import torch.nn.functional as F
# Método 1: usar nn.Module
linear_module = nn.Linear(10, 5)
output1 = linear_module(torch.randn(3, 10))
# Método 2: usar la interfaz funcional
weight = torch.randn(5, 10)
bias = torch.randn(5)
output2 = F.linear(torch.randn(3, 10), weight, bias)
print(Forma de salida con nn.Module:, output1.shape)
print(Forma de salida con nn.functional:, output2.shape)
Diferencias entre ambos:
nn.LinearEs una clase de módulo que guarda los parámetros de pesos y sesgo, lo que facilita el entrenamiento y el guardado del modelo.F.linearEs una función que requiere pasar manualmente los pesos y el sesgo, y se usa a menudo en situaciones donde no hay parámetros aprendibles.
Nota: aunque las operaciones matemáticas son las mismas, al construir redes neuronales normalmente se usa
nn.Linear, ya que este registra los parámetros automáticamente, lo que facilita su actualización por el optimizador.
Preguntas frecuentes
P1: ¿Cómo ver el número de parámetros de una capa Linear?
Para una capa lineal de (in_features, out_features):
- Número de parámetros de peso: in_features * out_features
- Número de parámetros de sesgo: out_features (si bias=True)
Ejemplo
import torch.nn as nn
linear = nn.Linear(100, 50)
print(Número total de parámetros:, sum(p.numel() for p in linear.parameters()))
print(Parámetros de peso:, linear.weight.numel())
print(Parámetros de sesgo:, linear.bias.numel())
P2: ¿Cómo congelar los parámetros de una capa Linear?
Si quieres fijar ciertas capas para que no participen en el entrenamiento, puedes establecerrequires_grad=False:
Ejemplo
import torch.nn as nn
linear = nn.Linear(10, 5)
# Congela el peso para que no participe en el cálculo de gradientes
linear.weight.requires_grad = False
# Congela el sesgo
linear.bias.requires_grad = False
# Verifica
print(Peso requires_grad:, linear.weight.requires_grad)
print(Sesgo requires_grad:, linear.bias.requires_grad)
Casos de uso
nn.LinearEs una de las capas más utilizadas en redes neuronales; los principales escenarios de aplicación incluyen:
- Perceptrón multicapa (MLP): como capa totalmente conectada, mapea las características a un nuevo espacio de características.
- Clasificador: al final de redes convolucionales o recurrentes, se usa una capa totalmente conectada para clasificar.
- Transformación de características: aplica una transformación lineal a los datos para reducir o aumentar la dimensionalidad.
- Mecanismo de atención: en el Transformer se usa para generar las matrices Q, K, V.
Otras extensiones