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

人工智能之深度学习_[4]-神经网络入门

文章目录

  • 神经网络基础
    • 1 神经网络
      • 1.1 神经网络概念
        • 1.1.1 什么是神经网络
        • 1.1.2 如何构建神经网络
        • 1.1.3 神经网络内部状态值和激活值
      • 1.2 激活函数
        • 1.2.1 网络非线性因素理解
        • 1.2.2 常见激活函数
          • 1.2.2.1 Sigmoid 激活函数
          • 1.2.2.2 Tanh 激活函数
          • 1.2.2.3 ReLU 激活函数
          • 1.2.2.4 SoftMax激活函数
        • 1.2.3 如何选择激活函数
      • 1.3 参数初始化
        • 1.3.1 常见参数初始化方法
        • 1.3.2 如何选择参数初始化
      • 1.4 神经网络搭建和参数计算
        • 1.4.1 构建神经网络
        • 1.4.2 观察数据形状变化
        • 1.4.3 模型参数计算
        • 1.4.4 查看模型参数
    • 2 损失函数
      • 2.1 损失函数概念
      • 2.2 分类任务损失函数
        • 2.2.1 多分类任务损失函数
        • 2.2.2 二分类任务损失函数
      • 2.3 回归任务损失函数
        • 2.3.1 MAE损失函数
        • 2.3.2 MSE损失函数
        • 2.3.3 Smooth L1损失函数

神经网络基础

1 神经网络

深度学习神经网络就是大脑仿生,数据从输入到输出经过一层一层的神经元产生预测值的过程就是前向传播(也叫正向传播)

前向传播涉及到人工神经元是如何工作的(也就是神经元的初始化、激活函数),神经网络如何搭建,权重参数计算、数据形如何状变化。千里之行始于足下,我们一起进入深度学习的知识海洋吧。

1.1 神经网络概念

1.1.1 什么是神经网络

人工神经网络(Artificial Neural Network, 简写为ANN)也简称为神经网络(NN),是一种模仿生物神经网络结构和功能的计算模型。它由多个互相连接的人工神经元(也称为节点)构成,可以用于处理和学习复杂的数据模式,尤其适合解决非线性问题。人工神经网络是机器学习中的一个重要模型,尤其在深度学习领域中得到了广泛应用。

人脑可以看做是一个生物神经网络,由众多的神经元连接而成。各个神经元传递复杂的电信号,树突接收到输入信号,然后对信号进行处理,通过轴突输出信号。下图是生物神经元示意图:

当电信号通过树突进入到细胞核时,会逐渐聚集电荷。达到一定的电位后,细胞就会被激活,通过轴突发出电信号。

1.1.2 如何构建神经网络

神经网络是由多个神经元组成,构建神经网络就是在构建神经元。以下是神经网络中神经元的构建说明:

这个流程就像,来源不同树突(树突都会有不同的权重)的信息, 进行的加权计算, 输入到细胞中做加和,再通过激活函数输出细胞值。

同一层的多个神经元可以看作是通过并行计算来处理相同的输入数据,学习输入数据的不同特征。每个神经元可能会关注输入数据中的不同部分,从而捕捉到数据的不同属性。

接下来,我们使用多个神经元来构建神经网络,相邻层之间的神经元相互连接,并给每一个连接分配一个强度,如下图所示:

神经网络中信息只向一个方向移动,即从输入节点向前移动,通过隐藏节点,再向输出节点移动。其中的基本部分是:

  1. 输入层(Input Layer): 即输入x的那一层(如图像、文本、声音等)。每个输入特征对应一个神经元。输入层将数据传递给下一层的神经元。
  2. 输出层(Output Layer): 即输出y的那一层。输出层的神经元根据网络的任务(回归、分类等)生成最终的预测结果。
  3. 隐藏层(Hidden Layers): 输入层和输出层之间都是隐藏层,神经网络的“深度”通常由隐藏层的数量决定。隐藏层的神经元通过加权和激活函数处理输入,并将结果传递到下一层。

特点是:

  • 同一层的神经元之间没有连接
  • 第N层的每个神经元和第N-1层的所有神经元相连(这就是Fully Connected的含义),这就是全连接神经网络(FCNN)
  • 全连接神经网络接收的样本数据是二维的,数据在每一层之间需要以二维的形式传递
  • 第N-1层神经元的输出就是第N层神经元的输入
  • 每个连接都有一个权重值(w系数和b系数)
1.1.3 神经网络内部状态值和激活值

每一个神经元工作时,前向传播会产生两个值,内部状态值(加权求和值)激活值反向传播时会产生激活值梯度内部状态值梯度

  • 内部状态值

    • 神经元或隐藏单元的内部存储值,它反映了当前神经元接收到的输入、历史信息以及网络内部的权重计算结果。
    • 每个输入 x i x_i xi都有一个与之相乘的权重 w i w_i wi,表示每个输入信号的重要性。
    • z=w⋅x+b
      • w:权重矩阵
      • x:输入值
      • b:偏置
  • 激活值

    • 通过激活函数(如 ReLU、Sigmoid、Tanh)对内部状态值进行非线性变换后得到的结果。激活值决定了当前神经元的输出。
    • a=f(z)
      • f:激活函数
      • z:内部状态值

通过控制每个神经元的内部状态值、激活值的大小;每一层的内部状态值的方差、每一层的激活值的方差可让整个神经网络工作的更好。

所以下面两个小结,我们将要学习神经元的激活函数,神经元的权重初始化。

1.2 激活函数

1.2.1 网络非线性因素理解
  • 没有引入非线性因素的网络等价于使用一个线性模型来拟合

  • 通过给网络输出增加激活函数, 实现引入非线性因素, 使得网络模型可以逼近任意函数, 提升网络对复杂问题的拟合能力

激活函数用于对每层的输出数据进行变换, 进而为整个网络注入了非线性因素。此时, 神经网络就可以拟合各种曲线。如果不使用激活函数,整个网络虽然看起来复杂,其本质还相当于一种线性模型,如下公式所示:

在这里插入图片描述

另外通过图像可视化的形式理解:

神经网络可视化

我们发现增加激活函数之后, 对于线性不可分的场景,神经网络的拟合能力更强。

1.2.2 常见激活函数

激活函数主要用来向神经网络中加入非线性因素,以解决线性模型表达能力不足的问题,它对神经网络有着极其重要的作用。我们的网络参数在更新时,使用的反向传播算法(BP),这就要求我们的激活函数必须可微。

