【深度学习实验】网络优化与正则化(七):超参数优化方法——网格搜索、随机搜索、贝叶斯优化、动态资源分配、神经架构搜索

文章目录

  • 一、实验介绍
  • 二、实验环境
    • 1. 配置虚拟环境
    • 2. 库版本介绍
  • 三、优化算法
    • 0. 导入必要的库
    • 1. 随机梯度下降SGD算法
      • a. PyTorch中的SGD优化器
      • b. 使用SGD优化器的前馈神经网络
    • 2.随机梯度下降的改进方法
      • a. 学习率调整
      • b. 梯度估计修正
    • 3. 梯度估计修正:动量法Momentum
    • 4. 自适应学习率
    • 5. Adam算法
  • 四、参数初始化
  • 五、数据预处理
  • 六、逐层归一化
  • 七、超参数优化
    • 0. 前期准备
      • a. 神经网络模型
      • b. 训练和评估函数
      • c. 分类数据
    • 1. 网格搜索
      • a. 基本步骤
      • b. 代码实现
    • 2. 随机搜索
      • a. 基本步骤
      • b. 优缺点
      • c. 代码实现
    • 3. 贝叶斯优化
      • a.基本步骤
      • b. 代码实现
    • 4. 动态资源分配
    • 5. 神经架构搜索

一、实验介绍

  深度神经网络在机器学习中应用时面临两类主要问题:优化问题和泛化问题。

  • 优化问题:深度神经网络的优化具有挑战性。

    • 神经网络的损失函数通常是非凸函数,因此找到全局最优解往往困难。
    • 深度神经网络的参数通常非常多,而训练数据也很大,因此使用计算代价较高的二阶优化方法不太可行,而一阶优化方法的训练效率通常较低。
    • 深度神经网络存在梯度消失梯度爆炸问题,导致基于梯度的优化方法经常失效。
  • 泛化问题:由于深度神经网络的复杂度较高且具有强大的拟合能力,很容易在训练集上产生过拟合现象。因此,在训练深度神经网络时需要采用一定的正则化方法来提高网络的泛化能力。

  目前,研究人员通过大量实践总结了一些经验方法,以在神经网络的表示能力、复杂度、学习效率和泛化能力之间取得良好的平衡,从而得到良好的网络模型。本系列文章将从网络优化和网络正则化两个方面来介绍如下方法:

  • 在网络优化方面,常用的方法包括优化算法的选择参数初始化方法数据预处理方法逐层归一化方法超参数优化方法
  • 在网络正则化方面,一些提高网络泛化能力的方法包括ℓ1和ℓ2正则化权重衰减提前停止丢弃法数据增强标签平滑等。

  本文将介绍神经网络优化的逐层归一化方法,包括批量归一化、层归一化、权重归一化(略)、局部响应归一化(略)等

二、实验环境

  本系列实验使用了PyTorch深度学习框架,相关操作如下:

1. 配置虚拟环境

conda create -n DL python=3.7 
conda activate DL
pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
conda install matplotlib
 conda install scikit-learn

2. 库版本介绍

软件包本实验版本目前最新版
matplotlib3.5.33.8.0
numpy1.21.61.26.0
python3.7.16
scikit-learn0.22.11.3.0
torch1.8.1+cu1022.0.1
torchaudio0.8.12.0.2
torchvision0.9.1+cu1020.15.2

三、优化算法

  神经网络的参数学习是一个非凸优化问题.当使用梯度下降法来进行优化网络参数时,参数初始值的选取十分关键,关系到网络的优化效率和泛化能力.参数初始化的方式通常有以下三种:

0. 导入必要的库

from torch import nn

1. 随机梯度下降SGD算法

  随机梯度下降(Stochastic Gradient Descent,SGD)是一种常用的优化算法,用于训练深度神经网络。在每次迭代中,SGD通过随机均匀采样一个数据样本的索引,并计算该样本的梯度来更新网络参数。具体而言,SGD的更新步骤如下:

  1. 从训练数据中随机选择一个样本的索引。
  2. 使用选择的样本计算损失函数对于网络参数的梯度。
  3. 根据计算得到的梯度更新网络参数。
  4. 重复以上步骤,直到达到停止条件(如达到固定的迭代次数或损失函数收敛)。

