深度神经网络中的混合精度训练

Mixed-Precision Training of Deep Neural Networks | NVIDIA Technical Blog

目录

混合精度成功训练的技术

FP32 累加

损失缩放 loss scaling

FP32 Master Copy of Weights

混合精度训练迭代过程

AMP混合精度训练介绍

FP16和FP32的区别

FP16的优势

FP16的问题

解决P16的精度问题策略

1、混合精度计算

2、损失缩放(Loss scaling)

3、权重备份

Apex

代码格式

不同的训练模式说明

O0 纯FP32

O1 混合精度

O2混合精度

O3纯FP16

torch.cuda.amp

参考连接


深度神经网络 (DNN) 在许多领域取得了突破,包括图像处理和理解、语言建模、语言翻译、语音处理、游戏等。为了实现这些结果,DNN 的复杂性一直在增加,这反过来又增加了训练这些网络所需的计算资源。混合精度训练通过使用较低精度的计算(FP16)来降低所需的资源,这具有以下优点。

  • 减少所需的内存量。半精度浮点格式 (FP16) 使用 16 位,而单精度 (FP32) 使用 32 位。降低所需的内存可以训练更大的模型或使用更大的小批量进行训练。
  • 缩短训练或推理时间。执行时间可能对内存或算术带宽敏感。半精度将访问的字节数减半,从而减少了在内存受限层中花费的时间。与单精度相比,NVIDIA GPU 的半精度算术吞吐量提高了 8 倍,从而加快了数学受限层的速度。

图 1.bigLSTM 英语语言模型的训练曲线显示了本文中描述的混合精度训练技术的好处。Y 轴是训练损失。不带损耗缩放的混合精度(灰色)在一段时间后会发散,而带损耗缩放的混合精度(绿色)与单精度模型(黑色)匹配。

图 1.大型LSTM 英语语言模型的训练曲线显示了本文中描述的混合精度训练技术的好处。Y 轴是训练损失。不带损耗缩放的混合精度(灰色)在一段时间后会发散,而带损耗缩放的混合精度(绿色)与单精度模型(黑色)匹配。

由于 DNN 训练传统上依赖于 IEEE 单精度格式,因此本文的重点是半精度训练,同时保持单精度实现的网络精度(如图 1 所示)。这种技术称为混合精度训练,因为它同时使用单精度和半精度表示。

混合精度成功训练的技术

半精度浮点格式由 1 个符号位、5 个指数位和 10 个小数位组成。支持的指数值属于 [-24, 15] 范围,这意味着该格式支持 [2-24,65,504]范围。由于这比 [2-149, ~3.4×1038] 范围支持单精度格式,训练某些网络需要额外考虑。本节介绍了成功训练半精度 DNN 的三种技术:将 FP16 产品累积到 FP32 中;损失缩放;以及砝码的 FP32 主副本。借助这些技术, NVIDIA 和百度研究院能够匹配所有经过训练的网络的单精度结果准确性(混合精度训练)。请注意,并非所有网络都需要使用所有这些技术进行训练。

有关如何在各种框架中应用这些技术的详细说明,包括可用的代码示例,请参阅混合精度训练用户指南。

FP32 累加

NVIDIA Volta GPU 架构引入了 Tensor Core 指令,该指令将半精度矩阵相乘,将结果累积为单精度或半精度输出。我们发现,累积到单个精度对于获得良好的训练结果至关重要。累积值在写入内存之前转换为半精度。cuDNN 和 CUBLAS 库提供了多种依赖于 Tensor Core 进行算术运算的函数。

损失缩放 loss scaling

训练 DNN 时会遇到四种类型的张量:激活、激活梯度、权重和权重梯度。根据我们的经验,激活、权重和权重梯度落在半精度表示的值大小范围内。然而,对于某些网络,小幅度激活梯度低于半精度范围。例如,考虑图 2 中训练 Multibox SSD 检测网络时遇到的激活梯度直方图,该直方图显示了 log2 刻度上值的百分比。小于 2-24 的值在半精度格式中变为零。

请注意,激活梯度不使用大多数半精度范围,激活梯度往往是幅度小于 1 的小值。因此,我们可以通过将激活梯度乘以比例因子 S 来将它们“移位”到 FP16 表示的范围内。在SSD网络的情况下,将梯度乘以8就足够了。这表明激活梯度值小于 2-27与该网络的训练无关,而保留 [2-27, 2-24) 范围。