1.2.2.1 Sigmoid 激活函数

激活函数公式:

激活函数求导公式:

在这里插入图片描述

sigmoid 激活函数的函数图像如下:

  • 从sigmoid函数图像可以得到,sigmoid 函数可以将任意的输入映射到 (0, 1) 之间,当输入的值大致在**<-6或者>6**时,意味着输入任何值得到的激活值都是差不多的,这样会丢失部分的信息。比如:输入100和输入10000经过 sigmoid的激活值几乎都是等于1的,但是输入的数据之间相差100倍的信息就丢失了。

  • 对于sigmoid函数而言,输入值在**[-6, 6]之间输出值才会有明显差异**,输入值在**[-3, 3]之间才会有比较好的效果**

  • 通过上述导数图像,我们发现导数数值范围是 (0, 0.25),当输入的值**<-6或者>6时,sigmoid激活函数图像的导数接近为 0**,此时网络参数将更新极其缓慢,或者无法更新。

  • 一般来说,sigmoid网络在5层之内就会产生梯度消失现象。而且,该激活函数的激活值并不是以0为中心的,激活值总是偏向正数,导致梯度更新时,只会对某些特征产生相同方向的影响,所以在实践中这种激活函数使用的很少。sigmoid函数一般只用于二分类的输出层

在 PyTorch中使用sigmoid函数的示例代码如下:

import torch
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号"""
绘制激活函数图像时出现以下提示,需要将anaconda3/Lib/site-packages/torch/lib目录下的libiomp5md.dll文件删除
OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.
"""# 创建画布和坐标轴
_, axes = plt.subplots(1, 2)# 函数图像
x = torch.linspace(-20, 20, 1000)
# 输入值x通过sigmoid函数转换成激活值y
y = torch.sigmoid(x)
axes[0].plot(x, y)
axes[0].grid()
axes[0].set_title('Sigmoid 函数图像')# 导数图像
x = torch.linspace(-20, 20, 1000, requires_grad=True)
torch.sigmoid(x).sum().backward()# x.detach():输入值x的ndarray数组
# x.grad:计算梯度,求导
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title('Sigmoid 导数图像')plt.show()
1.2.2.2 Tanh 激活函数

Tanh叫做双曲正切函数,其公式如下:

在这里插入图片描述

激活函数求导公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tanh的函数图像、导数图像如下:

  • 由上面的函数图像可以看到,Tanh函数将输入映射到(-1, 1)之间,图像以0为中心,激活值在0点对称,当输入的值大概**<-3或者>3** 时将被映射为-1或者1。其导数值范围 (0, 1),当输入的值大概**<-3或者>3**时,其导数近似0。

  • 与Sigmoid相比,它是以0为中心的,使得其收敛速度要比Sigmoid快,减少迭代次数。然而,从图中可以看出,Tanh两侧的导数也为0,同样会造成梯度消失。

  • 若使用时可在隐藏层使用tanh函数,在输出层使用sigmoid函数

在 PyTorch 中使用tanh函数的示例代码如下:

import torch
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号_, axes = plt.subplots(1, 2)# 函数图像
x = torch.linspace(-20, 20, 1000)
y = torch.tanh(x)
axes[0].plot(x, y)
axes[0].grid()
axes[0].set_title('Tanh 函数图像')# 导数图像
x = torch.linspace(-20, 20, 1000, requires_grad=True)
torch.tanh(x).sum().backward()axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title('Tanh 导数图像')plt.show()
1.2.2.3 ReLU 激活函数

ReLU 激活函数公式如下:

激活函数求导公式:

在这里插入图片描述

ReLU 的函数图像、导数图像如下:

  • ReLU 激活函数将小于0的值映射为0,而大于0的值则保持不变,它更加重视正信号,而忽略负信号,这种激活函数运算更为简单,能够提高模型的训练效率。
  • 当x<0时,ReLU导数为0,而当x>0时,则不存在饱和问题。所以,ReLU 能够在x>0时保持梯度不衰减,从而缓解梯度消失问题。然而,随着训练的推进,部分输入会落入小于0区域,导致对应权重无法更新。这种现象被称为“神经元死亡”。
  • ReLU是目前最常用的激活函数。与sigmoid相比,RELU的优势是:
    • 采用sigmoid函数,计算量大(指数运算),反向传播求误差梯度时,计算量相对大;而采用Relu激活函数,整个过程的计算量节省很多
    • sigmoid函数反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练;而采用relu激活函数,当输入的值>0时,梯度为1,不会出现梯度消失的情况
    • Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生

在 PyTorch 中使用ReLU函数的示例代码如下:

import torch
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号_, axes = plt.subplots(1, 2)# 函数图像
x = torch.linspace(-20, 20, 1000)
y = torch.relu(x)
axes[0].plot(x, y)
axes[0].grid()
axes[0].set_title('Tanh 函数图像')# 导数图像
x = torch.linspace(-20, 20, 1000, requires_grad=True)
torch.relu(x).sum().backward()axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title('Tanh 导数图像')plt.show()
1.2.2.4 SoftMax激活函数

softmax用于多分类过程中,它是二分类函数sigmoid在多分类上的推广,目的是将多分类的结果以概率的形式展现出来

计算方法如下图所示:

SoftMax就是将网络输出的logits通过softmax函数,映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们将它理解成概率,选取概率最大(也就是值对应最大的)节点,作为我们的预测目标类别。

在 PyTorch 中使用SoftMax函数的示例代码如下:

import torchscores = torch.tensor([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75])
# dim=0, 按行计算
probabilities = torch.softmax(scores, dim=0)
print(probabilities)

程序输出结果:

tensor([0.0212, 0.0177, 0.0202, 0.0202, 0.0638, 0.0287, 0.0185, 0.0522, 0.0183,0.7392])
1.2.3 如何选择激活函数

除了上述的激活函数,还存在很多其他的激活函数,如下图所示:
>

对于隐藏层:

  1. 优先选择ReLU激活函数
  2. 如果ReLu效果不好,那么尝试其他激活,如Leaky ReLu等。
  3. 如果你使用了ReLU, 需要注意一下Dead ReLU问题,避免出现0梯度从而导致过多的神经元死亡。
  4. 少使用sigmoid激活函数,可以尝试使用tanh激活函数

对于输出层:

  1. 二分类问题选择sigmoid激活函数
  2. 多分类问题选择softmax激活函数
  3. 回归问题选择identity激活函数

1.3 参数初始化

