Video classification with UniFormer基于统一分类器的视频分类

本文主要介绍了UniFormer: Unified Transformer for Efficient Spatial-Temporal Representation Learning
代码:https://github.com/Sense-X/UniFormer/tree/main/video_classification

UNIFormer

动机

由于视频具有大量的局部冗余和复杂的全局依赖关系,因此从视频中学习丰富的、多尺度的时空语义是一项具有挑战性的任务。

最近的研究主要是由三维卷积神经网络和Vision Transformer驱动的。虽然三维卷积可以有效地聚集局部上下文来抑制来自小三维邻域的局部冗余,但由于感受域有限,它缺乏捕获全局依赖的能力。另外,vision Transformer通过自注意机制可以有效地捕获长时间依赖,但由于各层tokens之间存在盲目的相似性比较,限制了减少局部冗余。
在这里插入图片描述
视频transformer对浅层的局部特征编码比较低效,在时空上都只能学习到临近的信息

方法

提出了一种新型的统一Transformer(UniFormer),它以一种简洁的形式,将三维卷积和时空自注意的优点集成在一起,并在计算和精度之间取得了较好的平衡。与传统的Transformer不同的是,关系聚合器通过在浅层和深层中分别局部和全局tokens相关性来处理时空冗余和依赖关系。
在这里插入图片描述
由上图可知,UniFormer模型其中的特色组件是:动态位置嵌入(DPE)、多头关系聚合器(MHRA)和前馈网络(FFN)
在这里插入图片描述

动态位置嵌入(DPE)

之前的方法主要采用图像任务的绝对或相对位置嵌入。然而,当测试较长的输入帧时,绝对位置嵌入应该通过微调插值到目标输入大小。相对位置嵌入由于缺乏绝对位置信息而修改了自注意,表现较差。为了克服上述问题,扩展了条件位置编码(CPE)来设计DPE。
在这里插入图片描述

其中DWConv表示简单的三维深度卷积与零填充。由于卷积的共享参数和局部性,DPE可以克服置换不变性,并且对任意输入长度都很友好。此外,在CPE中已经证明,零填充可以帮助边界上的token意识到自己的绝对位置,因此所有token都可以通过查询其邻居来逐步编码自己的绝对时空位置信息

class SpeicalPatchEmbed(nn.Module):""" Image to Patch Embedding"""def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768):super().__init__()img_size = to_2tuple(img_size)patch_size = to_2tuple(patch_size)num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // patch_size[0])self.img_size = img_sizeself.patch_size = patch_sizeself.num_patches = num_patchesself.norm = nn.LayerNorm(embed_dim)self.proj = conv_3xnxn(in_chans, embed_dim, kernel_size=patch_size[0], stride=patch_size[0])def forward(self, x):B, C, T, H, W = x.shape# FIXME look at relaxing size constraints# assert H == self.img_size[0] and W == self.img_size[1], \#     f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."x = self.proj(x)B, C, T, H, W = x.shapex = x.flatten(2).transpose(1, 2)x = self.norm(x)x = x.reshape(B, T, H, W, -1).permute(0, 4, 1, 2, 3).contiguous()return x

多头关系聚合器(MHRA)

设计了一种替代的关系聚合器(RA),它可以将三维卷积和时空自注意灵活地统一在一个简洁的Transformer中,分别解决了浅层和深层的视频冗余和依赖问题。具体来说,MHRA通过多头融合进行tokens关系学习:
在这里插入图片描述

  1. 输入张量为 X ∈ R C × T × H × W , r e s h a p e 为 X ∈ R L × C X \in \mathbb{R}^{C \times T \times H \times W} , reshape为 \mathbf{X} \in \mathbb{R}^{L \times C} XRC×T×H×W,reshapeXRL×C L = T × H × W L=T \times H \times W L=T×H×W
  2. 通过线性转换,可以将 X \mathbf{X} X 转换为上下文信息 V n ( X ) ∈ R L × C N , n \mathrm{V}_{n}(\mathbf{X}) \in \mathbb{R}^{L \times \frac{C}{N}} , \mathrm{n} Vn(X)RL×NCn 表示第几个head。
  3. 然后关系聚合器 RA通过token affinity A n ∈ R L × L \mathrm{A}_{n} \in \mathbb{R}^{L \times L} AnRL×L 来融合上下文信息得到 R n ( X ) ∈ R L × C N \mathbf{R}_{n}(\mathbf{X}) \in \mathbb{R}^{L \times \frac{C}{N}} Rn(X)RL×NC
  4. 最后concat所有的head信息,并通过 U ∈ C L × C \mathbf{U} \in \mathbb{C}^{L \times C} UCL×C聚合所有head的信息。

