pytorch基础:模型的权值初始化与损失函数

news2024/10/6 17:48:13

文章目录

    • 一、权值初始化
      • 1.2Kaiming初始化
      • 1.4 十种权重初始化方法
    • 2.损失函数
      • 2.1损失函数初步介绍
      • 2.2交叉熵损失CrossEntropyLoss
    • 2.3 剩余的17种损失函数介绍

一、权值初始化

在搭建好网络模型之后,一个重要的步骤就是对网络模型中的权值进行初始化。适当的权值初始化可以加快模型的收敛,而不恰当的权值初始化可能引发梯度消失或者梯度爆炸,最终导致模型无法收敛。

1.1 梯度消失与梯度爆炸
梯度消失:如果导数小于1,那么随着网络层数的增加,梯度更新信息会朝着指数衰减的方式减少这就是梯度消失。梯度消失时,越靠近输入层的参数w越是几乎纹丝不动。

梯度爆炸:在反向传播过程中需要对激活函数进行求导,如果导数大于1,那么随着网络层数的增加,梯度更新将会朝着指数爆炸的方式增加。梯度爆炸时,越是靠近输入层的参数w越是上蹿下跳。

二者问题问题都是因为网络太深,网络权值更新不稳定造成的。本质上是因为梯度反向传播中的连乘效应(小于1连续相乘多次)。

1.2 Xavier初始化
方差一致性原则:让每一个网络层输出值的方差尽量等于1 ,主要针对饱和激活函数,如sigmoid,tanh。

我们先尝试通过手动设置均匀分布来初始化:

    def initialize(self):
        for m in self.modules():
            # 判断这一层是否为线性层,如果为线性层则初始化权值
            if isinstance(m, nn.Linear):
               
                # 计算均匀分布的上限、下限
                 a = np.sqrt(6 / (self.neural_num + self.neural_num))
 
                 # 把a变换到 tanh,计算增益。观察数据输入到激活函数之后,标准差的变化
                 tanh_gain = nn.init.calculate_gain('tanh')
                 a *= tanh_gain
                # 均匀分布初始化权重
                 nn.init.uniform_(m.weight.data, -a, a)

这里用到一个函数nn.init.calculate_gain(nonlinearity,param=None)

作用:是计算激活函数的方差变化尺度,就是输入数据的方差除以经过激活函数之后的输出数据的方差。

  • nonlinearity:表示激活函数的名称,如tanh。
  • param: 表示激活函数的参数,如Leaky
    ReLU的negative_slop。

可以看到输出结果稳定在0.6左右:
在这里插入图片描述
我们再来直接调用Pytorch 提供的 Xavier 初始化方法

nn.init.xavier_uniform_(tensor, gain=1.0)

  def initialize(self):
        for m in self.modules():
            if isinstance(m, nn.Linear):
                # Xavier初始化权重
                tanh_gain = nn.init.calculate_gain('tanh')
                nn.init.xavier_uniform_(m.weight.data, gain=tanh_gain)

输出结果同上。

注意:2012年AlexNet出现之后,非饱和函数relu也用到了神经网络中,而Xavier初始化对于relu就不好使了,这会导致输出方差越来越大,层数多了依然会出现爆炸现象。如下图所示:
在这里插入图片描述

1.2Kaiming初始化

针对上述问题,何凯明等人就提出了针对Relu这种非饱和函数的Kaming初始化方法.
nn.init.kaiming_normal_(tensor, a=0, mode=‘fan_in’, nonlinearity=‘leaky_relu’)

    def initialize(self):
        for m in self.modules():
            if isinstance(m, nn.Linear):
 
                #Pytorch提供的初始化方法
                nn.init.kaiming_normal_(m.weight.data)
  

输出结果表明,Relu输出梯度爆炸问题得到了解决
在这里插入图片描述

1.4 十种权重初始化方法