我们在构建网络之后,网络中的参数是需要初始化的。我们需要初始化的参数主要有权重偏置偏置一般初始化为0即可,而对权重的初始化则会更加重要。

参数初始化的作用:

  • 防止梯度消失或爆炸:初始权重值过大或过小会导致梯度在反向传播中指数级增大或缩小。
  • 提高收敛速度:合理的初始化使得网络的激活值分布适中,有助于梯度高效更新。
  • 保持对称性破除:权重的初始化需要打破对称性,否则网络的学习能力会受到限制。
1.3.1 常见参数初始化方法
  • 随机初始化

    • 均匀分布初始化:权重参数初始化从区间均匀随机取值,默认区间为(0,1)。可以设置为在(- 1 d 1\over\sqrt{d} d 1, 1 d 1\over\sqrt{d} d 1)均匀分布中生成当前神经元的权重,其中d为神经元的输入数量。

    • 正态分布初始化:随机初始化从均值为0,标准差是1的高斯分布中取样,使用一些很小的值对参数W进行初始化

    • 优点:能有效打破对称性

    • 缺点:随机选择范围不当可能导致梯度问题

    • 适用场景:浅层网络或低复杂度模型。隐藏层1-3层,总层数不超过5层。

  • 全0初始化:将神经网络中的所有权重参数初始化为0

    • 优点:实现简单
    • 缺点:无法打破对称性,所有神经元更新方向相同,无法有效训练
    • 适用场景:几乎不使用,仅用于偏置项的初始化
  • 全1初始化:将神经网络中的所有权重参数初始化为1

    • 优点:实现简单
    • 缺点
      • 无法打破对称性,所有神经元更新方向相同,无法有效训练
      • 会导致激活值在网络中呈指数增长,容易出现梯度爆炸
    • 适用场景
      • 测试或调试:比如验证神经网络是否能正常前向传播和反向传播
      • 特殊模型结构:某些稀疏网络或特定的自定义网络中可能需要手动设置部分参数为1
      • 偏置初始化:偶尔可以将偏置初始化为小的正值(如 0.1),但很少用1作为偏置的初始值
  • 固定值初始化:将神经网络中的所有权重参数初始化为某个固定值

    • 优点:实现简单
    • 缺点
      • 无法打破对称性,所有神经元更新方向相同,无法有效训练
      • 初始权重过大或过小可能导致梯度爆炸或梯度消失
    • 适用场景
      • 测试或调试
  • kaiming初始化,也叫做HE初始化:专为ReLU和其变体设计,考虑到ReLU激活函数的特性,对输入维度进行缩放

    • HE初始化分为正态分布的HE初始化、均匀分布的HE初始化
      • 正态分布的he初始化
        • w权重值从均值为0, 标准差为std中随机采样,std = sqrt(2 / fan_in)
        • std值越大,w权重值离均值0分布相对较广,计算得到的内部状态值有较大的正值或负值
      • 均匀分布的he初始化
        • 它从[-limit,limit] 中的均匀分布中抽取样本, limitsqrt(6 / fan_in)
      • fan_in 输入神经元的个数,当前层接受的来自上一层的神经元的数量。简单来说,就是当前层接收多少个输入
    • 优点:适合 ReLU,能保持梯度稳定
    • 缺点:对非 ReLU 激活函数效果一般
    • 适用场景:深度网络(10层及以上),使用 ReLU、Leaky ReLU 激活函数
  • xavier初始化,也叫做Glorot初始化:根据网络输入和输出的维度自动选择权重范围,使输入和输出的方差相同

    • xavier初始化分为正态分布的xavier初始化、均匀分布的xavier初始化

      • 正态化的Xavier初始化
        • w权重值从均值为0, 标准差为std中随机采样,std = sqrt(2 / (fan_in + fan_out))
        • std值越小,w权重值离均值0分布相对集中,计算得到的内部状态值有较小的正值或负值
      • 均匀分布的Xavier初始化
        • [-limit,limit] 中的均匀分布中抽取样本, limit 是 sqrt(6 / (fan_in + fan_out))
      • fan_in 是输入神经元个数,当前层接受的来自上一层的神经元的数量。简单来说,就是当前层接收多少个输入
      • fan_out 是输出神经元个数,当前层输出的神经元的数量,也就是当前层会传递给下一层的神经元的数量。简单来说,就是当前层会产生多少个输出。
    • 优点:适用于Sigmoid、Tanh 等激活函数,解决梯度消失问题

    • 缺点:对 ReLU 等激活函数表现欠佳

    • 适用场景:深度网络(10层及以上),使用 Sigmoid 或 Tanh 激活函数

import torch.nn as nn# 1. 均匀分布随机初始化
def test01():linear = nn.Linear(5, 3)# 从0-1均匀分布产生参数nn.init.uniform_(linear.weight)nn.init.uniform_(linear.bias)print(linear.weight.data)# 2. 固定初始化
def test02():linear = nn.Linear(5, 3)nn.init.constant_(linear.weight, 5)print(linear.weight.data)# 3. 全0初始化
def test03():linear = nn.Linear(5, 3)nn.init.zeros_(linear.weight)print(linear.weight.data)# 4. 全1初始化
def test04():linear = nn.Linear(5, 3)nn.init.ones_(linear.weight)print(linear.weight.data)# 5. 正态分布随机初始化
def test05():linear = nn.Linear(5, 3)nn.init.normal_(linear.weight, mean=0, std=1)print(linear.weight.data)# 6. kaiming 初始化
def test06():# kaiming 正态分布初始化linear = nn.Linear(5, 3)nn.init.kaiming_normal_(linear.weight)print(linear.weight.data)# kaiming 均匀分布初始化linear = nn.Linear(5, 3)nn.init.kaiming_uniform_(linear.weight)print(linear.weight.data)# 7. xavier 初始化
def test07():# xavier 正态分布初始化linear = nn.Linear(5, 3)nn.init.xavier_normal_(linear.weight)print(linear.weight.data)# xavier 均匀分布初始化linear = nn.Linear(5, 3)nn.init.xavier_uniform_(linear.weight)print(linear.weight.data)
1.3.2 如何选择参数初始化
  • 激活函数的选择:根据激活函数的类型选择对应的初始化方法

    • Sigmoid/Tanh:xavier 初始化
    • ReLU/Leaky ReLU:kaiming 初始化
  • 神经网络模型的深度

    • 浅层网络:随机初始化即可
    • 深层网络:需要考虑方差平衡,如 xavier 或 kaiming 初始化

