深度学习基础03_BP算法(下)过拟合和欠拟合

目录

一、BP算法(下)

0、反向传播代码回顾

写法一:

写法二(更常用):

1、BP中的梯度下降

1.数学描述

2.传统下降方式

3.优化梯度下降方式

指数加权平均

Momentum

AdaGrad

RMSProp

Adam(常用)

总结

二、过拟合和欠拟合

1、概念

1.过拟合

2.欠拟合

3.判断

2、解决欠拟合

3、解决过拟合

1.L2正则化

2.L1正则化

3.Dropout

4.其他方法


一、BP算法(下)

0、反向传播代码回顾

作为深度学习里的核心部分,再来回顾一下完整的全连接神经网络的反向传播代码框架的两种写法:

写法一:
import torch
import torch.nn as nn
import torch.optim as optim

# 构建网络
Class MyNet(nn.module):
    def __init__(self,input_size,output_size):
        super(MyNet,self).__init__()
        # 定义网络结构
        self.linear1 = nn.Linear(input_size,2)
        self.linear2 = nn.Linear(2,2)
        self.linear3 = nn.Linear(2,output_size)
        # 激活函数 sigmoid
        self.activation = torch.sigmoid

        # 网络参数初始化 这里选择自动初始化
        """
        若要手动初始化:
        # 权重
        self.linear1.weight.data = torch.tensor([[0.10,0.20],[0.25,0.35]])
        # 偏置
        self.linear1.bias.data = torch.tensor([0.30,0.30])
        适合结构形式固定时的神经网络
        """

    def forward(self,x):
    # 定义前向传播过程
    x = self.linear1(x)
    x = self.activation(x)
    x = self.linear2(x)
    x = self.activation(x)
    x = self.linear3(x)
    x = self.activation(x)
    return x


# 训练模型
def train():
    # 创建数据集
    inputs = torch.tensor([[0.05, 0.10]])
    target = torch.tensor([[0.01, 0.99]])
    # 定义神经网络结构
    net = MyNet(2,2)
    # 定义优化器
    optimizer = optim.SGD(net.parameters(),lr=0.05)
    # 定义损失函数
    loss_fn = nn.MSELoss()
    # 训练
    epoch = 500
    for i in range(epoch):
        # 前向传播 获得网络输出值
        y_pred = net(inputs)
        # 计算误差
        loss = loss_fn(y_pred,target)
        # 梯度清零
        optimizer.zero_grad()
        # 反向传播
        loss.backward()
        # 更新梯度
        optimizer.step()
    # 打印更新后的所有网络参数
    print(net.state_dict())


if __name__ == "__main__":
    train()
        


写法二(更常用):
import torch
import torch.nn as nn
import torch.optim as optim

class MyNet(nn.Module):

    def __init__(self,input_size,output_size):
        super(MyNet, self).__init__()
        # 定义网络结构 nn.Sequention 一种序列容器,可以将多个层按顺序堆叠在一起
        # 隐藏层
        hide1层 有input_size个特征,3个输出(3个神经元) '3行2列'
        self.hide1 = nn.Sequential(nn.Linear(input_size,3),nn.Sigmoid())
        self.hide2 = nn.Sequential(nn.Linear(3,2),nn.Sigmoid())
        self.hide2 = nn.Sequential(nn.Linear(2,4),nn.Sigmoid())
        # 输出层 输入进来每条数据有12个特征w 输出output_size个结果
        self.out = nn.Sequential(nn.Linear(4,output_size),nn.Sigmoid())

    def forward(self,input):
    # 前向传播过程
    x = self.hide1(input)
    x = self.hide2(x)
    x = self.hide3(x)
    y_pred = self.out(x)
    return  y_pred


