模型参数初始化(weights_init)——torch.nn.init、加载预权重

模型参数初始化(weights_init)——torch.nn.init、加载预权重


文章目录

  • 模型参数初始化(weights_init)——torch.nn.init、加载预权重
  • 前言
    • 一、单层初始化
      • 1、nn.init.constant、nn.init.normal、nn.init.uniform
      • 2、nn.init.eye
      • 3、nn.init.sparse
      • 4、nn.init.dirac
      • 5、xavier_uniform、xavier_normal
      • 6、kaiming_uniform、kaiming_normal
      • 7、nn.init.orthogonal
    • 二、模型初始化
    • 三、加载预权重代码
  • 总结


前言

网络模型预权重设置加载初始化。


一、单层初始化

常见函数
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

1、nn.init.constant、nn.init.normal、nn.init.uniform

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)

2、nn.init.eye

使用常数1对tensor的主对角线进行赋值,其余位置为常数0(函数只适用于二维)

import torch
from torch import nn
#--------------------------------------------------------#
w = torch.Tensor(3, 5)
# 函数只适用于二维
# 使用常数1对tensor的主对角线进行赋值,其余位置为常数0
a = nn.init.eye_(w)
#--------------------------------------------------------#
a

3、nn.init.sparse

生成稀疏矩阵。(函数只适用于二维)
sparsity :每列中需要被设置成零的元素比例。
std :用于生成的正态分布的标准差。

import torch
from torch import nn
#--------------------------------------------------------#
# 生成稀疏矩阵。
# sparsity :每列中需要被设置成零的元素比例。
# std :用于生成的正态分布的标准差。
b = nn.init.sparse_(w, sparsity=0.5,std=0.01)
#--------------------------------------------------------#
b

4、nn.init.dirac

填充{3, 4, 5}维输入张量或变量。在卷积层尽可能多的保存输入通道特性

import torch
from torch import nn
# 填充{3, 4, 5}维输入张量或变量。在卷积层尽可能多的保存输入通道特性
w = torch.empty(4, 4, 4)
nn.init.dirac_(w)

5、xavier_uniform、xavier_normal

对于Xavier初始化方式,pytorch提供了uniform和normal两种:

用一个均匀分布生成值,填充输入的张量或变量。结果张量中的值采样自U(-a, a),其中

模型参数初始化(weights_init)——torch.nn.init、加载预权重_第1张图片

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)
#-----------------------------------------------------------#

6、kaiming_uniform、kaiming_normal

在ReLU网络中,假定每一层有一半的神经元被激活,另一半为0
模型参数初始化(weights_init)——torch.nn.init、加载预权重_第2张图片

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')

7、nn.init.orthogonal

用(半)正交矩阵填充输入的张量或变量。输入张量必须至少是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")

总结

未完待续,,,,

你可能感兴趣的:(基础学习,深度学习,人工智能)