a. PyTorch中的SGD优化器

   Pytorch官方教程

optimizer = torch.optim.SGD(model.parameters(), lr=0.2)

b. 使用SGD优化器的前馈神经网络

   【深度学习实验】前馈神经网络(final):自定义鸢尾花分类前馈神经网络模型并进行训练及评价

2.随机梯度下降的改进方法

  传统的SGD在某些情况下可能存在一些问题,例如学习率选择困难和梯度的不稳定性。为了改进这些问题,提出了一些随机梯度下降的改进方法,其中包括学习率的调整和梯度的优化。

a. 学习率调整

在这里插入图片描述

  • 学习率衰减(Learning Rate Decay):随着训练的进行,逐渐降低学习率。常见的学习率衰减方法有固定衰减、按照指数衰减、按照时间表衰减等。
  • Adagrad:自适应地调整学习率。Adagrad根据参数在训练过程中的历史梯度进行调整,对于稀疏梯度较大的参数,降低学习率;对于稀疏梯度较小的参数,增加学习率。这样可以在不同参数上采用不同的学习率,提高收敛速度。
  • Adadelta:与Adagrad类似,但进一步解决了Adagrad学习率递减过快的问题。Adadelta不仅考虑了历史梯度,还引入了一个累积的平方梯度的衰减平均,以动态调整学习率。
  • RMSprop:也是一种自适应学习率的方法,通过使用梯度的指数加权移动平均来调整学习率。RMSprop结合了Adagrad的思想,但使用了衰减平均来减缓学习率的累积效果,从而更加稳定。

b. 梯度估计修正

  • Momentum:使用梯度的“加权移动平均”作为参数的更新方向。Momentum方法引入了一个动量项,用于加速梯度下降的过程。通过积累之前的梯度信息,可以在更新参数时保持一定的惯性,有助于跳出局部最优解、加快收敛速度。
  • Nesterov accelerated gradient:Nesterov加速梯度(NAG)是Momentum的一种变体。与Momentum不同的是,NAG会先根据当前的梯度估计出一个未来位置,然后在该位置计算梯度。这样可以更准确地估计当前位置的梯度,并且在参数更新时更加稳定。
  • 梯度截断(Gradient Clipping):为了应对梯度爆炸或梯度消失的问题,梯度截断的方法被提出。梯度截断通过限制梯度的范围,将梯度控制在一个合理的范围内。常见的梯度截断方法有阈值截断和梯度缩放。

3. 梯度估计修正:动量法Momentum

【深度学习实验】网络优化与正则化(一):优化算法:使用动量优化的随机梯度下降算法(Stochastic Gradient Descent with Momentum)

4. 自适应学习率

【深度学习实验】网络优化与正则化(二):基于自适应学习率的优化算法详解:Adagrad、Adadelta、RMSprop

5. Adam算法

  Adam算法(Adaptive Moment Estimation Algorithm)[Kingma et al., 2015]可以看作动量法和 RMSprop 算法的结合,不但使用动量作为参数更新方向,而且可以自适应调整学习率
【深度学习实验】网络优化与正则化(三):随机梯度下降的改进——Adam算法详解(Adam≈梯度方向优化Momentum+自适应学习率RMSprop)~入选综合热榜
在这里插入图片描述

四、参数初始化

【深度学习实验】网络优化与正则化(四):参数初始化及其Pytorch实现——基于固定方差的初始化(高斯、均匀分布),基于方差缩放的初始化(Xavier、He),正交初始化

五、数据预处理

【深度学习实验】网络优化与正则化(五):数据预处理详解——标准化、归一化、白化、去除异常值、处理缺失值~入选综合热榜
在这里插入图片描述

六、逐层归一化

