Pytorch常用的函数(八)常见优化器SGD,Adagrad,RMSprop,Adam,AdamW总结

Pytorch常用的函数(八)常见优化器SGD,Adagrad,RMSprop,Adam,AdamW总结

  • 在深度学习中,优化器的目标是通过调整模型的参数,最小化(或最大化)一个损失函数。

  • 优化器使用梯度下降等迭代方法来更新模型的参数,以使损失函数达到最优或接近最优。

在这里插入图片描述

  • 如下图,优化算法可分为一阶算法和二阶算法,常用的是一阶算法,今天主要介绍下一阶优化相关的优化器。

在这里插入图片描述

1 SGD优化算法

1.1 梯度下降法概述

1.1.1 梯度下降法概念

        梯度下降法(Gradient Descent)是一种常用的优化算法,用于最小化(或最大化)一个函数。在机器学习和深度学习中,梯度下降法被广泛应用于训练模型,通过调整模型的参数来最小化损失函数。

θ = θ − α ∗ Δ J ( θ ) θ = θ - α * \Delta J(θ) θ=θαΔJ(θ)

其中:

  • θ表示要更新的参数向量或矩阵。
  • α是学习率(learning rate),控制参数更新的步长。
  • ∇J(θ)是损失函数J关于参数θ的梯度向量。

1.2 梯度下降法三个变种

1.2.1 批量梯度下降BGD

        BGD是批量梯度下降(Batch Gradient Descent)的缩写,是一种基本的梯度下降优化算法。在批量梯度下降中,每次参数更新时使用整个训练数据集的梯度.

计算公式

在这里插入图片描述

图示

在这里插入图片描述

特点

  • 全局最优解:由于BGD使用整个训练数据集的梯度,它有潜力收敛到全局最优解(如果存在)。
  • 低效性:BGD的计算开销较大,因为在每次参数更新步骤中需要计算整个数据集的梯度。对于大规模系统和大型数据集,这可能会导致训练时间较长。
  • 稳定性:由于使用整个数据集的梯度,BGD的参数更新相对稳定,不容易受到单个样本或噪声的影响。
  • 需要注意的是,尽管BGD可能收敛到全局最优解,但它也可能陷入糟糕的局部最小值中。
1.2.2 随机梯度下降SGD

        随机梯度下降(Stochastic Gradient Descent,SGD)是一种基于随机采样的梯度下降优化算法。与批量梯度下降(BGD)每次都使用整个训练数据集的梯度相比,SGD每次仅使用单个样本或一小批样本的梯度进行参数更新。

计算公式

在这里插入图片描述

图示

在这里插入图片描述

特点

  • 更快的更新速度:由于每次更新只使用一个样本或一小批样本的梯度,SGD的参数更新速度比BGD更快。这使得SGD在大规模数据集上具有优势,特别是在迭代次数较少的情况下。
  • 可能陷入局部最小值:由于使用随机采样的梯度,SGD的参数更新在每次迭代中都具有一定的随机性。这可能导致SGD在搜索空间中陷入局部最小值,而无法达到全局最优解。
  • 然而,这种随机性也有助于SGD跳出局部最小值并继续搜索更好的解。
  • 由于其随机性采样和快速更新的特点,SGD能够在多个局部最小值之间进行搜索,有助于找到更好的局部最小值或接近全局最优解。
1.2.3 小批量梯度下降Mini-BGD

        Mini-Batch Gradient Descent(小批量梯度下降)是介于批量梯度下降(BGD)和随机梯度下降(SGD)之间的一种梯度下降优化算法。它在每次参数更新时使用一小批次的样本来计算梯度和更新参数.

计算公式

在这里插入图片描述

图示

在这里插入图片描述

特点

  • 折中的更新速度:相比于BGD,Mini-Batch Gradient Descent的参数更新速度更快,因为每次使用的样本数量较少。这使得Mini-Batch Gradient Descent在大规模数据集上具有一定的优势。与SGD相比,Mini-Batch Gradient Descent的参数更新速度较慢,但相对更稳定。
  • 梯度估计的抖动减少:与SGD相比,Mini-Batch Gradient Descent的梯度估计具有更小的抖动。由于使用的是一小批次的样本,梯度计算的结果更加平滑,减少了随机性带来的波动。
  • 内存效率:相对于BGD需要存储整个训练数据集的梯度以及SGD需要存储单个样本的梯度,Mini-Batch Gradient Descent在内存使用方面更有效率。它只需存储每个小批量样本的梯度,使得在处理大型数据集时更加可行。
  • 可调节的更新步长:Mini-Batch Gradient Descent的学习率可以根据需要进行调整,以控制参数更新的步长。这使得算法能够更好地平衡快速收敛和避免震荡之间的权衡。