def train():
    # 数据集
    inputs = torch.tensor([[0.05, 0.10],
                           [0.05,0.18],
                           [0.05,0.310]])
    target = torch.tensor([[1,2],[0,3],[2,4]],dtype=torch.float32)
    # 定义网络结构
    net = MyNet(2,2)
    # 优化器
    optimizer = optim.SGD(net.parameters(), lr=0.1)
    # 定义损失函数
    loss_fn = torch.nn.MSELoss()
    # 训练
    epoch = 500
    for i in range(epoch):
        # 前向传播
        # 获得网络输出值
        y_pred = net(inputs) # module父类已实现前向传播
        # 计算误差
        loss = loss_fn(y_pred, target)
        # 梯度清零
        optimizer.zero_grad()
        # 反向传播
        loss.backward()
        #更新梯度
        optimizer.step()
        
        # 打印更新后的网络参数
    print(net.state_dict())

if __name__ == "__main__":
    train()
    

1、BP中的梯度下降

1.数学描述

梯度下降公式:w_{ij}^{new}= w_{ij}^{old} - \alpha \frac{\partial E}{\partial w_{ij}},其中\alpha是学习率。

  • 学习率太小,每次训练之后的效果太小,增加时间和算力成本。

  • 学习率太大,大概率会跳过最优解,进入无限的训练和震荡中。

  • 解决的方法就是,学习率也需要随着训练的进行而变化。

过程

初始化参数→计算梯度→更新参数→迭代更新→达到终止条件

2.传统下降方式

根据计算梯度时数据量不同,常见的方式有:批量梯度下降BGD、随机梯度下降SGD、小批量下降MGBD。

它们的特点以及优劣可参考:机器学习基础07_sklearn梯度下降&岭回归&拉索回归&逻辑回归_sklearn 梯度下降法-CSDN博客

但都存在问题: 

  • 收敛速度慢:BGD和MBGD使用固定学习率,太大会导致震荡,太小又收敛缓慢。

  • 局部最小值和鞍点问题:SGD在遇到局部最小值或鞍点时容易停滞,导致模型难以达到全局最优。

  • 训练不稳定:SGD中的噪声容易导致训练过程中不稳定,使得训练陷入震荡或不收敛。

3.优化梯度下降方式

传统的梯度下降优化算法中,可能会碰到以下情况:

碰到平缓区域,梯度值较小,参数优化变慢;碰到 “鞍点” ,梯度为 0,参数无法优化;碰到局部最小值等

对于这些问题, 出现了一些对梯度下降算法的优化方法,例如:Momentum、AdaGrad、RMSprop、Adam 等:

指数加权平均

指数移动加权平均(Exponential Moving Average简称EMA)则是参考各数值,并且各数值的权重都不同,距离越远的数字对平均数计算的贡献就越小(权重较小),距离越近则对平均数的计算贡献就越大(权重越大)。

计算公式

  • St 表示指数加权平均值(EMA);

  • Yt 表示 t 时刻的值;

  • \beta是平滑系数,取值范围为 0\leq \beta < 1,其越接近 1,表示对历史数据依赖性越高;越接近 0 则越依赖当前数据。该值越大平均数越平缓。

import torch
import numpy as np
import matplotlib.pyplot as plt


"""
**指数移动加权平均**(Exponential Moving Average简称EMA)
参考各数值,并且各数值的权重都不同
距离越远的数字对平均数计算的贡献越小(权重较小)
距离越近则对平均数的计算贡献就越大(权重越大)
"""
def test01():
    # 模拟温度
    np.random.seed(666)
    y = np.random.randint(5,40,30)
    print(y)
    x = np.arange(30)
    plt.plot(x,y,c='b')
    plt.scatter(x,y,c='r')
    plt.show()

def test02(beta=0.9):
    # 模拟温度
    np.random.seed(666)
    y = np.random.randint(5,40,30)
    print(y)
    x = np.arange(30)
    y_ema = []
    for i in range(30):
        if i==0:
            y_ema.append(y[0])
        else:
            st = beta*y_ema[-1] + (1-beta)*y[i]
            y_ema.append(st)

    plt.plot(x,np.array(y_ema),c='b')
    plt.scatter(x,y,c='r')
    plt.show()


if __name__ == '__main__':
    # test01()
    test02()
Momentum

