MMCV1.6.0之Runner/Hook/OptimizerHook(反向传播+参数更新)、Fp16OptimizerHook、自定义优化器与config设置

OptimizerHook

这段代码定义了一个名为 OptimizerHook 的类,它是一个用于优化器的自定义操作钩子。该钩子包含了一些用于梯度裁剪和检测异常参数的操作。这对于在深度学习训练过程中优化模型的性能和调试模型非常有用。

类的定义
OptimizerHook 类继承自 Hook,实现了一些与优化器相关的自定义操作。
参数说明
grad_clip: 一个字典,用于配置梯度裁剪的参数。默认值为 None。
detect_anomalous_params: 一个布尔值,用于调试目的。这将减慢训练速度,检测不包含在计算图中的异常参数。默认值为 False。

@HOOKS.register_module()
class OptimizerHook(Hook):"""A hook contains custom operations for the optimizer.Args:grad_clip (dict, optional): A config dict to control the clip_grad.Default: None.detect_anomalous_params (bool): This option is only used fordebugging which will slow down the training speed.Detect anomalous parameters that are not included inthe computational graph with `loss` as the root.There are two cases- Parameters were not used duringforward pass.- Parameters were not used to produceloss.Default: False."""def __init__(self,grad_clip: Optional[dict] = None,detect_anomalous_params: bool = False):self.grad_clip = grad_clipself.detect_anomalous_params = detect_anomalous_paramsdef clip_grads(self, params):params = list(filter(lambda p: p.requires_grad and p.grad is not None, params))if len(params) > 0:return clip_grad.clip_grad_norm_(params, **self.grad_clip)def after_train_iter(self, runner):runner.optimizer.zero_grad()if self.detect_anomalous_params:self.detect_anomalous_parameters(runner.outputs['loss'], runner)runner.outputs['loss'].backward()if self.grad_clip is not None:grad_norm = self.clip_grads(runner.model.parameters())if grad_norm is not None:# Add grad norm to the loggerrunner.log_buffer.update({'grad_norm': float(grad_norm)},runner.outputs['num_samples'])runner.optimizer.step()def detect_anomalous_parameters(self, loss: Tensor, runner) -> None:logger = runner.loggerparameters_in_graph = set()visited = set()def traverse(grad_fn):if grad_fn is None:returnif grad_fn not in visited:visited.add(grad_fn)if hasattr(grad_fn, 'variable'):parameters_in_graph.add(grad_fn.variable)parents = grad_fn.next_functionsif parents is not None:for parent in parents:grad_fn = parent[0]traverse(grad_fn)traverse(loss.grad_fn)for n, p in runner.model.named_parameters():if p not in parameters_in_graph and p.requires_grad:logger.log(level=logging.ERROR,msg=f'{n} with shape {p.size()} is not 'f'in the computational graph \n')

主要逻辑
初始化参数

接受 grad_clip 和 detect_anomalous_params 两个可选参数,并将它们赋值给实例变量。
clip_grads 方法

过滤出需要梯度裁剪的参数。
如果有参数需要裁剪,使用 clip_grad.clip_grad_norm_ 函数进行梯度裁剪。
after_train_iter 方法

每次训练迭代后被调用。
清零优化器的梯度。
如果启用了异常参数检测,调用 detect_anomalous_parameters 方法。
反向传播计算梯度。
如果启用了梯度裁剪,调用 clip_grads 方法,并将裁剪后的梯度范数记录到日志中。
更新优化器的参数。
detect_anomalous_parameters 方法

用于检测计算图中未包含的异常参数。
遍历损失的计算图,收集在图中的参数。
将模型中的参数与计算图中的参数进行比对,找出未包含在计算图中的参数,并记录错误日志。
总结
OptimizerHook 类提供了一种灵活的方法来管理和调试优化器的操作。通过梯度裁剪,可以防止梯度爆炸问题。而通过检测异常参数,可以帮助用户在训练过程中发现可能未正确参与计算的参数,从而提高模型的训练效率和效果。这对于大型深度学习模型的训练和调试尤为重要。

Fp16OptimizerHook(支持 FP16 精度的优化器钩子)

这段代码定义了一个名为 Fp16OptimizerHook 的类,它继承自 OptimizerHook,用于支持 FP16 精度的优化器钩子。这对于使用混合精度训练(Mixed Precision Training)以加速深度学习模型训练和减少显存使用非常有用。