图2.以单精度训练 Multibox SSD 检测器网络时记录的激活梯度直方图。Y 轴是对数刻度上所有值的百分比。X 轴是绝对值的对数刻度,也是零的特殊条目。例如,在此训练课程中,66.8% 的值为零,而 4% 的值介于 2-32 和 2-30 之间。

图2.以单精度训练 Multibox SSD 检测器网络时记录的激活梯度直方图。Y 轴是对数刻度上所有值的百分比。X 轴是绝对值的对数刻度,也是零的特殊条目。例如,在此培训课程中,66.8% 的值为零,而 4% 的值介于 2 之间-32和 2-30.

确保梯度落入半精度表示的范围内的一种非常有效的方法是将训练损失乘以比例因子。这仅增加了一次乘法,并且通过链式规则,它确保所有梯度都按比例放大(或向上移动),而无需额外费用。损失缩放可确保恢复丢失到零的相关梯度值。在权重更新之前,权重梯度需要按相同的因子 S 缩小。缩减操作可以与权重更新本身融合(导致没有额外的内存访问)或单独执行。有关详细信息,请参阅《混合精度训练用户指南》和《混合精度训练》白皮书。

FP32 Master Copy of Weights

DNN 训练的每次迭代都会通过添加相应的权重梯度来更新网络权重。权重梯度幅度通常明显小于相应的权重,尤其是在与学习率相乘(或Adam或Adagrad等优化器的自适应计算因子)相乘之后。如果其中一个加法太小而无法产生半精度表示差异,则此幅度差异可能导致不会发生更新(例如,由于指数差大,较小的加法在移位以对齐二进制点后变为零)。

对于以这种方式丢失更新的网络,一个简单的补救措施是以单精度维护和更新权重的主副本。在每次迭代中,都会制作一个主权重的半精度副本,并将其用于正向和反向传播,从而获得性能优势。在权重更新期间,计算出的权重梯度将转换为单精度,并用于更新主副本,并在下一次迭代中重复该过程。因此,我们只在需要的地方将半精度存储与单精度存储混合使用。

混合精度训练迭代过程

上面介绍的三种技术可以组合到每个训练迭代的以下步骤序列中。对传统迭代过程的补充以粗体显示。

  1. 制作权重的 FP16 副本
  2. 使用 FP16 权重和激活进行前向传播
  3. 将产生的损失乘以比例因子 S
  4. 使用 FP16 权重、激活及其梯度向后传播
  5. 将权重梯度乘以 1/S
  6. (可选)处理权重梯度(梯度裁剪、权重衰减等)
  7. 更新 FP32 中权重的主副本

AMP混合精度训练介绍

AMP(Automatic mixed precision):自动混合精度,该方法在训练网络时将单精度(FP32)与半精度(FP16)结合在一起,它使用FP16即半精度浮点数存储和计算,从而实现节省显存和加快训练速度的目的。

常用的两种实现amp的方式:

  • NVIDIA Apex使用apex.amp (O1模式开启自研kernel会出现Nan值,禁用自研kernel之后没有Nan值;O2没有Nan值)
  • Pytorch 1.6版本后自带torch.cuda.amp (开启自研kernel 也会出现Nan值;禁用自研kernel之后没有Nan值)

FP16和FP32的区别

FP16和FP32在计算机的不同存储方法:

半精度浮点数 (FP16): 计算机使用 2 字节 (16 位) 存储,表示范围为 [5.9e-8,65504]

单精度浮点数 (FP32) :计算机使用 4 字节 (32 位) 存储,表示范围为 [1.4e-45,3.4e38],FP32 能够表示的范围要比 FP16 大的多得多。

FP16的优势

默认情况下,大多数深度学习框架都采用FP32进行训练。相比与FP32,FP16具有一下优势:

  •  1.减少显存占用,这使得我们可以用更大的 batch size
  •  2.加快训练和推断的计算
  •  3.NVIDIA Tensor Core支持

FP16的问题

如果我们简单地把模型权重和输入从 FP32 转化成 FP16,虽然可以加快速度,但是模型的精度会被严重影响,原因如下:

  • 1. 溢出错误:由于FP16的动态范围比FP32位的狭窄很多,因此,在计算过程中很容易出现上溢出和下溢出,溢出之后就会出现"NaN"的问题。

    Multibox SSD网络训练过程中激活梯度值的直方图。2%的值在[2−34,2−32)范围内,2%的数值在[2–24,2−23)范围内,以及67%的数值为零。

  • 2. 舍入误差:当梯度过小时,小于当前区间内的最小间隔时,该次梯度更新可能会失败