1.4 神经网络搭建和参数计算

1.4.1 构建神经网络

在pytorch中定义深度神经网络其实就是层堆叠的过程,继承自nn.Module,实现两个方法:

  • __init__方法中定义网络中的层结构,主要是全连接层,并进行初始化
  • forward方法,在实例化模型的时候,底层会自动调用该函数。该函数中为初始化定义的layer传入数据,进行前向传播等。

接下来我们来构建如下图所示的神经网络模型:

编码设计如下:

  • 第1个隐藏层:权重初始化采用标准化的xavier初始化 激活函数使用sigmoid
  • 第2个隐藏层:权重初始化采用标准化的He初始化 激活函数采用relu
  • out输出层线性层 假若多分类,采用softmax做数据归一化

构造神经网络模型代码:

import torch
import torch.nn as nn
from torchsummary import summary  # 计算模型参数,查看模型结构, pip install torchsummary -i https://mirrors.aliyun.com/pypi/simple/# 创建神经网络模型类
class Model(nn.Module):# 初始化属性值def __init__(self):# 调用父类的初始化属性值super(Model, self).__init__()# 创建第一个隐藏层模型, 3个输入特征,3个输出特征self.linear1 = nn.Linear(3, 3)# 初始化权重nn.init.xavier_normal_(self.linear1.weight)nn.init.zeros_(self.linear1.bias)# 创建第二个隐藏层模型, 3个输入特征(上一层的输出特征),2个输出特征self.linear2 = nn.Linear(3, 2)# 初始化权重nn.init.kaiming_normal_(self.linear2.weight, nonlinearity='relu')nn.init.zeros_(self.linear2.bias)# 创建输出层模型self.out = nn.Linear(2, 2)# 创建前向传播方法,自动执行forward()方法def forward(self, x):# 数据经过第一个线性层x = self.linear1(x)# 使用sigmoid激活函数x = torch.sigmoid(x)# 数据经过第二个线性层x = self.linear2(x)# 使用relu激活函数x = torch.relu(x)# 数据经过输出层x = self.out(x)# 使用softmax激活函数# dim=-1:每一维度行数据相加为1x = torch.softmax(x, dim=-1)return x

训练神经网络模型代码:

# 创建构造模型函数
def train():# 实例化model对象my_model = Model()# 随机产生数据my_data = torch.randn(5, 3)print("my_data-->", my_data)print("my_data shape", my_data.shape)# 数据经过神经网络模型训练output = my_model(my_data)print("output-->", output)print("output shape-->", output.shape)# 计算模型参数# 计算每层每个神经元的w和b个数总和print("======计算模型参数======")summary(my_model, input_size=(3,), batch_size=5)# 查看模型参数print("======查看模型参数w和b======")for name, parameter in my_model.named_parameters():print(name, parameter)if __name__ == '__main__':train()
1.4.2 观察数据形状变化
  • 观察程序输入和输出的数据形状变化

    • 输入5行数据,输出也是5行数据
    • 输入5行数据3个特征,经过第一个隐藏层是3个特征,经过第二个隐藏层是2个特征,经过输出层是2个特征
    • 模型最终预测结果是:5行2列数据
    mydata.shape---> torch.Size([5, 3])
    output.shape---> torch.Size([5, 2])
    mydata--->tensor([[-0.3714, -0.8578, -1.6988],[ 0.3149,  0.0142, -1.0432],[ 0.5374, -0.1479, -2.0006],[ 0.4327, -0.3214,  1.0928],[ 2.2156, -1.1640,  1.0289]])
    output--->tensor([[0.5095, 0.4905],[0.5218, 0.4782],[0.5419, 0.4581],[0.5163, 0.4837],[0.6030, 0.3970]], grad_fn=<SoftmaxBackward>)
    
1.4.3 模型参数计算
  • 模型参数的计算

    • 以第一个隐层为例:该隐层有3个神经元,每个神经元的参数为:4个(w1,w2,w3,b1),所以一共用3x4=12个参数。

    • 输入数据和网络权重是两个不同的事儿!对于初学者理解这一点十分重要,要分得清。

    ----------------------------------------------------------------Layer (type)               Output Shape         Param #
    ================================================================Linear-1                     [5, 3]              12Linear-2                     [5, 2]               8Linear-3                     [5, 2]               6
    ================================================================
    Total params: 26
    Trainable params: 26
    Non-trainable params: 0
    ----------------------------------------------------------------
    Input size (MB): 0.00
    Forward/backward pass size (MB): 0.00
    Params size (MB): 0.00
    Estimated Total Size (MB): 0.00
    ----------------------------------------------------------------
    
1.4.4 查看模型参数
  • 通常继承nn.Module,撰写自己的网络层。它强大的封装不需要我们定义可学习的参数(比如卷积核的权重和偏置参数)。

  • 如何才能查看封装好的,可学习的网络参数哪?

    • 模块实例名.name_parameters(),会分别返回name和parameter
    # 实例化model对象
    mymodel = Model()# 查看网络参数
    for name, parameter in mymodel.named_parameters():# print('name--->', name)# print('parameter--->', parameter)print(name, parameter)
    

    结果显示

    linear1.weight Parameter containing:
    tensor([[ 0.1715, -0.3711,  0.1692],[-0.2497, -0.6156, -0.4235],[-0.7090, -0.0380,  0.4790]], requires_grad=True)
    linear1.bias Parameter containing:
    tensor([-0.2320,  0.3431,  0.2771], requires_grad=True)
    linear2.weight Parameter containing:
    tensor([[-0.5044, -0.7435, -0.6736],[ 0.6908, -0.1466, -0.0019]], requires_grad=True)
    linear2.bias Parameter containing:
    tensor([0.2340, 0.4730], requires_grad=True)
    out.weight Parameter containing:
    tensor([[ 0.5185,  0.4019],[-0.4313, -0.3438]], requires_grad=True)
    out.bias Parameter containing:
    tensor([ 0.4521, -0.6339], requires_grad=True)
    

2 损失函数

2.1 损失函数概念

在深度学习中, 损失函数是用来衡量模型参数质量的函数, 衡量的方式是比较网络输出(预测值)和真实输出(真实值)的差异。

模型通过最小化损失函数的值来调整参数,使其输出更接近真实值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

损失函数在不同的文献中名称是不一样的,主要有以下几种命名方式

损失函数作用:

  • 评估性能:反映模型预测结果与目标值的匹配程度。
  • 指导优化:通过梯度下降等算法最小化损失函数,优化模型参数。