动量(Momentum)是对梯度下降的优化方法,可以更好地应对梯度变化和梯度消失问题,从而提高训练模型的效率和稳定性。

  • 惯性效应: 该方法加入前面梯度的累积,这种惯性使得算法沿着当前的方向继续更新。如遇到鞍点,也不会因梯度逼近零而停滞。

  • 减少震荡: 该方法平滑了梯度更新,减少在鞍点附近的震荡,帮助优化过程稳定向前推进。

  • 加速收敛: 该方法在优化过程中持续沿着某个方向前进,能够更快地穿越鞍点区域,避免在鞍点附近长时间停留。

梯度计算公式:St = β * S_{t-1} + (1- β) * Wt

  1. S_{t-1} 表示历史梯度移动加权平均值

  2. Wt 表示当前时刻的梯度值

  3. β 为权重系数

梯度下降公式中梯度的计算,就不再是当前时刻 t 的梯度值,而是历史梯度值的指数移动加权平均值:

W_{t+1}=W_{t}-\alpha *D_t

api

optimizer = optim.SGD(model.parameters(), lr=0.05, momentum=0.4)  # 学习率和动量值可以根据实际情况调整,momentum 参数指定了动量系数,默认为0。动量系数通常设置为 0 到0.5 之间的一个值,但也可以根据具体的应用场景调整

def train():
    # 数据集
    inputs = torch.tensor([[0.05, 0.10],
                           [0.05,0.18],
                           [0.05,0.310]])
    target = torch.tensor([[1,2],[0,3],[2,4]],dtype=torch.float32)
    # 定义网络结构
    net = MyNet(2,2)
    # 优化器 加入动量值
    optimizer = optim.SGD(net.parameters(), lr=0.01,momentum=0.6)
    # 定义损失函数
    mes = torch.nn.MSELoss()
    # 训练
    epoch = 100
    for i in range(epoch):
        # 前向传播
        # 获得网络输出值
        y_pred = net(inputs) # module父类已实现前向传播
        # 计算误差
        loss = mes(y_pred, target)
        # 梯度清零
        optimizer.zero_grad()
        # 反向传播
        loss.backward()
        #更新梯度
        optimizer.step()
AdaGrad

AdaGrad(Adaptive Gradient Algorithm)为每个参数引入独立的学习率,它根据历史梯度的平方和来调整这些学习率,这样就使得参数具有较大的历史梯度的学习率减小,而参数具有较小的历史梯度的学习率保持较大,从而实现更有效的学习。

学习率计算公式:

其中s是累积平方梯度, s = s + g ⊙ g,⊙ 表示各个分量相乘;σ是小常数 σ = 1e-8( 用于防止除零操作)

参数更新公式:

优点

  • 自适应学习率:由于每个参数的学习率是基于其梯度的累积平方和 来动态调整的,这意味着学习率会随着时间步的增加而减少,对梯度较大且变化频繁的方向非常有用,防止了梯度过大导致的震荡。

  • 适合稀疏数据:AdaGrad 在处理稀疏数据时表现很好,因为它能够自适应地为那些较少更新的参数保持较大的学习率。

缺点

  1. 学习率过度衰减:随着时间的推移,累积的时间步梯度平方值越来越大,导致学习率逐渐接近零,模型会停止学习。

  2. 不适合非稀疏数据:在非稀疏数据的情况下,学习率过快衰减可能导致优化过程早期停滞。

AdaGrad是一种有效的自适应学习率算法,然而由于学习率衰减问题,我们会使用改 RMSProp 或 Adam 来替代。

 api

optimizer = optim.Adagrad(model.parameters(), lr=0.9)  # 设置学习率

RMSProp

RMSProp(Root Mean Square Propagation)在时间步中,不是简单地累积所有梯度平方和,而是使用指数加权平均来逐步衰减过时的梯度信息。这种方法专门用于解决AdaGrad在训练过程中学习率过度衰减的问题。

使用指数移动平均累积历史梯度:

学习率和参数更新公式和AdaGrad没有变化。