【深度学习实验】网络优化与正则化(六):逐层归一化方法——批量归一化、层归一化、权重归一化、局部响应归一化

七、超参数优化

0. 前期准备

a. 神经网络模型

class SimpleNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size, output_size)
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.softmax(x)
        return x

b. 训练和评估函数

def train_and_evaluate(model, X_train, y_train, X_val, y_val, criterion, optimizer, epochs=10):
    for epoch in range(epochs):
        model.train()
        optimizer.zero_grad()
        outputs = model(X_train)
        loss = criterion(outputs, y_train)
        loss.backward()
        optimizer.step()

    model.eval()
    val_outputs = model(X_val)
    _, predictions = torch.max(val_outputs, 1)
    val_accuracy = accuracy_score(y_val.numpy(), predictions.numpy())
    return val_accuracy

c. 分类数据

在这里插入代码片

1. 网格搜索

  网格搜索(Grid Search)是一种穷举搜索方法,它尝试在预定义的超参数空间中的所有可能组合中找到最佳配置。具体来说,如果总共有 K K K个超参数,每个超参数可以取 m k m_k mk 个不同的值,那么网格搜索将尝试 m 1 × m 2 × . . . × m K m_1 × m_2 × ... × m_K m1×m2×...×mK 个不同的超参数组合。
  在网格搜索中,如果某些超参数是连续的,而不是离散的,可以将其离散化为几个"经验"值。这样做的目的是为了限制搜索空间,以便更有效地寻找最佳配置。虽然这种方法可能会在某些情况下忽略超参数的细微变化,但在实践中,它可以帮助减少搜索的复杂性。
  网格搜索是一种简单但有效的方法,特别适用于超参数空间较小的情况。然而,对于超参数空间较大或高维的情况,随机搜索、贝叶斯优化或演化算法等方法可能更具优势,它们可以更灵活地探索超参数空间,而不会受到穷举搜索的限制。

a. 基本步骤

  1. 定义超参数空间: 首先,需要明确定义每个超参数的可能取值。这可以通过指定每个超参数的候选值范围来完成。
  2. 创建参数网格: 对于每个超参数,选择一组候选值。将这些候选值组合成一个网格,即每个超参数的所有可能组合。如果超参数的取值空间是离散的,那么可以使用所有可能的离散值;如果是连续的,可以选择一些合适的离散化值。
  3. 设置评估指标: 定义一个评估指标,用于度量每个超参数组合的性能。这通常是在验证集或开发集上的性能表现,如准确率、误差率等。目标是最小化或最大化该指标,具体取决于任务类型。
  4. 训练和评估模型: 对于每个超参数组合,在训练集上训练模型,并在验证集上评估性能。使用定义的评估指标来度量每个模型的性能。
  5. 选择最佳超参数组合: 通过比较所有超参数组合的性能,选择具有最佳性能的超参数组合。
  6. 可视化和分析: 可以通过可视化方法,如学习曲线或热力图,来进一步分析超参数的影响。这有助于了解模型在超参数空间中的表现。
  7. 验证和测试: 最终,使用选定的最佳超参数组合在测试集上验证模型的性能,确保所选超参数对未见数据的泛化效果。

b. 代码实现

hidden_sizes = [64, 128, 256]
learning_rates = [0.001, 0.01, 0.1]

best_accuracy = 0
best_params = {}

for hidden_size in hidden_sizes:
    for learning_rate in learning_rates:
        model = SimpleNN(input_size=20, hidden_size=hidden_size, output_size=2)
        optimizer = SGD(model.parameters(), lr=learning_rate)
        criterion = nn.CrossEntropyLoss()

        accuracy = train_and_evaluate(model, torch.FloatTensor(X_train), torch.LongTensor(y_train),
                                      torch.FloatTensor(X_test), torch.LongTensor(y_test), criterion, optimizer)

        if accuracy > best_accuracy:
            best_accuracy = accuracy
            best_params = {'hidden_size': hidden_size, 'learning_rate': learning_rate}