类的定义
Fp16OptimizerHook 类继承自 OptimizerHook,实现了一些用于支持 FP16 精度的自定义操作。
参数说明
grad_clip: 一个字典,用于配置梯度裁剪的参数。默认值为 None。
coalesce: 一个布尔值,指示是否合并小的梯度张量以提高通信效率。默认值为 True。
bucket_size_mb: 一个整数,指示梯度桶的大小(以MB为单位)。默认值为 -1。
loss_scale: 一个浮点数、字符串或字典,配置损失缩放的参数。如果是浮点数,则使用静态损失缩放。如果是字符串,则必须为 ‘dynamic’,使用动态损失缩放。如果是字典,则包含 GradScaler 的参数。默认值为 512。
distributed: 一个布尔值,指示是否使用分布式训练。默认值为 True。

@HOOKS.register_module()class Fp16OptimizerHook(OptimizerHook):"""FP16 optimizer hook (using PyTorch's implementation).If you are using PyTorch >= 1.6, torch.cuda.amp is used as the backend,to take care of the optimization procedure.Args:loss_scale (float | str | dict): Scale factor configuration.If loss_scale is a float, static loss scaling will be used withthe specified scale. If loss_scale is a string, it must be'dynamic', then dynamic loss scaling will be used.It can also be a dict containing arguments of GradScalar.Defaults to 512. For Pytorch >= 1.6, mmcv uses officialimplementation of GradScaler. If you use a dict version ofloss_scale to create GradScaler, please refer to:https://pytorch.org/docs/stable/amp.html#torch.cuda.amp.GradScalerfor the parameters.Examples:>>> loss_scale = dict(...     init_scale=65536.0,...     growth_factor=2.0,...     backoff_factor=0.5,...     growth_interval=2000... )>>> optimizer_hook = Fp16OptimizerHook(loss_scale=loss_scale)"""def __init__(self,grad_clip: Optional[dict] = None,coalesce: bool = True,bucket_size_mb: int = -1,loss_scale: Union[float, str, dict] = 512.,distributed: bool = True):self.grad_clip = grad_clipself.coalesce = coalesceself.bucket_size_mb = bucket_size_mbself.distributed = distributedself._scale_update_param = Noneif loss_scale == 'dynamic':self.loss_scaler = GradScaler()elif isinstance(loss_scale, float):self._scale_update_param = loss_scaleself.loss_scaler = GradScaler(init_scale=loss_scale)elif isinstance(loss_scale, dict):self.loss_scaler = GradScaler(**loss_scale)else:raise ValueError('loss_scale must be of type float, dict, or 'f'"dynamic", got {loss_scale}')def before_run(self, runner) -> None:"""Preparing steps before Mixed Precision Training."""# wrap model mode to fp16wrap_fp16_model(runner.model)# resume from state dictif 'fp16' in runner.meta and 'loss_scaler' in runner.meta['fp16']:scaler_state_dict = runner.meta['fp16']['loss_scaler']self.loss_scaler.load_state_dict(scaler_state_dict)def copy_grads_to_fp32(self, fp16_net: nn.Module,fp32_weights: Tensor) -> None:"""Copy gradients from fp16 model to fp32 weight copy."""for fp32_param, fp16_param in zip(fp32_weights,fp16_net.parameters()):if fp16_param.grad is not None:if fp32_param.grad is None:fp32_param.grad = fp32_param.data.new(fp32_param.size())fp32_param.grad.copy_(fp16_param.grad)def copy_params_to_fp16(self, fp16_net: nn.Module,fp32_weights: Tensor) -> None:"""Copy updated params from fp32 weight copy to fp16 model."""for fp16_param, fp32_param in zip(fp16_net.parameters(),fp32_weights):fp16_param.data.copy_(fp32_param.data)def after_train_iter(self, runner) -> None:"""Backward optimization steps for Mixed Precision Training. Fordynamic loss scaling, please refer tohttps://pytorch.org/docs/stable/amp.html#torch.cuda.amp.GradScaler.1. Scale the loss by a scale factor.2. Backward the loss to obtain the gradients.3. Unscale the optimizer’s gradient tensors.4. Call optimizer.step() and update scale factor.5. Save loss_scaler state_dict for resume purpose."""# clear grads of last iterationrunner.model.zero_grad()runner.optimizer.zero_grad()self.loss_scaler.scale(runner.outputs['loss']).backward()self.loss_scaler.unscale_(runner.optimizer)# grad clipif self.grad_clip is not None:grad_norm = self.clip_grads(runner.model.parameters())if grad_norm is not None:# Add grad norm to the loggerrunner.log_buffer.update({'grad_norm': float(grad_norm)},runner.outputs['num_samples'])# backward and update scalerself.loss_scaler.step(runner.optimizer)self.loss_scaler.update(self._scale_update_param)# save state_dict of loss_scalerrunner.meta.setdefault('fp16', {})['loss_scaler'] = self.loss_scaler.state_dict()

