PyTorch torch.nn.Linear 関数
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)
# 处理二维输入 (batch, features)
input_2d = torch.randn(8, 10)
output_2d = linear(input_2d)
print("二维输入 -> 输出:", input_2d.shape, "->", output_2d.shape)
# 处理三维输入 (batch, seq, features)
input_3d = torch.randn(4, 6, 10)
output_3d = linear(input_3d)
print("三维输入 -> 输出:", input_3d.shape, "->", output_3d.shape)
# 处理四维输入 (batch, channels, height, width)
input_4d = torch.randn(2, 3, 4, 10)
output_4d = linear(input_4d)
print("四维输入 -> 输出:", 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.LinearPyTorch のデフォルトの初期化戦略が使用されます。
重みを手動で初期化することもできます:
実例
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
# 方法一:使用 nn.Module
linear_module = nn.Linear(10, 5)
output1 = linear_module(torch.randn(3, 10))
# 方法二:使用函数式接口
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はモジュールクラスであり、重みとバイアスパラメータを保存するため、トレーニングとモデル保存が容易です。F.linearは関数であり、重みとバイアスを手動で渡す必要があり、学習可能なパラメータがない場合によく使用されます。
注意:両者の数学的演算は同じですが、ニューラルネットワークを構築する際は通常
nn.Linearを使用します。これはパラメータを自動的に登録し、オプティマイザの更新を容易にするためです。
よくある質問
Q1: 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())
Q2: 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("权重 requires_grad:", linear.weight.requires_grad)
print("偏置 requires_grad:", linear.bias.requires_grad)
使用シーン
nn.Linearはニューラルネットワークで最も一般的に使用される層の一つであり、主な適用シーンは次のとおりです:
- 多層パーセプトロン (MLP): 全結合層として、特徴を新しい特徴空間にマッピングします。
- 分類器: 畳み込みネットワークまたはリカレントネットワークの最後に、全結合層を使用して分類します。
- 特徴変換: データに線形変換を施し、次元削減または次元増加を実現します。
- アテンション機構: Transformer で Q、K、V 行列を生成するために使用されます。
その他の拡張