Swin transformer 论文阅读记录 代码分析
该篇文章,是我解析 Swin transformer 论文原理(结合pytorch版本代码)所记,图片来源于源paper或其他相应博客。
代码也非原始代码,而是从代码里摘出来的片段,配上简单数据,以便理解。
当然,也可能因为设置数据不当,造成误解,请多指教。
刚写了一部分。先发布。希望多多指正。
Figure 1.
(a) The proposed Swin Transformer builds hierarchical feature maps by merging image patches (shown in gray) in deeper layers ,
and has linear computation complexity to input image size due to computation of self-attention only within each local window (shown in red).
It can thus serve as a general-purpose backbone for both image classification and dense recognition tasks.
(b) In contrast, previous vision Transformers produce feature maps of a single low resolution and have quadratic computation complexity to input image size due to computation of self attention globally.
模型结构图
Figure 3.
(a) The architecture of a Swin Transformer (Swin-T);
(b) two successive Swin Transformer Blocks (notation presented with Eq. (3)).
W-MSA and SW-MSA are multi-head self attention modules with regular and shifted windowing configurations, respectively.
Stage 1 – Patch Embedding
It first splits an input RGB image into non-overlapping patches by a patch splitting module, like ViT.
Each patch is treated as a “token” and its feature is set as a concatenation of the raw pixel RGB values.
In our implementation, we use a patch size of 4×4 and thus the feature dimension of each patch is 4×4×3 = 48.(channel–3)
A linear embedding layer is applied on this raw-valued feature to project it to an arbitrary dimension (denoted as C).
这个表述,linear embedding layer,我感觉不太准确,但是,后半部分比较准确,哈哈,将channel–3变成了96.
Several Transformer blocks with modified self-attention computation (Swin Transformer blocks) are applied on these patch tokens.
The Transformer blocks maintain the number of tokens (H/4 × W/4), and together with the linear embedding are referred to as “Stage 1”.
代码
以下代码来自于model.py:
class PatchEmbed(nn.Module):"""2D Image to Patch Embedding"""
"""
@ time : 2024/12/17
"""
import torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt
import torch.nn as nn
import torch.nn.functional as Fclass PatchEmbed(nn.Module):"""2D Image to Patch Embedding"""def __init__(self, patch_size=4, in_c=3, embed_dim=96, norm_layer=None):super().__init__()patch_size = (patch_size, patch_size)self.patch_size = patch_sizeself.in_chans = in_cself.embed_dim = embed_dimself.proj = nn.Conv2d(in_c, embed_dim, kernel_size=patch_size, stride=patch_size)self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()def forward(self, x):_, _, H, W = x.shape# padding# 如果输入图片的H,W不是patch_size的整数倍,需要进行paddingpad_input = (H % self.patch_size[0] != 0) or (W % self.patch_size[1] != 0)if pad_input:# to pad the last 3 dimensions,# (W_left,W_right, H_top,H_bottom, C_front,C_back)x = F.pad(x,(0, self.patch_size[1] - W % self.patch_size[1],0, self.patch_size[0] - H % self.patch_size[0],0, 0))# 下采样patch_size倍x = self.proj(x)_, _, H, W = x.shape# flatten: [B, C, H, W] -> [B, C, HW]# transpose: [B, C, HW] -> [B, HW, C]x = x.flatten(2).transpose(1, 2)x = self.norm(x)print(x.shape)# torch.Size([1, 3136, 96])# 224/4 * 224/4 = 3136return x, H, Wif __name__ == '__main__':img_path = "tulips.jpg"img = Image.open(img_path)plt.imshow(img)# [N, C, H, W]print(img.size)# (500,375)#img_size = 224data_transform = transforms.Compose([transforms.Resize(int(img_size * 1.14)),transforms.CenterCrop(img_size),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])img = data_transform(img)print(img.shape)# torch.Size([3, 224, 224])# expand batch dimensionimg = torch.unsqueeze(img, dim=0)print(img.shape)# torch.Size([1, 3, 224, 224])# split image into non-overlapping patchespatch_embed = PatchEmbed(norm_layer=nn.LayerNorm)patch_embed(img)
Stage 2 – 3.2. Shifted Window based Self-Attention
Shifted window partitioning in successive blocks
The window-based self-attention module lacks connections across windows, which limits its modeling power.
To introduce cross-window connections while maintaining the efficient computation of non-overlapping windows,
we propose a shifted window partitioning approach which alternates between two partitioning configurations in consecutive Swin Transformer blocks.
为了在保持非重叠窗口高效计算的同时引入跨窗口连接,我们提出了一种移位窗口划分方法,该方法在连续的Swin Transformer块中交替使用两种不同的划分配置。
Figure 2.
In layer l (left), a regular window partitioning scheme is adopted, and self-attention is computed within each window.
In the next layer l + 1 (right), the window partitioning is shifted, resulting in new windows.
The self-attention computation in the new windows crosses the boundaries of the previous windows in layer l, providing connections among them.
在新窗口中进行的自注意力计算跨越了第l层中先前窗口的边界,从而在它们之间建立了连接。
Efficient batch computation for shifted configuration
An issue with shifted window partitioning is that it will result in more windows, and some of the windows will be smaller than M×M.
Here, we propose a more efficient batch computation approach by cyclic-shifting toward the top-left direction(向左上方向循环移动), as illustrated in Figure 4.
这里的 more efficient,是说相对于直观方法 padding—mask来说:
A naive solution is to pad the smaller windows to a size of M×M and mask out the padded values when computing attention.
Figure 4. Illustration of an efficient batch computation approach for self-attention in shifted window partitioning.
After this shift, a batched window may be composed of several sub-windows that are not adjacent in the feature map, so a masking mechanism is employed to limit self-attention computation to within each sub-window.
在此转换之后,批处理窗口可能由特征图中不相邻的几个子窗口组成,因此采用掩蔽机制将自注意力计算限制在每个子窗口内。
With the cyclic-shift, the number of batched windows remains the same as that of regular window partitioning, and thus is also efficient.
通过循环移位,批处理窗口的数量与常规窗口分区的数量保持不变,因此也是高效的。
上图和叙述,并不太直观,找了相关资料,一起分析:
移动完成之后,4是一个单独区域,5、3为一组,7、1为一组,8、6、2、0为一组。
但,5、3本身是两个图像的边缘,混在一起计算不是乱了吗?一起计算也没问题,ViT也是全局计算的。
但,Swin-Transformer为了防止这个问题,在代码中使用了masked MSA,这样就能够通过设置蒙板来隔绝不同区域的信息了。
源码中具体的方法就是将不计算的位置元素减去100。
这里需要注意的是,在窗口数据进行滑动完之后,需要将数据还原回去,即挪回到原来的位置上。
代码
以下代码来自于model.py:
def window_partition(x, window_size: int):"""将feature map按照window_size划分成一个个没有重叠的window主要思路是将feature转成 (num_windows*B, window_size*window_size, C)的shape,把需要self-attn计算的window排列到第0维,一次并行的qkv就可以了Args:x: (B, H, W, C)window_size (int): window size(M)Returns:windows: (num_windows*B, window_size, window_size, C)"""B, H, W, C = x.shape# B,224,224,C# B,56,56,Cx = x.view(B, H // window_size, window_size, W // window_size, window_size, C)# B,32,7,32,7,C# B,8,7,8,7,C# permute:# [B, H//Mh, Mh, W//Mw, Mw, C] -># [B, H//Mh, W//Mh, Mw, Mw, C]# B,32,32,7,7,C# B,8,8,7,7,C# view:# [B, H//Mh, W//Mw, Mh, Mw, C] -># [B*num_windows, Mh, Mw, C]# B*1024,7,7,C# B*64,7,7,C# 32*32 = 1024# 224 / 7 = 32windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)return windows
分析:将 [B, C, 56, 56] 最后变成了[64B, C, 7, 7],原先的 B*C 张 56*56 的特征图,最后变成了 B*64*C张7*7的特征;
即,我们有64B个样本,每个样本包含C个7x7的通道。
注意,window_size–M–7,是每个window的大小,7*7,不是7*7个window,我刚开始混淆了这一点。
class BasicLayer(nn.Module):# A basic Swin Transformer layer for one stage.def __init__(self, dim, depth, num_heads, window_size,mlp_ratio=4., qkv_bias=True, drop=0., attn_drop=0.,drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False):super().__init__()self.dim = dimself.depth = depthself.window_size = window_sizeself.use_checkpoint = use_checkpointself.shift_size = window_size // 2# 7//2 = 3# build blocksself.blocks = nn.ModuleList([SwinTransformerBlock(dim=dim,num_heads=num_heads,window_size=window_size,shift_size=0 if (i % 2 == 0) else self.shift_size,mlp_ratio=mlp_ratio,qkv_bias=qkv_bias,drop=drop,attn_drop=attn_drop,drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,norm_layer=norm_layer)for i in range(depth)])...# depth: 2, 2, 6, 2# 即,第一层,depth=2, 有两个SwinTransformerBlock,shift_size分别为:0,3# 即,第二层,depth=2, 有两个SwinTransformerBlock,shift_size分别为:0,3# 即,第三层,depth=6, 有两个SwinTransformerBlock,shift_size分别为:# 0,3,0,3,0,3# 即,第四层,depth=2, 有两个SwinTransformerBlock,shift_size分别为:0,3def create_mask(self, x, H, W):# calculate attention mask for SW-MSA
import numpy as np
import torchH = 7
W = 7
window_size = 7
shift_size = 3Hp = int(np.ceil(H / window_size)) * window_size
Wp = int(np.ceil(W / window_size)) * window_size# 拥有和feature map一样的通道排列顺序,方便后续window_partition
img_mask = torch.zeros((1, Hp, Wp, 1))
# [1, Hp, Wp, 1]
print(img_mask, '\n')h_slices = (slice(0, -window_size),slice(-window_size, -shift_size),slice(-shift_size, None)
)
print(h_slices, '\n')
# (slice(0, -7, None), slice(-7, -3, None), slice(-3, None, None))w_slices = (slice(0, -window_size),slice(-window_size, -shift_size),slice(-shift_size, None)
)
print(w_slices, '\n')
# (slice(0, -7, None), slice(-7, -3, None), slice(-3, None, None))cnt = 0
for h in h_slices:for w in w_slices:img_mask[:, h, w, :] = cntcnt += 1print(img_mask)
import torchimg_mask = torch.rand((2, 3))
print(img_mask)
'''
tensor([[0.7410, 0.6020, 0.5195],[0.9214, 0.2777, 0.8418]])
'''
attn_mask = img_mask.unsqueeze(1) - img_mask.unsqueeze(2)
print(attn_mask)
'''
tensor([[[ 0.0000, -0.1390, -0.2215],[ 0.1390, 0.0000, -0.0825],[ 0.2215, 0.0825, 0.0000]],[[ 0.0000, -0.6437, -0.0796],[ 0.6437, 0.0000, 0.5642],[ 0.0796, -0.5642, 0.0000]]])
'''print(img_mask.unsqueeze(1))
'''
tensor([[[0.7410, 0.6020, 0.5195]],[[0.9214, 0.2777, 0.8418]]])
'''
print(img_mask.unsqueeze(2))
'''
tensor([[[0.7410],[0.6020],[0.5195]],[[0.9214],[0.2777],[0.8418]]])
'''
上面那个代码,需要根据下面这个代码对应着走,shift_size–torch.roll()
class SwinTransformerBlock(nn.Module):# Swin Transformer Block....def forward(self, x, attn_mask):H, W = self.H, self.WB, L, C = x.shapeassert L == H * W, "input feature has wrong size"shortcut = xx = self.norm1(x)x = x.view(B, H, W, C)# pad feature maps to multiples of window size# 把feature map给pad到window size的整数倍pad_l = pad_t = 0pad_r = (self.window_size - W % self.window_size) % self.window_sizepad_b = (self.window_size - H % self.window_size) % self.window_size# 注意F.pad的顺序,刚好是反着来的, 例如:# x.shape = (b, h, w, c)# x = F.pad(x, (1, 1, 2, 2, 3, 3))# x.shape = (b, h+6, w+4, c+2)# 源码可能有误,修改成下面的# x = F.pad(x, (0, 0, pad_l, pad_r, pad_t, pad_b))x = F.pad(x, (0, 0, pad_t, pad_b, pad_l, pad_r))_, Hp, Wp, _ = x.shape# cyclic shiftif self.shift_size > 0:# paper中,滑动的size是窗口大小的/2(向下取整)# torch.roll以H,W的维度为例子,负值往左上移动,正值往右下移动。# 溢出的值在对角方向出现。即循环移动。shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))else:shifted_x = xattn_mask = None# partition windowsx_windows = window_partition(shifted_x, self.window_size) # [nW*B, Mh, Mw, C]x_windows = x_windows.view(-1, self.window_size * self.window_size, C) # [nW*B, Mh*Mw, C]# W-MSA/SW-MSAattn_windows = self.attn(x_windows, mask=attn_mask) # [nW*B, Mh*Mw, C]...
其中,torch.roll()方法简易示例如下:
import torchx = torch.randn(1, 4, 4, 3)
print(x, '\n')shifted_x = torch.roll(x, shifts=(-3, -3), dims=(1, 2))
print(shifted_x, '\n')
为了方便理解,我更换了维度:
import torchx = torch.randn(1, 3, 7, 7)
print(x, '\n')shifted_x = torch.roll(x, shifts=(-3, -3), dims=(2, 3))
print(shifted_x, '\n')
Relative position bias
Relative Position Bias通过给自注意力机制的输出加上一个与token相对位置相关的偏置项,从而增强了模型对局部和全局信息的捕捉能力。
实现方式:
1、构建相对位置索引:
- 首先,需要确定一个 window size ,并在该窗口内计算token之间的相对位置。
- 通过构建相对位置索引表(relative position index table),可以方便地查询任意两个token之间的相对位置。
2、可学习的偏置表:
- 初始化一个与相对位置索引表大小相同的可学习参数表(relative position bias table),这些参数在训练过程中会被优化。
- 根据相对位置索引,从偏置表中查询对应的偏置值,并将其加到自注意力机制的输出上。
3、计算过程:
- 在自注意力机制的计算中,通常会将 Q、K 和 V 进行矩阵乘法运算,得到注意力得分。
- 然后,将 Relative Position Bias 加到注意力得分上,再进行 softmax 运算,最后与 V 相乘得到最终的输出。
代码
import torchcoords_h = torch.arange(7)
coords_w = torch.arange(7)a, b = torch.meshgrid([coords_h, coords_w], indexing="ij")coords = torch.stack(torch.meshgrid([coords_h, coords_w], indexing="ij"))coords_flatten = torch.flatten(coords, 1)
# [2, Mh*Mw]
# print(coords_flatten)
'''
tensor([
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6],
[0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2,3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6]
])
'''
# [2, Mh*Mw, 1] - [2, 1, Mh*Mw]
relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]
relative_coords = relative_coords.permute(1, 2, 0).contiguous()
# [Mh*Mw, Mh*Mw, 2]
'''
tensor([[[ 0, 0],[ 0, -1],[ 0, -2],...,[-6, -4],[-6, -5],[-6, -6]],[[ 0, 1],[ 0, 0],[ 0, -1],...,[-6, -3],[-6, -4],[-6, -5]],[[ 0, 2],[ 0, 1],[ 0, 0],...,[-6, -2],[-6, -3],[-6, -4]],...,[[ 6, 4],[ 6, 3],[ 6, 2],...,[ 0, 0],[ 0, -1],[ 0, -2]],[[ 6, 5],[ 6, 4],[ 6, 3],...,[ 0, 1],[ 0, 0],[ 0, -1]],[[ 6, 6],[ 6, 5],[ 6, 4],...,[ 0, 2],[ 0, 1],[ 0, 0]]])
'''
relative_coords[:, :, 0] += 6
# shift to start from 0relative_coords[:, :, 1] += 6
relative_coords[:, :, 0] *= 13relative_position_index = relative_coords.sum(-1)
print(relative_position_index.shape)
# torch.Size([49, 49])# print(relative_position_index)
'''
tensor([[ 84, 83, 82, ..., 2, 1, 0],[ 85, 84, 83, ..., 3, 2, 1],[ 86, 85, 84, ..., 4, 3, 2],...,[166, 165, 164, ..., 84, 83, 82],[167, 166, 165, ..., 85, 84, 83],[168, 167, 166, ..., 86, 85, 84]])
'''
其中,
relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]
这行代码是用来计算一个二维坐标点集 coords_flatten 中所有点对之间的相对坐标(或位移)。
未对行列加乘操作之前的矩阵,relative_coords 是一个形状为 (N, N, 2) 的数组,其中 relative_coords[i, j, :] 表示从点 i 到点 j 的相对坐标(或位移)。
结合其他博客的分析:
如图,假设我们现在有一个window-size=2的feature map;
这里面如果用绝对位置来表示位置索引;
然后如果用相对位置表示,就会有4个情况,但分别都是以自己为(0, 0)计算其他token的相对位置。
分别把4个相对位置展开,得到4x4的矩阵,如最下的矩阵所示。
请注意这里说的都是位置索引,并不是最后的位置编码。因为后面我们会根据相对位置索引去取对应位置的参数。取出来的值才是相对位置编码。
源码中,作者还将二维索引给转成了一维索引。如果直接将行列相加,就变成一维了。但这样(0, 1)和(1, 0)得到的结果都是1,这样肯定不行。来看看源码的做法怎么做的:
首先,所有行、列都加上M-1,其次将所有的行索引乘上2M-1
最后行索引和列索引相加,保证了相对位置关系,也不会出现0+1 = 1+0 的现象了。
刚刚也说了,之前计算的是相对位置索引,并不是实际位置偏执参数。
真正使用到的数值需要从relative position bias table,这个表的长度是等于(2M-1)X(2M-1)的。在代码中它是一个可学习参数。
import torch
from torch import nnwindow_size = (7, 7)
num_heads = 3relative_position_bias_table = nn.Parameter(torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads)
)
print(relative_position_bias_table)
......
nn.init.trunc_normal_(self.relative_position_bias_table, std=.02)
Stage 3 – patch merging layers
To produce a hierarchical representation, the number of tokens is reduced by patch merging layers as the network gets deeper.
The first patch merging layer concatenates the features of each group of 2×2 neighboring patches, and applies a linear layer on the 4C-dimensional concatenated features.
首个补丁合并层将每组2×2相邻补丁的特征进行拼接,并在拼接后的4C维特征上应用一个线性层。
This reduces the number of tokens by a multiple of 2×2=4(2 ×downsampling of resolution), and the output dimension is set to 2C.
Swin Transformer blocks are applied afterwards for feature transformation, with the resolution kept at H/8 × W/8.
同样,结合其他大神分析,图展示如下:
Related Work
Self-attention based backbone architectures
Instead of using sliding windows, we propose to shift windows between consecutive layers, which allows for a more efficient implementation in general hardware.
。。。。。
Cited link or paper name
- Swin Transformer: Hierarchical Vision Transformer using Shifted Windows.
- https://blog.csdn.net/weixin_42392454/article/details/141395092
相关文章:

Swin transformer 论文阅读记录 代码分析
该篇文章,是我解析 Swin transformer 论文原理(结合pytorch版本代码)所记,图片来源于源paper或其他相应博客。 代码也非原始代码,而是从代码里摘出来的片段,配上简单数据,以便理解。 当然&…...

信息安全概论
文章目录 预测题重要考点1.遇到什么威胁有什么漏洞怎么缓解分析题2.网络安全现状分析 2.网络安全亮点 时间信息安全概论期末简答题软件学院实验室服务器安全风险分析与PDRR策略 1.1 信息时代的特点1.2 信息安全威胁1.3信息安全趋势1.4 研究网络与信息安全的意义2.1安全风险分析…...

2024年12月16日Github流行趋势
项目名称:PDFMathTranslate 项目维护者:Byaidu reycn hellofinch Wybxc YadominJinta项目介绍:基于 AI 完整保留排版的 PDF 文档全文双语翻译,支持 Google/DeepL/Ollama/OpenAI 等服务,提供 CLI/GUI/Docker。项目star数…...
Go 1.24即将到来!
Go 1.24 尚未发布。以下是正在撰写中的发布说明,预计 Go 1.24 将于 2025 年 2 月发布。 语言改进 Go 1.24 现在全面支持 泛型类型别名:类型别名可以像定义类型一样被参数化。详情请参阅语言规范。目前,可通过设置 GOEXPERIMENTnoaliastypep…...