2.2 分类任务损失函数

在深度学习的分类任务中使用最多的是交叉熵损失函数,所以在这里我们着重介绍这种损失函数。

2.2.1 多分类任务损失函数

在多分类任务通常使用softmax将logits转换为概率的形式,所以多分类的交叉熵损失也叫做softmax损失,它的计算方法是:

其中:

  • yi是样本x属于某一个类别的真实概率
  • 而f(x)是样本属于某一类别的预测分数
  • S是softmax激活函数,将属于某一类别的预测分数转换成概率
  • L用来衡量真实值y和预测值f(x)之间差异性的损失结果

例子:

上图中的交叉熵损失为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从概率角度理解,我们的目的是最小化正确类别所对应的预测概率的对数的负值(损失值最小),如下图所示:

在PyTorch中使用nn.CrossEntropyLoss()实现,如下所示:

import torch
from torch import nn# 分类损失函数:交叉熵损失使用nn.CrossEntropyLoss()实现。nn.CrossEntropyLoss()=softmax + 损失计算
def test01():# 设置真实值: 可以是热编码后的结果也可以不进行热编码# y_true = torch.tensor([[0, 1, 0], [0, 0, 1]], dtype=torch.float32)# 注意的类型必须是64位整型数据y_true = torch.tensor([1, 2], dtype=torch.int64)y_pred = torch.tensor([[0.2, 0.6, 0.2], [0.1, 0.8, 0.1]], requires_grad=True, dtype=torch.float32)# 实例化交叉熵损失,默认求平均损失# reduction='sum':总损失loss = nn.CrossEntropyLoss()# 计算损失结果my_loss = loss(y_pred, y_true).detach().numpy()print('loss:', my_loss)
2.2.2 二分类任务损失函数

在处理二分类任务时,我们不再使用softmax激活函数,而是使用sigmoid激活函数,那损失函数也相应的进行调整,使用二分类的交叉熵损失函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中:

  • y是样本x属于某一个类别的真实概率

  • 而y^是样本属于某一类别的预测概率

  • L用来衡量真实值y与预测值y^之间差异性的损失结果。

在PyTorch中实现时使用nn.BCELoss() 实现,如下所示:

import torch
from torch import nndef test02():# 1 设置真实值和预测值# 预测值是sigmoid输出的结果y_pred = torch.tensor([0.6901, 0.5459, 0.2469], requires_grad=True)y_true = torch.tensor([0, 1, 0], dtype=torch.float32)# 2 实例化二分类交叉熵损失loss = nn.BCELoss()# 3 计算损失my_loss = loss(y_pred, y_true).detach().numpy()print('loss:', my_loss)

2.3 回归任务损失函数

2.3.1 MAE损失函数

**Mean absolute loss(MAE)**也被称为L1 Loss,是以绝对误差作为距离

损失函数公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

曲线如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特点是:

  • 由于L1 loss具有稀疏性,为了惩罚较大的值,因此常常将其作为正则项添加到其他loss中作为约束。((0点不可导, 产生稀疏矩阵))
  • L1 loss的最大问题是梯度在零点不平滑,导致会跳过极小值
  • 适用于回归问题中存在异常值或噪声数据时,可以减少对离群点的敏感性

在PyTorch中使用nn.L1Loss()实现,如下所示:

import torch
from torch import nn# 计算inputs与target之差的绝对值
def test03():# 1 设置真实值和预测值y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)# 2 实例MAE损失对象loss = nn.L1Loss()# 3 计算损失my_loss = loss(y_pred, y_true).detach().numpy()print('loss:', my_loss)
2.3.2 MSE损失函数

**Mean Squared Loss/ Quadratic Loss(MSE loss)**也被称为L2 loss,或欧氏距离,它以误差的平方和的均值作为距离

损失函数公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

曲线如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特点是:

  • L2 loss也常常作为正则项,对于离群点(outliers)敏感,因为平方项会放大大误差

  • 当预测值与目标值相差很大时, 梯度容易爆炸

    • 梯度爆炸:网络层之间的梯度(值大于 1.0)重复相乘导致的指数级增长会产生梯度爆炸
  • 适用于大多数标准回归问题,如房价预测、温度预测等

在PyTorch中通过nn.MSELoss()实现:

import torch
from torch import nndef test04():# 1 设置真实值和预测值y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)# 2 实例MSE损失对象loss = nn.MSELoss()# 3 计算损失my_loss = loss(y_pred, y_true).detach().numpy()print('myloss:', my_loss)
2.3.3 Smooth L1损失函数

smooth L1说的是光滑之后的L1,是一种结合了均方误差(MSE)和平均绝对误差(MAE)优点的损失函数。它在误差较小时表现得像 MSE,在误差较大时则更像 MAE。

Smooth L1损失函数如下式所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中:𝑥=f(x)−y 为真实值和预测值的差值。

从上图中可以看出,该函数实际上就是一个分段函数

  • 在[-1,1]之间实际上就是L2损失,这样解决了L1的不光滑问题
  • 在[-1,1]区间外,实际上就是L1损失,这样就解决了离群点梯度爆炸的问题

特点是:

  • 对离群点更加鲁棒:当误差较大时,损失函数会线性增加(而不是像MSE那样平方增加),因此它对离群点的惩罚更小,避免了MSE对离群点过度敏感的问题

  • 计算梯度时更加平滑:与MAE相比,Smooth L1在小误差时表现得像MSE,避免了在训练过程中因使用绝对误差而导致的梯度不连续问题

在PyTorch中使用nn.SmoothL1Loss()计算该损失,如下所示:

import torch
from torch import nndef test05():# 1 设置真实值和预测值y_true = torch.tensor([0, 3])y_pred = torch.tensor([0.6, 0.4], requires_grad=True)# 2 实例smmothL1损失对象loss = nn.SmoothL1Loss()# 3 计算损失my_loss = loss(y_pred, y_true).detach().numpy()print('loss:', my_loss)

相关文章:

人工智能之深度学习_[4]-神经网络入门

文章目录 神经网络基础1 神经网络1.1 神经网络概念1.1.1 什么是神经网络1.1.2 如何构建神经网络1.1.3 神经网络内部状态值和激活值 1.2 激活函数1.2.1 网络非线性因素理解1.2.2 常见激活函数1.2.2.1 Sigmoid 激活函数1.2.2.2 Tanh 激活函数1.2.2.3 ReLU 激活函数1.2.2.4 SoftMa…...