print("Grid Search - Best Parameters:", best_params)
print("Grid Search - Best Accuracy:", best_accuracy)

2. 随机搜索

  随机搜索是一种更灵活的超参数优化方法,相较于网格搜索,它不受先验定义的超参数网格的限制。通过在超参数空间中进行随机采样,随机搜索能够更有效地探索可能的超参数组合,特别是当某些超参数对模型性能的影响相对较小或难以预测时。
  随机搜索的主要优势在于它避免了网格搜索中的过度尝试不重要的超参数组合。对于那些对性能有较大影响的超参数,随机搜索有更大的可能性在更早的阶段找到优秀的配置,而不受网格搜索的较粗略采样的限制。

a. 基本步骤

  1. 定义超参数空间: 确定每个超参数的可能取值范围。这可以是一个离散的集合,也可以是一个连续的区间。
  2. 选择随机超参数组合: 对于每次迭代,从超参数空间中随机选择一个超参数组合。这可以通过在每个超参数的取值范围内进行均匀或非均匀的随机采样来完成。
  3. 训练和评估模型: 使用所选的超参数组合,在训练集上训练模型,并在验证集或开发集上评估性能。这通常涉及训练模型直到收敛或达到预定义的迭代次数。
  4. 更新最佳配置: 比较当前超参数组合的性能与已知的最佳性能,如果性能更好,则更新最佳配置。
  5. 重复迭代: 重复以上步骤,直到达到预定的迭代次数或计算资源限制。

b. 优缺点

  • 相对于网格搜索,随机搜索的主要优点在于:

    • 灵活性: 不受先验定义的网格限制,能够在超参数空间中更灵活地进行探索。
    • 高效性: 特别适用于超参数空间较大的情况,避免了网格搜索中不必要的尝试。
  • 然而,随机搜索也有一些局限性:

    • 不保证最优解: 由于是随机选择,不保证找到全局最优的超参数配置。
    • 不充分利用超参数之间的相关性: 与贝叶斯优化等方法相比,随机搜索不利用不同超参数之间的相关性,可能在搜索过程中浪费一些资源。

c. 代码实现

num_trials = 10

best_accuracy = 0
best_params = {}

for _ in range(num_trials):
    hidden_size = random.choice([64, 128, 256])
    learning_rate = random.choice([0.001, 0.01, 0.1])

    model = SimpleNN(input_size=20, hidden_size=hidden_size, output_size=2)
    optimizer = SGD(model.parameters(), lr=learning_rate)
    criterion = nn.CrossEntropyLoss()

    accuracy = train_and_evaluate(model, torch.FloatTensor(X_train), torch.LongTensor(y_train),
                                  torch.FloatTensor(X_test), torch.LongTensor(y_test), criterion, optimizer)

    if accuracy > best_accuracy:
        best_accuracy = accuracy
        best_params = {'hidden_size': hidden_size, 'learning_rate': learning_rate}

print("Random Search - Best Parameters:", best_params)
print("Random Search - Best Accuracy:", best_accuracy)

3. 贝叶斯优化

  贝叶斯优化是一种基于贝叶斯统计的自适应超参数优化方法,它通过在搜索空间中建立一个目标函数的概率模型,来智能地选择下一组待试验的超参数。这种方法相对于随机搜索和网格搜索更加高效,特别适用于计算资源受限的情况下。

