当前位置: 首页 > news >正文

深度学习笔记12

1.神经网络的代价函数

        神经网络可同时用于解决分类问题和回归问题,对于不同的问题会在输出层后,加上不同的变换函数。一般来说,回归问题使用恒等函数f(x)=x,分类问题使用sigmoid或softmax函数。而不同的变换函数,也对应不同的代价函数。

神经网络解决回归问题

        在使用神经网络解决回归问题时,会在输出层后,加上恒等函数,不会对输入值做任何修改。如果神经网络只预测一个回归值,那么使用的代价函数和线性回归中的代价函数一样,都是均方误差函数MSE。如果线性回归需要预测多个回归值,则需要将每个回归目标的均方误差计算出来,然后相加得到总误差。

总的代价函数:

MSE=\frac{1}{mn}\sum_{i=1}^{m}\sum_{j=1}^{n}(y_{ij}-\hat{y}_{ij})^2

m:样本个数

n:目标个数

y_{ij}:真实值

\hat{y}_{ij}:预测值

i:第i个样本

j:第j个目标

\sum_{j=1}^{n}:计算单独每个样本的n个目标的真实值和预测值的平方差

\sum_{i=1}^{m}:将m个样本对应的误差加到一起

神经网络解决分类问题 

        当使用神经网络解决分类问题时,最后一层的每个神经元都会对应一个类型,每个神经元的输出通过变换函数转换为类别对应的概率。如果每个类别之间是互斥的,就将神经元的输出值,输入到softmax函数中,将其转化为这几个互斥的类别对应的概率(p_1+p_2+...=1)。

        另一种情况是多标签分类,每个类别之间互不打扰,相互独立,这时要将神经元的输出值,分别输入到sigmoid函数中,经过sigmoid函数的计算,可以得到这些不同类别的概率,它们是多个无关联的、0-1之间的实数。

代价函数

         在解决分类问题时,一般使用交叉熵损失函数。对于互斥的分类问题,神经网络会使用与softmax回归形式完全相同的交叉熵损失函数。对于多标签分类问题,神经网络使用与逻辑回归形式相似的交叉熵损失函数。

互斥的多分类问题:E=-\frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{n}y_k^{(i)}log(p_k^{(i)})

多标签分类问题:E=-\frac{1}{m}\sum_{i=1}^{m}\sum_{k=1}^{n}(y_k^{(i)}log(p_k^{(i)})+(1-y_k^{(i)})log(1-p_k^{(i)}))

2.小批量梯度下降算法        

        梯度下降算法有三种常见的形式:批量梯度下降、随机梯度下降和小批量梯度下降

  • 批量梯度下降:

         每次迭代中,批量梯度下降算法都会基于所有的训练样本,计算损失函数的梯度,因此可以得到一条平滑的收敛曲线。训练数据:100个样本,迭代轮数50,在每一轮迭代中都会一起使用这100个样本,计算整个训练集的梯度,更新模型参数,所以总更新次数:50次

  • 随机梯度下降:

        会在一轮完整的迭代过程中,遍历整个训练集,但是每次更新只基于一个样本计算梯度,这样会得到一条震荡的收敛曲线。训练数据:100个样本,迭代轮数50,每一轮迭代会遍历这100个样本,每次汇集孙某一个样本的梯度,更新模型参数,所以总更新次数:100*50=5000

  • 小批量梯度下降:

        结合批量梯度下降和随机梯度下降的优点,每次迭代会从训练集中,随机选择一个小批量,计算梯度,更新模型。训练数据:100个样本,迭代轮数50,小批量大小20,在每一轮迭代中会有5次小批量的迭代,所以总更新次数:(100/20)*50=250

梯度下降算法比较
优点缺点
批量梯度下降每次迭代会使用整个训练集计算梯度,可以得到准确的梯度方向如果数据集非常大时,就导致每次迭代的速度都非常慢,计算成本就会很高
随机梯度下降每次只用一个样本训练,所以迭代速度会非常快,迭代具有震荡属性,可以跳出局部最优解更新的方向会不稳定,可能永远都不会真正的收敛
小批量梯度下降结合随机梯度下降的高效性和批量梯度下降的稳定性,它比随机梯度下降有更稳定的收敛,同时又比批量梯度下降计算的更快
方法是否稳定迭代速度局部最优解
批量梯度下降稳定可能停留
随机梯度下降不稳定可跳出
小批量梯度下降较稳定较快可跳出

