【center-loss 中心损失函数】 参数与应用

news2024/12/27 12:35:21

文章目录

  • 前言
  • 简单总结一下
  • 参数对比
    • 解释参数
    • 权重衰减(L2正则化)
    • 动量
    • 其他参数
    • 运行


前言

之前我们已经完全弄明白了中心损失函数里的代码是什么意思,并且怎么用的了,现在我们来运行它。

论文:https://ydwen.github.io/papers/WenECCV16.pdf
github代码:https://github.com/KaiyangZhou/pytorch-center-loss

前文:【center-loss 中心损失函数】 原理及程序解释(完)

简单总结一下

这段主代码,还是先以小见大。

首先,有很多点,以普通的拟合直线为例子,假设直线是用来做分类问题,一条直线分成两类,或者说是回归问题,则就是,每个点落在两类的例子是多少。(可以想象可以用来做很多事。)
我们是这样一步一步做的
1、确立损失函数(作为评判好的模型的标准)。(损失函数有很多可选,具体使用具体分析)
2、随机设置权重参数(作为最后好的模型的参数)。(随机函数也有很多可选)
3、确立模型(如:y=wx+b)
4、计算当前的参数得出的值与实际值(标签值)的误差(可跳,损失函数里一般有此值),后代入(1)中的损失函数求得损失值。
5、确定降低损失值的方法。(有梯度下降法或数学公式法)注意这里是对损失函数求导!!!
6、得出由方法计算出的参数值。

贴一下:(梯度下降法的代码)

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt

# 生成模拟数据,假设真实的w为2,b为3
np.random.seed(0) # 设置随机种子
x = np.linspace(0, 10, 100) # 生成100个在[0,10]的等距数 (包括0,10)
y = 2 * x + 3 + np.random.normal(0, 1, 100) # 生成y值,加入噪声

# 定义一元线性回归模型
def linear_regression(x, w, b):
    return w * x + b