优点

  • 适应性强:RMSProp自适应调整每个参数的学习率,对于梯度变化较大的情况非常有效,使得优化过程更加平稳。

  • 适合非稀疏数据:相比于AdaGrad,RMSProp更加适合处理非稀疏数据,因为它不会让学习率减小到几乎为零。

  • 解决过度衰减问题:通过引入指数加权平均,RMSProp避免了AdaGrad中学习率过快衰减的问题,保持了学习率的稳定性

缺点

  1. 依赖于超参数的选择:RMSProp的效果对衰减率  \beta 和学习率  \alpha 的选择比较敏感,需要一些调参工作。

需要注意的是:AdaGrad 和 RMSProp 都是对于不同的参数分量使用不同的学习率,如果某个参数分量的梯度值较大,则对应的学习率就会较小,如果某个参数分量的梯度较小,则对应的学习率就会较大一些。

api

optimizer = optim.RMSprop(model.parameters(), lr=0.7, momentum=0.9)  # 设置学习率和动量

Adam(常用)

Adam(Adaptive Moment Estimation)算法将动量法和RMSProp的优点结合在一起:

Momentum 使用指数加权平均计算当前的梯度值、AdaGrad、RMSProp 使用自适应的学习率,Adam 结合了 Momentum、RMSProp 的优点,使用:移动加权平均的梯度和移动加权平均的学习率。使得能够自适应学习率的同时,也能够使用 Momentum 的优点。

优点

  1. 高效稳健:Adam结合了动量法和RMSProp的优势,在处理非静态、稀疏梯度和噪声数据时表现出色,能够快速稳定地收敛。

  2. 自适应学习率:Adam通过一阶和二阶动量的估计,自适应调整每个参数的学习率,避免了全局学习率设定不合适的问题。

  3. 适用大多数问题:Adam几乎可以在不调整超参数的情况下应用于各种深度学习模型,表现良好。

缺点

  1. 超参数敏感:尽管Adam通常能很好地工作,但它对初始超参数(如 \beta_1、 \beta_2 和 \eta)仍然较为敏感,有时需要仔细调参。

  2. 过拟合风险:由于Adam会在初始阶段快速收敛,可能导致模型陷入局部最优甚至过拟合。因此,有时会结合其他优化算法(如SGD)使用。

api

optimizer = optim.Adam(model.parameters(), lr=0.05)  # 设置学习率

总结

在实际应用中,根据数据的规模和计算资源的情况,选择合适的梯度下降方式(批量、随机、小批量)及其变种(如动量法、Adam等)可以显著提高模型训练的效率和效果。

Adam是目前最为流行的优化算法之一,因其稳定性和高效性,广泛应用于各种深度学习模型的训练中。Adam结合了动量法和RMSProp的优点,能够在不同情况下自适应调整学习率,并提供快速且稳定的收敛表现。

二、过拟合和欠拟合

在训练深层神经网络时,由于模型参数较多,在数据量不足时很容易过拟合。而正则化技术主要就是用于防止过拟合,提升模型的泛化能力(对新数据表现良好)和鲁棒性(对异常数据表现良好)。

1、概念

1.过拟合

过拟合是指模型对训练数据拟合能力很强并表现很好,但在测试数据上表现较差。

过拟合常见原因有:

  1. 数据量不足:当训练数据较少时,模型可能会过度学习数据中的噪声和细节。

  2. 模型太复杂:如果模型很复杂,也会过度学习训练数据中的细节和噪声。

  3. 正则化强度不足:如果正则化强度不足,可能会导致模型过度学习训练数据中的细节和噪声。

2.欠拟合

欠拟合是由于模型学习能力不足,无法充分捕捉数据中的复杂关系。

3.判断

过拟合

训练误差低,但验证时误差高。模型在训练数据上表现很好,但在验证数据上表现不佳,说明模型可能过度拟合了训练数据中的噪声或特定模式。

欠拟合

训练误差和测试误差都高。模型在训练数据和测试数据上的表现都不好,说明模型可能太简单,无法捕捉到数据中的复杂模式。

