项目快过:知识蒸馏 | 目标检测 |FGD | Focal and Global Knowledge Distillation for Detectors
公开时间:2022年3月9号
项目地址:https://github.com/yzd-v/FGD
论文地址:https://arxiv.org/pdf/2111.11837
知识蒸馏已成功地应用于图像分类。然而,目标检测要复杂得多,大多数知识蒸馏方法都失败了
。本文指出,在目标检测中,教师和学生的特征在不同的领域有很大的差异,特别是在前景和背景上。如果我们平均地提取它们,特征图之间的不均匀差异将会对蒸馏产生负面影响
。因此,我们提出了聚焦蒸馏和全局蒸馏(FGD)。聚焦蒸馏将前景和背景分开,迫使学生专注于教师的临界像素和通道
。全局蒸馏重建了不同像素之间的关系,并将其从教师转移到学生身上,补偿了聚焦蒸馏中全局信息的缺失
。
由于我们的方法只需要计算特征图上的损失,因此FGD可以应用于各种检测器
。 我们在不同骨架的各种检测器上进行了实验,结果表明,该学生检测器取得了良好的mAP改进,为2~3个点。
1、核心观点
1.1 区分FG与BG的蒸馏差异
教师和学生的特征在不同的领域有很大的差异,特别是在前景和背景上。
作者通过实验表明,对fg与bg不做取得的蒸馏,还不如单独对fg或bg进行蒸馏。这里fb是是bbox对应的特征图区域,bg是背景对应的特征图区域。
1.2 具体实现
1、对backbone的输出进行Global Distillation操作,使教师模型与学生模型的输出解决
2、在neck的输出上,根据bbox区分前景与背景,分别进行蒸馏,然后loss加权
总体loss实现:
Focal Distillation
对前景与背景分别设定loss权重进行蒸馏,同时附加spatial和chanel的attention蒸馏结构,使学生模型模拟教师模型
Global Distillation
1.3 有益效果
基于表3可以发现FGD的蒸馏方式,对于各类任务(目标检测、实力分割、关键点检测)均有提升效果,基本能提升3个点左右。
与其他目标检测蒸馏策略相比,FGD方法能提升02~0.7个点的精度,同时蒸馏后的S模型精度比T模型要略高。
蒸馏后的特征图变化
2、消融实验
2.1 focal and global distillation
基于这里的对比可以发现,仅蒸馏backbone或对neck进行有区别蒸馏,均能取得良好效果。但
两个一起蒸馏能额外取得0.2个点的提升。
2.2 Spatial attention 与 Channel attention
这里的蒸馏效果差异如下,同样是结合2个维度蒸馏,能提升0.1~0.2个点。同时表明spatial蒸馏更有效
2.3 GcBlock作用
通常蒸馏是直接对比教师模型与学生模型的差异,而本文中提到基于GcBlock对二者进行高维度映射后在计算loss。这里可以发现GcBlock是蒸馏有效的基本条件,否则涨点幅度较小。
2.4 蒸馏温度
在neck中进行蒸馏时,考虑了教师输出的spatial与chanel的分布特征,具体如下所示
这里通过消融实验,表明蒸馏温度对效果的影响。0.5或0.8为最佳值,这表明需要对教师的输出进行加热,体现出显著的分布特征,学生模型才能学习好。
3、实现代码
基于mmdet进行实现
3.1 配置文件
https://github.com/yzd-v/FGD/blob/master/configs/distillers/fgd/fgd_faster_rcnn_r101_fpn_2x_distill_faster_rcnn_r50_fpn_2x_coco.py
基于对配置文件的分析,博主认为只有一个针对neck层的FeatureLoss
_base_ = ['../../_base_/datasets/coco_detection.py','../../_base_/schedules/schedule_2x.py', '../../_base_/default_runtime.py'
]
# model settings
find_unused_parameters=True
temp=0.5
alpha_fgd=0.00005
beta_fgd=0.000025
gamma_fgd=0.00005
lambda_fgd=0.0000005
distiller = dict(type='DetectionDistiller',teacher_pretrained = 'https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r101_fpn_2x_coco/faster_rcnn_r101_fpn_2x_coco_bbox_mAP-0.398_20200504_210455-1d2dac9c.pth',init_student = True,distill_cfg = [ dict(student_module = 'neck.fpn_convs.3.conv',teacher_module = 'neck.fpn_convs.3.conv',output_hook = True,methods=[dict(type='FeatureLoss',name='loss_fgd_fpn_3',student_channels = 256,teacher_channels = 256,temp = temp,alpha_fgd=alpha_fgd,beta_fgd=beta_fgd,gamma_fgd=gamma_fgd,lambda_fgd=lambda_fgd,)]),dict(student_module = 'neck.fpn_convs.2.conv',teacher_module = 'neck.fpn_convs.2.conv',output_hook = True,methods=[dict(type='FeatureLoss',name='loss_fgd_fpn_2',student_channels = 256,teacher_channels = 256,temp = temp,alpha_fgd=alpha_fgd,beta_fgd=beta_fgd,gamma_fgd=gamma_fgd,lambda_fgd=lambda_fgd,)]),dict(student_module = 'neck.fpn_convs.1.conv',teacher_module = 'neck.fpn_convs.1.conv',output_hook = True,methods=[dict(type='FeatureLoss',name='loss_fgd_fpn_1',student_channels = 256,teacher_channels = 256,temp = temp,alpha_fgd=alpha_fgd,beta_fgd=beta_fgd,gamma_fgd=gamma_fgd,lambda_fgd=lambda_fgd,)]),dict(student_module = 'neck.fpn_convs.0.conv',teacher_module = 'neck.fpn_convs.0.conv',output_hook = True,methods=[dict(type='FeatureLoss',name='loss_fgd_fpn_0',student_channels = 256,teacher_channels = 256,temp = temp,alpha_fgd=alpha_fgd,beta_fgd=beta_fgd,gamma_fgd=gamma_fgd,lambda_fgd=lambda_fgd,)]),])student_cfg = 'configs/faster_rcnn/faster_rcnn_r50_fpn_2x_coco.py'
teacher_cfg = 'configs/faster_rcnn/faster_rcnn_r101_fpn_2x_coco.py'
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(_delete_=True, grad_clip=dict(max_norm=35, norm_type=2))
data = dict(samples_per_gpu=2,workers_per_gpu=2,)
3.2 forward_train函数
detection_distiller.py 中的forward_train函数定义了模型蒸馏的前向推理流程,可以发现就是针对配置文件中的layer计算FeatureLoss
def forward_train(self, img, img_metas, **kwargs):"""Args:img (Tensor): Input images of shape (N, C, H, W).Typically these should be mean centered and std scaled.img_metas (list[dict]): A List of image info dict where each dicthas: 'img_shape', 'scale_factor', 'flip', and may also contain'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'.For details on the values of these keys see:class:`mmdet.datasets.pipelines.Collect`.Returns:dict[str, Tensor]: A dictionary of loss components(student's losses and distiller's losses)."""with torch.no_grad():self.teacher.eval()feat = self.teacher.extract_feat(img)student_loss = self.student.forward_train(img, img_metas, **kwargs)buffer_dict = dict(self.named_buffers())for item_loc in self.distill_cfg:student_module = 'student_' + item_loc.student_module.replace('.','_')teacher_module = 'teacher_' + item_loc.teacher_module.replace('.','_')student_feat = buffer_dict[student_module]teacher_feat = buffer_dict[teacher_module]for item_loss in item_loc.methods:loss_name = item_loss.namestudent_loss[loss_name] = self.distill_losses[loss_name](student_feat,teacher_feat,kwargs['gt_bboxes'], img_metas)return student_loss
3.3 Focal Global Distillation 代码
代码地址:
https://github.com/yzd-v/FGD/blob/master/mmdet/distillation/losses/fgd.py
这里的代码实现比较复杂,博主认为是将Focal Distillation部分+Global 部分的GcBlock针对同一layer对象进行实现,并没有像论文示意图中作用于不同的layer
import torch.nn as nn
import torch.nn.functional as F
import torch
from mmcv.cnn import constant_init, kaiming_init
from ..builder import DISTILL_LOSSES@DISTILL_LOSSES.register_module()
class FeatureLoss(nn.Module):"""PyTorch version of `Focal and Global Knowledge Distillation for Detectors`Args:student_channels(int): Number of channels in the student's feature map.teacher_channels(int): Number of channels in the teacher's feature map. temp (float, optional): Temperature coefficient. Defaults to 0.5.name (str): the loss name of the layeralpha_fgd (float, optional): Weight of fg_loss. Defaults to 0.001beta_fgd (float, optional): Weight of bg_loss. Defaults to 0.0005gamma_fgd (float, optional): Weight of mask_loss. Defaults to 0.001lambda_fgd (float, optional): Weight of relation_loss. Defaults to 0.000005"""def __init__(self,student_channels,teacher_channels,name,temp=0.5,alpha_fgd=0.001,beta_fgd=0.0005,gamma_fgd=0.001,lambda_fgd=0.000005,):super(FeatureLoss, self).__init__()self.temp = tempself.alpha_fgd = alpha_fgdself.beta_fgd = beta_fgdself.gamma_fgd = gamma_fgdself.lambda_fgd = lambda_fgdif student_channels != teacher_channels:self.align = nn.Conv2d(student_channels, teacher_channels, kernel_size=1, stride=1, padding=0)else:self.align = Noneself.conv_mask_s = nn.Conv2d(teacher_channels, 1, kernel_size=1)self.conv_mask_t = nn.Conv2d(teacher_channels, 1, kernel_size=1)self.channel_add_conv_s = nn.Sequential(nn.Conv2d(teacher_channels, teacher_channels//2, kernel_size=1),nn.LayerNorm([teacher_channels//2, 1, 1]),nn.ReLU(inplace=True), # yapf: disablenn.Conv2d(teacher_channels//2, teacher_channels, kernel_size=1))self.channel_add_conv_t = nn.Sequential(nn.Conv2d(teacher_channels, teacher_channels//2, kernel_size=1),nn.LayerNorm([teacher_channels//2, 1, 1]),nn.ReLU(inplace=True), # yapf: disablenn.Conv2d(teacher_channels//2, teacher_channels, kernel_size=1)) #FcBlockself.reset_parameters()def forward(self,preds_S,preds_T,gt_bboxes,img_metas):"""Forward function.Args:preds_S(Tensor): Bs*C*H*W, student's feature mappreds_T(Tensor): Bs*C*H*W, teacher's feature mapgt_bboxes(tuple): Bs*[nt*4], pixel decimal: (tl_x, tl_y, br_x, br_y)img_metas (list[dict]): Meta information of each image, e.g.,image size, scaling factor, etc."""assert preds_S.shape[-2:] == preds_T.shape[-2:],'the output dim of teacher and student differ'if self.align is not None:preds_S = self.align(preds_S)N,C,H,W = preds_S.shapeS_attention_t, C_attention_t = self.get_attention(preds_T, self.temp)S_attention_s, C_attention_s = self.get_attention(preds_S, self.temp)Mask_fg = torch.zeros_like(S_attention_t)Mask_bg = torch.ones_like(S_attention_t)wmin,wmax,hmin,hmax = [],[],[],[]for i in range(N):new_boxxes = torch.ones_like(gt_bboxes[i])new_boxxes[:, 0] = gt_bboxes[i][:, 0]/img_metas[i]['img_shape'][1]*Wnew_boxxes[:, 2] = gt_bboxes[i][:, 2]/img_metas[i]['img_shape'][1]*Wnew_boxxes[:, 1] = gt_bboxes[i][:, 1]/img_metas[i]['img_shape'][0]*Hnew_boxxes[:, 3] = gt_bboxes[i][:, 3]/img_metas[i]['img_shape'][0]*Hwmin.append(torch.floor(new_boxxes[:, 0]).int())wmax.append(torch.ceil(new_boxxes[:, 2]).int())hmin.append(torch.floor(new_boxxes[:, 1]).int())hmax.append(torch.ceil(new_boxxes[:, 3]).int())area = 1.0/(hmax[i].view(1,-1)+1-hmin[i].view(1,-1))/(wmax[i].view(1,-1)+1-wmin[i].view(1,-1))for j in range(len(gt_bboxes[i])):Mask_fg[i][hmin[i][j]:hmax[i][j]+1, wmin[i][j]:wmax[i][j]+1] = \torch.maximum(Mask_fg[i][hmin[i][j]:hmax[i][j]+1, wmin[i][j]:wmax[i][j]+1], area[0][j])Mask_bg[i] = torch.where(Mask_fg[i]>0, 0, 1)if torch.sum(Mask_bg[i]):Mask_bg[i] /= torch.sum(Mask_bg[i])fg_loss, bg_loss = self.get_fea_loss(preds_S, preds_T, Mask_fg, Mask_bg, C_attention_s, C_attention_t, S_attention_s, S_attention_t)mask_loss = self.get_mask_loss(C_attention_s, C_attention_t, S_attention_s, S_attention_t)rela_loss = self.get_rela_loss(preds_S, preds_T)loss = self.alpha_fgd * fg_loss + self.beta_fgd * bg_loss \+ self.gamma_fgd * mask_loss + self.lambda_fgd * rela_lossreturn lossdef get_attention(self, preds, temp):""" preds: Bs*C*W*H """N, C, H, W= preds.shapevalue = torch.abs(preds)# Bs*W*Hfea_map = value.mean(axis=1, keepdim=True)S_attention = (H * W * F.softmax((fea_map/temp).view(N,-1), dim=1)).view(N, H, W)# Bs*Cchannel_map = value.mean(axis=2,keepdim=False).mean(axis=2,keepdim=False)C_attention = C * F.softmax(channel_map/temp, dim=1)return S_attention, C_attentiondef get_fea_loss(self, preds_S, preds_T, Mask_fg, Mask_bg, C_s, C_t, S_s, S_t):loss_mse = nn.MSELoss(reduction='sum')Mask_fg = Mask_fg.unsqueeze(dim=1)Mask_bg = Mask_bg.unsqueeze(dim=1)C_t = C_t.unsqueeze(dim=-1)C_t = C_t.unsqueeze(dim=-1)S_t = S_t.unsqueeze(dim=1)fea_t= torch.mul(preds_T, torch.sqrt(S_t))fea_t = torch.mul(fea_t, torch.sqrt(C_t))fg_fea_t = torch.mul(fea_t, torch.sqrt(Mask_fg))bg_fea_t = torch.mul(fea_t, torch.sqrt(Mask_bg))fea_s = torch.mul(preds_S, torch.sqrt(S_t))fea_s = torch.mul(fea_s, torch.sqrt(C_t))fg_fea_s = torch.mul(fea_s, torch.sqrt(Mask_fg))bg_fea_s = torch.mul(fea_s, torch.sqrt(Mask_bg))fg_loss = loss_mse(fg_fea_s, fg_fea_t)/len(Mask_fg)bg_loss = loss_mse(bg_fea_s, bg_fea_t)/len(Mask_bg)return fg_loss, bg_lossdef get_mask_loss(self, C_s, C_t, S_s, S_t):mask_loss = torch.sum(torch.abs((C_s-C_t)))/len(C_s) + torch.sum(torch.abs((S_s-S_t)))/len(S_s)return mask_lossdef spatial_pool(self, x, in_type):batch, channel, width, height = x.size()input_x = x# [N, C, H * W]input_x = input_x.view(batch, channel, height * width)# [N, 1, C, H * W]input_x = input_x.unsqueeze(1)# [N, 1, H, W]if in_type == 0:context_mask = self.conv_mask_s(x)else:context_mask = self.conv_mask_t(x)# [N, 1, H * W]context_mask = context_mask.view(batch, 1, height * width)# [N, 1, H * W]context_mask = F.softmax(context_mask, dim=2)# [N, 1, H * W, 1]context_mask = context_mask.unsqueeze(-1)# [N, 1, C, 1]context = torch.matmul(input_x, context_mask)# [N, C, 1, 1]context = context.view(batch, channel, 1, 1)return contextdef get_rela_loss(self, preds_S, preds_T):loss_mse = nn.MSELoss(reduction='sum')context_s = self.spatial_pool(preds_S, 0)context_t = self.spatial_pool(preds_T, 1)out_s = preds_Sout_t = preds_Tchannel_add_s = self.channel_add_conv_s(context_s)out_s = out_s + channel_add_schannel_add_t = self.channel_add_conv_t(context_t)out_t = out_t + channel_add_trela_loss = loss_mse(out_s, out_t)/len(out_s)return rela_lossdef last_zero_init(self, m):if isinstance(m, nn.Sequential):constant_init(m[-1], val=0)else:constant_init(m, val=0)def reset_parameters(self):kaiming_init(self.conv_mask_s, mode='fan_in')kaiming_init(self.conv_mask_t, mode='fan_in')self.conv_mask_s.inited = Trueself.conv_mask_t.inited = Trueself.last_zero_init(self.channel_add_conv_s)self.last_zero_init(self.channel_add_conv_t)
相关文章:
项目快过:知识蒸馏 | 目标检测 |FGD | Focal and Global Knowledge Distillation for Detectors
公开时间:2022年3月9号 项目地址:https://github.com/yzd-v/FGD 论文地址:https://arxiv.org/pdf/2111.11837 知识蒸馏已成功地应用于图像分类。然而,目标检测要复杂得多,大多数知识蒸馏方法都失败了。本文指出&#…...
Spring Boot日志总结
文章目录 1.我们的日志2.日志的作用3.使用日志对象打印日志4.日志框架介绍5.深入理解门面模式(外观模式)6.日志格式的说明7.日志级别7.1日志级别分类7.2配置文件添加日志级别 8.日志持久化9.日志文件的拆分9.1官方文档9.2IDEA演示文件分割 10.日志格式的配置11.更简单的日志输入…...
PostgreSQL最常用数据类型-重点说明自增主键处理
简介 PostgreSQL提供了非常丰富的数据类型,我们平常使用最多的基本就3类: 数字类型字符类型时间类型 这篇文章重点介绍这3中类型,因为对于高并发项目还是推荐:尽量使用简单类型,把运算和逻辑放在应用中,…...
androidstudio 最新继承 proto kts 方式
在Android Studio中,如果你使用的是Kotlin DSL(.kts文件)来配置你的Gradle项目,并且你想集成Protocol Buffers(Proto),你需要稍微调整你的配置方式。以下是如何在Kotlin DSL中配置Proto集成的步…...
【STM32学习】TB6612FNG驱动芯片的学习,驱动电路的学习
目录 1、TB6612电机驱动芯片 1.1如下是芯片的引脚图: 1.2如下图是电机的控制逻辑: 1.3MOS管运转逻辑 1.3典型应用电路 2、H桥驱动电路 2.1、单极模式 2.2、双极模式 2.3、高低端MOS管导通条件 2.4、H桥电路设计 2.5、自举电路 3、电气特性 3…...
【AI战略思考13】克服懒惰,保持专注,提升效率,不再焦虑
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 引言 我发现自己最近非常懒惰,浪费了很多时间,也容易分心,不够专注,效率低下,且每天都有点焦虑,因此制定了下面的要求和作息时间表。 目…...
基于Vue3+Element Plus 实现多表单校验
使用场景 表单校验在日常的开发需求中是一种很常见的需求,通常在提交表单发起请求前校验用户输入是否符合规则,通常只需formRef.value.validate()即可校验,但是,例如一些多步骤表单、动态表单、以及不同的用户角色可能看到不同的表…...
“岗位复合化、技能层次化” 高职大数据技术专业人才培养实践
在全球数字化浪潮的推动下,大数据技术已经成为引领社会进步和经济发展的核心动力。随着《关于深化现代职业教育体系建设改革的意见》等系列指导问文件的发布,我国高职大数据技术专业的教育正迎来全新机遇与挑战。这些政策不仅明确了职业教育改革的方向&a…...
Day2 生信新手笔记: Linux基础
一、基础知识 1.1 服务器 super computer 或 server 1.2 组学数据分析 组学数据:如基因组学、转录组学、蛋白质组学等; 上游分析:主要涉及原始数据的获取和初步处理,计算量大,消耗的资源较多,在服务器完…...
AI开发-数据可视化库-Seaborn
1 需求 概述 Seaborn 是一个基于 Python 的数据可视化库,它建立在 Matplotlib 之上。其主要目的是使数据可视化更加美观、方便和高效。它提供了高层次的接口和各种美观的默认主题,能够帮助用户快速创建出具有吸引力的统计图表,用于数据分析和…...
如何把Qt exe文件发送给其他人使用
如何把Qt exe文件发送给其他人使用 1、先把 Debug改成Release2、重新构建项目3、运行项目4、找到release文件夹5、新建文件夹,存放exe文件6、打开qt控制台串口7、下载各种文件8、压缩,发送压缩包给别人 1、先把 Debug改成Release 2、重新构建项目 3、运行…...
力扣103.二叉树的锯齿形层序遍历
题目描述 题目链接103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例 1ÿ…...
MOH: MULTI-HEAD ATTENTION AS MIXTURE-OFHEAD ATTENTION
当前的问题 多头注意力使用多个头部可以提高模型的精度。然而,并不是所有的注意力头都具有同样的重要性。一些研究表明,许多注意力头可以被修剪而不影响准确性。 此外,在多头注意中,每个注意头并行操作,最终输出是所…...
Linux的文件系统
这里写目录标题 一.文件系统的基本组成索引节点目录项文件数据的存储扇区三个存储区域 二.虚拟文件系统文件系统分类进程文件表读写过程 三.文件的存储连续空间存放方式缺点 非连续空间存放方式链表方式隐式链表缺点显示链接 索引数据库缺陷索引的方式优点:多级索引…...
力扣78题详解:C语言实现子集问题
力扣78题详解:C语言实现子集问题 题目描述 给定一个不含重复元素的整数数组 nums,返回其所有可能的子集(幂集)。 说明:解集不能包含重复的子集,顺序无关。 示例 输入:nums [1,2,3] 输出&am…...
按行数据拆分到工作表-Excel易用宝
有这样一份工作表,现在要对工作表按指定行数进行拆分,如果你还在选择数据区域复制粘贴到每个工作表中,那这样的效率也太低了。 按指定行数拆分工作表,就用易用宝。 单击Excel易用宝,合并与拆分,拆分工作表…...
.net core 创建linux服务,并实现服务的自我更新
目录 创建服务创建另一个服务,用于执行更新操作给你的用户配置一些systemctl命令权限 创建服务 /etc/systemd/system下新建服务配置文件:yourapp.service,内容如下: [Unit] Descriptionyourapp Afternetwork.target[Service] Ty…...
无人机的起降装置:探索起飞和降落的秘密 !
一、起降系统的运行方式 起飞方式 垂直起飞:小型无人机通常采用垂直起飞方式,利用螺旋桨产生的升力直接从地面升起。这种方式适用于空间有限或需要快速起飞的场景。 跑道起飞:大型无人机或需要较长起飞距离的无人机,可能会采用…...
Apache Airflow 快速入门教程
Apache Airflow已经成为Python生态系统中管道编排的事实上的库。与类似的解决方案相反,由于它的简单性和可扩展性,它已经获得了普及。在本文中,我将尝试概述它的主要概念,并让您清楚地了解何时以及如何使用它。 Airflow应用场景 …...
数学题转excel;数学题库;数学试卷转excel;大风车excel
一、数学试卷转excel 有些需要刷题的朋友,需要将题库数学题转为excel格式,便于管理 前端时间帮一位朋友实现了数学题转excel,包括选择题、填空题、分析题 示例: 二、问题 数学题是最难以处理的试题,理由如下 1、有…...
【C++】类和对象(下)
目录 前言 一、再探构造函数 二、类型转换 三、static 成员 四、友元 五、内部类 六、匿名对象 七、对象拷贝时的编译器优化 总结 前言 本文主要内容:构造函数的再探--初始化列表、内置类型与自定义类型之间的转换、类的static成员、友元、内部类、匿名对…...
vue多页面应用集成时权限处理问题
在多页面应用(MPA)中,权限管理通常会涉及到每个页面的访问控制、身份验证、以及权限校验。以下是几种常见的权限处理方式: 1. 前端路由权限控制 原理:虽然是多页面应用,通常每个页面会独立加载和渲染&…...
输出保留3位小数的浮点数
输出保留3位小数的浮点数 C语言代码C代码Java代码Python代码 💐The Begin💐点点关注,收藏不迷路💐 读入一个单精度浮点数,保留3位小数输出这个浮点数。 输入 只有一行,一个单精度浮点数。 输出 也只有一…...
openssl的运用
一、概述 Opssl是一个用于TLS/SSL协议的工具包,也是一个通用密码库。 包含了国密sm2 sm3 sm4,包含了对称加密,非对称加密,单项散列,伪随机、签名,密码交换,证书等一些算法库。 为了深层次的学习…...
C++STL之vector(超详细)
CSTL之vector 1.vector基本介绍2.vector重要接口2.1.构造函数2.2.迭代器2.3.空间2.3.1.resize2.3.2.capacity 2.4.增删查找 3.迭代器失效4.迭代器分类 🌟🌟hello,各位读者大大们你们好呀🌟🌟 🚀Ὠ…...
RabbitMQ消息可靠性保证机制5--消息幂等性处理
RabbitMQ层面有实现“去重机制”来保证“恰好一次”吗?答案是没并没有,而且现在主流的消息中间件都没有实现。 一般解决重复消息的办法是:在消费端让我们消费消息操作具有幂等性。 幂等性问题并不是消息系统独有,而是࿰…...
24/12/1 算法笔记<强化学习> 创建Maze交互
我们今天制作一个栅格的游戏。 我们直接上代码教学。 1.载入库和查找相应的函数版本 import numpy as np import time import sysif sys.version_info.major 2:import Tkinter as tk else:import tkinter as tk 2.设置长宽和单元格大小 UNIT 40 MAZE_H 4 MAZE_W 4 3.初始…...
c++:模版 template
一、模版 1.格式: template <typname T> 2.实现 2.1自动推导 模板只对紧跟在后面的第一行代码有效,如果后面还想定义模板函数需要重新定义模板 #include <iostream> #include <string>template <typename T> void Print(T v…...
javascript切换类、删除类、修改类以及增加类
在JavaScript中,操作DOM元素的类(class)是一个常见的操作。以下是一些基本的方法来切换类、删除类、修改类以及增加内联样式: 切换类(Toggle Class) 切换类意味着如果类存在则移除它,如果不存…...
区块链学习笔记(2)--区块链的交易模型part1
模型基础 区块链的tx分为两种模型,分别是比特币为代表的UTXO(Unspent Transaction Output)模型,和以太坊为代表的Account模型。前者适用于货币记账,后者适用于链上应用。 UTXO模型 类似于现金的交易模型 一个tx包含…...
反射知识总结
狂神说 反射的功能: 类加载内存分析 类加载的时候,class对象就形成了。 类无论有多少对象,class对象只有一个。 获取类对象三种方式 反射,就是通过api获取一个类的类对象: 有三种方式: 方法一…...
selenium部署分布式 UI 自动化测试环境-Docker
一、根据selenium/hub官网的配置信息,进行配置。 How to run this image The Hub and Nodes will be created in the same network and they will recognize each other by their container name. A Docker network needs to be created as a first step.Create …...
算法刷题Day5: BM52 数组中只出现一次的两个数字
描述: 一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 要求:空间复杂度 O(1),时间复杂度O(n)。 题目传送门 is here 思路: 方法一:最简单的思路就…...
使用docker-compose部署搜索引擎ElasticSearch6.8.10
背景 Elasticsearch 是一个开源的分布式搜索和分析引擎,基于 Apache Lucene 构建。它被广泛用于实时数据搜索、日志分析、全文检索等应用场景。 Elasticsearch 支持高效的全文搜索,并提供了强大的聚合功能,可以处理大规模的数据集并进行快速…...
多线程篇-5--线程分类(线程类型,springboot中常见线程类型,异步任务线程)
常见的线程类型包括用户线程(User Threads)、守护线程(Daemon Threads)、主线程(Main Thread)、工作线程(Worker Threads)和线程池中的线程。 一、用户线程(User Thread…...
详解高斯消元
详解高斯消元 好东西,可以求所有一次方程组的解。 \color {red} 好东西,可以求所有一次方程组的解。 好东西,可以求所有一次方程组的解。 前置知识 一般消元法的公理: 两方程互换,解不变; 一方程乘以非零数 k k k,解不变; 一方程乘以数 k k k加上另一方程,解不变。 …...
【Python网络爬虫笔记】5-(Request 带参数的get请求) 爬取豆瓣电影排行信息
目录 1.抓包工具查看网站信息2.代码实现3.运行结果 1.抓包工具查看网站信息 请求路径 url:https://movie.douban.com/typerank请求参数 页面往下拉,出现新的请求结果,参数start更新,每次刷新出20条新的电影数据 2.代码实现 # 使用网络爬…...
泷羽sec- shell编程(8) until循环以及函数基本创建调用 学习笔记
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
Apache Flink从Kafka中消费商品数据,并进行商品分类的数量统计题
使用Apache Flink从Kafka中消费商品数据,并进行商品分类的数量统计是一个典型的流处理任务。以下是一个详细的步骤指南和示例代码,帮助你实现这一功能。 ### 前提条件 1. **安装Flink**:确保你的环境中已经安装了 Apache Flink。 2. **安装…...
Ubuntu 安装 MariaDB
安装 MariaDB具体步骤 1、更新软件包索引: sudo apt update2、安装 MariaDB 服务器: sudo apt install mariadb-server3、启动 MariaDB 服务(如果未自动启动): sudo systemctl start mariadb4、设置 MariaDB 开机启…...
GPT打字机效果—— fetchEventSouce进行sse流式请求
EventStream基本用法 与 WebSocket 不同的是,服务器发送事件是单向的。数据消息只能从服务端到发送到客户端(如用户的浏览器)。这使其成为不需要从客户端往服务器发送消息的情况下的最佳选择。 const evtSource new EventSource(“/api/v1/…...
Leetcode 3373. Maximize the Number of Target Nodes After Connecting Trees II
Leetcode 3373. Maximize the Number of Target Nodes After Connecting Trees II 1. 接替思路2. 代码实现 题目链接:3373. Maximize the Number of Target Nodes After Connecting Trees II 1. 接替思路 这一题和前一题Leetcode 3372其实整体思路上并没有啥太大…...
JS的魔法三角:constructor、prototype与__proto__
在JavaScript中,constructor、prototype和__proto__是与对象创建和继承机制紧密相关的三个概念。理解它们之间的关系对于掌握JavaScript的面向对象编程至关重要。下面将详细介绍这个魔法三角: 1. constructor 定义:constructor是一个函数&am…...
用c语言完成俄罗斯方块小游戏
用c语言完成俄罗斯方块小游戏 这估计是你在编程学习过程中的第一个小游戏开发,怎么说呢,在这里只针对刚学程序设计的学生,就是说刚接触C语言没多久,有一点功底的学生看看,简陋的代码,简陋的实现࿰…...
Leetcode打卡:N皇后
执行结果:通过 题目:51 N皇后 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#…...
位运算在嵌入式系统开发中的应用
目录 一、数据存储与节省 “绝技” 1.1. 传感器数据存储挑战 1.2. 位运算解决方案 1.2.1. 数据整合 1.2.2. 数据提取 1.3. 收益分析 二、硬件控制 “精准操纵术” 2.1. 位运算操控硬件寄存器的实例 2.2. 位运算在硬件控制中的优势 2.3. 电机驱动芯片寄存器控制示例 …...
livekit 服务部署
本地起 1. 拉取生成文件镜像 sudo docker pull livekit/generate 2. 生成配置文件 sudo docker run --rm -v $PWD:/output livekit/generate --local (记住输出信息) 3. 拉取livekit/livekit-server sudo docker pull livekit/livekit-server 4. 开始运行服务 sudo docker run…...
笔记:visual studio2022编译 和 运行 VTK9.4.0
一、下载源码 VTK官网下载对应源码。 Download | VTKhttps://vtk.org/download/ 二、编译动态库(基于Win11 24h) 1. 用VS打开VTK源码的CMakeLists.txt,等待项目配置完成。 生成完毕如图 2.生成动态库,点击全部生成,…...
【Linux | 计网】TCP协议深度解析:从连接管理到流量控制与滑动窗口
目录 前言: 1、三次握手和四次挥手的联系: 为什么挥手必须要将ACK和FIN分开呢? 2.理解 CLOSE_WAIT 状态 CLOSE_WAIT状态的特点 3.FIN_WAIT状态讲解 3.1、FIN_WAIT_1状态 3.2、FIN_WAIT_2状态 3.3、FIN_WAIT状态的作用与意义 4.理解…...
Qt Sensors 传感器控制介绍篇
文章目录 Qt Sensors 模块介绍前言 什么是 Qt Sensors?主要特点: 支持的传感器类型Qt Sensors 的核心组件应用场景优势总结 Qt Sensors 模块介绍 前言 随着现代硬件设备的不断发展,传感器已成为许多设备(如智能手机、平板电脑和…...