根据上下文的域大小,可以将MHRA分为 local MHRA 和global MHRA
在网络浅层中,目标是学习小三维时空中局部时空背景下的详细视频表示:值仅依赖于token之间的相对3D位置
在这里插入图片描述

class CBlock(nn.Module):def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0.,drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm):super().__init__()self.pos_embed = conv_3x3x3(dim, dim, groups=dim)self.norm1 = bn_3d(dim)self.conv1 = conv_1x1x1(dim, dim, 1)self.conv2 = conv_1x1x1(dim, dim, 1)self.attn = conv_5x5x5(dim, dim, groups=dim)# NOTE: drop path for stochastic depth, we shall see if this is better than dropout hereself.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()self.norm2 = bn_3d(dim)mlp_hidden_dim = int(dim * mlp_ratio)self.mlp = CMlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)def forward(self, x):x = x + self.pos_embed(x)x = x + self.drop_path(self.conv2(self.attn(self.conv1(self.norm1(x)))))x = x + self.drop_path(self.mlp(self.norm2(x)))return x   

在网络深层中,关注于在全局视频帧中捕获长远token依赖关系:通过比较全局视图中所有token的内容相似性
在这里插入图片描述

class SABlock(nn.Module):def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0.,drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm):super().__init__()self.pos_embed = conv_3x3x3(dim, dim, groups=dim)self.norm1 = norm_layer(dim)self.attn = Attention(dim,num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale,attn_drop=attn_drop, proj_drop=drop)# NOTE: drop path for stochastic depth, we shall see if this is better than dropout hereself.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()self.norm2 = norm_layer(dim)mlp_hidden_dim = int(dim * mlp_ratio)self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)def forward(self, x):x = x + self.pos_embed(x)B, C, T, H, W = x.shapex = x.flatten(2).transpose(1, 2)x = x + self.drop_path(self.attn(self.norm1(x)))x = x + self.drop_path(self.mlp(self.norm2(x)))x = x.transpose(1, 2).reshape(B, C, T, H, W)return x

模型代码