2、解决欠拟合

  1. 增加模型复杂度:引入更多的参数、增加神经网络的层数或节点数量,使模型能够捕捉到数据中的复杂模式。

  2. 增加特征:通过特征工程添加更多有意义的特征,使模型能够更好地理解数据。

  3. 减少正则化强度:适当减小 L1、L2 正则化强度,允许模型有更多自由度来拟合数据。

  4. 训练更长时间:如果是因为训练不足导致的欠拟合,可以增加训练的轮数或时间.

3、解决过拟合

1.L2正则化

L2 正则化通过在损失函数中添加权重参数的平方和来实现,目标是惩罚过大的参数值:

L_{\text{total}}(\theta) = L(\theta) + \lambda \cdot \frac{1}{2} \sum_{i} \theta_i^2

其中\frac{1}{2} \sum_{i} \theta_i^2是所有权重参数的平方和,称为 L2 正则化项;\theta_i 是模型的第 i 个权重参数。

L2 正则化会惩罚权重参数过大的情况,通过参数平方值对损失函数进行约束。

梯度更新

\theta_{t+1} = \theta_t - \eta \left( \nabla L(\theta_t) + \lambda \theta_t \right)

参数越大惩罚力度就越大,从而让参数逐渐趋向于较小值,避免出现过大的参数。

作用

  1. 防止过拟合:当模型过于复杂、参数较多时,模型会倾向于记住训练数据中的噪声,导致过拟合。L2 正则化通过抑制参数的过大值,使得模型更加平滑,降低模型对训练数据噪声的敏感性。

  2. 限制模型复杂度:L2 正则化项强制权重参数尽量接近 0,避免模型中某些参数过大,从而限制模型的复杂度。通过引入平方和项,L2 正则化鼓励模型的权重均匀分布,避免单个权重的值过大。

  3. 提高模型的泛化能力:正则化项的存在使得模型在测试集上的表现更加稳健,避免在训练集上取得极高精度但在测试集上表现不佳。

  4. 平滑权重分布L2 正则化不会将权重直接变为 0,而是将权重值缩小。这样模型就更加平滑的拟合数据,同时保留足够的表达能力。

import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=0.001)  # L2 正则化,weight_decay就是L2正则化前面的参数λ
2.L1正则化

L1 正则化通过在损失函数中添加权重参数的绝对值之和来约束模型的复杂度:

L_{\text{total}}(\theta) = L(\theta) + \lambda \sum_{i} |\theta_i|

其中\sum_{i} |\theta_i|是所有权重参数的绝对值之和,这个项即为 L1 正则化项。

梯度更新

\theta_{t+1} = \theta_t - \eta \left( \nabla L(\theta_t) + \lambda \cdot \text{sign}(\theta_t) \right)

其中sign()是符号函数,\theta_t为正时取1,为负时取值为-1,等于0时为0。

因为 L1 正则化依赖于参数的绝对值,其梯度更新时不是简单的线性缩小,而是通过符号函数来直接调整参数的方向。这就是为什么 L1 正则化能促使某些参数完全变为 0

作用

  1. 稀疏性:L1 正则化的一个显著特性是它会促使许多权重参数变为 。这是因为 L1 正则化倾向于将权重绝对值缩小到零,使得模型只保留对结果最重要的特征,而将其他不相关的特征权重设为零,从而实现 特征选择 的功能。

  2. 防止过拟合:通过限制权重的绝对值,L1 正则化减少了模型的复杂度,使其不容易过拟合训练数据。相比于 L2 正则化,L1 正则化更倾向于将某些权重完全移除,而不是减小它们的值。

  3. 简化模型:由于 L1 正则化会将一些权重变为零,因此模型最终会变得更加简单,仅依赖于少数重要特征。这对于高维度数据特别有用,尤其是在特征数量远多于样本数量的情况下。

  4. 特征选择:因为 L1 正则化会将部分权重置零,因此它天然具有特征选择的能力,有助于自动筛选出对模型预测最重要的特征。