解决P16的精度问题策略

论文里提到下面三个策略:Micikevicius, Paulius, Sharan Narang, et al. “Mixed Precision Training.” ArXiv:1710.03740 [Cs, Stat], February 15, 2018. https://arxiv.org/abs/1710.03740

1、混合精度计算

 在内存中用FP16做储存和乘法从而加速计算,而用FP32做累加避免舍入误差。混合精度训练的策略有效地缓解了舍入误差的问题。

2、损失缩放(Loss scaling)

为了解决下溢出的问题,对计算出来的 loss 值进行缩放 (scale),由于链式法则的存在,对 loss 的缩放会作用在每个梯度上,这些梯度会平移到 FP16 的有效范围内。这样就可以用 FP16 存储梯度而又不会溢出了。此外,在进行更新之前,需要先将缩放后的梯度转化为 FP32,再将梯度反缩放(unscale)回去。 

反向传播前:将loss手动增大缩放因子 (loss_scale)倍

反向传播后:将权重梯度缩小缩放因子 (loss_scale)倍,恢复正常值

3、权重备份

将模型权重、激活值、梯度等数据用 FP16 来存储,同时维护一份 FP32 的模型权重副本(master-weight)用于更新。前向使用FP16,在反向传播得到 FP16 的梯度以后,将其转化成 FP32 并 unscale,最后更新 FP32 的模型权重。

尽管与单精度训练相比,保持额外的权重副本会使权重的内存需求增加50%,但对整体内存使用的影响要小得多。对于训练来说,由于更大的batch size和每层的输出值被保存以在反向传播过程中重复使用,因此内存消耗主要由这些输出值决定。由于输出值也以半精度格式存储,因此训练深度神经网络的总内存消耗大致减半。

Apex

代码格式

APEX中,用户不需要手动将模型或数据类型转换为.half(),只需要从现有的默认 (FP32) 脚本开始,添加与 Amp API 对应的三行,然后就可以使用混合精度进行训练。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

from apex.fp16_utils import *

from apex import amp,optimizers

model = ...

optimizer  = ...

model, optimizer = amp.initialize(model, optimizer,

                      opt_level= ,

                 keep_batchnorm_fp32= ,

                 loss_scale=,

                 )

with amp.scale_loss(loss, optimizer) as scaled_loss:

    scaled_loss.backward()

optimizer.step()

optimizer.zero_grad()

不同的训练模式说明

NVIDIA的APEX混合精度库为例,里面提供了多种策略,可以根据不同的场景进行使用:

  • opt_level:O0(纯FP32),O1和O2是混合精度的不同实现,O3(纯FP16),还有O4,O5使用BFLOAT16

  • cast_model_type:将模型的参数转换为所需的类型。

  • patch_torch_functions:patch所有 Torch 函数和 Tensor 方法以执行 Tensor Core 友好的操作,例如 FP16 中的 GEMM 和卷积,以及任何受益于 FP32 中的 FP32 精度的操作。

  • keep_batchnorm_fp32:将 batchnorm 权重保持在 FP32 ,模型的其余部分是 FP16。

  • master_weights:保持 FP32 权重。

  • loss_scale:float值 or "dynamic"(自适应调整损失比例)。动态损失放大(dynamic loss scaling),为了充分利用FP16的范围,缓解舍入误差,将loss*loss_scale。如果产生上溢出,则跳出参数更新,缩小放大倍数使其不溢出。在2000步后再尝试使用大的scale来充分利用FP16的范围。

蓝色为默认值

opt_level

O0

O1

O2

O3

cast_model_typetorch.float32Nonetorch.float16torch.float16
patch_torch_functionsFalseTrueFalseFalse

patch_torch_functions_type

None

torch.float16

NoneNone
keep_batchnorm_fp32NoneNone(自动设为TRUE)TrueFalse
master_weightsFalseNoneTrueFalse
loss_scale

1.0

"dynamic"

"dynamic"

1.0

O0 纯FP32

纯FP32训练,可作为accuracy的baseline