注意:下文SGD一般为小批量梯度下降Mini-BGD

1.2 带动量的SGD(常用)

        虽然随机梯度下降仍然是非常受欢迎的优化方法,但其学习过程有时会很慢。动量方法 (Polyak, 1964) 旨在加速学习, 特别是处理高曲率、小但一致的梯度, 或是带噪声的梯度。动量算法积累了之前梯度指数级衰减的移动平均, 并且继续沿该方向移动。

1.2.1 算法过程

在这里插入图片描述

实践中, α 的一般取值为0.5,0.9 和0.99。

1.2.2 算法图示

在这里插入图片描述

动态效果展示

在这里插入图片描述

1.2.3 特点

  1. 动量的积累:带动量的随机梯度下降利用一个动量变量来积累梯度的历史信息。在每次参数更新时,动量项会考虑前一次更新的方向和幅度。
  2. 加速参数更新:由于动量的引入,带动量的随机梯度下降可以加速参数更新的速度。当梯度在相同方向上持续增加时,动量项会逐渐增大,从而加速参数更新。这有助于在梯度方向上形成更大的动量,更快地接近最优解。
  3. 减少参数更新方向的震荡:动量项可以减少参数更新方向的震荡,特别是在存在噪声或不稳定梯度的情况下。通过考虑历史梯度的平均方向,动量可以平滑参数更新的路径,减少震荡现象。

1.2.4 作用

  • 加速收敛:带动量的随机梯度下降可以加速模型的收敛速度。通过积累历史梯度信息,它能够更快地朝着梯度下降的方向移动,从而加速参数的更新过程。
  • 跳出局部最小值:由于动量的引入,带动量的随机梯度下降能够在搜索空间中跳出局部最小值并继续寻找更好的解。通过考虑历史梯度的方向和幅度,动量项可以帮助算法在平坦区域上获得更大的动量,并有助于跳过局部极小点。
  • 平滑参数更新路径:动量项可以减少参数更新方向的震荡。通过考虑历史梯度的平均方向,带动量的随机梯度下降可以平滑参数更新的路径,使得参数更新更加稳定。

1.3 NAG

1.3.1 算法原理

        等价于 SGD with Nesterov Momentum,利用当前位置处先前的梯度值先做一个参数更新,然后在更新后的位置再求梯度,将此部分梯度然后跟之前累积下来的梯度值矢量相加,简单的说就是先根据之前累积的梯度方向模拟下一步参数更新后的值,然后将模拟后的位置处梯度替换动量方法中的当前位置梯度。

        现在有一个预测后一步位置梯度的步骤,所以当在山谷附近时,预测到会跨过山谷时(跨过山谷后梯度方向会发生变化),该项梯度就会对之前梯度有个修正,相当于阻止了其跨度太大。

1.3.2 算法原理图

SGD with Momentum

在这里插入图片描述

NAG

在这里插入图片描述

1.3.3 算法详述

在这里插入图片描述

        动量的方法,我们发现参数更新是基于两部分组成,一部分为当前位置的梯度,另一部分为前面累计下来的梯度值,参数更新方向就是将两者矢量相加的方向,但是我们会发现一个问题,当刚好下降到山谷附近时,如果这个时候继续以这样的方式更新参数,我们会有一个较大的幅度越过山谷,即:模型遇到山谷不会自动减弱更新的幅度。

  • 论文:On the importance of initialization and momentum in deep learning

1.4 Pytorch 中SGD的实现

torch.optim.SGD(params,          # 优化器要优化的参数lr=0.001,        # 初始学习率momentum=0,      # 动量,一般设置为0.9dampening=0, weight_decay=0,  # 权值衰减系数,也就是L2正则项的系数nesterov=False,  # 是否启用NAG*, maximize=False,  # 默认是最小化lossforeach=None, differentiable=False
)