和L2的对比

  • L1 正则化 更适合用于产生稀疏模型,会让部分权重完全为零,适合做特征选择。

  • L2 正则化 更适合平滑模型的参数,避免过大参数,但不会使权重变为零,适合处理高维特征较为密集的场景。

对于 L1 正则化,PyTorch 的优化器并不直接支持,需要手动将 L1 惩罚项添加到损失函数中。

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


def train():
    """
    L1 正则化通过在损失函数中添加权重参数的绝对值之和来约束模型的复杂度。
    需手动添加
    """
    # 数据集
    inputs = torch.tensor([[0.5,1.0,1.5],
                           [0.5,3.1,1.8]])
    target = torch.tensor([[0.5],[1.5]])
    # 定义网络结构
    model = nn.Linear(3,1)
    # 优化器
    optimizer = optim.SGD(model.parameters(),lr=0.1)
    # 定义损失函数
    loss_fn = torch.nn.MSELoss()
    # 预测
    y_pred = model(inputs)
    # 计算损失:L1 正则化 加其加入到总损失中
    l1_lambda = 0.001
    l1_norm = sum(p.abs().sum() for p in model.parameters())
    loss = loss_fn(y_pred, target)+l1_lambda*l1_norm
    # 梯度清零
    if model.weight.grad is not None:
        model.weight.grad.zero_()
    # 反向传播
    loss.backward()
    # 参数更新
    optimizer.step()
    print(loss)
3.Dropout

Dropout 是一种在训练过程中随机丢弃部分神经元的技术。它通过减少神经元之间的依赖来防止模型过于复杂,从而避免过拟合。

Dropout过程:

  1. 按照指定的概率把部分神经元的值设置为0;

  2. 为了规避该操作带来的影响,需对非 0 的元素使用缩放因子1/(1-p)进行强化。

import torch
import torch.nn as nn


def test01():
    """
    Dropout 是一种在训练过程中随机丢弃部分神经元的技术,
    通过减少神经元之间的依赖来防止模型过于复杂,从而避免过拟合。
    """
    x = torch.tensor([[1,2,3,1,3,4,5,3,5,6]],dtype = torch.float32)
    # 按照指定的概率把部分神经元的值设置为0
    drop = nn.Dropout(0.6)
    print(x.shape)
    x = drop(x)
    print(x)
    print(x.shape)
    print(sum(sum(x!=0))/x.shape[1])


def test02():
    torch.manual_seed(666)
    x = torch.randint(0, 8, (3, 12)).float()
    w = torch.randn(12, 1, requires_grad=True)

    drop = nn.Dropout(0.5)
    # 随机抛点
    x = drop(x)

    output = x@w
    print(output)

    loss = output.sum()
    loss.backward()
    print(w.grad.flatten())



if __name__ == '__main__':
    # test01()
    test02()
4.其他方法

简化模型

  • 减少网络层数和参数: 通过减少网络的层数、每层的神经元数量或减少卷积层的滤波器数量,可以降低模型的复杂度,减少过拟合的风险。

  • 使用更简单的模型: 对于复杂问题,使用更简单的模型或较小的网络架构可以减少参数数量,从而降低过拟合的可能性。

数据增强

通过对训练数据进行各种变换(如旋转、裁剪、翻转、缩放等),可以增加数据的多样性,提高模型的泛化能力。

早停

早停是一种在训练过程中监控模型在验证集上的表现,并在验证误差不再改善时停止训练的技术。这样可避免训练过度,防止模型过拟合。

模型集成

通过将多个不同模型的预测结果进行集成,可以减少单个模型过拟合的风险。常见的集成方法包括投票法、平均法和堆叠法。

交叉验证

使用交叉验证技术可以帮助评估模型的泛化能力,并调整模型超参数,以防止模型在训练数据上过拟合。

这些方法可以单独使用,也可以结合使用,以有效地防止参数过大和过拟合。根据具体问题和数据集的特点,选择合适的策略来优化模型的性能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实现PDF文档加密,访问需要密码