O1 混合精度

  • 权重为FP32
  • 前向:对Pytorch func和Tensor method进行自动转换,根据黑白名单自动决定使用FP16(GEMM,卷积),还是FP32(softmax)进行计算。
  • 白名单函数强制 FP16(将conv的input,weight,bias转换为FP16类型),黑名单函数使用FP32。
  • 其余函数则根据参数类型自动判断,如果参数都是 FP16,则以 FP16 运行,如果有一个参数为 FP32,则以 FP32 运行。 对于那些在 FP16 环境中运行不稳定的模块,我们会将其添加到黑名单中,强制它在 FP32 的精度下运行。
  • 动态损失缩放(dynamic loss scaling)

O1步骤:

  1. 根据黑白名单对 PyTorch 内置的函数和一些tensor进行包装 
  2.  将 loss_scale 初始化为一个很大的值 
  3.  对于每次迭代 
  • (a). 前向传播:按照黑白名单自动选择数据类型进行计算。 白名单:拷贝FP32模型并且转换成 FP16 进行计算
  • (b). 将 loss 乘以 loss_scale
  • (c). 反向传播: 计算出梯度FP16
  • (d). 将梯度 unscale ,即除以 loss_scale 
  • (e). 每次更新前检查溢出问题(检查梯度中有没有infnan),如果检测到 inf 或 nan

                      i. loss_scale /= 2

                      ii. 跳过此次更新

  • (f). optimizer.step(),利用 FP16 的梯度更新 FP32 的模型参数

  • (g). 如果连续2000次迭代都没有出现 inf 或 nan,则 loss_scale *= 2

以 nn.Linear 为例, 这个模块有两个权重参数 weight 和 bias,输入为 input,前向传播就是调用了 torch.nn.functional.linear(input, weight, bias),对于白名单来说,就是把权重参数 weight 和 bias和input转换为 FP16再进行计算。

黑白名单

lists里有三个文件:functional_overrides.py,tensor_overrides.py,torch_overrides.py分别定义了黑白名单(FP16/FP32的适用情况)

O2混合精度

  • 除了 BN 层以外的模型权重为 FP16
  • 创建一个FP32的权重副本

O2步骤:

  1. 除了 BN 层以外的模型权重和梯度转化为 FP16输入类型也转化为 FP16,模型输出类型不设置为FP32
  2. 维护一个 FP32 的模型权重副本用于更新
  3. 将 loss_scale 初始化为一个很大的值;
  4. 对于每次迭代
  • (a). 前向传播: 除了 BN 层权重是 FP32,模型其它部分都是 FP16,得到FP32的loss
  • (b). 将 loss 乘以 loss_scale转换为FP16
  • (c). loss反向传播,计算得到 FP16 的梯度 
  • (d). 将 FP16 梯度转化为 FP32,并unscale
  • (e). 如果检测到梯度 inf 或 nan

                  i. loss_scale /= 2

                  ii. 跳过此次更新

  • (f). optimizer.step(),利用 FP16 的梯度更新 FP32 的模型参数
  • sgd中params[i].add_(grads[i], alpha=-lr)FP32+FP16=FP32

  • (g). 如果连续2000次迭代都没有出现 inf 或 nan,则 loss_scale *= 2

O3纯FP16

纯FP16来当速度的baseline

torch.cuda.amp

PyTorch 从 1.6 以后开始支持amp,即torch.cuda.amp module,类似于apex的O1模式:
torch.cuda.amp 给用户提供了较为方便的混合精度训练机制,“方便”体现在两个方面:

1.amp 会自动为算子选择合适的数值精度(FP32、FP16)

该名单在 torch\testing\_internal\autocast_test_lists.py里定义

  • CUDA Ops that can autocast to float16
    __matmul__, addbmm, addmm, addmv, addr, baddbmm, bmm, chain_matmul, multi_dot, conv1d, conv2d, conv3d, conv_transpose1d, conv_transpose2d, conv_transpose3d, GRUCell, linear, LSTMCell, matmul, mm, mv, prelu, RNNCell
  • CUDA Ops that can autocast to float32
    __pow__, __rdiv__, __rpow__, __rtruediv__, acos, asin, binary_cross_entropy_with_logits, cosh, cosine_embedding_loss, cdist, cosine_similarity, cross_entropy, cumprod, cumsum, dist, erfinv, exp, expm1, group_norm, hinge_embedding_loss, kl_div, l1_loss, layer_norm, log, log_softmax, log10, log1p, log2, margin_ranking_loss, mse_loss, multilabel_margin_loss, multi_margin_loss, nll_loss, norm, normalize, pdist, poisson_nll_loss, pow, prod, reciprocal, rsqrt, sinh, smooth_l1_loss, soft_margin_loss, softmax, softmin, softplus, sum, renorm, tan, triplet_margin_loss
  • CUDA Ops that promote to the widest input type
    这些操作不需要特定的 dtype 来保持稳定性,但需要多个输入并要求输入的 dtype 匹配。如果所有输入都是 float16,则运算在 中运行float16。如果任何输入是float32,autocast 将所有输入转换为float32并运行 op in float32。

    addcdiv addcmul_ atan2_ bilinear_ cross_ dot_ grid_sample_ index_put_ scatter_add_ tensordot