class Uniformer(nn.Module):"""Vision Transformer一个PyTorch实现:`一个图像值16x16词:大规模图像识别的Transformer` - https://arxiv.org/abs/2010.11929"""def __init__(self, cfg):super().__init__()# 从配置中提取各种参数depth = cfg.UNIFORMER.DEPTH  # 模型深度num_classes = cfg.MODEL.NUM_CLASSES  # 类别数量img_size = cfg.DATA.TRAIN_CROP_SIZE  # 图像尺寸in_chans = cfg.DATA.INPUT_CHANNEL_NUM[0]  # 输入通道数embed_dim = cfg.UNIFORMER.EMBED_DIM  # 嵌入维度head_dim = cfg.UNIFORMER.HEAD_DIM  # 头部维度mlp_ratio = cfg.UNIFORMER.MLP_RATIO  # MLP比例qkv_bias = cfg.UNIFORMER.QKV_BIAS  # QKV偏置qk_scale = cfg.UNIFORMER.QKV_SCALE  # QKV缩放representation_size = cfg.UNIFORMER.REPRESENTATION_SIZE  # 表示维度drop_rate = cfg.UNIFORMER.DROPOUT_RATE  # Dropout率attn_drop_rate = cfg.UNIFORMER.ATTENTION_DROPOUT_RATE  # 注意力Dropout率drop_path_rate = cfg.UNIFORMER.DROP_DEPTH_RATE  # 随机深度衰减率split = cfg.UNIFORMER.SPLIT  # 是否分裂std = cfg.UNIFORMER.STD  # 是否标准化self.use_checkpoint = cfg.MODEL.USE_CHECKPOINT  # 使用检查点self.checkpoint_num = cfg.MODEL.CHECKPOINT_NUM  # 检查点数量logger.info(f'Use checkpoint: {self.use_checkpoint}')  # 日志:使用检查点logger.info(f'Checkpoint number: {self.checkpoint_num}')  # 日志:检查点数量self.num_classes = num_classesself.num_features = self.embed_dim = embed_dim  # 为了与其他模型保持一致,设置特征数量和嵌入维度norm_layer = partial(nn.LayerNorm, eps=1e-6)  # 层标准化函数# 创建不同尺寸的Patch嵌入层self.patch_embed1 = SpeicalPatchEmbed(img_size=img_size, patch_size=4, in_chans=in_chans, embed_dim=embed_dim[0])  # Patch嵌入层1self.patch_embed2 = PatchEmbed(img_size=img_size // 4, patch_size=2, in_chans=embed_dim[0], embed_dim=embed_dim[1], std=std)  # Patch嵌入层2self.patch_embed3 = PatchEmbed(img_size=img_size // 8, patch_size=2, in_chans=embed_dim[1], embed_dim=embed_dim[2], std=std)  # Patch嵌入层3self.patch_embed4 = PatchEmbed(img_size=img_size // 16, patch_size=2, in_chans=embed_dim[2], embed_dim=embed_dim[3], std=std)  # Patch嵌入层4self.pos_drop = nn.Dropout(p=drop_rate)  # 位置Dropout层dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depth))]  # 随机深度衰减规则num_heads = [dim // head_dim for dim in embed_dim]  # 头部数量# 创建Transformer块并组成模型的不同部分self.blocks1 = nn.ModuleList([CBlock(dim=embed_dim[0], num_heads=num_heads[0], mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i], norm_layer=norm_layer) for i in range(depth[0])])  # 第一个部分的Transformer块self.blocks2 = nn.ModuleList([CBlock(dim=embed_dim[1], num_heads=num_heads[1], mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i+depth[0]], norm_layer=norm_layer) for i in range(depth[1])])  # 第二个部分的Transformer块if split:self.blocks3 = nn.ModuleList([SplitSABlock(dim=embed_dim[2], num_heads=num_heads[2], mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i+depth[0]+depth[1]], norm_layer=norm_layer)for i in range(depth[2])])  # 如果拆分,创建第三个部分的Split Self-Attention块self.blocks4 = nn.ModuleList([SplitSABlock(dim=embed_dim[3], num_heads=num_heads[3], mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i+depth[0]+depth[1]+depth[2]], norm_layer=norm_layer)for i in range(depth[3])])  # 如果拆分,创建第四个部分的Split Self-Attention块else:self.blocks3 = nn.ModuleList([SABlock(dim=embed_dim[2], num_heads=num_heads[2], mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i+depth[0]+depth[1]], norm_layer=norm_layer)for i in range(depth[2])])  # 创建第三个部分的Self-Attention块self.blocks4 = nn.ModuleList([SABlock(dim=embed_dim[3], num_heads=num_heads[3], mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i+depth[0]+depth[1]+depth[2]], norm_layer=norm_layer)for i in range(depth[3])])  # 创建第四个部分的Self-Attention块self.norm = bn_3d(embed_dim[-1])  # 3D批标准化层# 表示层if representation_size:self.num_features = representation_sizeself.pre_logits = nn.Sequential(OrderedDict([('fc', nn.Linear(embed_dim, representation_size)),  # 全连接层('act', nn.Tanh())  # Tanh激活函数]))else:self.pre_logits = nn.Identity()  # 如果没有设置表示维度,则为恒等映射# 分类器头部self.head = nn.Linear(embed_dim[-1], num_classes) if num_classes > 0 else nn.Identity()  # 分类器线性层或恒等映射self.apply(self._init_weights)  # 初始化权重# 初始化某些参数的权重for name, p in self.named_parameters():if 't_attn.qkv.weight' in name:nn.init.constant_(p, 0)  # 初始化t_attn.qkv.weight为常数0if 't_attn.qkv.bias' in name:nn.init.constant_(p, 0)  # 初始化t_attn.qkv.bias为常数0if 't_attn.proj.weight' in name:nn.init.constant_(p, 1)  # 初始化t_attn.proj.weight为常数1if 't_attn.proj.bias' in name:nn.init.constant_(p, 0)  # 初始化t_attn.proj.bias为常数0def _init_weights(self, m):"""初始化权重函数"""if isinstance(m, nn.Linear):trunc_normal_(m.weight, std=.02)  # 使用截断正态分布初始化权重if isinstance(m, nn.Linear) and m.bias is not None:nn.init.constant_(m.bias, 0)  # 初始化偏置为常数0elif isinstance(m, nn.LayerNorm):nn.init.constant_(m.bias, 0)  # 初始化偏置为常数0nn.init.constant_(m.weight, 1.0)  # 初始化权重为常数1.0@torch.jit.ignoredef no_weight_decay(self):"""指定不进行权重衰减的参数"""return {'pos_embed', 'cls_token'}def get_classifier(self):"""获取分类器头部"""return self.headdef reset_classifier(self, num_classes, global_pool=''):"""重置分类器Args:num_classes (int): 新的类别数量global_pool (str): 全局池化方式"""self.num_classes = num_classesself.head = nn.Linear(self.embed_dim, num_classes) if num_classes > 0 else nn.Identity()  # 重新设置分类器头部def inflate_weight(self, weight_2d, time_dim, center=False):"""权重膨胀Args:weight_2d: 二维权重张量time_dim: 时间维度center (bool): 是否中心化Returns:Tensor: 膨胀后的三维权重张量"""if center:weight_3d = torch.zeros(*weight_2d.shape)weight_3d = weight_3d.unsqueeze(2).repeat(1, 1, time_dim, 1, 1)middle_idx = time_dim // 2weight_3d[:, :, middle_idx, :, :] = weight_2delse:weight_3d = weight_2d.unsqueeze(2).repeat(1, 1, time_dim, 1, 1)weight_3d = weight_3d / time_dimreturn weight_3ddef get_pretrained_model(self, cfg):"""获取预训练模型Args:cfg: 配置文件Returns:dict: 预训练模型参数字典"""if cfg.UNIFORMER.PRETRAIN_NAME:checkpoint = torch.load(model_path[cfg.UNIFORMER.PRETRAIN_NAME], map_location='cpu')if 'model' in checkpoint:checkpoint = checkpoint['model']elif 'model_state' in checkpoint:checkpoint = checkpoint['model_state']state_dict_3d = self.state_dict()for k in checkpoint.keys():if checkpoint[k].shape != state_dict_3d[k].shape:if len(state_dict_3d[k].shape) <= 2:logger.info(f'Ignore: {k}')  # 忽略不匹配的参数continuelogger.info(f'Inflate: {k}, {checkpoint[k].shape} => {state_dict_3d[k].shape}')  # 膨胀参数形状time_dim = state_dict_3d[k].shape[2]checkpoint[k] = self.inflate_weight(checkpoint[k], time_dim)if self.num_classes != checkpoint['head.weight'].shape[0]:del checkpoint['head.weight'] del checkpoint['head.bias'] return checkpointelse:return Nonedef forward_features(self, x):"""前向传播特征提取Args:x (tensor): 输入张量Returns:tensor: 特征提取结果"""x = self.patch_embed1(x)x = self.pos_drop(x)for i, blk in enumerate(self.blocks1):if self.use_checkpoint and i < self.checkpoint_num[0]:x = checkpoint.checkpoint(blk, x)else:x = blk(x)x = self.patch_embed2(x)for i, blk in enumerate(self.blocks2):if self.use_checkpoint and i < self.checkpoint_num[1]:x = checkpoint.checkpoint(blk, x)else:x = blk(x)x = self.patch_embed3(x)for i, blk in enumerate(self.blocks3):if self.use_checkpoint and i < self.checkpoint_num[2]:x = checkpoint.checkpoint(blk, x)else:x = blk(x)x = self.patch_embed4(x)for i, blk in enumerate(self.blocks4):if self.use_checkpoint and i < self.checkpoint_num[3]:x = checkpoint.checkpoint(blk, x)else:x = blk(x)x = self.norm(x)x = self.pre_logits(x)return xdef forward(self, x):"""前向传播Args:x (tensor): 输入张量Returns:tensor: 输出结果"""x = x[0]x = self.forward_features(x)x = x.flatten(2).mean(-1)x = self.head(x)return x