01. 背景 今天下午老板神秘兮兮的来问我&#xff0c;能不能做个文档加密功能&#xff0c;就是那种用户下载打开需要密码才能打开的那种效果。boss都发话了&#xff0c;那必须可以。 需求&#xff1a;将 pdf 文档经过加密处理&#xff0c;客户下载pdf文档&#xff0c;打开文档需…

Apache Doris 现行版本 Docker-Compose 运行教程

特别注意&#xff01;Doris On Docker 部署方式仅限于开发环境或者功能测试环境&#xff0c;不建议生产环境部署&#xff01; 如有生产环境或性能测试集群部署诉求&#xff0c;请使用裸机/虚机部署或K8S Operator部署方案&#xff01; 原文阅读&#xff1a;Apache Doris 现行版…

1.Git安装与常用命令

前言 Git中会用到的一些基本的Linux命令 ls/ll 查看文件目录 (ll可以看隐藏文件)cat 查看文件内容touch 创建文件vi vi编辑器 1.下载与安装 安装成功后鼠标右键会出现Git Bash和Git GUI Git GUI&#xff1a;GUI图形化界面 Git Bash&#xff1a;Git提供的命令行工具 当安装…

A058-基于Spring Boot的餐饮管理系统的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看项目链接获取⬇️&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600个选题ex…

【AI系统】Ascend C 语法扩展

Ascend C 语法扩展 Ascend C 的本质构成其实是标准 C加上一组扩展的语法和 API。本文首先对 Ascend C 的基础语法扩展进行简要介绍&#xff0c;随后讨论 Ascend C 的两种 API——基础 API 和高阶 API。 接下来针对 Ascend C 的几种关键编程对象——数据存储、任务间通信与同步…

【合作原创】使用Termux搭建可以使用的生产力环境(二)

前言 上期文章没看的可以先从上期文章开始看起 【合作原创】使用Termux搭建可以使用的生产力环境&#xff08;一&#xff09;-CSDN博客 目前我们已经完成了FinalShell ssh连接手机Termux的功能了&#xff0c;这期我们继续朝我们的目标前进。今天早上有读者进群以为生成环境指…