2.amp 提供了loss_scaling 操作 ,为了防止下溢,将loss乘以一个比例因子,并对缩放后的loss反向传播,然后将梯度除以相同的比例因子

代码格式:

model = Net().cuda()

optimizer = optim.SGD(model.parameters(), ...)

scaler = torch.cuda.amp.GradScaler()

for epoch in epochs:

    for input, target in data:

        optimizer.zero_grad()

        with autocast():

            output = model(input)

            loss = loss_fn(output, target)

        # 用scaler,scale loss(FP16),backward得到scaled的梯度(FP16)

        scaler.scale(loss).backward()

        # scaler 更新参数,会先自动unscale梯度,如果有nan或inf,自动跳过

        scaler.step(optimizer)

        scaler.update() # scaler factor更新

参考连接

apex官方代码:GitHub - NVIDIA/apex: A PyTorch Extension: Tools for easy mixed precision and distributed training in Pytorch

nvidia apex官方文档: Apex (A PyTorch Extension) — Apex 0.1.0 documentation

自动混合精度简介 - 墨天轮

全网最全-混合精度训练原理 - 知乎

由浅入深的混合精度训练教程

Micikevicius, Paulius, Sharan Narang, et al. “Mixed Precision Training.” ArXiv:1710.03740 [Cs, Stat], February 15, 2018. https://arxiv.org/abs/1710.03740

torch.amp文档  https://pytorch.org/docs/stable/amp.html#

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

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

相关文章

select for update会锁表还是行锁还是其它

select for update含义 select查询语句是不会加锁的,但是 select for update除了有查询的作用外,还会加锁呢,而且它是悲观锁哦。至于加了是行锁还是表锁,这就要看是不是用了索引/主键啦。 没用索引/主键的话就是表锁&#xff0c…

2下载Spring,第一个Spring程序+引用Log4j2

https://www.yuque.com/dujubin/ltckqu/kipzgd#,注意的是,现在(202401)SpringFramework从release搬到了snapshot下,在这下面找到6.0.2下载. 下载后解压到文件夹,整个框架包含非常多jar包。 然后就可以在p…

C#中使用as关键字将对象转换为指定类型

目录 一、定义 二、示例 三、生成 使用as关键字可以将对象转换为指定类型,与is关键字不同,is关键字用于检查对象是否与给定类型兼容,如果兼容则返回true,如果不兼容则返回false。而as关键字会直接进行类型转换,如果…

金融中IC和IR的定义

当谈到金融领域时,IC(Information Coefficient)和IR(Information Ratio)通常是用来评估投资组合管理绩效的指标。它们都涉及到投资者对信息的利用和管理的效果。 信息系数(IC - Information Coefficient&a…

Dependency Dialogue Acts — Annotation Scheme and Case Study [论文解读]

原文链接:https://arxiv.org/pdf/2302.12944.pdf 摘要 在本文中,我们介绍了依存对话行为(Dependency Dialog Act, DDA),这是一个新颖的框架,旨在捕捉多方对话中说话者意图的结构。DDA结合并适应了现有对话标注框架的特点&#x…

ElasticSearch使用Grafana监控服务状态-Docker版

文章目录 版本信息构建docker-compose.yml参数说明 创建Prometheus配置文件启动验证配置Grafana导入监控模板模板说明 参考资料 版本信息 ElasticSearch:7.14.2 elasticsearch_exporter:1.7.0(latest) 下载地址:http…

【Java 进阶篇】Linux 常用命令使用详解:玩转命令行的魔法世界

在计算机的世界里,Linux是一个强大而富有魅力的操作系统。对于很多小白用户来说,刚接触Linux时可能感觉有些陌生,尤其是在命令行界面下。然而,正是这个看似晦涩的命令行,才是Linux系统最为强大和灵活的地方。本文将围绕…

Python trash-cli模块实现Linux服务器回收站

概述: trash-cli是一个用于管理类 Unix 系统垃圾箱的命令行工具。它提供了一个安全的替代方案来代替传统的 rm 命令,后者会永久删除文件和目录。使用 trash-cli,文件和目录被移动到垃圾箱中,这样就可以在意外删除的情况下恢复它们…

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)