Pytorch中提供了许多权重初始化方法,可以分为下面四大类

  • 针对饱和激活函数(sigmoid, tanh):Xavier均匀分布, Xavier正态分布

  • 针对非饱和激活函数(relu及变种):Kaiming均匀分布, Kaiming正态分布

  • 三个常用的分布初始化方法:均匀分布,正态分布,常数分布 三个特殊的矩阵初始化方法:正交矩阵初始化,单位矩阵初始化,稀疏矩阵初始化

2.损失函数

2.1损失函数初步介绍

损失函数: 衡量模型输出与真实标签的差异.而我们谈损失函数的时候,往往会有三个概念:损失函数,代价函数,目标函数.

函数名定义
损失函数(Loss Function)计算一个样本的模型输出与真实标签的差异Loss = f(y^,y)
代价函数 (Cost Function)计算整个样本的模型输出与真实标签的差异,是所有样本损失函数的平均值 在这里插入图片描述
目标函数(objective Function)代价函数加上正则项.实际上就直接说成损失函数

2.2交叉熵损失CrossEntropyLoss

nn.CrossEntropyLoss
function:nn.LogSoftmax()与nn.NULLLoss()结合,进行交叉熵计算
在这里插入图片描述

主要参数:

weight:各类别的loss设置权限
ignore_index:忽略某个类别
reduction:计算模式,可为none/sum/mean
none:逐个元素计算
sum:返回所有元素求和,返回标量
mean:加权平均,返回标量(默认)
 

在这里插入图片描述
注意:使用nn.LogSoftmax()将概率归一化,应为交叉熵损失函数一般用在分类任务当中,而分类任务通常需要计算两个输出的概率值,所以交叉熵损失函数用来衡量两个概率分布之间的差异,交叉熵值越低,说明两个概率分布越近。

熵之间的关系

熵:用来描述整个概率分布的不确定性,熵越大,不确定性越高

信息熵 :自信息用于描述单个事件的不确定性,信息熵就是求自信息的期望

相对熵:也被称为 KL 散度,用于衡量两个分布的相似性(距离)

交叉熵 = 信息熵 + 相对熵

优化交叉熵:等价于优化相对熵

这里是引用

在这里插入图片描述

# 构建虚拟数据
 
# 这里就是模型预测的输出, 这里是两个类,可以看到模型输出是数值,我们得softmax一下转成分布
inputs = torch.tensor([[1, 2], [1, 3], [1, 3]], dtype=torch.float)
# 标签。这里的类型必须是long, 两个类0和1
target = torch.tensor([0, 1, 1], dtype=torch.long)
 
# ---------------- CrossEntropy loss: reduction ----------------
 
    # 三种模式的损失函数
    loss_f_none = nn.CrossEntropyLoss(weight=None, reduction='none')
    loss_f_sum = nn.CrossEntropyLoss(weight=None, reduction='sum')
    loss_f_mean = nn.CrossEntropyLoss(weight=None, reduction='mean')
 
    # forward
    loss_none = loss_f_none(inputs, target)
    loss_sum = loss_f_sum(inputs, target)
    loss_mean = loss_f_mean(inputs, target)
 
    # view
    print("Cross Entropy Loss:\n ", loss_none, loss_sum, loss_mean)

reslt shown below:
在这里插入图片描述
路人贾的手写算法:

# --------------------------------- compute by hand
 
    idx = 0
 
    input_1 = inputs.detach().numpy()[idx]      # [1, 2]
    target_1 = target.numpy()[idx]              # [0]
 
    # 第一项
    x_class = input_1[target_1]
 
    # 第二项
    sigma_exp_x = np.sum(list(map(np.exp, input_1)))
    log_sigma_exp_x = np.log(sigma_exp_x)
 
    # 输出loss
    loss_1 = -x_class + log_sigma_exp_x
 
    print("第一个样本loss为: ", loss_1)

her result:
在这里插入图片描述
接下来我们对每个样本进行权值缩放:

# ----------------------------------- weight -----------------------------------
 
    # def loss function
    weights = torch.tensor([1, 2], dtype=torch.float)
    # weights = torch.tensor([0.7, 0.3], dtype=torch.float)
 
    #有几个类,weight就要设几个值
    loss_f_none_w = nn.CrossEntropyLoss(weight=weights, reduction='none')
    loss_f_sum = nn.CrossEntropyLoss(weight=weights, reduction='sum')
    loss_f_mean = nn.CrossEntropyLoss(weight=weights, reduction='mean')
 
    # forward
    loss_none_w = loss_f_none_w(inputs, target)
    loss_sum = loss_f_sum(inputs, target)
    loss_mean = loss_f_mean(inputs, target)
 
    # view
    print("\nweights: ", weights)
    print(loss_none_w, loss_sum, loss_mean)
 
 
# --------------------------------- compute by hand
 
    weights = torch.tensor([1, 2], dtype=torch.float)
    weights_all = np.sum(list(map(lambda x: weights.numpy()[x], target.numpy())))  # [0, 1, 1]  # [1 2 2]
    mean = 0
    loss_f_none = nn.CrossEntropyLoss(reduction='none')
    loss_none = loss_f_none(inputs, target)
    loss_sep = loss_none.detach().numpy()
    for i in range(target.shape[0]):
 
        x_class = target.numpy()[i]
        tmp = loss_sep[i] * (weights.numpy()[x_class] / weights_all)
        mean += tmp
 
    print(mean)

result below:

在这里插入图片描述设置的时候,target那里第一个标签为0,权重为1;后两个标签为1,权重为2。所以分母不再是3个样本,而是1+2+2, 毕竟后两个样本权为2, 一个样本顶第一个的这样的2个。

可以观察到,第一个loss没有变;第二个和第三个loss变为原来的2倍

所以mean模式下求平均不是除以样本的个数,而是样本所占的权值的总份数。

加权之后:sum直接求和,mean需要求加权平均

2.3 剩余的17种损失函数介绍

在这里插入图片描述

# ----------------------------------- 1 NLLLoss -----------------------------------
 
    weights = torch.tensor([1, 1], dtype=torch.float)
 
    loss_f_none_w = nn.NLLLoss(weight=weights, reduction='none')
    loss_f_sum = nn.NLLLoss(weight=weights, reduction='sum')
    loss_f_mean = nn.NLLLoss(weight=weights, reduction='mean')
 
    # forward
    loss_none_w = loss_f_none_w(inputs, target)
    loss_sum = loss_f_sum(inputs, target)
    loss_mean = loss_f_mean(inputs, target)
 
    # view
    print("\nweights: ", weights)
    print("NLL Loss", loss_none_w, loss_sum, loss_mean)

在这里插入图片描述
在这里插入图片描述

# ----------------------------------- 2 BCE Loss -----------------------------------
 
    inputs = torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtype=torch.float)
    target = torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtype=torch.float)
 
    target_bce = target
 
 
    # itarget 将输入值压缩到[0-1]
    inputs = torch.sigmoid(inputs)
 
    weights = torch.tensor([1, 1], dtype=torch.float)
 
    loss_f_none_w = nn.BCELoss(weight=weights, reduction='none')
    loss_f_sum = nn.BCELoss(weight=weights, reduction='sum')
    loss_f_mean = nn.BCELoss(weight=weights, reduction='mean')
 
    # forward
    loss_none_w = loss_f_none_w(inputs, target_bce)
    loss_sum = loss_f_sum(inputs, target_bce)
    loss_mean = loss_f_mean(inputs, target_bce)
 
    # view
    print("\nweights: ", weights)
    print("BCE Loss", loss_none_w, loss_sum, loss_mean)

在这里插入图片描述

在这里插入图片描述