ASP.NET Blazor部署方式有哪些?

今天我们来说说Blazor的三种部署方式&#xff0c;如果大家还不了解Blazor&#xff0c;那么我先简单介绍下Blazor Blazor 是一种 .NET 前端 Web 框架&#xff0c;在单个编程模型中同时支持服务器端呈现和客户端交互性&#xff1a; ● 使用 C# 创建丰富的交互式 UI。 ● 共享使用…...

Cyber Security 101-Security Solutions-Firewall Fundamentals(防火墙基础)

了解防火墙并亲身体验 Windows 和 Linux 内置防火墙。 任务1&#xff1a;防火墙的用途是什么 我们看到商场、银行、 餐馆和房屋。这些警卫被安置在 这些区域用于检查进出人员。这 维护此检查的目的是确保没有人在没有 被允许。这个警卫充当了他所在区域和访客之间的一堵墙。 …...

本地仓库管理之当前分支内的操作

以刚搭建好的git仓库为例&#xff0c;刚搭建完的仓库只有master分支&#xff0c;使用git branch查看当前的分支情况。 elfubuntu:~/work/example/hello$ git branch *所在分支为当前分支&#xff0c;即master分支 当前分支进行源码修改时简单流程图如下&#xff1a; 在当前分…...

【Unity3D】3D物体摆放、场景优化案例Demo

目录 PlaceManager.cs(放置管理类) Ground.cs(地板类) 和 GroundData.cs(地板数据类) 额外知识点说明 1、MeshFilter和MeshRenderer的Bounds区别 2、Gizmos 绘制一个平行于斜面的立方体 通过网盘分享的文件&#xff1a;PlaceGameDemo2.unitypackage 链接: https://pan.baid…...

ORACLE 12C开启EM EXPRESS过程

1 首先启动监听和关闭ORACLE/LINUX防火墙&#xff08;这一步略过&#xff09; lsnrctl start 2 然后查看http和https端口 select dbms_xdb_config.gethttpsport() from dual; select dbms_xdb_config.gethttpport() from dual; 3 设置em端口 exec dbms_xdb_config.setHTTPSPo…...

JavaScript学习笔记(1)

html 完成了架子&#xff0c; css 做了美化&#xff0c;但是网页是死的&#xff0c;我们需要给他注入灵魂&#xff0c;所以接下来我们需要学习 JavaScript&#xff0c;这门语言会让我们的页面能够和用户进行交互。 一、引入方式 1.内部脚本 将 JS 代码定义在 HTML 页面中 Jav…...

【PCL】Segmentation 模块—— 欧几里得聚类提取(Euclidean Cluster Extraction)

1、简介 PCL 的 Euclidean Cluster Extraction&#xff08;欧几里得聚类提取&#xff09; 是一种基于欧几里得距离的点云聚类算法。它的目标是将点云数据分割成多个独立的簇&#xff08;clusters&#xff09;&#xff0c;每个簇代表一个独立的物体或结构。该算法通过计算点与点…...

CMake技术细节:解决未定义,提供参数

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…...

BUUCTF_Web(October 2019 Twice SQL injection)

October 2019 Twice SQL injection 知识点&#xff1a; 二次注入&#xff1a; 当用户提交的恶意数据被存入数据库后&#xff0c;应用程序再把它读取出来用于生成新的SQL语句时&#xff0c;如果没有相应的安全措施&#xff0c;是有可能发生SQL注入的&#xff0c;这种注入就叫…...

CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法

下载软件时出现以下问题 直接把CentOS-AppStream.repo改个名字就行 cd /etc/yum.repos.d/ mv CentOS-AppStream.repo CentOS-AppStream.repo.bak就可以了 解决思路 把AI问遍&#xff0c;无人会&#xff0c;解决法 想要下载软件通通失败了&#xff0c;解决方法当然是问AI&am…...

LeetCode 2661. First Completely Painted Row or Column

&#x1f517; https://leetcode.com/problems/first-completely-painted-row-or-column 题目 给一个 m*n 的二维数组&#xff0c;给一个 arr 的一纬数组元素由 [1, m * n] 组成遍历 arr&#xff0c;对二维数组中对应的元素进行染色返回执行到 arr 的第几个 index 的时候&…...

git的安装

目录 下载 安装 下载 前往官网下载安装包Git 点击dowmload选择适合自己的版本 安装 next 全选 是否修改库名&#xff0c;默认master 使用默认的 使用默认的 配置实验选项&#xff08;新功能&#xff0c;可以不选&#xff09; 不点 最后安装在d盘&#xff0c;programfile…...

C#性能优化技巧:利用Lazy<T>实现集合元素的延迟加载

一、C#中的Lazy C#中的Lazy<T>是一个泛型类&#xff0c;它实现了延迟加载&#xff08;Lazy Initialization&#xff09;的功能。延迟加载是指对象的创建被推迟&#xff0c;直到第一次被使用时才进行实例化。这对于大型或资源密集型对象的性能优化非常有用&#xff0c;因…...

Jenkins-基于Role的鉴权机制

jenkins自带了一些全局性的安全配置。 但无法通过job等相对细粒度的来控制使用者的权限。但它可以借助相关的插件实现细颗粒的权限控制。 插件&#xff1a; Role-based Authorization Strategy 需要在configure global security中配置授权策略如下&#xff1a; 保存后&#x…...

Python 并发编程的终极武器:使用 `multiprocessing` 模块征服计算密集型任务

Python 并发编程的终极武器:使用 multiprocessing 模块征服计算密集型任务 在Python中,由于全局解释器锁(GIL)的存在,多线程在处理CPU密集型任务时并不能真正实现并行,而是以交替执行的方式模拟并发,效率提升有限。为了充分利用多核CPU的优势,我们需要使用多进程。mul…...

vscode如何选用不同的python的解释器

在 VS Code 中设置 Python 的运行环境需要以下几个步骤&#xff0c;具体配置取决于你的开发环境和需求&#xff1a; 1. 安装必要工具 安装 Python&#xff1a; 确保已在系统中安装 Python&#xff08;推荐通过 Python 官方网站 安装&#xff09;。安装 VS Code 和 Python 扩展…...

MyBatis 注解开发详解

MyBatis 注解开发详解 MyBatis 支持使用注解来进行数据库操作。注解方式将 SQL 语句直接写在 Java 接口中&#xff0c;通过注解来完成 CRUD&#xff08;增删改查&#xff09;操作&#xff0c;省去了使用 XML 配置的繁琐步骤。这种方式适合简单项目或快速原型开发&#xff0c;因…...