在这里插入图片描述

  • SGD开启动量梯度时,额外的内存/显存消耗只有momentum_buffer,是1倍的模型参数量;
  • 不开启动量梯度则没有额外内存/显存消耗。

2 AdaGrad优化算法

2.1 自适应学习率

  • Adagrad(Adaptive Gradient)的核心思想是,深度模型带来的稀疏性,导致模型中一些参数可能频繁获得较大梯度,另一些参数偶尔获得较大梯度,若采用统一学习率导致后者的更新会非常缓慢。基于此,可以调节模型中不同参数的学习率,而不是用统一的学习率。
  • 如果一个参数的历史累计梯度更新量大,则降低该参数的学习率;如果一个参数的历史累计梯度更新量小,则增大该参数的学习率。

2.2 AdaGrad 算法

在这里插入图片描述

  • 因为梯度有正有负,所以对梯度的平方进行累计,然后再开根号。
  • 为了避免分母为0,加了一项随机扰动 δ \delta δ
  • 可以看成对每个参数分别调节学习率,也可以看成调节每个参数的梯度。

2.3 AdaGrad优缺点

优点:

  • 前期较小的时候, 分母较小,能够放大梯度;
  • 后期较大的时候, 分母较大,能够约束梯度;
  • 无需手动调整梯度;
  • 这一方法在稀疏数据场景下表现非常好。

缺点:

  • 仍依赖于人工设置一个全局学习率,一般采用默认值0.01;
  • 中后期,分母上梯度平方的累加将会越来越大,分母会不断积累使 Δ θ t Δθ_t Δθt趋近于0,学习率就会收缩并最终会变得非常小使得训练提前结束

2.6 pytorch 中AdaGrad的实现

torch.optim.Adagrad(params, lr=0.01,                     # 学习率lr_decay=0,                  # 学习率衰减系数weight_decay=0,              # 权重衰减系数initial_accumulator_value=0, eps=1e-10,                   # 添加到分母以提高数值稳定性foreach=None, *, maximize=False,              # 默认最小化lossdifferentiable=False
)

在这里插入图片描述

  • Adagrad优化器实现中加入了学习率衰减机制、权重衰减机制;
  • 该算法需要给每一个待更新的模型参数设置一个累计统计量 s t a t e _ s u m t − 1 state\_sum_{t-1} state_sumt1 ,所以额外的内存/显存消耗是1倍的模型参数量。
  • 论文:Adaptive Subgradient Methods for Online Learning and Stochastic Optimization

3 RMSProp优化算法

3.1 概述

  • RMSProp(root mean square propagation)优化算法是Hinton提出的,也属于自适应梯度范畴。
  • 指数移动平均EMA(Exponential Moving Average),是一种给予近期数据更高权重的平均方法。
  • 区别于Adagrad之处是它采用了EMA方式来统计每个参数的最近的累计梯度量,所以多次迭代后不会导致模型参数更新缓慢
  • RMSProp适合处理非平稳目标 - 对于RNN效果很好。
  • 不过,RMSProp依然依赖于全局学习率。

3.2 算法流程

  • RMSProp算法是AdaGrad算法的改进,修改AdaGrad以在非凸条件下效果更好,解决了AdaGrad所面临的问题。
  • RMSProp主要思想:使用指数加权移动平均的方法计算累积梯度,以丢弃遥远的梯度历史信息。
  • 不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。

RMSProp 的标准形式

在这里插入图片描述

带Nesterov 动量的形式

在这里插入图片描述

  • Hinton 建议设定 γ 为 0.9, 学习率 η 为 0.001。

3.3 pytorch 实现

torch.optim.RMSprop(params, lr=0.01,        # 学习率alpha=0.99,     # 平滑常数eps=1e-08,      # 添加到分母以提高数值稳定性weight_decay=0, # 权重衰减momentum=0,     # 动量因子centered=False, # 如果为True,则计算中心化的RMSProp,梯度将通过其方差的估计进行归一化foreach=None,maximize=False, differentiable=False
)