主要逻辑
初始化参数

接受 grad_clip、coalesce、bucket_size_mb、loss_scale 和 distributed 五个参数,并将它们赋值给实例变量。
根据 loss_scale 的类型,初始化 GradScaler 对象。
before_run 方法

在混合精度训练开始前的准备步骤。
将模型包装为 FP16 精度。
从状态字典中恢复 loss_scaler 的状态。
copy_grads_to_fp32 方法

将 FP16 模型中的梯度复制到 FP32 权重副本中。
copy_params_to_fp16 方法

将更新后的 FP32 权重副本的参数复制到 FP16 模型中。
after_train_iter 方法

每次训练迭代后被调用。
清零上一次迭代的梯度。
将损失按比例缩放并进行反向传播计算梯度。
将优化器的梯度张量取消缩放。
如果启用了梯度裁剪,调用 clip_grads 方法,并将裁剪后的梯度范数记录到日志中。
调用 optimizer.step() 并更新缩放因子。
保存 loss_scaler 的状态字典。
总结
Fp16OptimizerHook 类提供了一种灵活的方法来管理和支持混合精度训练。通过使用 PyTorch 的 torch.cuda.amp 模块,可以显著加速模型训练并减少显存使用。它还包括梯度裁剪和异常参数检测的功能,可以帮助用户在训练过程中更好地管理和调试模型。

# fp16 settings
fp16 = dict(loss_scale=512.)
您还可以设置fp16 = dict(loss_scale='dynamic')启用自动损失缩放。

Pytorch支持的自定义优化器

我们已经支持使用所有由PyTorch实现的优化器,唯一的修改就是更改配置文件的优化器字段。例如,如果您想要使用ADAM(注意性能可能会下降很多),修改可以如下所示。

optimizer = dict(type='Adam', lr=0.0003, weight_decay=0.0001)

要修改模型的学习率,用户只需修改optimizer配置中的lr即可。用户可以直接在PyTorch的API文档后面设置参数。
在这里插入图片描述

定制自行实现的优化器

1、Define a new optimizer(定义一个新的优化器)

一个定制的优化器可以定义如下。假设您想添加一个名为MyOptimizer的优化器,它有参数a、b和c。您需要创建一个名为mmdet/core/optimizer的新目录。然后在文件中实现新的优化器,例如在mmdet/core/optimizer/my_optimizer.py中:

from .registry import OPTIMIZERS
from torch.optim import Optimizer
@OPTIMIZERS.register_module()
class MyOptimizer(Optimizer):def __init__(self, a, b, c)

2. 将优化器添加到注册表

要找到上面定义的模块,首先应该将该模块导入主命名空间。实现这一目标有两种选择。
(1)修改mmdet/core/optimizer/init.py来导入它。新定义的模块应该导入到mmdet/core/optimizer/init.py中,这样注册表就会找到新模块并添加它:

from .my_optimizer import MyOptimizer

(2)Use custom_imports in the config to manually import it (使用配置中的custom_imports手动导入它)

custom_imports = dict(imports=['mmdet.core.optimizer.my_optimizer'], allow_failed_imports=False)

模块 mmdet.core.optimizer.my_optimizer 会在程序开始时被导入,并且 MyOptimizer 类将会被自动注册。请注意,只需要导入包含 MyOptimizer 类的包,而不需要直接导入 mmdet.core.optimizer.my_optimizer.MyOptimizer。
实际上,用户可以使用这种导入方法使用完全不同的文件目录结构,只要模块根可以位于PYTHONPATH。

3.在配置文件中指定优化器

然后你可以在配置文件的优化器字段中使用MyOptimizer。在配置文件中,优化器由字段优化器定义,如下所示:

optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)

To use your own optimizer, the field can be changed to

optimizer = dict(type='MyOptimizer', a=a_value, b=b_value, c=c_value)

自定义优化器构造函数

某些模型可能有一些针对优​​化的参数设置,例如 BatchNorm 层的权重衰减。用户可以通过自定义优化器构造函数来进行这些细粒度的参数调整。

from mmcv.utils import build_from_cfgfrom mmcv.runner.optimizer import OPTIMIZER_BUILDERS, OPTIMIZERS
from mmdet.utils import get_root_logger
from .my_optimizer import MyOptimizer@OPTIMIZER_BUILDERS.register_module()
class MyOptimizerConstructor(object):def __init__(self, optimizer_cfg, paramwise_cfg=None):def __call__(self, model):return my_optimizer

默认的优化器构造函数mmcv/mmcv/runner/optimizer
/default_constructor.py
在这里实现,它也可以作为新优化器构造函数的模板。

@OPTIMIZER_BUILDERS.register_module()
class DefaultOptimizerConstructor:"""Default constructor for optimizers.By default each parameter share the same optimizer settings, and weprovide an argument ``paramwise_cfg`` to specify parameter-wise settings.It is a dict and may contain the following fields:- ``custom_keys`` (dict): Specified parameters-wise settings by keys. Ifone of the keys in ``custom_keys`` is a substring of the name of oneparameter, then the setting of the parameter will be specified by``custom_keys[key]`` and other setting like ``bias_lr_mult`` etc. willbe ignored. It should be noted that the aforementioned ``key`` is thelongest key that is a substring of the name of the parameter. If thereare multiple matched keys with the same length, then the key with loweralphabet order will be chosen.``custom_keys[key]`` should be a dict and may contain fields ``lr_mult``and ``decay_mult``. See Example 2 below.- ``bias_lr_mult`` (float): It will be multiplied to the learningrate for all bias parameters (except for those in normalizationlayers).- ``bias_decay_mult`` (float): It will be multiplied to the weightdecay for all bias parameters (except for those innormalization layers and depthwise conv layers).- ``norm_decay_mult`` (float): It will be multiplied to the weightdecay for all weight and bias parameters of normalizationlayers.- ``dwconv_decay_mult`` (float): It will be multiplied to the weightdecay for all weight and bias parameters of depthwise convlayers.- ``bypass_duplicate`` (bool): If true, the duplicate parameterswould not be added into optimizer. Default: False.Args:model (:obj:`nn.Module`): The model with parameters to be optimized.optimizer_cfg (dict): The config dict of the optimizer.Positional fields are- `type`: class name of the optimizer.Optional fields are- any arguments of the corresponding optimizer type, e.g.,lr, weight_decay, momentum, etc.paramwise_cfg (dict, optional): Parameter-wise options.Example 1:>>> model = torch.nn.modules.Conv1d(1, 1, 1)>>> optimizer_cfg = dict(type='SGD', lr=0.01, momentum=0.9,>>>                      weight_decay=0.0001)>>> paramwise_cfg = dict(norm_decay_mult=0.)>>> optim_builder = DefaultOptimizerConstructor(>>>     optimizer_cfg, paramwise_cfg)>>> optimizer = optim_builder(model)Example 2:>>> # assume model have attribute model.backbone and model.cls_head>>> optimizer_cfg = dict(type='SGD', lr=0.01, weight_decay=0.95)>>> paramwise_cfg = dict(custom_keys={'.backbone': dict(lr_mult=0.1, decay_mult=0.9)})>>> optim_builder = DefaultOptimizerConstructor(>>>     optimizer_cfg, paramwise_cfg)>>> optimizer = optim_builder(model)>>> # Then the `lr` and `weight_decay` for model.backbone is>>> # (0.01 * 0.1, 0.95 * 0.9). `lr` and `weight_decay` for>>> # model.cls_head is (0.01, 0.95)."""def __init__(self, optimizer_cfg, paramwise_cfg=None):if not isinstance(optimizer_cfg, dict):raise TypeError('optimizer_cfg should be a dict',f'but got {type(optimizer_cfg)}')self.optimizer_cfg = optimizer_cfgself.paramwise_cfg = {} if paramwise_cfg is None else paramwise_cfgself.base_lr = optimizer_cfg.get('lr', None)self.base_wd = optimizer_cfg.get('weight_decay', None)self._validate_cfg()