stm32学习总结:5、Proteus8STM32CubeMXMDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题) 文章目录 stm32学习总结:5、Proteus8STM32CubeMXMDK仿真串口并使用串口打印日志(注意重定向printf到串口打印…

网络路由跟踪工具

随着企业网络需求的增长,组织发现监控和管理其网络基础设施变得越来越困难。网络管理员正在转向其他工具和资源,这些工具和资源可以使他们的工作更轻松一些,尤其是在故障排除方面。 目前,网络管理员主要使用简单、免费提供的实用…

Consule安装与SpringBoot集成

Consule Consul 是由 HashiCorp 开发的一款软件工具,提供了一组功能,用于服务发现、配置管理和网络基础设施自动化。它旨在帮助组织管理现代分布式和微服务架构系统的复杂性。以下是Consul的一些关键方面和功能: 服务发现:Consul…

Spring AOP的环境搭建、切入点表达式、通知注解

Spring AOP的实现 Spring AOP环境搭建AOP坐标依赖引入添加xml配置实现三层架构 定义切入点Pointcut("匹配规则")切入点表达式1. 执行所有的公共方法2.执行任意的set方法3.设置指定包下的任意类的任意方法 (指定包: com.svt.service)4.设置指定包及于包下的任意类的任…

Apache Commons BCEL与Java字节码操作

第1章:Apache Commons BCEL简介 大家好,我是小黑,咱们今天来聊聊Apache Commons BCEL(Byte Code Engineering Library)。你可能会问,BCEL是什么鬼?别急,小黑这就给你娓娓道来。BCEL…

力扣刷题-二叉树-二叉搜索树中的搜索

700 二叉搜索树中的搜索 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。 例如, 在上述示例中,如果要找的值是 5&#x…

npm安装sharp出现的问题(安装失败的问题及解决)

npm安装sharp库出现的问题及解决 npm安装sharp出现的问题及解决: Buffer的使用以及对图片的操作(通过sharp库对图片进行操作) npm安装sharp出现的问题及解决: 在使用npm安装sharp一直安装不成功。后面发现安装sharp需要依赖libvip…

Spring常用注解及模拟用户登录流程示例

注解 Resource注解实现自动注入 (反射)代码块xml配置文件 Autowired注解实现自动化注入代码块xml配置文件 扫描器-四个注解Dao层-RepositoryService层-ServiceController层-Controller测试任意类-Component 常用注解示例-模拟用户登录配置自动扫描的xml文件实体类Userdao层消息…

【机器学习基础】DBSCAN

🚀个人主页:为梦而生~ 关注我一起学习吧! 💡专栏:机器学习 欢迎订阅!相对完整的机器学习基础教学! ⭐特别提醒:针对机器学习,特别开始专栏:机器学习python实战…

知识图谱企业图谱怎么做

随着人工智能技术的不断发展,知识图谱技术逐渐在各行各业得到了广泛应用,为各行业企业提供了强有力的数据分析手段。尤其是在金融、医疗、电商等领域,企业知识图谱技术可以帮助企业解决数据孤岛、信息孤岛等问题,实现数据整合与共…

腾讯云企业用户优惠活动整理汇总

腾讯云一直致力于为广大企业用户提供高品质、高性价比的云计算产品和服务。为了帮助企业用户更好地了解腾讯云的优惠活动,本文将对腾讯云企业用户的优惠活动进行整理汇总。 一、新客专享福利 腾讯云为新用户提供了一系列的优惠活动,除了可以领取专属代金…

[Mac软件]Boxy SVG 4.20.0 矢量图形编辑器

Boxy SVG 是一款入门级矢量图形编辑器,具有全套基本功能、易于学习的选项卡式界面和可自定义的键盘快捷键。有了它,您可以轻松创建横幅、图标、按钮、图形、界面草图,甚至有趣的表情包。 编辑器支持使用多种工具创建和编辑矢量对象&#xff…