a.基本步骤

  1. 定义超参数空间: 和其他优化方法一样,首先需要定义每个超参数的可能取值范围。
  2. 选择初始样本点: 选择一组初始的超参数样本点,通常是通过随机选择或者根据先验知识选择的。
  3. 建立概率模型: 使用已有的样本点,建立一个对目标函数的概率模型。常用的模型包括高斯过程(Gaussian Process)和随机森林。
  4. 选择下一个样本点: 基于当前的概率模型,选择下一个超参数样本点,这个选择通常是基于对目标函数的不确定性的评估。一种常见的策略是使用“概率提升(Probability of Improvement)”或“置信区间(Expected Improvement)”等指标来评估每个点的潜在收益。
  5. 采样和评估: 在选择的超参数点处进行模型的训练和评估,得到目标函数的值。
  6. 更新概率模型: 将新的样本点加入已有的样本,然后更新概率模型,以更准确地表示目标函数。
  7. 重复迭代: 重复上述步骤,直到达到预定的迭代次数或满足其他停止准则。

  贝叶斯优化的优势在于它能够根据已有样本来预测目标函数的形状,从而更聪明地选择下一个样本点,尤其在高维空间和计算资源有限的情况下表现得更为明显。时序模型优化(Sequential Model-Based Optimization,SMBO)是一种基于序列的贝叶斯优化方法,其中的“时序”指的是通过不断地迭代来逐步改善模型。

b. 代码实现

def objective(trial):
    hidden_size = trial.suggest_categorical('hidden_size', [64, 128, 256])
    learning_rate = trial.suggest_loguniform('learning_rate', 0.001, 0.1)

    model = SimpleNN(input_size=20, hidden_size=hidden_size, output_size=2)
    optimizer = SGD(model.parameters(), lr=learning_rate)
    criterion = nn.CrossEntropyLoss()

    accuracy = train_and_evaluate(model, torch.FloatTensor(X_train), torch.LongTensor(y_train),
                                  torch.FloatTensor(X_test), torch.LongTensor(y_test), criterion, optimizer)

    return -accuracy  # Optuna minimizes the objective function, so we use negative accuracy.

sampler = TPESampler(seed=42)
study = optuna.create_study(sampler=sampler)
study.optimize(objective, n_trials=10)

print("Bayesian Optimization - Best Parameters:", study.best_params)
print("Bayesian Optimization - Best Accuracy:", -study.best_value)  # Convert back to positive accuracy

在这里插入图片描述

4. 动态资源分配

  动态资源分配是一种在超参数优化中更加智能地分配有限资源的方法。它的核心思想是通过早期停止和逐次减半等策略,在训练过程中识别哪些超参数组合可能不会带来较好的性能,从而及时中止这些配置的评估,将资源更多地留给其他有潜力的配置。以下是动态资源分配的一般步骤,特别是逐次减半方法:

  1. 定义超参数空间和总资源预算: 和其他超参数优化方法一样,首先需要定义每个超参数的可能取值范围,并确定可用的总资源预算(例如,摇臂的次数)。
  2. 初始化超参数配置: 随机选择一组初始的超参数配置,并开始评估它们的性能。
  3. 逐次减半: 将总资源预算分配给一组超参数配置,并在每一轮中选择性能较好的一半进行下一轮的评估。这个过程会重复进行,逐次减半资源分配,直到达到预定的轮数或资源用尽。
  4. 早期停止策略: 对于正在评估的每个超参数配置,可以通过监测学习曲线的形状,比如早期停止来判断是否中止当前训练。如果学习曲线不收敛或者收敛较差,可以中止当前训练,将资源留给其他配置。
  5. 选择最佳超参数配置: 根据逐次减半的过程,选择性能最好的超参数配置作为最终的结果。

  逐次减半方法通过在每一轮中聚焦于性能较好的超参数配置,更有可能找到全局最优或局部最优的配置。这种方法尤其适用于计算资源受限的情况,可以在较短时间内找到性能较好的超参数配置。
在这里插入图片描述

