一. nn.Conv2d和F.conv2d权重替换方式分别如下
import torch
import torch.nn as nn
import torch.nn.functional as F
class net(nn.Module):
def __init__(self):
super(net, self).__init__()
self.conv = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=(3, 3), bias=None)
params = torch.tensor([-1, 0, 1, -2, 0, -2, -1, 0, 1]*9, dtype=torch.float32)
kernel = nn.Parameter(params.view(3, 3, 3, 3), requires_grad=True)
self.conv.weight = kernel
def forward(self, x):
out = self.conv(x)
return out
class net2(nn.Module):
def __init__(self):
super(net2, self).__init__()
params = torch.tensor([-1, 0, 1, -2, 0, -2, -1, 0, 1]*9, dtype=torch.float32)
self.kernel = nn.Parameter(params.view(3, 3, 3, 3), requires_grad=True)
def forward(self, x):
out = F.conv2d(x, self.kernel)
return out
if __name__ == '__main__':
input = torch.rand(1, 3, 5, 5)
model = net()
print(model(input))
model2 = net2()
print(model2(input))
运行结果:
二. 对比总结:
- 在实际工程中,如果需要梯度反传,需要将requires_grad=True,反之设为False
- nn.Conv2d默认bias=True,而F.conv2d默认bias=False,这个需要特别注意,否者两个结果会不一样
- 手动设置卷积权重在一些特殊情况下很有用,一般的权重初始化有
1) 均匀分布初始化(随机初始化权重在给定的范围内) nn.init.uniform_(m.weight, a=-0.1, b=0.1)
2) 正态分布初始化 nn.init.normal_(m.weight, mean=0.0, std=0.01)
3) 常数初始化 nn.init.constant_(m.weight, val=0.01)
4) Xavier均匀分布初始化(适用于保持输入和输出的方差一致) nn.init.xavier_uniform_(m.weight, gain=1.0)
5) Xavier正态分布初始化 nn.init.xavier_normal_(m.weight, gain=1.0)
6) He均匀分布初始化(适用于ReLU激活函数的神经网络) nn.init.kaiming_uniform_(m.weight, mode=‘fan_in’, nonlinearity=‘relu’)
7) He正态分布初始化(适用于ReLU激活函数的神经网络) nn.init.kaiming_normal_(m.weight, mode=‘fan_in’, nonlinearity=‘relu’)