总结

原文提出了一种新的UniFormer,它可以有效地统一3D卷积和时空自注意力在一个简洁的Transformer格式,以克服视频冗余和依赖。我们在浅层采用局部MHRA,大大减少了计算负担,在深层采用全局MHRA,学习全局令牌关系。大量的实验表明,我们的UniFormer在流行的视频基准测试Kinetics-400/600和Something-Something V1/V2上实现了准确性和效率之间的较好平衡。

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

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

相关文章

C语言基本语句介绍

c程序的执行部分是由语句组成的。程序的功能也是由执行语句来实现的&#xff0c;c语句分为6类 1表达式语句 表达式语句由表达式加上分号“&#xff1b;”组成 一般形式&#xff1a;表达式&#xff1b; 2函数调用语句 由函数名&#xff0c;实际参数加上分号“&#xff1b;”…

【MySQL】事务管理

文章目录 什么是事务为什么会出现事务事务的版本支持事务的提交方式事务的相关演示事务的隔离级别查看与设置隔离级别读未提交&#xff08;Read Uncommitted&#xff09;读提交&#xff08;Read Committed&#xff09;可重复读&#xff08;Repeatable Read&#xff09;串行化&a…

神经网络中参数与超参数的区别是什么?

在神经网络中&#xff0c;参数和超参数是两个非常重要但概念上不同的元素。它们的主要区别在于它们在模型训练和构建中的角色和如何被确定。 参数&#xff08;Parameters&#xff09; 定义&#xff1a;参数是神经网络在训练过程中学习的变量。这些包括权重&#xff08;weights…