5. 神经架构搜索

  神经架构搜索(Neural Architecture Search,NAS)是一种探索神经网络结构的自动化方法。与传统的由人类专家手动设计神经网络结构不同,NAS旨在通过使用机器学习技术来搜索神经网络的结构,以提高性能。基本上,神经架构搜索的目标是找到一个最优的神经网络结构,使得在给定任务上的性能达到最佳。这可以通过定义一个搜索空间,其中包含各种可能的网络结构来实现。每个网络结构都可以用一个参数化的描述来表示,通常是一个变长的字符串。这个描述包含了网络的层次结构、每一层的类型、连接方式等信息。

  神经架构搜索通常采用元学习的思想。这意味着有一个控制器,负责生成神经网络结构的描述。这个控制器本身可以是一个循环神经网络(RNN),它学会生成有效的网络结构描述。控制器的训练过程通常使用强化学习来完成。奖励信号一般是由生成的子网络在开发集或验证集上的性能,例如准确率。整个神经架构搜索的流程如下:

  1. 定义搜索空间: 确定神经网络结构的参数化表示,并定义一个搜索空间,包含各种可能的网络结构。
  2. 设计控制器: 创建一个控制器,通常是一个循环神经网络(RNN),负责生成神经网络结构的描述。
  3. 初始化控制器: 初始化控制器的参数。
  4. 强化学习训练: 通过强化学习算法,如REINFORCE,训练控制器。在每一轮训练中,生成一个网络结构描述,训练该结构的子网络,然后使用性能作为奖励信号来更新控制器的参数。
  5. 搜索过程: 通过不断迭代上述过程,搜索最佳的神经网络结构描述。
  6. 评估最优结构: 使用测试集评估最终选择的最优神经网络结构的性能。

  神经架构搜索的优势在于它可以自动发现复杂的网络结构,而不需要人类专家的介入。这使得神经网络设计更具有普适性和适应性,能够更好地适应不同的任务和数据。然而,NAS也面临着计算资源消耗大、搜索空间巨大等挑战。近年来,许多改进的方法和算法被提出,以提高神经架构搜索的效率。

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

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

相关文章

万宾科技智能井盖传感器,提升市政井盖健康

市政井盖就是城市里不可或缺的基础设施之一,关于它的监测工作可马虎不得。它承载着保护市民的交通安全以及城市正常运转的重要使命。虽然现在城市化的速度很快,但是传统的市政井盖管理方式变得有些力不从心了。井盖的覆盖范围很广,如果单单依…

Python爬虫动态ip代理防止被封的方法

目录 前言 一、什么是动态IP代理? 二、如何获取代理IP? 1. 付费代理IP 2. 免费代理IP 3. 自建代理IP池 三、如何使用代理IP爬取数据? 1. 使用requests库设置代理IP 2. 使用urllib库设置代理IP 3. 使用selenium库设置代理IP 四、常…

实现MQTT协议的服务器端和客户端的双向交互

公司和第三方合作开发一个传感器项目,想要通过电脑或者手机去控制项目现场的传感器控制情况。现在的最大问题在于,现场的边缘终端设备接入的公网方式是无线接入,无法获取固定IP,所以常规的HTTP协议通信就没法做,现在打…

群晖7.2安装Jellyfin+alist+CloudDriver搭建无盘影院中心

群晖7.2安装JellyfinalistCloudDriver搭建无盘影音中心。 实现思路如下: Jellyfin:提供个人影院功能。 alist(xiaoya):给影院提供海量影音资源。 CloudDriver2:alist的资源为网络资源,通过C…

lvgl 画圆弧时进入 HardFault

目录 一、现象描述 lvgl 版本 二、问题分析 lvgl 需要的资源新建mcu 工程时默认分配的资源问题解决 一、现象描述 移植完lvgl 之后,能正常显示label,但是button arc 等复杂的控件都不能正常显示。调用官方的画圆弧demo 时,在多次调用 _lv…

业务流程图用什么软件画?这10款流程图软件,好用到飞起!

业务流程图是什么? 业务流程图是一种用于表示业务过程中活动流向的图形表示方法,它使用标准化的图形元素(如箭头、椭圆、方框等)来表达一个过程中各个环节之间的关系。在这个图形表示中,每个元素都有特定的含义和功能…

C#WPF用户控件及自定义控件实例

本文演示C#WPF自定义控件实例 用户控件(UserControl)和自定义控件(CustomControl)都是对UI控件的一种封装方式,目的都是实现封装后控件的重用。 只不过各自封装的实现方式和使用的场景上存在差异。 1 基于UserControl 创建 创建控件最简单一个方法就是基于UserControl …