FFmpeg库之ffplay
文章目录 FFmpeg环境搭建ffplay使用通用选项视频选项音频选项快捷键使用滤镜直播拉流 FFmpeg环境搭建 FFmpeg官网 FFmpeg环境搭建 ./configure \--prefix"$HOME/ffmpeg" \--extra-cflags"-I$HOME/ffmpeg/include" \--extra-ldflags"-L$HOME/ffmpeg…...

scala中模式匹配的应用
package test34object test6 {case class Person(name:String)case class Student(name:String, className:String)// match case 能根据 类名和属性的信息,匹配到对应的类// 注意:// 1 匹配的时候,case class的属性个数要对上// 2 属性名不需…...

WebRTC搭建与应用(一)-ICE服务搭建
WebRTC搭建与应用(一) 近期由于项目需要在研究前端WebGL渲染转为云渲染,借此机会对WebRTC、ICE信令协议等有了初步了解,在此记录一下,以防遗忘。 第一章 ICE服务搭建 文章目录 WebRTC搭建与应用(一)前言一、ICE是什么?二、什么…...

【计算机视觉基础CV】03-深度学习图像分类实战:鲜花数据集加载与预处理详解
本文将深入介绍鲜花分类数据集的加载与处理方式,同时详细解释代码的每一步骤并给出更丰富的实践建议和拓展思路。以实用为导向,为读者提供从数据组织、预处理、加载到可视化展示的完整过程,并为后续模型训练打下基础。 前言 在计算机视觉的深…...
Kafka学习篇
Architecture 系统间解耦,异步通信,削峰填谷 Topic 消息主题,用于存储消息 Partition 分区,通过扩大分区,可以提高存储量 Broker 部署Kafka服务的设备 Leader kafka主分区 Follwer kafka从分区 高性能之道:…...

冬日养仓鼠小指南:温暖与陪伴同行
随着冬日的脚步悄然来临,家中可爱的小仓鼠也需要我们给予更多的关怀与呵护。仓鼠虽小,但它们的冬日养护却大有学问,关乎着这些小生命能否健康快乐地度过寒冷季节。 保暖是冬季养仓鼠的首要任务。我们可以为仓鼠的小窝增添一些保暖材料&#…...

【计算机视觉基础CV】05 - 深入解析ResNet与GoogLeNet:从基础理论到实际应用
引言 在上一篇文章中,我们详细介绍了ResNet与GoogLeNet的网络结构、设计理念及其在图像分类中的应用。本文将继续深入探讨如何在实际项目中应用这些模型,特别是如何保存训练好的模型、加载模型以及使用模型进行新图像的预测。通过这些步骤,读…...
Python爬虫之代理的设置
【1】urllib中使用公开代理 import urllib.requesturl http://www.baidu.com/s?wdipheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 }# 请求对象的定制 request urllib.req…...

Canoe E2E校验自定义Checksum算法
文章目录 一、添加 DBC文件二、导入要仿真的ECU节点三、编写 CAPL脚本1. 创建 .can 文件2. 设置counter递增3. 设置 CRC 算法,以profile01 8-bit SAE J1850 CRC校验为例 四、开始仿真五、运行结果CRC在线校验 当E2E的 CRC算法非常规算法,则需要自己编写代…...

[HNCTF 2022 Week1]你想学密码吗?
下载附件用记事本打开 把这些代码放在pytho中 # encode utf-8 # python3 # pycryptodemo 3.12.0import Crypto.PublicKey as pk from hashlib import md5 from functools import reducea sum([len(str(i)) for i in pk.__dict__]) funcs list(pk.__dict__.keys()) b reduc…...

端到端自动驾驶大模型:视觉-语言-动作模型 VLA
模型框架定义、模型快速迭代能力是考查智驾团队出活能力的两个核心指标。在展开讨论Vision-Language-Action Models(VLA)之前,咱们先来讨论端到端自动驾驶大模型设计。 目录 1. 端到端自动驾驶大模型设计 1.1 模型输入设计 1.2 模型输出设计 1.3 实现难点分析 …...

druid与pgsql结合踩坑记
最近项目里面突然出现一个怪问题,数据库是pgsql,jdbc连接池是alibaba开源的druid,idea里面直接启动没问题,打完包放在centos上和windows上cmd窗口都能直接用java -jar命令启动,但是放到国产信创系统上就是报错…...

【xxl-job】XXL-Job源码深度剖析:分布式任务调度的艺术与实践
XXL-Job源码深度剖析 核心概念1、调度中心2、执行器3、任务 来个Demo1、搭建调度中心2、执行器和任务添加3、创建执行器和任务 从执行器启动说起1、初始化JobHandler2、创建一个Http服务器3、注册到调度中心 任务触发原理⭐⭐⭐1、任务如何触发?调度线程scheduleThr…...

图漾相机-ROS1_SDK_ubuntu版本编译(新版本)
文章目录 官网编译文档链接官网SDK下载链接1、下载 Camport ROS1 SDK1.下载git2、下载链接 2、准备编译工作1、安装 catkin2、配置环境变量3. 将Camport3中的linux库文件拷贝到 user/lib目录下4、修改lunch文件制定相机(可以放在最后可以参考在线文档)**…...

项目二十三:电阻测量(需要简单的外围检测电路,将电阻转换为电压)测量100,1k,4.7k,10k,20k的电阻阻值,由数码管显示。要求测试误差 <10%
资料查找: 01 方案选择 使用单片机测量电阻有多种方法,以下是一些常见的方法及其原理: 串联分压法(ADC) 原理:根据串联电路的分压原理,通过测量已知电阻和待测电阻上的电压,计算出…...

【NLP 17、NLP的基础——分词】
我始终相信,世间所有的安排都有它的道理;失之东隅,收之桑榆 —— 24.12.20 一、中文分词的介绍 1.为什么讲分词? ① 分词是一个被长期研究的任务,通过了解分词算法的发展,可以看到NLP的研究历程 ② 分词…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...