【动态规划】--- 斐波那契数模型

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey &#x1f3e0; 第N个泰波那契数模型 &#x1f4cc; 题目解析 第N个泰波那契数 题目要求的是泰波那契数&#xff0c;并非斐波那契数。 &…...

【EdgeAI实战】(1)STM32 边缘 AI 生态系统

【EdgeAI实战】&#xff08;1&#xff09;STM32 边缘 AI 生态系统 【EdgeAI实战】&#xff08;1&#xff09;STM32 边缘 AI 生态系统 1. STM32 边缘人工智能1.1 X-CUBE-AI 扩展包1.2 STM32 AI Model Zoo1.3 ST AIoT Craft 2. STM32N6 AI 生态系统 (STM32N6-AI)2.1 STM32N6 AI 产…...

【陕西省乡镇界】面图层shp格式arcgis数据乡镇名称和编码2020年wgs84坐标无偏移内容测评

标题中的“陕西省乡镇界面图层shp格式arcgis数据乡镇名称和编码2020年wgs84坐标无偏移.zip”表明这是一个地理信息系统&#xff08;GIS&#xff09;的数据集&#xff0c;专为陕西省的乡镇区域设计。该数据集以Shapefile&#xff08;shp&#xff09;格式提供&#xff0c;是GIS领…...

Fabric区块链网络搭建:保姆级图文详解

目录 前言1、项目环境部署1.1 基础开发环境1.2 网络部署 2、后台环境2.1、环境配置2.2、运行springboot项目 3、PC端3.1、安装依赖3.2、修改区块链网络连接地址3.3、启动项目 前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加…...

HTML 表单和输入标签详解

HTML 表单是网页与用户交互的重要工具&#xff0c;它允许用户输入数据并将其提交到服务器。表单在网页中的应用非常广泛&#xff0c;例如登录、注册、搜索、评论等功能都离不开表单。本文将详细介绍 HTML 表单及其相关标签的使用方法&#xff0c;帮助你全面掌握表单的设计与实现…...

sql实战解析-sum()over(partition by xx order by xx)

该窗口函数功能 sum( c )over( partition by a order by b) 按照一定规则汇总c的值&#xff0c;具体规则为以a分组&#xff0c;每组内按照b进行排序&#xff0c;汇总第一行至当前行的c的加和值。 从简单开始一步一步讲&#xff0c; 1、sum( )over( ) 对所有行进行求和 2、sum(…...

Vue平台开发三——项目管理页面

前言 对于多个项目的使用&#xff0c;可能需要进行项目切换管理&#xff0c;所以这里创建一个项目管理页面&#xff0c;登录成功后跳转这个页面&#xff0c;进行选择项目&#xff0c;再进入Home页面展示对应项目的内容。 一、实现效果图预览 二、页面内容 功能1、项目列表展…...

JDBC实验测试

一、语言和环境 实现语言&#xff1a;Java。 环境要求&#xff1a;IDEA2023.3、JDK 17 、MySQL8.0、Navicat 16 for MySQL。 二、技术要求 该系统采用 SWING 技术配合 JDBC 使用 JAVA 编程语言完成桌面应用开发。 三、功能要求 某电商公司为了方便客服查看用户的订单信…...

使用 vllm 部署 MiniCPM-o 2.6

使用 vllm 部署MiniCPM-o 2.6 1. 创建虚拟环境2. 克隆代码3. 从代码安装 vllm4. 安装 flash-attn5. 启动 MiniCPM-o 2.66. 使用 chatbox 客户端访问并测试一下 1. 创建虚拟环境 conda create -n vllm_openbmb python3.11 -y conda activate vllm_openbmb 2. 克隆代码 git clo…...

WSL 2 自动更新 虚拟 IP 到 window hosts

window下的wsl2 开发中使用到 域名映射&#xff0c;但是WSL2 每次启动都会被分配一个虚拟的 ip 地址&#xff0c;每次启动虚拟ip 都不一样&#xff0c;导致要频繁 更改 window 的 hosts 文件&#xff0c;太麻烦了&#xff0c;所以写一个自动执行的 .sh 脚本&#xff0c;每次启动…...

非常棒的长文本输入大模型:MiniMax以及基于它的海螺AI模型

非常棒的长文本输入大模型&#xff1a;基于MiniMax的海螺AI模型&#xff0c;快来体验一下吧&#xff01; 海螺AI—MiniMax 旗下生产力产品&#xff0c;你的AI伙伴&#xff0c;10倍速提升工作学习效率 这个大模型最大的特点就是支持长文本输入&#xff0c;而且是从内部就擅长对长…...

python milvus及curl命令进行query请求