# --------------------------------- 17 CTC Loss -----------------------------------------
    T = 50      # Input sequence length
    C = 20      # Number of classes (including blank)
    N = 16      # Batch size
    S = 30      # Target sequence length of longest target in batch
    S_min = 10  # Minimum target length, for demonstration purposes
 
    # Initialize random batch of input vectors, for *size = (T,N,C)
    inputs = torch.randn(T, N, C).log_softmax(2).detach().requires_grad_()
 
    # Initialize random batch of targets (0 = blank, 1:C = classes)
    target = torch.randint(low=1, high=C, size=(N, S), dtype=torch.long)
 
    input_lengths = torch.full(size=(N,), fill_value=T, dtype=torch.long)
    target_lengths = torch.randint(low=S_min, high=S, size=(N,), dtype=torch.long)
 
    ctc_loss = nn.CTCLoss()
    loss = ctc_loss(inputs, target, input_lengths, target_lengths)
 
    print("CTC loss: ", loss)

在这里插入图片描述

本文参考
系统学习Pytorch笔记六:模型的权值初始化与损失函数介绍

[PyTorch 学习笔记] 4.2 损失函数 - 知乎 (zhihu.com)
https://jrs0511.blog.csdn.net/article/details/129091637 路人贾

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2192513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot框架在明星周边销售网站中的应用

3系统分析 3.1可行性分析 通过对本星之语明星周边产品销售网站实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本星之语明星周边产品销售网站采用JAVA作为开发语…

国庆期间不停歇—学习ROS2第四天

1.现在终端中创建文件 其次在该文件目录下打开,最后在VS中 创建两个文件夹,最后一个是src 在终端中创建pkg, ros2 pkg create demo_python_topic --build-type ament_python --dependencies rclpy example_interfaces --license Apache-2.0…

