本文通過實例代碼講解如何在PyTorch中管理神經網絡參數,包括參數訪問、多種初始化方法、自定義初始化以及參數綁定技術。所有代碼可直接運行,適合深度學習初學者進階學習。
1. 定義網絡與參數訪問
1.1 定義單隱藏層多層感知機
import torch
from torch import nn# 定義單隱藏層多層感知機
net1 = nn.Sequential(nn.Linear(4, 8), # 輸入層4維,隱藏層8維nn.ReLU(),nn.Linear(8, 1) # 輸出層1維
)
x = torch.rand(2, 4) # 隨機生成2個4維輸入向量
net1(x) # 前向傳播
1.2 訪問網絡參數
# 訪問第二層(索引2)的參數(權重和偏置)
print(net1[2].state_dict())# 查看參數類型、數據和梯度
print(type(net1[2].bias)) # 類型:Parameter
print(net1[2].bias) # 參數值(含梯度信息)
print(net1[2].bias.data) # 參數數據(張量)
print(net1[2].bias.grad) # 梯度(未反向傳播時為None)
1.3 批量訪問參數
# 訪問第一層的參數名稱和形狀
print(*[(name, param.shape) for name, param in net1[0].named_parameters()])# 訪問整個網絡的參數
print(*[(name, param.shape) for name, param in net1.named_parameters()])# 通過state_dict直接訪問參數數據
print(net1.state_dict()['2.bias'].data)
2. 參數初始化方法
2.1 內置初始化
# 正態分布初始化權重,偏置置零
def init_normal(model):if isinstance(model, nn.Linear):nn.init.normal_(model.weight, mean=0, std=0.01)nn.init.zeros_(model.bias)net1.apply(init_normal)
print(net1[0].weight.data[0], net1[0].bias.data[0])# 常數初始化(權重為1,偏置為0)
def init_constant(model):if isinstance(model, nn.Linear):nn.init.constant_(model.weight, 1)nn.init.zeros_(model.bias)net1.apply(init_constant)
print(net1[0].weight.data[0], net1[0].bias.data[0])
2.2 分層初始化
# 對第一層使用Xavier初始化,第二層使用常數42初始化
def xavier(model):if isinstance(model, nn.Linear):nn.init.xavier_uniform_(model.weight)def init_42(model):if isinstance(model, nn.Linear):nn.init.constant_(model.weight, 42)net1[0].apply(xavier)
net1[2].apply(init_42)
print(net1[0].weight.data[0])
print(net1[2].weight.data)
2.3 自定義初始化
# 自定義初始化:權重在[-10,10]均勻分布,并過濾絕對值小于5的值
def my_init(model):if isinstance(model, nn.Linear):print(f'init weight {model.weight.shape}')nn.init.uniform_(model.weight, -10, 10)model.weight.data *= (model.weight.abs() >= 5)net1.apply(my_init)
print(net1[0].weight.data[:2]) # 顯示前兩行權重
3. 參數綁定與共享
3.1 直接修改參數
# 直接操作參數數據
net1[0].weight.data[:] += 1 # 所有權重+1
net1[0].weight.data[0, 0] = 42 # 修改特定位置權重
print(net1[0].weight.data[0]) # 輸出第一行權重
3.2 參數共享
# 共享線性層參數
shared_layer = nn.Linear(8, 8)
net3 = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),shared_layer, nn.ReLU(), # 第2層shared_layer, nn.ReLU(), # 第4層(共享參數)nn.Linear(8, 1)
)# 驗證參數共享
print(net3[2].weight.data[0] == net3[4].weight.data[0]) # 輸出全True
net3[2].weight.data[0, 0] = 100
print(net3[2].weight.data[0] == net3[4].weight.data[0]) # 修改后仍為True
4. 嵌套網絡結構
# 構建嵌套網絡
def model1():return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),nn.Linear(8, 4), nn.ReLU())def model2():net = nn.Sequential()for i in range(4):net.add_module(f'model{i}', model1())return netrgnet = nn.Sequential(model2(), nn.Linear(4, 1))
print(rgnet) # 打印網絡結構
總結
本文演示了PyTorch中參數管理的核心操作,包括:
-
通過
state_dict
和named_parameters
訪問參數 -
使用內置初始化方法(正態分布、常數、Xavier)
-
自定義初始化邏輯
-
參數的直接修改與共享
-
復雜嵌套網絡的定義
掌握這些技能可以更靈活地設計和優化神經網絡模型。建議讀者在實踐中結合具體任務調整初始化策略,并注意參數共享時的梯度傳播特性。
提示:以上代碼需要在PyTorch環境中運行,建議使用Jupyter Notebook逐步調試以觀察中間結果。