代码如下: from pymilvus import MilvusClient client = MilvusClient( uri="http://localhost:19530", token="root:Milvus" ) res = client.query( collection_name="query_collection", filter="color like \"…...

谈谈MySQL中的索引和事务

目录 1. 索引 1.1 索引介绍 1.2 缺陷 1.3 使用 1.3.1 查看索引 1.3.2 创建索引 1.3.3 删除索引 2. 索引底层的数据结构 2.1 B树 3. 事务 3.1 为什么使用事务 3.2 事务的使用 3.3 事务的基本特性 1. 索引 1.1 索引介绍 索引相当于一本书的目录(index), 在一…...

Java 资源管理教程:掌握 close 方法、Cleaner 类与 Runtime.addShutdownHook

在 Java 编程中&#xff0c;高效地管理资源是至关重要的&#xff0c;特别是当你处理文件、数据库连接、网络连接等有限资源时。为了确保这些资源得到正确释放&#xff0c;Java 提供了多种机制。本教程将深入探讨 close 方法、Cleaner类以及 Runtime.addShutdownHook 方法&#…...

tensorflow源码编译在C++环境使用

https://tensorflow.google.cn/install/source?hlzh-cn查看tensorflow和其他需要下载软件对应的版本&#xff0c;最好一模一样 1、下载TensorFlow源码 https://github.com/tensorflow/tensorflow 2、安装编译protobuf&#xff08;3.9.2&#xff09; protobuf版本要和TensorFlo…...

算法日记8:StarryCoding60(单调栈)

一、题目 二、解题思路&#xff1a; 题意为让我们找到每个元素的左边第一个比它小的元素&#xff0c;若不存在则输出-1 2.1法一&#xff1a;暴力&#xff08;0n2&#xff09; 首先&#xff0c;我们可以想到最朴素的算法&#xff1a;直接暴力两层for达成目标核心代码如下&…...

HarmonyOS快速入门

HarmonyOS快速入门 1、基本概念 UI框架&#xff1a; HarmonyOS提供了一套UI开发框架&#xff0c;即方舟开发框架&#xff08;ArkUI框架&#xff09;。方舟开发框架可为开发者提供应用UI开发所必需的能力&#xff0c;比如多种组件、布局计算、动画能力、UI交互、绘制等。 方…...

基于微信小程序高校订餐系统的设计与开发ssm+论文源码调试讲解

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…...

stm32使用MDK5.35时遇到*** TOOLS.INI: TOOLCHAIN NOT INSTALLED

mdk5.35出现*** TOOLS.INI: TOOLCHAIN NOT INSTALLED的问题&#xff01;&#xff01;&#xff01;&#xff01; 以管理员身份重新打开MDK5.35.0.0&#xff0c;用keygen破解密码&#xff0c;但是一直提示我是没有破解成功。 解决办法&#xff1a; target 改成ARM...

Java面试专题——常见面试题1

引入 本文属于专题中的常见面试题模块&#xff0c;属于面试时经常遇到的&#xff0c;适合需要面试的小伙伴做面试前复习准备用&#xff0c;后续会持续补充 1.面向对象基本特征 面向对象的基本特征是什么&#xff1f;怎么理解&#xff1f; 面向对象的基本特征是封装、继承、…...

【C++】在线五子棋对战项目网页版

目录 1.Websocket 1.1.Websocket的简单认识 1.2.什么是轮询呢&#xff1f; 1.3.websocket协议切换过程 1.4.websocketpp库常用接口认识 1.5.websocketpp库搭建服务器流程 1.6.websocketpp库搭建服务器 2.mysqlclient库-接口认识 3.项目模块的划分&#xff1a; 4.项目…...

【Docker】搭建一个功能强大的自托管虚拟浏览器 - n.eko

前言 本教程基于群晖的NAS设备DS423的docker功能进行搭建&#xff0c;DSM版本为 DSM 7.2.2-72806 Update 2。 n.eko 支持多种类型浏览器在其虚拟环境中运行&#xff0c;本次教程使用 Chromium​ 浏览器镜像进行演示&#xff0c;支持访问内网设备和公网地址。 简介 n.eko 是…...

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证7)

本文验证基于请求头中传递token信息的认证方式&#xff0c;webapi项目的控制器类中新建如下函数&#xff0c;仅通过验证的客户端能调用&#xff0c;需要客户端请求在Header中添加’Authorization’: Bearer token’的键值对且通过token验证后才能调用。 [Authorize] [HttpGet]…...

Linux 内核自旋锁spinlock(一)

文章目录 前言一、自旋锁1.1 简介1.2 API1.2.1 spin_lock/spin_unlock1.2.2 spin_lock_irq/spin_unlock_irq1.2.3 spin_lock_irqsave/spin_unlock_irqstore1.2.4 spin_lock_bh/spin_unlock_bh1.2.5 补充 二、自选锁原理三、自旋锁在内核的使用3.1 struct file3.2 struct dentry…...

JAVA 使用反射比较对象属性的变化,记录修改日志。使用注解【策略模式】,来进行不同属性枚举值到中英文描述的切换,支持前端国际化。

1.首先定义一个接口&#xff0c;接口中有两个方法&#xff0c;分别是将属性转换成英文描述和中文描述。 其实就是将数据库中记录的 0 1 &#xff0c;转换成后面的描述 这边定义了中文转换为默认方法&#xff0c;是因为有些属性不需要进行中文转换&#xff0c;或者该属性的枚举…...

利用免费GIS工具箱实现高斯泼溅切片,将 PLY 格式转换为 3dtiles

在地理信息系统&#xff08;GIS&#xff09;和三维数据处理领域&#xff0c;不同数据格式有其独特应用场景与优势。PLY&#xff08;Polygon File Format&#xff09;格式常用于存储多边形网格数据&#xff0c;而 3DTiles 格式在 Web 端三维场景展示等方面表现出色。将 PLY 格式…...

Mysql视图(学习自用)

一、概念 二、创建视图 三、查询视图 四、修改视图 五、删除视图 六、视图检查选项 七、视图的更新 八、视图的作用...

企业内训|基于华为昇腾910B算力卡的大模型部署和调优-上海某央企智算中心

近日上海&#xff0c;TsingtaoAI为某央企智算中心交付华为昇腾910B算力卡的大模型部署和调优课程。课程深入讲解如何在昇腾NPU上高效地训练、调优和部署PyTorch与Transformer模型&#xff0c;并结合实际应用场景&#xff0c;探索如何优化和迁移模型至昇腾NPU平台。课程涵盖从模…...

linux下一些参数的说明

/proc/sys/net/corebpf_jit_enable 作用&#xff1a;用于控制是否启用BPF&#xff08;Berkeley Packet Filter&#xff09;的即时编译&#xff08;JIT&#xff09;功能。当启用该功能时&#xff0c;JIT编译器会将eBPF&#xff08;extended Berkeley Packet Filter&#xff09;…...

CKS认证 | Day1 K8s集群部署与安全配置

一、K8s安全运维概述 Kubernetes&#xff08;K8s&#xff09; 是一个广泛使用的容器编排平台&#xff0c;用于自动化部署、扩展和管理容器化应用程序。随着 K8s 在生产环境中的普及&#xff0c;安全运维成为确保系统稳定性和数据安全的关键。 1.1 安全运维的重要性 万物互联&…...

新手上路:Anaconda虚拟环境创建和配置以使用PyTorch和DGL

文章目录 前言步骤 1: 安装 Anaconda步骤 2: 创建新的 Anaconda 环境步骤 3: 安装最新版本的 PyTorch步骤 4: 安装特定版本的 PyTorch步骤 5: 安装最新版本的 DGL步骤 6: 安装特定版本的 DGL步骤 7: Pycharm中使用虚拟环境解释器第一种情况&#xff1a;创建新项目第二种情况&am…...

什么是PCB的Mark点?如何进行设计Mark点?

一、什么是Mark点&#xff1f; PCB的Mark点&#xff0c;也被称为基准点或光学定位点&#xff0c;是在印刷电路板&#xff08;Printed Circuit Board, PCB&#xff09;上设置的一种特殊标记。 ​ 图1.1 PCB的Mark点 Mark点的主要作用是为表面贴装技术&#xff08;Surface Mount…...