其他设置

使用梯度剪辑来稳定训练:

有些模型需要使用梯度剪辑来剪辑梯度以稳定训练过程。示例如下:

optimizer_config = dict(_delete_=True, grad_clip=dict(max_norm=35, norm_type=2))

如果您的配置继承了已设置的基础配置optimizer_config,则可能需要_delete_=True覆盖不必要的设置。

使用动量计划来加速模型收敛:

我们支持动量调度,根据学习速率修改模型的动量,使模型更快地收敛。动量调度器通常与LR调度器一起使用,例如,在三维检测中使用以下配置来加速收敛。更多细节,请参考CyclicLrUpdater和CyclicMomentumUpdater的实现。

lr_config = dict(policy='cyclic',target_ratio=(10, 1e-4),cyclic_times=1,step_ratio_up=0.4,
)
momentum_config = dict(policy='cyclic',target_ratio=(0.85 / 0.95, 1),cyclic_times=1,step_ratio_up=0.4,
)

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

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

相关文章

documents4j 将word转pdf文件,本地(Windows)测试没问题,部署到服务器(centos)报错

问题 报错如下&#xff1a; 代码 首先要保证你的Java代码没问题&#xff0c;可以参考下面代码 maven依赖 <!--documents4j--> <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><versi…

解决mysql事件调度器重启服务后自动失效的问题

前段时间为通过mysql事件生成测试数据&#xff0c;今天发现数据在10:57后停止了CREATE EVENT IF NOT EXISTS insert_random_data ON SCHEDULE EVERY 10 SECOND DO INSERT INTO test (createtime, random_number) VALUES (NOW(), FLOOR(RAND() * 100));检查事件状态&#…

C++String类的手撕实现

目录 构造函数 提前准备工作&#xff1a; 有参构造 析构函数 c_str 无参构造&#xff1a; 无参和有参的结合 operater[]的实现 简易版的迭代器 begin end 原因&#xff1a; reserve 思想步骤 获取_capacity 和 _size 测试 push_back 思想步骤 append insert…

平安养老险广西分公司开展7.8公益健步行活动

近日&#xff0c;平安养老保险股份有限公司&#xff08;以下简称“平安养老险”&#xff09;广西分公司在南宁邕江沿岸开展“7.8”公益健步行活动&#xff0c;在分公司班子的号召下&#xff0c;各部门内外勤员工均踊跃参与。 员工们沿途随手捡拾垃圾&#xff0c;传递积极、绿色…

就在刚刚,中国 IMO 奥数遗憾地失去了第一名的宝座,连续五年的统治地位被美国队所终结。

&#x1f431; 个人主页&#xff1a;TechCodeAI启航&#xff0c;公众号&#xff1a;TechCodeAI &#x1f64b;‍♂️ 作者简介&#xff1a;2020参加工作&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab; 优质专…

Vue3开源Tree组件研发:节点勾选支持v-model

自研Tree组件有两个原因&#xff1a;1. 目前开源UI对Tree组件的用户API不太友好&#xff0c;2. 提升Vue3组件自研能力。 目前已实现的功能见上面思维导图。想象Tree组件的一个使用场景&#xff1a;后台管理员通过Tree组件来完成用户角色授权&#xff0c;同时支持对权限进行新增…

Spring中使用到的设计模式及其源码分析

前言 众所周知&#xff0c;Spring框架是一个强大而灵活的开发框架。这不&#xff0c;上次的面试刚问到这些&#xff0c;没防住&#xff01;&#xff01;&#xff01;因此下来总结一下。这篇文章主要介绍Spring中使用到的设计模式&#xff0c;自己做个面试复盘&#xff0c;同时…

Spring Security 原理

Spring Security是一个功能强大且广泛使用的身份验证和授权框架&#xff0c;专为保护Java应用程序的安全性而设计。它提供了一套可配置的安全性规则和机制&#xff0c;用于对应用程序的资源进行访问控制和保护。以下是Spring Security的主要原理&#xff1a; 1. 过滤器链&…

引领安全新风尚:WT2605/WT2003H芯片方案赋能电动汽车,打造智能低速安全报警器"