小批量梯度下降算法的实现 

1.小批量数据的准备

import numpy as np
import matplotlib.pyplot as plt
import torch
from torch.utils.data import DataLoader
from torch.utils.data import TensorDataset
#设置一个固定的随机种子,确保每次运行得到相同的数据
np.random.seed(0)
#随机生成100个横坐标x,范围在0-2
x=2*np.random.rand(100,1)
#生成带有噪音的纵坐标y,数据基本分布在y=2x+3附近
y=3+2*x+np.random.randn(100,1)*0.5
plt.scatter(x, y,marker='x',color='red')#将训练数据x、y转为张量
x=torch.from_numpy(x).float()
y=torch.from_numpy(y).float()#使用TensorDataset,将x和y组成训练集
dataset=TensorDataset(x,y)
#使用DataLoader,构造随机的小批量数据
dataloader=DataLoader(dataset,#使用一个小批量的数据规模为20batch_size=20,#随机打乱数据的顺序shuffle=True)
print("dataloader len=%d"%(len(dataloader)))
for index,(data,label) in enumerate(dataloader):print("index = %d num=%d"%(index,len(data )))

x=2*np.random.rand(100,1) 

  • np.random.rand(100,1):使用 NumPyrand 函数生成一个形状为 (100,1)(100,1)(100,1) 的随机数组,里面的数值均匀分布在 000 到 111 之间。

  • 2 * np.random.rand(100,1):将生成的数组乘以 2,使得数值范围扩展到 000 到 222 之间。

y=3+2*x+np.random.randn(100,1)*0.5 

np.random.randn(100,1) * 0.5:生成形状为 (100,1)(100,1)(100,1) 的随机噪声项,使 y 中的值带有一些波动。np.random.randn(100,1) 使用标准正态分布(均值为 0,标准差为 1)生成随机数,将其乘以 0.5 缩小标准差,使得噪声更小、波动更平滑。

np.random.rand 生成的随机数均匀分布在 [0,1),而 np.random.randn 生成的随机数服从标准正态分布,中心在 0。 

DataLoader(dataset, batch_size=20, shuffle=True)

  • DataLoaderPyTorch 中的一个类,用于将数据集分成小批量并进行迭代读取。这样可以有效地处理大量数据而不必一次性全部加载到内存中,特别是在训练深度学习模型时非常重要。
  • dataset

    • 这是要加载的数据集,即前面用 TensorDataset(x, y) 定义的 datasetDataLoader 将使用该数据集来加载数据。
  • batch_size=20

    • 设定每个小批量的大小为 20,意味着每次加载器会返回 20 个样本。
    • 在训练过程中,小批量(batch)数据能够加速模型的梯度计算,同时可以让模型在批量数据的平均梯度上进行更新,有助于稳定训练。
  • shuffle=True

    • 设置 shuffle=True 会在每个 epoch(轮次)开始前打乱数据集的顺序,以避免模型训练受样本顺序的影响,有助于提升模型的泛化能力。
    • 在训练时,数据的随机性能够帮助模型更好地学习到数据的真实分布,防止过拟合。

w = torch.randn(1, requires_grad=True)

        初始化了模型的权重参数 w,并启用了自动求导功能(requires_grad=True),表示 w 将在训练过程中计算其梯度。 尽管我们在定义时启用了 requires_grad=True,只是告诉 PyTorch 这个张量(比如 w)需要计算和记录梯度,但这并不会主动计算出梯度。实际上,梯度计算只在调用 loss.backward() 时才会触发

dataloader len=5
index = 0 num=20
index = 1 num=20
index = 2 num=20
index = 3 num=20
index = 4 num=20 

2.小批量梯度下降算法迭代 

#带迭代的参数w和b
w=torch.randn(1,requires_grad=True)
b=torch.randn(1,requires_grad=True)
#进入模型的迭代循环
for epoch in range(1,51):#迭代轮数#在一个迭代轮次中,以小批量的方式,使用dataloader对数据进行遍历#batch_idx表示当前遍历的批次#data和label表示这个批次的训练数据和标记for batch_idx,(data,label) in enumerate(dataloader):h=x*w+b#计算当前直线的预测值,保存到h#计算预测值h和真实值y之间的均方误差,保存到loss中loss=torch.mean((h-y)**2)loss.backward()#计算代价loss关于参数w和b的偏导数#进行梯度下降,沿着梯度下降的反方向,更新w和b的值w.data-=0.01*w.grad.datab.data-=0.01*b.grad.data#清空张量w和b中的梯度信息,为下一次迭代做准备w.grad.zero_()b.grad.zero_()#每次迭代,都打印当前迭代的轮数epoch#数据的批次batch_idx和loss损失值print("epoch (%d) batch (%d) loss=%.3lf"%(epoch,batch_idx,loss.item()))

for batch_idx, (data, label) in enumerate(dataloader):

  • enumerate(dataloader) 是一个迭代器,它会遍历 dataloader 并在每次迭代时返回当前批次的索引 batch_idx 和该批次的数据 (data, label)
  • dataloader 是由 DataLoader 创建的对象,负责将数据集 dataset 分割为小批量,以便模型可以逐批次读取数据进行训练

 

3.图像绘制 

#打印w和b的值,并绘制直线
print('w=%.3lf,b=%.3lf'%(w.item(),b.item()))
w=w.item()
b=b.item()
x=np.linspace(0,2,100)
h=w*x+b
plt.plot(x,h)
plt.show()

 

4.结果分析

        每次运行代码时返回的 wb 不一样,主要是由于以下几个原因:

  • 随机初始化:

w = torch.randn(1, requires_grad=True) b = torch.randn(1, requires_grad=True)

        这里的 torch.randn 会从标准正态分布(均值 0,标准差 1)中随机生成 wb 的初始值。每次运行代码时,wb 的初始值通常是不同的,这会导致训练过程中的更新路径不同,从而影响最终的值。

  • 数据中的随机噪声

y = 3 + 2 * x + np.random.randn(100, 1) * 0.5

        虽然设置了 np.random.seed(0),使得每次运行生成的 xy 都相同,但在模型初始化时 wb 是随机的,每次不同的初始 wb 会影响模型在不同批次上的更新路径,进而影响训练结果。

  • 小批量数据的随机顺序:

dataloader = DataLoader(dataset, batch_size=20, shuffle=True)

  DataLoadershuffle=True 参数会在每个 epoch 开始时随机打乱数据的顺序。每次运行代码时,小批量数据的顺序会不同,因此参数更新的路径也会不同。

 

 


http://www.mrgr.cn/news/70328.html

相关文章:

  • 【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
  • 【TEST】Apache JMeter + Influxdb + Grafana
  • 大模型系列11-ray
  • HashMap源码详解
  • listening comprehension
  • Excel求和如何过滤错误值
  • 铠侠代理商 | KIOXIA SLC闪存选型和应用
  • Java爬虫精准获得JD商品SKU信息
  • RobotFrameWork环境搭建及使用
  • Ubuntu 的 ROS 操作系统安装与测试
  • MySQL 基础
  • 【flask开启进程,前端内容图片化并转pdf-会议签到补充】
  • 01-SpringBoot3快速入门
  • 改进图卷积+informer时间序列预测代码
  • java XMLStreamConstants.CDATA 无法识别 <![CDATA[]]>
  • Verilog和VHDL有什么区别?
  • YOLO 网络的原理及发展史
  • 《Linux服务与安全管理》| 文件权限管理操作
  • 实时高效,全面测评快递100API的物流查询功能
  • 【K8S系列 】在K8S集群怎么查看各个pod占用的资源大小与详细解决方案【已解决】
  • 【工作技术栈】【arthas】arthas使用方式总结(诊断问题+方法执行)
  • 沃德云商协:助力多组织无障碍沟通与合作的平台
  • 2024年精选SaaS招聘系统平台汇总
  • gcc 1.c和g++ 1.c编译阶段有什么区别?如何知道g++编译默认会定义_GNU_SOURCE?
  • 2024MoonBit全球编程创新挑战赛参赛作品“飞翔的小鸟”技术开发指南
  • 模糊搜索:在不确定性中寻找精确结果