网络模型预权重设置加载初始化。
常见函数
nit.uniform
nn.init.normal
nn.init.constant
nn.init.eye
nn.init.dirac
nn.init.xavier_uniform
nn.init.xavier_normal
nn.init.kaiming_uniform
nn.init.kaiming_normal
nn.init.orthogonal
nn.init.sparse
import torch
from torch import nn
conv1 = nn.Conv2d(3, 9, kernel_size=3, stride=2, padding=3)
# conv1.weight 权值
# conv1.bias 偏置
#-----------------------------------------------------------------------------------------------------------#
# 赋值常数
a = nn.init.constant_(conv1.weight, 0.1)
# 使用常数1对tensor赋值
b = nn.init.ones_(conv1.bias)
# 使用常数0对tensor赋值
c = nn.init.zeros_(conv1.bias)
# 按正态分布N ( μ 或 m e a n , σ 或 s t d ) N(\mu或mean,\sigma或std)N(μ或mean,σ或std)对tensor随机赋值
# torch.nn.init.normal_(tensor, mean=0.0, std=1.0)
d = nn.init.normal_(conv1.bias)
# 按均匀分布U(a,b)对tensor随机赋值
# torch.nn.init.uniform_(tensor, a=0.0, b=1.0)
e = nn.init.uniform_(conv1.bias)
#-----------------------------------------------------------------------------------------------------------#
print(e)
使用常数1对tensor的主对角线进行赋值,其余位置为常数0(函数只适用于二维)
import torch
from torch import nn
#--------------------------------------------------------#
w = torch.Tensor(3, 5)
# 函数只适用于二维
# 使用常数1对tensor的主对角线进行赋值,其余位置为常数0
a = nn.init.eye_(w)
#--------------------------------------------------------#
a
生成稀疏矩阵。(函数只适用于二维)
sparsity :每列中需要被设置成零的元素比例。
std :用于生成的正态分布的标准差。
import torch
from torch import nn
#--------------------------------------------------------#
# 生成稀疏矩阵。
# sparsity :每列中需要被设置成零的元素比例。
# std :用于生成的正态分布的标准差。
b = nn.init.sparse_(w, sparsity=0.5,std=0.01)
#--------------------------------------------------------#
b
填充{3, 4, 5}维输入张量或变量。在卷积层尽可能多的保存输入通道特性
import torch
from torch import nn
# 填充{3, 4, 5}维输入张量或变量。在卷积层尽可能多的保存输入通道特性
w = torch.empty(4, 4, 4)
nn.init.dirac_(w)
对于Xavier初始化方式,pytorch提供了uniform和normal两种:
用一个均匀分布生成值,填充输入的张量或变量。结果张量中的值采样自U(-a, a),其中
import torch
from torch import nn
#-----------------------------------------------------------#
conv1 = nn.Conv2d(3, 15, kernel_size=7, stride=2, padding=3)
# 保持输入和输出的方差一致,这样就避免了所有输出值都趋向于0
# 用一个均匀分布生成值,填充输入的张量或变量
# gain - 可选的缩放因子
nn.init.xavier_uniform_(conv1.weight,gain=1)
#-----------------------------------------------------------#
# 用一个正态分布生成值,填充输入的张量或变量。
# gain - 可选的缩放因子
nn.init.xavier_normal_(conv1.weight,gain=1)
#-----------------------------------------------------------#
在ReLU网络中,假定每一层有一半的神经元被激活,另一半为0
nn.init.kaiming_uniform(tensor, a=0, mode='fan_in',nonlinearity='leaky_relu')
两函数的参数:
tensor – n维的torch.Tensor或autograd.Variable
a -这层之后使用的rectifier的斜率系数(ReLU的默认值为0)
mode -可以为“fan_in”(默认)或 “fan_out”
“fan_in”保留前向传播时权值方差的量级
“fan_out”保留反向传播时的量级
nonlinearity=‘leaky_relu’ - 非线性函数 建议“relu”或“leaky_relu”(默认值)使用。
import torch
from torch import nn
conv1 = nn.Conv2d(3, 15, kernel_size=7, stride=2, padding=3)
# 用一个均匀分布生成值,填充输入的张量或变量。
# nn.init.kaiming_uniform_(conv1.weight,mode='fan_in')
# 用一个正态分布生成值,填充输入的张量或变量。
# nn.init.kaiming_normal_(conv1.weight,mode='fan_in')
用(半)正交矩阵填充输入的张量或变量。输入张量必须至少是2维的,对于更高维度的张量,超出的维度会被展平,视作行等于第一个维度,列等于稀疏矩阵乘积的2维表示
import torch
from torch import nn
w = torch.Tensor(3, 5)
nn.init.orthogonal_(w)
import torch
from torch import nn
def weights_init(net, init_type='normal', init_gain = 0.02):
def init_func(m):
classname = m.__class__.__name__
if classname.find('Conv') != -1: # find()函数,实现查找classname中是否含有conv字符,没有返回-1;有返回0.
# 按正态分布N ( μ 或 m e a n , σ 或 s t d ) N(\mu或mean,\sigma或std)N(μ或mean,σ或std)对tensor随机赋值
if init_type == 'normal':
torch.nn.init.normal_(m.weight.data, 0.0, init_gain)
elif init_type == 'xavier': # 保持输入和输出的方差一致,这样就避免了所有输出值都趋向于0
torch.nn.init.xavier_normal_(m.weight.data, gain=init_gain)
elif init_type == 'kaiming': # 在ReLU网络中,假定每一层有一半的神经元被激活,另一半为0
torch.nn.init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
elif init_type == 'orthogonal': # 正交初始化
torch.nn.init.orthogonal_(m.weight.data, gain=init_gain)
else:
raise NotImplementedError('initialization method [%s] is not implemented' % init_type)
elif classname.find('BatchNorm2d') != -1:
# 按正态分布N ( μ 或 m e a n , σ 或 s t d ) N(\mu或mean,\sigma或std)N(μ或mean,σ或std)对tensor随机赋值
torch.nn.init.normal_(m.weight.data, 1.0, 0.02)
torch.nn.init.constant_(m.bias.data, 0.0) # 使用常数val对tensor赋值
print('initialize network with %s type' % init_type)
net.apply(init_func) # 对网络参数初始化
# 调用
weights_init(model)
# 实例化模型
model = YoloBody(anchors_mask, num_classes, phi, pretrained=pretrained)
# 模型初始化函数
weights_init(model)
# 加载预权重
if model_path != '':
if local_rank == 0:
print('Load weights {}.'.format(model_path))
#------------------------------------------------------#
# 根据预训练权重的Key和模型的Key进行加载
#------------------------------------------------------#
# 取出自己网络的参数字典
# 获取了模型中所有可学习的参数和所有不可学习参数
model_dict = model.state_dict()
# 加载预权重
# 加载预训练网络的参数字典
pretrained_dict = torch.load(model_path, map_location = device)
load_key, no_load_key, temp_dict = [], [], {}
for k, v in pretrained_dict.items(): # # k 参数名 v 对应参数值
if k in model_dict.keys() and np.shape(model_dict[k]) == np.shape(v):
temp_dict[k] = v
load_key.append(k)
else:
no_load_key.append(k)
model_dict.update(temp_dict)
model.load_state_dict(model_dict)
#------------------------------------------------------#
# 显示没有匹配上的Key
#------------------------------------------------------#
if local_rank == 0:
print("\nSuccessful Load Key:", str(load_key)[:500], "……\nSuccessful Load Key Num:", len(load_key))
print("\nFail To Load Key:", str(no_load_key)[:500], "……\nFail To Load Key num:", len(no_load_key))
print("\n\033[1;33;44m温馨提示,head部分没有载入是正常现象,Backbone部分没有载入是错误的。\033[0m")
未完待续,,,,