# 定义均方误差函数
def mean_squared_error(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 定义梯度下降算法
def gradient_descent(x, y, w, b, lr, epochs):
    # x: 自变量
    # y: 目标变量
    # w: 斜率的初始值
    # b: 截距的初始值
    # lr: 学习率
    # epochs: 迭代次数
    n = len(x) # 样本数量
    history_w = [] # 用来记录w的历史值
    history_b = [] # 用来记录b的历史值
    history_loss = [] # 用来记录损失函数的历史值

    for i in range(epochs): # 迭代epochs次
        # 计算预测值
        y_pred = linear_regression(x, w, b)
        # 计算损失值
        loss = mean_squared_error(y, y_pred)
        # 计算梯度
        dw = -2/n * np.sum((y - y_pred) * x)
        db = -2/n * np.sum(y - y_pred)
        # 更新w和b
        w = w - lr * dw
        b = b - lr * db
        # 记录w,b和损失值
        history_w.append(w)
        history_b.append(b)
        history_loss.append(loss)
        # 打印结果
        print(f"Epoch {i+1}: w={w:.4f}, b={b:.4f}, loss={loss:.4f}")

    return history_w, history_b, history_loss

# 设置超参数
w = 0 # 斜率的初始值
b = 0 # 截距的初始值
lr = 0.02 # 学习率
epochs = 200 # 迭代次数

# 调用梯度下降算法
history_w, history_b, history_loss = gradient_descent(x, y, w, b, lr, epochs)

# 绘制损失函数的变化曲线
plt.plot(range(epochs), history_loss, color="r")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.title("Loss Curve")
plt.show()

# 绘制最终的拟合直线
plt.scatter(x, y, color="b", label="Data")
plt.plot(x, linear_regression(x, history_w[-1], history_b[-1]), color="g", label="Fitted Line")
plt.xlabel("x")
plt.ylabel("y")
plt.title("Linear Regression")
plt.legend()
plt.show()

这里我们神经网络逻辑上还是一样。
1、确立损失函数 多了中心损失函数
2、随机设置权重参数nn.parameters()
3、确立模型这里用了CNN模型
4、求得损失值
5、确定降低损失值的方法这里也是梯度下降法
6、得出参数值

原来神经网路并没有想象中的那么高深,只是在原来基础上,做了很多的优化。
贴一下:(简单线性层的模型)

import torch
import torch.nn as nn
import torch.optim as optim

#设置随机种子
torch.manual_seed(0)
# 生成一些随机的输入和标签
x = torch.randn(100, 1) # 100个样本,每个样本有1个特征  randn
y = 3 * x + 5 + torch.randn(100, 1) # 100个样本,每个样本有1个标签,服从 y = 3x + 5 + 噪声 的分布

# 定义一个简单的线性模型
model = nn.Linear(1, 1) # 输入维度是1,输出维度是1
# 定义一个均方误差损失函数
criterion = nn.MSELoss()
# 定义一个随机梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01) # 学习率是0.01

# 训练100个迭代
for epoch in range(100):
    # 清零梯度
    optimizer.zero_grad()
    # 得到预测结果
    output = model(x)
    # 计算损失
    loss = criterion(output, y)
    # 反向传播,计算梯度
    loss.backward()
    # 更新参数
    optimizer.step()
    # 打印损失
    print(f"Epoch {epoch}, loss {loss.item():.4f}")

# 打印模型参数
print(model.weight)
print(model.bias)

参数对比

之前我们第一个代码与第二个用到的参数:
w:权重
b:偏置
lr:学习率,乘在梯度前
epoch:迭代次数

此github代码:
model.parameters():里面为W权重矩阵、b偏置
criterion_cent.parameters():里面为W权重矩阵、b偏置
lr:学习率,乘在梯度前 这里lr_model为0.001,lr_cent为0.5
epoch:迭代次数 这里为100
变化
weight_decay:权重衰减(=L2惩罚项),一般很小 ,防止过拟合 一般5e-4 这里为5e-4
momentum:动量,乘在速度项前,用来加速学习过程 一般0.5-0.9 这里为0.9
gamma:学习率下降,乘在学习率前,一般0-1之间 这里为0.5
stepsize:学习率下降周期,每隔多少stepsize下降一次 这里为20

torch.optim.SGD(params, lr=0.001, momentum=0, dampening=0, weight_decay=0, nesterov=False, *, maximize=False, foreach=None, differentiable=False)

未用到的默认参数:
nesterov:使用Nesterov动量方法,默认为False。
maximize:梯度找山顶,默认为False。
foreach:None时,在使用Cuda的情况下性能会更好,默认为None。
differentiable:选择为True时,可能会损害性能,默认为False。

解释参数

还是用官方SGD的图来解释一下更新的代码。
已知y(学习率),θ0(参数),f(θ)(目标损失函数),λ(权重衰减),μ(动量),τ(阻尼)
默认θ0为随机值,b1为0。(bt为中间量,或者叫动量缓冲区。累积了之前的梯度信息)
在这里插入图片描述
第一次迭代t=1时,求损失函数的梯度赋给g1,
如果权重衰减λ不为0,则g1 = g1 + λθ0。

以下讲解这行代码:

权重衰减(L2正则化)

这里在梯度中加入了权重参数θ0的信息,从而提高模型泛化的能力。

这个参数λ之所以很小,是因为我们不希望正则化项主导整个损失函数,而只是作为一个轻微的调整。

这个惩罚项会鼓励模型学习到更小的权重,因为大的权重会导致惩罚项增大,从而增加整体的损失函数值。

所以,当我们更新权重时,实际上是在原始梯度的基础上加上了这个惩罚项的梯度。这样做可以防止权重变得过大,有助于防止模型过拟合。

原理参考:机器学习中,L2正则化的原理,及其可以防止过拟合的原因

公式:
在这里插入图片描述
其中:L2范数为
在这里插入图片描述
这里是在损失函数环节上加的L2正则化。

这里解释下上文:g1 = g1 + λθ0
1、这里不是θ0 2,原因其实就是上面一步求梯度,已经将平方项移下来了(当然也有可能损失函数没有平方项)。
或者,我们可以看成,梯度项相加时,我们也要对 λ·IIwII2 求导,此时的平方项2就下来了,放进超参数里了。

2、至于L2范数里的求和为什么在g1 = g1 + λθ0 里没写,解释:是有这个操作的,只是求gt里也没写求和的操作,那为简便写伪代码起见,就也没写。

继续:

动量

如果动量u为0,则直接进行判断是否是求梯度最小还是梯度最大,如果最大则θ1 = θ0 + y x g1 ,如果最小则是θ1 = θ0 - y x g1 。

如果动量u不为0,此时判断t=1,则b1 = g1,
如果使用Nesterov动量方法,则g1 = g1 + ub1 (实际上是g1 =(1+u)x g1),如果不使用则g1 = b1。(可以看出Nesterov动量方法相比于原方法收敛更快)

然后如上更新。

t =2时,(λ、u不为0的情况 )损失函数求导得出g2-> g2 = g2+λθ1
此时判断t>1, 则b2 = ub1 +(1-τ)x g2 (此时b1 = g1) 可以看出当τ为0时,动量u起到一个加速作用

-> 之后同上。

momentum动量解释:
是用来加速梯度下降过程的,但如果动量值设置大于1,会导致更新步长过大,从而可能导致优化过程在最小值附近震荡,甚至发散,而不是收敛到最小值。动量的目的是为了帮助梯度下降算法更快地穿过平坦区域并减少震荡,但它也需要保证整个过程的稳定性。

dampening阻尼解释:
“dampening” 通常指的是减少振荡和过度调整的过程。在随机梯度下降(SGD)中,当使用动量(momentum)时,dampening 参数用于减少动量的影响,从而帮助稳定学习过程。如果设置为非零值,dampening 会减少累积过去梯度的速度,这样可以防止在最小值附近的过度震荡。

例如,在PyTorch的 torch.optim.SGD 优化器中,dampening 参数通常与动量一起使用。如果不希望使用动量的衰减效果,可以将 dampening 设置为0。如果设置了 dampening,每次更新时累积的动量会乘以 (1 - dampening )。这样,即使动量保持不变,通过调整 dampening,也可以控制优化过程的平滑程度

其他参数

# argparse.ArgumentParser() 创建一个ArgumentParser对象 用来处理命令行参数
parser = argparse.ArgumentParser("Center Loss Example")
# dataset # 数据集
# add_argument() 方法用于指定程序需要接受的命令参数
parser.add_argument('-d', '--dataset', type=str, default='mnist', choices=['mnist']) # 选择数据集 例:python main.py -d mnist
parser.add_argument('-j', '--workers', default=4, type=int,
                    help="number of data loading workers (default: 4)") # 数据加载工作线程数 例:python main.py -j 4 #-j表示短名称
# optimization # 优化
parser.add_argument('--batch-size', type=int, default=128) # 批大小
parser.add_argument('--lr-model', type=float, default=0.001, help="learning rate for model") # 学习率
parser.add_argument('--lr-cent', type=float, default=0.5, help="learning rate for center loss") # 中心损失学习率
parser.add_argument('--weight-cent', type=float, default=1, help="weight for center loss") # 中心损失权重
parser.add_argument('--max-epoch', type=int, default=100) # 最大迭代次数
parser.add_argument('--stepsize', type=int, default=20) # 学习率下降间隔 : 每隔多少个epoch下降一次
parser.add_argument('--gamma', type=float, default=0.5, help="learning rate decay") # 学习率衰减 : 学习率下降的倍数 比如0.5表示学习率减半
# model # 模型
parser.add_argument('--model', type=str, default='cnn') # 模型选择
# misc # 其他
parser.add_argument('--eval-freq', type=int, default=10) # 评估频率
parser.add_argument('--print-freq', type=int, default=50) # 打印频率 
parser.add_argument('--gpu', type=str, default='0') # GPU
parser.add_argument('--seed', type=int, default=1) # 随机种子
parser.add_argument('--use-cpu', action='store_true') # 是否使用CPU action='store_true' 表示如果有这个参数则为True
parser.add_argument('--save-dir', type=str, default='log') # 保存路径 保存训练日志 保存在log文件夹下
parser.add_argument('--plot', action='store_true', help="whether to plot features for every epoch") # 是否绘制特征图

args = parser.parse_args() # 解析参数 保存到args中

运行

进入colab官网白嫖gpu。
参考:利用谷歌colab跑github代码详细步骤

$ git clone https://github.com/KaiyangZhou/pytorch-center-loss
$ cd pytorch-center-loss
$ python main.py --eval-freq 1 --gpu 0 --save-dir log/ --plot

评估频率1epoch1次, gpu选择0号。保存在log文件夹下并绘图。
运行如下:
在这里插入图片描述
运行截图如下:
在这里插入图片描述

发现在第12epoch时就达到了97%的正确率。

在第32epoch时就基本上达到了高峰,然后逐渐下降。
在这里插入图片描述
如预期所见生成了log的文件夹。

在这里插入图片描述
选择train/epoch_33.png 如下:
在这里插入图片描述
分离表现的还不错。

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

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

相关文章

5. Java内存模型JMM

文章目录 计算机硬件存储体系基于计算机存储结构的 JMM Java 内存模型 JavaMemoryModelJMM规范下的三大特性原子性可见性有序性 多线程对变量的读写过程读取过程 多线程先行发生原则 happens-beforex,y 的 case 说明happens-before 原则说明happens-before 大原则happens-befor…

TCP重传机制、滑动窗口、拥塞控制

一、总述 TCP,Transmission Control Protocol,是一个面向连接、基于流式传输的可靠传输协议,考虑到的内容很多,比如数据包的丢失、损坏、分片和乱序等,TCP协议通过多种不同的机制来实现可靠传输。今天,重点…

数据库原理实验课(1)

目录 实验内容 安装头歌中的相关内容 具体过程 完结撒花~ 我也是第一次接触oracle的相关软件和操作,所以是一次傻瓜式教学记录 实验内容 安装头歌中的相关内容 具体过程 这是我在百度网盘中下载解压出来的oracle文件夹内的全部内容(可能有因为安装完…

C++指针(四)万字图文详解!

个人主页:PingdiGuo_guo 收录专栏:C干货专栏 前言 相关文章:C指针(一)、C指针(二)、C指针(三) 本篇博客是介绍函数指针、函数指针数组、回调函数、指针函数的。 点赞破六…

【校园安全】支小蜜防校园霸凌语音识别系统的好处

在校园安全领域,防校园霸凌语音识别系统的出现,为预防和应对校园霸凌行为提供了新的技术手段。本文将探讨防校园霸凌语音识别系统的好处,并分析其在校园安全建设中的重要作用。 通过安装在校园各个角落的语音识别设备,系统能够捕…

LeetCode 刷题 [C++] 第3题.无重复字符的最长子串

题目描述 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 题目分析 可以使用滑动窗口加哈希表来实现: 使用start和end两个变脸来表示滑动窗口的头部位置和尾部位置,两者开始均为0;借助哈希表来记录已经遍…

WinSCP下载安装并结合内网穿透实现固定公网TCP地址访问本地服务器

文章目录 1. 简介2. 软件下载安装:3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件,它的主要功能是在本地与远程计…

走向审计4.0:内部审计数字化转型的路径与方法【文末送书-34】

文章目录 走向审计4.0:内部审计数字化转型的路径与方法一、内部审计的发展阶段二、内部审计的逻辑架构三、内部审计数字化转型面临的问题四、内部审计数字化转型的框架方法五、内部审计的数字化转型能力体系六、内部审计的数字化转型路径七、内部审计的数字化系统平…

Research Agent:具有解决基于大型文本语料库的复杂问题,具备深度多跳推理的能力

原文地址:https://towardsdatascience.com/the-research-agent-4ef8e6f1b741 2023 年 8 月 29 日 问题简介 在2021年,开始应对基于大量文本回答问题的挑战。在预训练transformers之前的时代,这个问题很难破解。 人工智能和大型预训练tran…

143.和弦是什么?和声是什么?三和弦

内容参考于: 三分钟音乐社 上一个内容:142.音程的构唱练习 和弦的定义: 一个音可以把它称为单音 两个音可以把它称为音程 更多的音,通俗的定义上,三个音或者三个以上的音构成的集体就可以叫做和弦,这些音…

Redis进阶(三):主从复制

为了解决单点问题,实现多服务器部署redis,有几种解决方案可以实现:主从复制,主从哨兵还有集群。 何为主从复制 简单来说有三个服务器分别部署了redis-server程序,选中一个服务器当作主节点,其他的就是从节…

TypeScript 哲学 - Object Types

readonly 修饰对象和数组的 双向可分配性是不同的 Combind types 交叉类型对 值类型可以识别 never 但是 Object 类型识别不了 Tuple

AI时代PPT如何制作?用这10款pptai生成器一键制作!

ppt如何制作? 这可能是很多职场人或大学生日常头疼的问题,职场上随便一个工作汇报、提案展示、团队会议,学校里的小组作业、论文答辩等场景,都会用到ppt。 都说人是视觉动物,在两份文档内容质量一致的情况下&#xf…

Qt插件之输入法插件的构建和使用(二)

文章目录 主键盘搭建Google开源引擎音节分割工具类参考项目下载搭建好各个基础控件之后,就可以开发输入法的主界面和引擎了,这也是输入法的核心。 主键盘搭建 输入法的主界面本质上是一个QStackedWidget容器,将各个类型的输入键盘插入到容器中,然后根据业务需要切换不同的…

通过对话式人工智能打破语言障碍

「AI突破语言障碍」智能人工智能如何让全球交流无障碍 在当今互联的世界中,跨越语言界限进行交流的能力比以往任何时候都更加重要。 对话式人工智能(包括聊天机器人和语音助手等技术)在打破这些语言障碍方面发挥着关键作用。 在这篇博文中&am…

Java对接海康威视摄像头实现抓图

目录 一、下载SDK 二、拷贝示例代码 三、拷贝库文件 四、运行Demo 五、抓图业务 六、调参 ​七、发布Linux正式环境 一、下载SDK 海康开放平台 二、拷贝示例代码 三、拷贝库文件 这时候直接运行ClientDemo会报错,因为缺失库文件! 四、运行Demo …

13 OpenCv自定义线性滤波

文章目录 卷积算子示例 卷积 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作。Kernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point) 把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚…

杨辉三角(附html,Python,c++杨辉三角代码)

1、前言 杨辉三角很早学编程就知道,但不知道杨辉是古人! 一次偶然的机会,和杨辉三角对上了眼神——杨辉!究竟你是怎么发现杨辉三角的呢? 于是经过了长达3个月锲而不舍的探究。 终究也没发现自己想要的最终结果。 …

内螺旋面的计算

内螺旋面的计算 内螺旋面的计算是机械工程和数学领域中的一个重要问题。它涉及到三维几何、微积分和数值计算等多个方面的知识。内螺旋面的形状和特性对于许多机械装置和工程应用来说至关重要,因此准确计算内螺旋面的几何参数和性质至关重要。内螺旋面是一种特殊的…

warning: #188-D: enumerated type mixed with another type

警告解释:枚举类型混合了其它的数据类型; 解决方法: 1:检查代码,是不是存在混用;; 2:结构体初始化为 0 报warning,不能将结构体的第一个变量,使用枚举类型&am…