1.单隐藏层的多层感知机
import torch
from torch import nn
# 单隐藏层的多层感知机
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
X = torch.rand(size=(2, 4))
print(net(X))
2.查看全部参数访问:获取权重和偏置。指定层的参数 net[2]就是 nn.Linear(8, 1)
print(net[2].state_dict())
输出:
OrderedDict([('weight', tensor([[ 0.2506, -0.1574, -0.2171, 0.1743, -0.0860, -0.1802, -0.0337, 0.3189]])), ('bias', tensor([0.1444]))])
3.指定参数的访问--偏置
①查看指定偏置的类型
print(type(net[2].bias))
输出:
Parameter'代表参数可以优化
②查看指定偏置的数据
print(net[2].bias)
输出:
Parameter containing:
tensor([-0.0795], requires_grad=True)
③查看指定偏置的数值
print(net[2].bias.data)
输出:tensor([-0.0795])
④查看偏置的梯度(没有反向传播计算所以None)
print(net[2].bias.grad)
输出:None
4.访问指定net[0]层的参数
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
print(*[(name, param.shape) for name, param in net[0].named_parameters()])
输出:
('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))
[个人猜测不一定对:weight是8*4的原因,输入是4个维度,每个维度就有4个权重。输出是8个维度了,要带着前面输入的维度的4个权重,所以就是8*4]
5.访问整个网络层的参数
print(*[(name, param.shape) for name, param in net.named_parameters()])
输出:【激活函数没有权重和偏置】
('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))
注意:*[]是解包。把列表拆成一个一个元素。
6.指定特征名称的值的数据
print(net.state_dict()['2.bias'].data)
输出:tensor([-0.2114])
7.从嵌套块里面收集参数
def block1():
return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
nn.Linear(8, 4), nn.ReLU())
def block2(): # 用循环 加入4次block1
net = nn.Sequential()
for i in range(4):
# 在这里嵌套
net.add_module(f'block {i}', block1()) # Sequential()这样可以把字符串的名字传进去
return net
rgnet = nn.Sequential(block2(), nn.Linear(4, 1))
rgnet(X)
print(rgnet)
查看一下网络结构
Sequential(
(0): Sequential(
(block 0): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 1): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 2): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 3): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
)
(1): Linear(in_features=4, out_features=1, bias=True)
)
8.内置初始化参数
①内置初始化权重正态分布
def init_normal(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, mean=0, std=0.01)
nn.init.zeros_(m.bias)
net.apply(init_normal) # 遍历整个net网络里的各个层 挨个调用init_normal函数进行修改
print(net[0].weight.data[0])
print(net[0].bias.data[0])
net.apply(init_normal) 的说明:遍历net的所有层,如果是Linear层,就进行权重和偏置的初始化修改。
输出:
tensor([-0.0020, -0.0105, -0.0021, 0.0196])
tensor(0.)
②内置函数把权重变为一个数(为了演示,算法角度不能做)
def init_constant(m):
if type(m) == nn.Linear:
nn.init.constant_(m.weight, 1) # 权重全为1,变成一样的
nn.init.zeros_(m.bias)
net.apply(init_constant) # 遍历整个net网络里的各个层 挨个调用init_normal函数进行修改
print(net[0].weight.data[0])
print(net[0].bias.data[0])
输出:
9.自定义初始化权重和偏置
net[0].weight.data[:] += 1 # 每个权重都加1
net[0].weight.data[0, 0] = 42 # 第一个权重变为42
print(net[0].weight.data[0])
10.参数绑定
shared = nn.Linear(8, 8) # 里面有权重了
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
shared, nn.ReLU(),
shared, nn.ReLU(),
nn.Linear(8, 1))
net(X)
# 检查参数是否相同
print(net[2].weight.data[0] == net[4].weight.data[0])
net[2].weight.data[0, 0] = 100
# 确保它们实际上是同一个对象,而不只是有相同的值
print(net[2].weight.data[0] == net[4].weight.data[0])
shared在网络里是同一个内存 ,同一个对象。所以权重是一样的