[C#]使用纯opencvsharp部署yolov11-onnx图像分类模型

【官方框架地址】 https://github.com/ultralytics/ultralytics.git 【算法介绍】 使用纯OpenCvSharp部署YOLOv11-ONNX图像分类模型是一项复杂的任务,但可以通过以下步骤实现: 准备环境:首先,确保开发环境已安装OpenCvSharp和必…

Spring14——案例:利用AOP环绕通知计算业务层接口执行效率

前面介绍了这么多种通知类型,具体该选哪一种呢? 我们可以通过一些案例加深下对通知类型的学习。 34-案例:利用AOP环绕通知计算业务层接口执行效率 需求分析 这个需求也比较简单,前面我们在介绍AOP的时候已经演示过: 需求:任意业务层接口…

链表--链表的一个技巧

少年的书桌上没有虚度的光阴 2024.10.5 大家好,我是小苏。 今天给大家分享一下近期我刷力扣链表题的一个技巧! 我们知道,链表和数组的重要区别之一是: 链表不支持随机访问,数组支持 我们可以根据这一特性:把…

信息安全工程师(35)访问控制类型

前言 访问控制是几乎所有系统(包括计算机系统和非计算机系统)都需要用到的一种技术,它基于用户身份及其所归属的某项定义组来限制用户对某些信息项的访问,或限制对某些控制功能的使用。 一、自主访问控制(DAC&#xff…

ElasticSearch备考 -- Search across cluster

一、题目 配置两个集群,集群名称为my-application-01、my-application-02,导入es自带Sample flight data数据集,配置扩集群检索,查询数据 二、思考 准备工作有两个集群,并需要对集群配置角色中增加 remote_cluster_cl…

物联网智能设备:未来生活的变革者

文章目录 引言什么是物联网智能设备?技术架构应用场景挑战与解决方案未来发展趋势结论 引言 随着科技的迅猛发展,物联网(IoT)正在改变我们生活的方方面面。从智能家居到工业自动化,物联网智能设备正在逐步融入我们的日…

AI应用的东风,奥特曼不想错过

文|魏琳华 编|王一粟 作为炙手可热的AI公司,Open AI又一次拿到了一轮足以令对手眼红的巨额融资。10月2日,Open AI宣布顺利完成66亿美元融资,补上了烧钱研发亏损的同时,还为下一轮竞争拿到了资金支持。 跻…

【电商搜索】现代工业级电商搜索技术-中科院计算机研究所-生成型检索与多级相关性相结合

【电商搜索】现代工业级电商搜索技术-中科院计算机研究所-生成型检索与多级相关性相结合 目录 文章目录 【电商搜索】现代工业级电商搜索技术-中科院计算机研究所-生成型检索与多级相关性相结合目录0. 论文信息1. 摘要2. 研究背景3. 主要挑战4. 创新点5. 算法模型1. **标识符设…

还在“卷”长度?长文本模型真的基于上下文进行回复吗?

近年来,随着长文本模型(Long-context Model, LCM)技术的突飞猛进,处理长上下文的能力已成为各大语言模型(Large Language Model, LLM)的核心竞争力,也是各大技术厂商争夺的焦点。截至2023年12月…

SystemC学习(1)— SystemC安装与HelloWorld

SystemC学习(1)— SystemC安装与HelloWorld 一、前言 参考文档: 1、ubuntu系统安装systemc-2.3.4流程 2、SystemC语言学习笔记 3、SystemC资料2.ppt 4、SystemC入门笔记 二、安装包下载与安装 我们可以直接从官网下载SystemC的库安装包&a…

多字节字符集CString转换string

实现函数如下&#xff1a; std::string CStringToUTF8(const CString& str) {// Step 1: 将 MBCS (GBK) CString 转换为宽字符&#xff08;WCHAR&#xff09;int wideLen MultiByteToWideChar(CP_ACP, 0, str.GetString(), -1, NULL, 0);if (wideLen < 0)return "…

组件中$router/$route的由来(vue-router源码分析)

1.vue-router源码下载 我们可以到github上找到对应版本的vue-router 版本号可以到项目中的node_modules/vue-router/dist/vue-router.js查看嘴上面的许可证说明(package.json只提供了版本的大致范围 ^表示2.2.x 而~表示2.x.x 都为>的含义) 在github上的vue-router我们要选择…

一个月学会Java 第2天 认识类与对象

Day2 认识类与对象 第一章 初识类 经过一个程序的编写&#xff0c;应该对程序的结构有点好奇了吧&#xff0c;如果你有基础&#xff0c;接下来的肯定非常的易懂&#xff0c;如果你没有基础也没有关系&#xff0c;反复琢磨一下也就懂了&#x1f606; 我们来重复一下第一个程序 …

Vivado - JTAG to AXI Master (DDR4)

目录 1. 简介 2. JTAG 直接操作 DDR4 2.1 Block Design 2.2 AXI SmartConnect 2.3 DDR4 MIG 2.3.1 时钟和复位 2.3.2 AXI Slave 接口 2.4 XDC 约束 2.5 TCL 代码 2.5.1 写入 DDR4 2.5.2 读取 DDR4 3. HLS IP 操作 DDR4 3.1 Block Design 3.2 HLS IP 3.2.1 HLS 代…

TypeScript面向对象 01

使用class关键字来定义一个类。对象中主要包含了两个部分&#xff1a;属性和方法。 class Person {// 定义实例属性name:string glm;age:number 1234; } const a new Person(); console.log(a.name);在属性前使用static关键字可以定义类属性&#xff08;静态属性&#xff0…

Sebastian Raschka 最新博客:从头开始用 Llama 2 构建 Llama 3.2

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

自动驾驶-问题笔记-待解决

参考线的平滑方法 参考线平滑算法主要有三种&#xff1a; 离散点平滑&#xff1b;螺旋曲线平滑&#xff1b;多项式平滑&#xff1b; 参考链接&#xff1a;参考线平滑 对于平滑方法&#xff0c;一直不太理解平滑、拟合以及滤波三者的作用与区别&#xff1b; 规划的起点&#x…

代码随想录一刷完结

非常偶然的机会让我看到这个算法训练营的存在&#xff0c;虽然我也没有多大的动力&#xff0c;但当时就觉得没什么事情&#xff0c;想着刷刷题&#xff0c;为以后找工作打打基础。 收获 提示&#xff1a;在刷题过程中的收获 第一次使用CSDN记录&#xff0c;每次有别人点赞和收…