Docker在Centos7下的安装

1、卸载旧版本 执行如下指令对旧版本进行卸载: sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 执行完毕后,如果输入docker version发现do…

【MySQL学习笔记-001】- 创建表、插入数据、查看数据库结构

创建employees表 当创建一个表时,需要指定表的名称和每个列的名称和数据类型。以下是一个示例SQL语句,用于创建一个名为"employees"的表,其中包含员工ID、姓名、职位和工资等列: CREATE TABLE employees (employee_id…

单稳态中间继电器\UEG/A-2H/220V 8A导轨安装 JOSEF约瑟

UEG系列中间继电器 UEG/A-2H2D中间继电器UEG/A-4H4D中间继电器UEG/A-2D中间继电器 UEG/A-2H中间继电器UEG/A-4H中间继电器UEG/A-4D中间继电器 UEG/A-6H中间继电器UEG/A-6D中间继电器UEG/A-8H中间继电器 UEG/A-10D中间继电器UEG/A-10H中间继电器UEG/A-2DPDT中间继电器 UEG/A-4DP…

23111710[含文档+PPT+源码等]计算机毕业设计基于SpringBoot的体育馆场地预约赛事管理系统的设计

文章目录 **软件开发环境及开发工具:****功能介绍:****论文截图:****数据库:****实现:****代码片段:** 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 软件开发环境及…

国民技术Cortex-M0系列单片机IAP升级

考虑到设备部署到现场后有可能需要进行软件升级,之前做过PIC系列单片机的升级,现在想做个国民技术N32G031系列Cortex-M0内核的单片机IAP方案。 因为国民技术系列单片机在很多大程度上都模仿了STM32,所以我想其升级方案极有可能差不多。于是在…

C#开发的OpenRA游戏之属性BodyOrientation(6)

C#开发的OpenRA游戏之属性BodyOrientation(6) 在顶层定义里会发现这个属性: ^SpriteActor: BodyOrientation: QuantizeFacingsFromSequence: RenderSprites: SpriteActor是用来定义角色的基本属性,它的第一个属性就是BodyOrientation,这个属性主要用来描述角色的身体的…

DOA估计算法——Capon算法

1.波速形成基本思想 在理解Capon算法之前,我们有必要先了解波束形成的基本思想以及原理到底是什么。这有助于我们更好的理解Capon算法的思想。 图 1 如图1展示了均匀阵列波束导向的示意图。图中wm表示加权值,波速形成(DBF)的基本思想就是将各阵元输出进…

AVL树的底层实现

文章目录 什么是AVL树?平衡因子Node节点插入新节点插入较高左子树的左侧新节点插入较高左子树的右侧新节点插入较高右子树的左侧新节点插入较高右子树的右侧 验证是否为平衡树二叉树的高度AVL的性能 什么是AVL树? AVL树又称平衡二叉搜索树,相…

基于ssm+vue的程序设计课程可视化教学系统设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

Jmeter进行压力测试不为人知的秘密

jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单。因为jmeter是java开发的,所以运行的时候必须先要安装jdk才可以。jmeter是免…

Mysql中的进阶增删查改操作(二)

联合查询和合并查询 一.联合查询1.内连接2.外链接2.1左外连接2.2右外连接 3.自连接4.子查询5.合并查询 一.联合查询 步骤 1.进行笛卡尔积 2.列出连接条件 3.根据需求再列出其他条件 4.针对列进行精简(可以使用聚合函数) 我们先搭建一个多表查询的框架 这样一个多表查询就搭建出…

换硬币C语言(超详细分析!包会)

换硬币C语言(详解) 题目介绍分析题目代码题目讲解 题目介绍 分析 通过枚举的方式找出所有可能的找零方案,并统计满足条件的方案的个数。使用三层嵌套的循环遍历所有可能的组合,判断总金额是否等于给定的金额 x,并输出…