UG NX二次开发(C#)-选择对象居中(不是全部居中)

文章目录 1、前言2、什么是对象居中3、功能实现代码3.1 对象居中3.1 恢复原视图1、前言 在UG NX二次开发过程中,我们经常会用到居中以查看完整的模型,但是对于如果想展示某些对象,而不是全部模型时,那么我们就想将选择的对象(如体对象)居中查看,当查看结束后还能恢复到…

群控系统服务端开发模式-应用开发-短信工厂七牛云短信开发

一、七牛云短信工厂开发 1、添加框架对应的SDK composer require qiniu/php-sdk 2、添加七牛云工厂 在根目录下extend文件夹下Sms文件夹下channel文件夹下&#xff0c;创建七牛云短信发送工厂并命名为QiniuyunSmsSender。记住&#xff0c;一定要在七牛云短信发送工厂类名后面去…

机器学习概述,特征工程简述2.1——2.3

机器学习概述&#xff1a; 1.1人工智能概述 达特茅斯会议—人工智能的起点 机器学习是人工智能的一个实现途径 深度学习是机器学习的一个方法发展而来 1.1.2 机器学习和深度学习能做什么 传统预测 图像识别 自然语言处理 1.2什么是机器学习 数据 模型 预测 从历史数…

基于vite6+ vue3 + electron@33 实现的 局域网内互传文件的桌面软件

目录 项目介绍项目部分截图介绍下基础项目搭建先搭建一个vite 前端项目 再安装 electron 相关依赖依赖安装失败解决方案修改 vite配置文件和 ts 配置文件修改packjsonts相关配置项目结构介绍 项目介绍 前端 基于 vue3 ts windicss 后端 就是node 层 项目地址&#xff1a; h…

Linux 内核系统架构

Linux 内核是一个复杂且高度模块化的系统&#xff0c;负责操作硬件资源、管理进程和内存、提供网络服务、执行文件系统操作、进行设备驱动程序的管理等。它为用户空间提供了一个抽象层&#xff0c;并为应用程序提供了底层服务。本文将深入探讨 Linux 内核的系统架构&#xff0c…

TYUT设计模式精华版

七大原则 单一职责原则 职责要单一不能将太多的职责放在一个类中 开闭原则 软件实体对扩展是开放的&#xff0c;但对修改是关闭的 里氏代换原则 一个可以接受基类对象的地方必然可以接受子类 依赖倒转原则 要针对抽象层编程&#xff0c;而不要针对具体类编程 接口隔离原则 …

计算机网络——不同版本的 HTTP 协议

介绍 HTTP&#xff0c;即超文本传输协议&#xff08;HyperText Transfer Protocol&#xff09;&#xff0c;是应用层的一个简单的请求-响应协议&#xff0c;它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。本文将介绍 HTTP 协议各个版本。 HTTP/1.0 HTTP/1…

Fastapi + vue3 自动化测试平台---移动端App自动化篇

概述 好久写文章了&#xff0c;专注于新框架&#xff0c;新UI界面的实践&#xff0c;废话不多说&#xff0c;开搞 技术架构 后端&#xff1a; Fastapi Airtest multiprocessing 前端&#xff1a; 基于 Vue3、Vite、TypeScript、Pinia、Pinia持久化插件、Unocss 和 Elemen…

FreeRTOS之ARM CR5栈结构操作示意图

FreeRTOS之ARM CR5栈结构操作示意图 1 FreeRTOS源码下载地址2 ARM CR5栈结构操作宏和接口2.1 portSAVE_CONTEXT宏2.1.1 portSAVE_CONTEXT源码2.1.2 portSAVE_CONTEXT宏操作栈结构变化示意图 2.2 portRESTORE_CONTEXT宏2.2.1 portRESTORE_CONTEXT源码2.2.2 portRESTORE_CONTEXT宏…

警惕开源信息成为泄密源头

文章目录 前言一、信息公开需谨慎1、警惕采购招标泄密。2、警惕信息公开泄密。3、警惕社交媒体泄密。 二、泄密风险需严防1、健全制度&#xff0c;明确责任。2、加强管控&#xff0c;严格审查。3、提高意识&#xff0c;谨言慎行。 前言 大数据时代&#xff0c;信息在网络空间发…

指针(上)

目录 内存和地址 指针变量和地址 取地址&#xff08;&&#xff09; 解引用&#xff08;*&#xff09; 大小 类型 意义 const修饰 修饰变量 修饰指针 指针运算 指针- 整数 指针-指针 指针的关系运算 野指针 概念 成因 避免 assert断言 指针的使用 strl…

常见的数据结构---队列、树与堆的深入剖析

目录 一、队列 二、树 三、堆 在现代计算机科学与工程领域&#xff0c;队列、树和堆是三种极其重要的基础数据结构&#xff0c;它们各自具有独特的特点和应用。在日常开发中&#xff0c;合理选择和使用这些数据结构可以显著提高程序的效率和可维护性。它们不仅奠定了算法设计…

Java 整合图片处理相关一套:传输、保存、重命名、删除、AI图片文字识别、图片映射、vue3裁剪、设置黑白色、设置负片、提高照片品质

目录 一、vue3 axios spring boot文件传输 二、Java图片保存到本地 三、Java 本地图片重命名 四、Java 删除本地图片 五、 JavaAI图片文字识别 六、Java映射图片地址&#xff0c;前端直接访问图片 七、vue3 图片裁剪 八、Java 设置图片黑白色 九、Java 设置图片负片 …

web三、 window对象,延时器,定时器,时间戳,location对象(地址),本地存储-localStorage,数组去重new Set

一、 window对象 window对象 是一个全局对象&#xff0c;也可以说是JavaScript中的 顶级对象 像document、alert()、console.log()这些都是window的属性&#xff0c;基本BOM的属性和方法都是window的 所有通过 var定义 在全局作用域中的 变量 、 函数 都会变成window对象的属…