电动汽车低速报警器(AVAS)方案可采用WT2605或WT2003H方案芯片,可实现当车辆时速低于设定值(如20Km/h),报警器会发出类似发动机加速减速的声音,倒档时装置也会发出倒车警示,在嘈杂的城市环境中帮助提升行人对驶近的电动汽车的感知,降低行人、骑行者和弱势群体面临的风险。 WT26…

十分钟带你入门Go语言(Golang)开发

概述 Go语言是由 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go语言的设计目标是将静态语言的安全性和性能与动态语言的易用性相结合。Go语言在语言层面提供了对协程的支持&#xff0c;特别适合编写高并发的项目。随着使用Go语言…

基于opencv的答题卡识别

文章目录 一、背景需求二、处理步骤图片预处理检测到答题卡轮廓透视变换找每个圆圈的轮廓轮廓排序判断是否答题正确 一、背景需求 传统的手动评分方法耗时且容易出错&#xff0c;自动化评分可以可以显著提高评分过程的速度和准确性、减少人工成本。 答题卡图片处理效果如下&am…

想出国?去外企?建议网工无脑冲思科认证。

近年来&#xff0c;国内职场竞争愈发激烈&#xff0c;内卷现象严重&#xff0c;大部分人都面临着巨大的就业压力&#xff0c;或是找工作无门、或是中年危机悄然来临&#xff0c;时刻担心被职场优化。 在这样的背景下&#xff0c;出国或进入外企工作&#xff0c;成为了许多人寻…

[JavaScript] 动态获取方法参数名

JavaScript&#xff08;简称“JS”&#xff09;是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名&#xff0c;但是它也被用到了很多非浏览器环境中&#xff0c;JavaScript基于原型编程、多范式的动态脚本语言&am…

Optional类的使用 java8(附代码)

&#x1f370; 个人主页:_小白不加班__ &#x1f35e;文章有不合理的地方请各位大佬指正。 &#x1f349;文章不定期持续更新&#xff0c;如果我的文章对你有帮助➡️ 关注&#x1f64f;&#x1f3fb; 点赞&#x1f44d; 收藏⭐️ 文章目录 一、什么是Optional&#xff1f;二、…

科研绘图系列:R语言和弦图 (Chord diagram)

介绍 和弦图(Chord Diagram)是一种用于展示多个实体之间相互关系的数据可视化方法。它通常用于表示网络或系统中不同节点(实体)之间的连接强度或流量。和弦图由一个圆形布局组成,每个节点在圆周上占据一个扇形区域,节点之间的连接通过圆内的线条(和弦)来表示。 特点:…

数据结构第七讲:栈和队列OJ题

数据结构第七讲&#xff1a;栈和队列OJ题 1.有效的括号2.用队列实现栈3.用栈实现队列4.设计循环队列 1.有效的括号 链接: OJ题目链接 typedef char StackDataType;typedef struct Stack {StackDataType* arr;//使用一个指针来指向开辟的数组int capacity;//保存数组的空间大…

springboot爱宠屋宠物商店管理系统-计算机毕业设计源码52726

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…

【机器学习】正规方程的简单介绍以及如何使用Scikit-Learn实现基于正规方程的闭式解线性回归

引言 Scikit-learn 是一个开源的机器学习库&#xff0c;它支持 Python 编程语言。它提供了多种机器学习算法的实现&#xff0c;并用于数据挖掘和数据分析 文章目录 引言一、正规方程的定义二、正规方程的原理三、使用 Scikit-Learn 实现基于正规方程的闭式解线性回归3.1 工具3.…

实验15.多线程调度

简介 实验.多线程调度 内核线程 1.在时钟中断函数中处理中&#xff0c;减少当前线程pcb的tick&#xff0c;tick为0则启动调度2.调度&#xff0c;把当前线程pcb放入就绪对立队尾&#xff0c;把就绪线程队首拿出来执行主要代码 引导 省略内核 list.h #ifndef __LIB_KERNEL_…

【2024最新】 服务器安装Ubuntu20.04 (安装教程、常用命令、故障排查)持续更新中.....

安装教程&#xff08;系统、NVIDIA驱动、CUDA、CUDNN、Pytorch、Timeshift、ToDesk、花生壳&#xff09; 制作U盘启动盘&#xff0c;并安装系统 在MSDN i tell you下载Ubuntu20.04 Desktop 版本&#xff0c;并使用Rufus制作UEFI启动盘&#xff0c;参考UEFI安装Ubuntu使用GPTU…