赞
踩
import torch from torch import nn #具有单隐藏层的多层感知机 net = nn.Sequential(nn.Linear(4,8), nn.ReLU(), nn.Linear(8,1)) X = torch.rand(2,4) print(net(X)) """ tensor([[-0.4613], [-0.2691]], grad_fn=<AddmmBackward>) """ #当通过Sequential类定义模型时, 我们可以通过索引来访问模型的任意层。 print(net[2].state_dict()) """ OrderedDict([('weight', tensor([[-0.0274, -0.1189, 0.2617, -0.1651, -0.2382, -0.2734, -0.0991, 0.1985]])), ('bias', tensor([-0.1222]))]) 首先,这个全连接层包含两个参数,分别是该层的权重和偏置。 两者都存储为单精度浮点数float32。 注意: 参数名称允许唯一标识每个参数,即使在包含数百个层的网络中也是如此 """ #目标参数 print(type(net[2].bias)) print(net[2].bias) print(net[2].bias.data) """ <class 'torch.nn.parameter.Parameter'> Parameter containing: tensor([-0.1222], requires_grad=True) tensor([-0.1222) """ #访问每个参数的梯度 #由于我们还没有调用反向传播,所以参数的梯度处于初始状态 print(net[2].weight.grad == None) # True #一次性访问所有参数 print(*[(name, param.shape) for name, param in net.named_parameters()]) print(*[(name, param.shape) for name, param in net[0].named_parameters()]) """ ('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1])) ('weight', torch.Size([8, 4])) ('bias', torch.Size([8])) """ #另一种访问网络参数的方式 print(net.state_dict()['2.bias'].data) # tensor([-0.1222) #从嵌套块收集参数 def block1(): return nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 4), nn.ReLU()) def block2(): net = nn.Sequential() for i in range(2): # 在这里嵌套 net.add_module(f'block {i}', block1()) return net rgnet = nn.Sequential(block2(), nn.Linear(4, 1)) 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() ) ) (1): Linear(in_features=4, out_features=1, bias=True) ) """ #因为层是分层嵌套的,所以我们也可以像通过嵌套列表索引一样访问它们 print(rgnet[0][1][0].bias.data) #参数初始化 #首先调用内置的初始化器 #将所有权重参数初始化为标准差为0.01的高斯随机变量, 且将偏置参数设置为0。 # net = nn.Sequential(nn.Linear(4,8), nn.ReLU(), nn.Linear(8,1)) 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) #前面定义的init_normal函数应用于模型net中的每一层。 #apply方法会递归地遍历模型的所有子模块,并对每一个子模块调用init_normal函数。 print(net[0].weight.data[0]) print(net[0].bias.data[0]) """ tensor([-0.0055, 0.0028, -0.0095, -0.0059]) tensor(0.) 打印了模型net第一个全连接层的第一行权重和第一个偏置的值。 这里net[0]指的是net中的第一个子模块,也就是第一个全连接层nn.Linear(4, 8)。 通过.weight.data[0]访问权重的第一行,通过.bias.data[0]访问偏置的第一个元素。 """ ## net = nn.Sequential(nn.Linear(4,8), nn.ReLU(), nn.Linear(8,1)) def my_init(m): if type(m) == nn.Linear: #m.named_parameters() 返回该层的所有参数(名称和参数本身) print("Init", *[(name, param.shape) for name , param in m.named_parameters()][0]) #nn.init.uniform_ 函数将权重 m.weight 初始化为均匀分布在 -10 到 10 之间的值。 nn.init.uniform_(m.weight, -10, 10) m.weight.data = m.weight.data * ( m.weight.data.abs() >= 5) net.apply(my_init) print(net[0].weight[:2]) #从权重矩阵中提取前两行,即形状为 (2, 4) 的子矩阵 """ tensor([[ 6.7495, -0.0000, 0.0000, 0.0000], [-0.0000, -7.6540, -0.0000, 0.0000]], grad_fn=<SliceBackward>) """ #直接设置参数 net[0].weight.data[:] += 1 print(net[0].weight.data[:]) """ tensor([[ 7.7495, 1.0000, 1.0000, 1.0000], [ 1.0000, -6.6540, 1.0000, 1.0000], [10.3503, 1.0000, 9.9864, 1.0000], [ 6.7700, 1.0000, 8.1017, -4.6532], [-4.0572, 1.0000, 1.0000, 1.0000], [ 1.0000, 1.0000, 1.0000, 10.8596], [ 1.0000, 10.9898, 7.0317, -4.4541], [-5.0554, 1.0000, 1.0000, 1.0000]]) """ net[0].weight.data[0, 0] = 42 print(net[0].weight.data[0]) #tensor([42., 1., 1., 1.]) # 参数绑定 # 有时我们希望在多个层间共享参数: # 我们可以定义一个稠密层,然后使用它的参数来设置另一个层的参数。 # 我们需要给共享层一个名称,以便可以引用它的参数 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]) #tensor([True, True, True, True, True, True, True, True]) #tensor([True, True, True, True, True, True, True, True]) """ 表明第三个和第五个神经网络层的参数是绑定的。 它们不仅值相等,而且由相同的张量表示。 因此,如果我们改变其中一个参数,另一个参数也会改变。 这里有一个问题:当参数绑定时,梯度会发生什么情况? 答案是由于模型参数包含梯度,因此在反向传播期间第二个隐藏层 (即第三个神经网络层) 和第三个隐藏层(即第五个神经网络层)的梯度会加在一起。 """
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。