在这里插入图片描述

  • RMSProp优化器实现中还加入了权重衰减机制、动量梯度机制;
  • centered参数,其主要是通过估计方差来对梯度进行归一化,主要操作就是让二阶动量去减去平均梯度的平方,这样会使得结果更加平稳;
  • 该算法需要给每一个待更新的模型参数设置一个累计梯度统计量 v t v_t vt 、一个自适应梯度的动量 b t b_t bt ,所以额外的内存/显存消耗是2倍的模型参数量。

4 Adadelta

4.1 概述及算法流程

  • 从时间线上来看,AdaGrad算法是由John Duchi等人在2011年提出的。RMSProp算法是由Hinton在2012年提出的,Adadelta算法由Matthew D. Zeiler同样在2012年提出。

  • 我们已经知道,RMSProp是在AdaGrad的基础上引入了衰减量,从而解决不断地累加二阶动量导致最终学习率会接近于零以及训练提前终止的问题。

  • RMSProp优化器虽然可以对不同的权重参数自适应的改变学习率,但仍依赖于全局学习率。AdaDelta优化器对RMSProp算法进一步优化:AdaDelta算法额外维护一个状态变量 Δ x t Δx_t Δxt,并使用 R M S [ Δ x ] t RMS[Δx]_t RMS[Δx]t代替 RMSProp 中的学习率参数,使AdaDelta优化器不需要指定学习率这个超参数

    在这里插入图片描述

  • Adadelta在训练初中期,加速效果不错,很快;但是训练后期,反复在局部最小值附近抖动

算法流程如下:

在这里插入图片描述

4.2 pytorch 实现

  • 可以看到与RMSProp的区别就是加入了 u t u_t ut

在这里插入图片描述

  • 论文:ADADELTA: An Adaptive Learning Rate Method

4.3 不同优化算法效果对比

在这里插入图片描述

  • 从上图展现了不同算法在鞍点处的表现。
  • 这里,SGD、SGD-M、NAG 都受到了鞍点的严重影响,尽管后两者最终还是逃离了鞍点;
  • 而 Adagrad、RMSprop、Adadelta 都很快找到了正确的方向。

在这里插入图片描述

  • 从上图中可以看到不同算法在损失面等高线图中的学习过程,它们均同同一点出发,但沿着不同路径达到最小值点。
  • 其中 Adagrad、Adadelta、RMSprop 从最开始就找到了正确的方向并快速收敛;
  • SGD 找到了正确方向但收敛速度很慢;
  • SGD-M 和 NAG 最初都偏离了航道,但也能最终纠正到正确方向,SGD-M 偏离的惯性比 NAG 更大。

5 Adam 优化器(常用)

5.1 概述及算法实现流程

  • Adam是前述方法的集大成者。SGD-M在SGD基础上增加了一阶动量,AdaGrad和AdaDelta在SGD基础上增加了二阶动量。把一阶动量和二阶动量都用起来,就是Adam了。

  • Adam 算法即自适应矩估计(Adaptive Moment Estimation)方法。Adam算法的本质:其实就是Momentum+RMSProp的结合,然后再修正其偏差

  • Adam通常被认为对超参数的选择相当鲁棒,同时相比于AdaGrad,不用存储全局所有的梯度,适合处理大规模数据

  • 特点:

    • 结合了AdaGrad善于处理稀疏梯度和RMSProp善于处理非平稳目标的优点
    • 对内存需求较小
    • 为不同的参数计算不同的自适应学习率
    • 也适用于大多非凸优化
    • 适用于大数据集和高维空间
  • 论文:ADAM: A METHOD FOR STOCHASTIC(随机) OPTIMIZATION
    在这里插入图片描述

5.2 pytorch 实现