Rust-vec!与Vec::with_capacity初始化数组的区别

前言 这篇文章的实际上是对我在知乎上&#xff0c;下面这个问题的答案补充。 Rust能不能动态生成固定大小的数组&#xff08;array&#xff09;&#xff1f; 对于问题中的代码 fn main(){let n 3;let mut arr:[i32; n] [0;n] ; println!(":?", arr); }进行如下…

System学习笔记 - MacOs编译环境配置(一)

前言 好几年没有记录过东西&#xff0c;一是确实很忙&#xff0c;二是人也变懒了。新年开个新的学习计划&#xff0c;希望能坚持下去。 SystemC 简介 SystemC是一个建模语言&#xff0c;其本质是一个C的库&#xff0c;一般用于SoC建模&#xff0c;具体介绍不赘述&#xff0…

【学习记录】找最低位1/模块多次例化

一、找最低位1 要求&#xff1a;找出Nbit数据a中最低位1所在的位置&#xff0c;用onehot形式data_onehot表示 假设a1010_0100 将a减1&#xff0c;则可得最低位1后面所有数据为0的b,b1010_0011将b取反&#xff0c;得c,c0101_1100将a与c进行与操作&#xff0c;则可得 a&c 0…

CEEMDAN +组合预测模型(Transformer - BiLSTM+ ARIMA)

目录 往期精彩内容&#xff1a; 前言 1 风速数据CEEMDAN分解与可视化 1.1 导入数据 1.2 CEEMDAN分解 2 数据集制作与预处理 3 基于CEEMADN的 Transformer - BiLSTM 模型预测 3.1 定义CEEMDAN-Transformer - BiLSTM预测模型 3.2 设置参数&#xff0c;训练模型 4 基于A…

【Python学习】Python学习6-循环语句

目录 【Python学习】【Python学习】Python学习6-循环语句 前言for循环for循环示例通过序列索引迭代循环使用 else 语句 while循环while循环示例continue和 break无限循环循环使用 else 语句简单语句组 嵌套循环Python for 循环嵌套语法&#xff1a;Python while 循环嵌套语法&…

网络安全—IPSec安全策略

文章目录 网络拓扑添加策略ESP添加筛选器添加筛选器的操作另一台主机设置 AH 使用Windows Server 2003系统 网络拓扑 client1 IP 192.168.17.105client2 IP 192.168.17.106 只要保证两个主机在同一网段接口&#xff0c;即互相ping通即可完成策略的实现 下面的所有通讯都只是…

阿里云服务器ECS入门与基础运维

一、云服务器简介 1、服务器&#xff1a; (1) 概念&#xff1a; 服务器本身就是一种电脑&#xff0c;同样具备CPU、内存、硬盘、网卡、电源等硬件。 互联网对外提供网站、游戏、在线会议、网盘等服务&#xff0c;都需要将这些互联网服务部署到服务器中。 (2) 特点&#xf…

