参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战
import torch
from torch import nn
复制代码
先新建一个网络,生成测试数据X。
net = nn.Sequential(nn.Linear(4,8),
nn.ReLU(),
nn.Linear(8,2),
nn.MSELoss(),
nn.Linear(2,4))
print(net)
X = torch.rand(size=(5, 4))
复制代码
网络长这样。
>>
Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=2, bias=True)
(3): MSELoss()
(4): Linear(in_features=2, out_features=4, bias=True)
)
复制代码
内置初始化
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)
复制代码
调用内置的初始化器。下面的代码将所有权重参数初始化为标准差为0.01的高斯随机变量,且将偏置参数设置为0。
print(net[4].weight)
print(net[0].bias.data)
复制代码
>>
Parameter containing:
tensor([[ 0.0047, -0.0060],
[ 0.0135, -0.0032],
[ 0.0048, -0.0043],
[ 0.0058, 0.0013]], requires_grad=True)
tensor([0., 0., 0., 0., 0., 0., 0., 0.])
复制代码
输出一下权重和偏执看一下。
我们还可以将所有参数初始化为给定的常数。
def init_constant(m):
if type(m) == nn.Linear:
nn.init.constant_(m.weight, 5)
nn.init.zeros_(m.bias)
net.apply(init_constant)
print(net[4].weight)
print(net[0].bias.data)
复制代码
>>
Parameter containing:
tensor([[5., 5.],
[5., 5.],
[5., 5.],
[5., 5.]], requires_grad=True)
tensor([0., 0., 0., 0., 0., 0., 0., 0.])
复制代码
除此之外还可以为不同的层应用不同的初始化方法。
net[0].apply(init_normal)
net[2].apply(init_constant)
net[4].apply(init_constant)
print(net[0].weight.data)
print(net[2].weight.data)
复制代码
>>
tensor([[-0.0138, 0.0057, -0.0061, 0.0052],
[ 0.0126, -0.0008, -0.0102, -0.0230],
[ 0.0144, -0.0041, 0.0095, 0.0127],
[ 0.0108, -0.0063, -0.0181, -0.0175],
[-0.0085, 0.0055, -0.0014, -0.0086],
[-0.0082, 0.0100, -0.0025, -0.0020],
[ 0.0009, -0.0099, 0.0047, 0.0040],
[ 0.0020, -0.0097, -0.0025, -0.0075]])
tensor([[5., 5., 5., 5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5., 5., 5., 5.]])
复制代码
自定义初始化
除了初始化为常数,初始化为高斯分布,pytorch还支持其他初始化方法,更多初始化方法可以看官方手册: torch.nn.init — PyTorch 1.10.0 documentation
但是如果你说这些就是不能满足我的要求,我需要一个其他的初始化方法,那也可以自己写的啦。
比如我们使用以下的分布为任意权重参数 定义初始化方法:
def my_init(m):
if type(m) == nn.Linear:
nn.init.uniform_(m.weight, -10, 10)
m.weight.data *= m.weight.data.abs() >= 5
net.apply(my_init)
print(net[0].weight.data[0])
print(net[2].weight.data[0])
复制代码
>>
tensor([-8.9126, -7.9010, -0.0000, -0.0000])
tensor([-0.0000, -8.6281, 0.0000, 9.8472, -0.0000, 9.7564, 0.0000, 8.5654])
复制代码
实现了一个my_init
函数来应用到net
。这里只输出权重的第一行。
分析一下nn.init.uniform_(m.weight, -10, 10)
和 m.weight.data *= m.weight.data.abs() >= 5
两行代码。
要求是w有 的概率服从(-10,5)的均匀分布,有 的概率服从(5,10)的均匀分布,还有 的概率服等于0。
nn.init.uniform_(m.weight, -10, 10)
是将w全部初始化为(-10,10)的均匀分布。m.weight.data *= m.weight.data.abs() >= 5
进行判定,看每一个权重的绝对值是否大于等于5,如果大于等于5则证明在(5, 10)和(-10,-5)区间上,那返回true,也就是1,m.weight.data
乘1数值不变;反之会返回false,也就是0,将m.weight.data
置零。至于怎么保证 、 概率,因为是均匀分布,所以默认他们在区间上的分布已经均匀。
手动设定
直接接着上边那段代码写了,我们还可以手动修改某个参数的值,比如:
print(net[4].weight.data)
net[4].weight.data[:] += 10
print(net[4].weight.data)
net[4].weight.data[0, 0] = 666
print(net[4].weight.data)
复制代码
>>
tensor([[ 0.0000, 6.9226],
[-0.0000, -0.0000],
[-8.0648, 9.4455],
[-5.8219, 5.6904]])
tensor([[10.0000, 16.9226],
[10.0000, 10.0000],
[ 1.9352, 19.4455],
[ 4.1781, 15.6904]])
tensor([[666.0000, 16.9226],
[ 10.0000, 10.0000],
[ 1.9352, 19.4455],
[ 4.1781, 15.6904]])
复制代码
参数会在你手动修改的位置发生变化。
-
《动手学深度学习》系列更多可以看这里:《动手学深度学习》专栏(juejin.cn)
-
笔记Github地址:DeepLearningNotes/d2l(github.com)
还在更新中…………