torch.optim.Adam(params, lr=0.001,              # 学习率betas=(0.9, 0.999),    # 平滑常数eps=1e-08,             # 添加到分母以提高数值稳定性weight_decay=0,        # 权重衰减,注意:这里加到梯度上amsgrad=False,         # 如果amsgrad为True,保留历史最大的,记为v_{max},每次计算都是用最大的v_{max},否则是用当前v_t*, foreach=None, maximize=False,capturable=False, differentiable=False, fused=None)

在这里插入图片描述

5.3 效果展示

在这里插入图片描述

6 AdamW(常用)

6.1 算法原理

  • 我们已经知道Adam是集成一阶动量和二阶动量的优化器。AdamW是在Adam的基础上加入了weight decay正则化,但是Adam中已经有正则化,那么两者有什么区别呢?

  • 其实AdamW和Adam唯一的区别,就是weight decay的加入方式

    • 在Adam当中,weight decay是直接加入到梯度当中(如下图紫色部分);
    • AdamW直接在权重上进行衰减(如下图绿色)。
  • 人们发现,理论上更优的Adam算法,有时表现并不如SGD momentum好,尤其是在模型泛化性上。

    • 我们知道,L2范数(也叫权重衰减,weight decay)有助于提高模型的泛化性能。

    • 但是AdamW的作者证明,Adam算法弱化了L2范数的作用,所以导致了用Adam算法训练出来的模型泛化能力较弱。

    • 具体来说,在Adam中,权重衰减的梯度是直接加在 g t g_t gt 上的,这就导致权重衰减的梯度也会随着 g t g_t gt 去除以分母。当梯度的平方和累积过大时,权重衰减的作用就会被大大削弱。

在这里插入图片描述

在这里插入图片描述

  • 论文:DECOUPLED(解耦) WEIGHT DECAY REGULARIZATION

6.2 pytorch实现

torch.optim.AdamW(params, lr=0.001,betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, # 这里直接在权重上进行衰减amsgrad=False, *, maximize=False, foreach=None, capturable=False,differentiable=False, fused=None
)

在这里插入图片描述

6.3 Optimizer 收敛趋势对比图

在这里插入图片描述

参考:

  • Optimization Algorithms
  • github optimize demo
  • 论文:An overview of gradient descent optimization algorithms
  • Machine Learning Optimization Methods : Mechanics, Pros, And Cons

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

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

相关文章

【QT进阶】Qt http编程之实现websocket server服务器端

往期回顾 【QT进阶】Qt http编程之json解析的简单介绍-CSDN博客 【QT进阶】Qt http编程之nlohmann json库使用的简单介绍-CSDN博客 【QT进阶】Qt http编程之websocket的简单介绍-CSDN博客 【QT进阶】Qt http编程之实现websocket server服务器端 一、最终效果 通过ip地址和端口…

人工智能时代的关键技术:深入探索向量数据库及其在AI中的应用

文章目录 1. 理解向量数据库:二维模型示例2. 向量数据库中的数据存储与检索3. 向量数据库如何工作?4. 向量数据库如何知道哪些向量相似? 在人工智能技术日益成熟的当下,向量数据库作为处理和检索高维数据的关键工具,对…

【治理与监管题】

https://www.pcisecuritystandards.org/ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-88r1.pdf 介绍 网络安全是一个快速发展的环境,恶意行为者不遗余力地利用高度敏感系统中的漏洞,通常旨在造成敏感企业数据的严重破坏、破坏和…

Dropout Feature Ranking for Deep Learning Models

摘要 深度神经网络( deep neural networks,DNNs )在多个领域取得了最新的研究成果。不幸的是,DNNs因其不可解释性而臭名昭著,从而限制了其在生物和医疗保健等假说驱动领域的适用性。此外,在资源受限的环境下,设计依赖…

StorCli工具学习记录

StorCli工具学习记录 StorCLI(Storage Command Line Interface)是一款强大的命令行管理工具,用于管理和配置存储控制器。这一工具主要适用于Broadcom(原LSI)及Intel RAID控制器。 下面将详细介绍StorCLI的安装、特点、…

数据结构 - 顺序表实现通讯录

test.c文件 #define _CRT_SECURE_NO_WARNINGS 1#include "Contact.h" int main() {Con myContacts;ConInit(&myContacts);int choice;int index;char targetName[100];PerInfo contact; // 创建一个新的联系人信息实例while (1) {printf("\n--- 通讯录管理…

Linux下的UDEV机制/守护进程

一. Udev机制概念引入 ( 需要在 etc/udev/rules.d/ 下创建设备的相关规则,不然有可能udev机制生成的设备文件不具备可读可写的权限,adb无法成功通过该设备文件访问设备 ) a. 创建文件夹 sudo vim Xiaomi-audroid.rules b. 添加规则 …

景区ar导览实景导航小程序系统开发源码搭建

开发景区AR导览实景导航小程序系统需要以下步骤: 1. 确定需求和功能:根据景区AR导览实景导航的需求和功能,确定需要开发哪些功能模块,如AR实景导航、语音讲解、景点介绍、路线规划等。 2. 确定技术方案:选择适合的技…

在vscode上面进行分支merge的记录

前言:在我们的项目中,有两个分支:master和liutielong。现在要将liutielong分支的改动merge到master分支中。 如果master分支已经更改了,所以要先pull(这是在git bash里面的命令)。 git pull origin master…

5分钟——快速搭建后端springboot项目

5分钟——快速搭建后端springboot项目 1. idea新建工程2. 构建pom.xml文件3. 构建application.yml配置文件4. 构建springboot启动类5. 补充增删改查代码6. 运行代码 1. idea新建工程 点击右上角新建一个代码工程 别的地方不太一样也不用太担心,先创建一个工程就好…

学习配置文件

1.yml的语法格式问题: 2.配置文件获取数据: Value方式: Environment: 获取自定义对象的方式: 设置get和set方法,还有toString方法。 3. 日志配置: logo的配置: 日志插件&#xff…

汽车纵染压制专用液压机比例阀放大器

汽车纵染压制专用液压机比例阀放大器是一种专门用于汽车纵梁拉伸工艺的设备,它也可以用于其他金属薄板的压制成型及校正工艺。该类型的液压机通常具备独立的动力机构和电气系统,采用PLC技术进行控制,以确保操作的准确性和稳定性。除了纵梁拉伸…

【iOS】分类,扩展与关联对象

文章目录 前言一、分类实现原理二、分类加载流程三、扩展四、类别与类扩展的区别五、关联对象动态添加取值移除关联对象应用 总结 前言 上一篇章我们探究了类与对象的底层,这一篇我们探究一下分类,扩展与关联对象 一、分类实现原理 首先我们知道扩展是…

Rust :快速了解 VecDeque 双向队列

VecDeque是Rust标准库中的一个双端队列(double-ended queue)实现,它提供了在队列两端进行高效插入和删除操作的能力。双端队列是一种具有队列和栈的性质的数据结构,元素可以从两端弹出,其限定插入和删除操作在表的两端…

CentOS-7安装grafana

一、通用设置(分别在4台虚拟机设置) 1、配置主机名 hostnamectl set-hostname --static 主机名2、修改hosts文件 vim /etc/hosts 输入: 192.168.15.129 master 192.168.15.133 node1 192.168.15.134 node2 192.168.15.136 node33、 保持服…

GaussianEditor:快速可控的3D编辑与高斯飞溅

GaussianEditor: Swift and Controllable 3D Editing with Gaussian Splatting GaussianEditor:快速可控的3D编辑与高斯飞溅 Yiwen Chen*​1,2   Zilong Chen*​3,5   Chi Zhang2   Feng Wang3   Xiaofeng Yang2 陈怡雯 *​1,2 陈子龙 *​3,5 张驰 2 王峰 3 杨晓…

MySQL学习笔记7——视图和存储过程

视图和存储过程 一、视图1、视图的作用2、如何操作视图和视图中的数据3、视图的优缺点 二、存储过程1、如何创建存储过程2、调用存储过程3、修改和删除存储过程 一、视图 1、视图的作用 视图是一种虚拟表,我们可以把一段查询语句作为视图存储在数据库中&#xff0…

Cocos Creator 场景树与组件实例查找详解

前言 Cocos Creator 是一款由 Cocos-BCX 团队开发的一款基于 JavaScript 的游戏开发引擎,它提供了一套完整的游戏开发工具和资源,方便开发者快速构建游戏。在 Cocos Creator 中,场景树和组件实例的查找是非常重要的,它们可以帮助开…

.NET Core 中的 ORM 框架对比

在 .NET Core 中选择正确的对象关系映射 (ORM) 工具可能是开发生命周期中的关键决策。所选的 ORM 会影响应用程序的性能、可维护性和可伸缩性。在本文中,我们将深入分析三个突出的 ORM 选择:Entity Framework Core、Dapper 和 NHi…

算法设计与优化——向量中数据唯一化

0.概述 很多应用中,在进一步处理之前都要求数据元素互异。以网络搜索引擎为例,多个计算节点各自获得的局部搜索结果,需首先剔除其中重复的项目,方可合并为一份完整的报告。类似地,所谓向量的唯一化处理,就…