C语言编译器(C语言编程软件)完全攻略(第二十六部分:C-Free使用教程(使用C-Free编写C语言程序))

介绍常用C语言编译器的安装、配置和使用。 二十六、C-Free使用教程&#xff08;使用C-Free编写C语言程序&#xff09; 1、安装C-Free 5.0 C-Free 是一款国产的Windows下的C/C IDE&#xff0c;最新版本是 5.0&#xff0c;整个软件才 14M&#xff0c;非常轻巧&#xff0c;安装…

shell编程学习(二)

变量的类型 预定义变量 $$ 当前进程PID $? 命令执行后的返回状态.0 为执行正确&#xff0c;非 0 为执行错误 $# 位置参数的数量 $* 所有位置参数的内容 …

前端性能优化之图像优化

图像优化问题主要可以分为两方面&#xff1a;图像的选取和使用&#xff0c;图像的加载和显示。 图像基础 HTTP Archive上的数据显示&#xff0c;网站传输的数据中&#xff0c;60%的资源都是由各种图像文件组成的&#xff0c;当然这些是将各类型网站平均的结果&#xff0c;单独…

Mysql SQL审核平台Yearning本地部署

文章目录 前言1. Linux 部署Yearning2. 本地访问Yearning3. Linux 安装cpolar4. 配置Yearning公网访问地址5. 公网远程访问Yearning管理界面6. 固定Yearning公网地址 前言 Yearning 简单, 高效的MYSQL 审计平台 一款MYSQL SQL语句/查询审计工具&#xff0c;为DBA与开发人员使用…

阿里云服务器公网带宽1M/3M/5M/10M/50M百兆下载速度表

阿里云服务器公网带宽上传和下载速度对照表&#xff0c;1M带宽下载速度是128KB/秒&#xff0c;为什么不是1M/秒&#xff1f;阿腾云atengyun.com分享阿里云服务器带宽1M、2M、3M、5M、6M、10M、20M、30M、50M、100M及200M等公网带宽下载和上传速度对照表&#xff0c;附带宽价格表…

C# Winform 在低DPI创建窗体后,在高DPI运行时,窗体会自动拉伸,导致窗体显示不全

C# Winform 在低DPI创建窗体后&#xff0c;在高DPI运行时&#xff0c;窗体会自动拉伸&#xff0c;导致窗体显示不全&#xff0c; 比如在分辨率为100% 的电脑创建C#项目&#xff0c;当运动到分辨率为125%的电脑运行时&#xff0c;后者运行的窗体会自动拉伸&#xff0c;窗体显示…

【linux学习笔记】网络

目录 【linux学习笔记】网络检查、监测网络ping-向网络主机发送特殊数据包traceroute-跟踪网络数据包的传输路径netstat-检查网络设置及相关统计数据 【linux学习笔记】网络 检查、监测网络 ping-向网络主机发送特殊数据包 最基本的网络连接命令就是ping命令。ping命令会向指…

Java二叉树的遍历以及最大深度问题

Java学习面试指南&#xff1a;https://javaxiaobear.cn 1、树的相关概念 1、树的基本定义 树是我们计算机中非常重要的一种数据结构&#xff0c;同时使用树这种数据结构&#xff0c;可以描述现实生活中的很多事物&#xff0c;例如家谱、单位的组织架构、等等。 树是由n&#…

VMware中找到存在但是不显示的虚拟机(彻底发现)VMware已创建虚拟机不显示

删除VMware中的虚拟机的时候&#xff0c;可能没有把虚拟机完全删除&#xff0c;或者说 “移除” 后找不到虚拟机在哪里&#xff0c;内存空间也没有得到释放&#xff0c;那该如何解决呢&#xff1f; 1.明确&#xff1a; “移除” 不等于 “从磁盘删除” 移除&#xff1a;只…

【IPC通信--socket套接字--心跳包】

Socket 心跳包 提高网络通信稳定性 随着网络通信技术的不断发展&#xff0c;网络通信已成为我们日常工作和生活中不可或缺的一部分。但是在使用网络通信的过程中&#xff0c;时常会遇到网络延迟、丢包等问题&#xff0c;这些问题不仅影响我们的工作和生活效率&#xff0c;也会…