pytorch中创建maskrcnn模型

2024-04-29 07:04
文章标签 模型 创建 pytorch maskrcnn

本文主要是介绍pytorch中创建maskrcnn模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0.模型输入/输出参数参见

链接: pytorch的mask-rcnn的模型参数解释
核心代码
GeneralizedRCNN(这里以mask-rcnn来解释说明)

# 通过输入图像获取fpn特征图,注意这里的backbone不是直接的resnet,而是fpn化后的
features = self.backbone(images.tensors)
# 由于是mask-rcnn,故而是一个dict,这里是处理非fpn的包装为dict
if isinstance(features, torch.Tensor):features = OrderedDict([("0", features)])
# RPN负责生成候选区域(proposals)。它基于前面提取的特征features,以及输入图像images和目标targets(如果有的话,例如在训练阶段)来生成这些候选区域。同时,它也可能返回与候选区域生成相关的损失proposal_losses。
proposals, proposal_losses = self.rpn(images, features, targets)
#ROI Heads(Region of Interest Heads)负责对这些候选区域进行分类和边界框回归。它基于RPN生成的候选区域proposals,前面提取的特征features,以及输入图像的大小images.image_sizes和目标targets来执行这些任务。同时,它返回检测结果detections和与分类和边界框回归相关的损失detector_losses。
detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)
# 后处理步骤通常包括将检测结果从模型输出格式转换为更易于解释或可视化的格式。例如,它可能包括将边界框坐标从模型使用的格式转换为图像的实际像素坐标,或者对分类得分进行阈值处理以过滤掉低置信度的检测。
detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)  # type: ignore[operator]
# 汇总损失
losses = {}
losses.update(detector_losses)
losses.update(proposal_losses)

核心模型类:

MaskRCNN(FasterRCNN)
FasterRCNN(GeneralizedRCNN)
GeneralizedRCNN(nn.Module)
# 处理原始图像
GeneralizedRCNNTransform(nn.Module)
BackboneWithFPN(nn.Module)
IntermediateLayerGetter(nn.ModuleDict)
FeaturePyramidNetwork(nn.Module)
# RPN网络
RegionProposalNetwork(nn.Module)
# 建立anchor
AnchorGenerator(nn.Module)
# rpnhead
RPNHead(nn.Module)

1.提取特征图

通过骨干网络(如ResNet)提取输入图像的特征图

1.1 执行transform

对输入的images,targets执行transform,主要是标准化和resize的合并操作

1.1.1 images执行标准化操作

如果是采用的imagenet权重,则一般采用以下参数执行标准化操作.主要作用屏蔽图像色温/曝光一类的影响.
注意,传入到模型的images是0-1之间的float表示的tensor

image_mean = [0.485, 0.456, 0.406]
image_std = [0.229, 0.224, 0.225]

1.1.2 images执行resize操作

同一个batch的图像需要缩放到同一尺寸,才可以合并.
定义dataloader时的sampler,可以创建一个相似宽高比的图像分配到一组组成batch的sapmler以优化计算.
模型需要指定一个max_size以及一个min_size.过大/小的图像会被缩放至一个合适尺寸.
resize方法可以采用双线性插值法(pytorch的模型是这么干的),或者直接填充.

1.1.3targets的mask执行resize操作

图像resize了,mask也需要同样操作,不然对不上.方法和图像的一致

1.1.4 images执行合并tensor操作

将list(tensor([N,H,W]))[B] 合并为tensor[B,N,H,W]以便传入backbone

1.2 创建backbone,以及backbone_with_fpn

1.2.1 使用backbone网络,提取创建fpn网络

例如restnet50,不需要返回分类信息,而是前面的多层特征图信息,然后组合为fpn数据
调用栈
GeneralizedRCNN.forward->
RegionProposalNetwork.forward->
BackboneWithFPN.forward

backbone = resnet50(weights=weights_backbone, progress=progress, norm_layer=norm_layer)
backbone = _resnet_fpn_extractor(backbone, trainable_backbone_layers)

输出结果形如:
在这里插入图片描述

1.2.2 提取fpn特征数据

现在我们来提取输出features
一共分2步,body和fpn
body从backbone提取原始特征层数据 (pytorch 定义为 IntermediateLayerGetter 类)
fpn将其处理打包为fpn结构数据 (pytorch 定义为 FeaturePyramidNetwork 类)

def forward(self, x: Tensor) -> Dict[str, Tensor]:x = self.body(x)x = self.fpn(x)return x
1.2.2.1 body

resnet的网络结构如下,我们需要提取layer1-4的输出结果来构建fpn,
提取所有return_layers最后一个层,即layer4之前的所有层,即抛弃掉无用的avgpool和fc层
resnet50所有层
参考精简代码如下:

import copy
from collections import OrderedDictimport torch
from PIL import Image
from torchvision.models import resnet50, ResNet50_Weights
from torchvision import transformsif __name__ == '__main__':model = resnet50(weights=ResNet50_Weights.DEFAULT)original_img = Image.open("a.png").convert('RGB')ts = transforms.Compose([transforms.ToTensor()])img = ts(original_img)img = torch.unsqueeze(img, dim=0)model.eval()# 需要返回用以构建fpn层的名字return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}# 创建return_layers的副本return_layers_copy = copy.deepcopy(return_layers)# 存储有效的层layers = OrderedDict()# 提取所有return_layers最后一个层,即layer4之前的所有层,即抛弃掉无用的avgpool和fc层for name, module in model.named_children():layers[name] = moduleif name in return_layers_copy:del return_layers_copy[name]# 如果指示的层被删光了,说明遍历到最后一个了,跳出循环if not return_layers_copy:break# 创建结果集合out = OrderedDict()for name, module in layers.items():img = module(img)if name in return_layers:out_name = return_layers[name]out[out_name] = img# rs = model(img)print(out)

输出入下图
提取有用的层,并且获取数据

1.2.2.2 fpn

对body输出的out的4个结果分别执行1x1的卷积操作(共4个卷积核,输出均为256,输入是256~2048)得到结果
精简代码如下:

o2 = list()
in_channels_list = [256, 512, 1024, 2048]
out_channels = 256
# 使用一个1x1的卷积核处理为同样深度的特征图
inner_blocks = nn.ModuleList()
for index, in_channels in enumerate(in_channels_list):inner_block_module = nn.Conv2d(in_channels, out_channels, kernel_size=1, padding=0)inner_blocks.append(inner_blocks)# 等效于不设定激活函数和归一化层的Conv2d,注意Conv2dNormActivation会自动计算padding,以使之尺寸不变# inner_block_module2 = Conv2dNormActivation(in_channels, out_channels, kernel_size=1, padding=0, norm_layer=None,#                                            activation_layer=None)x = out.get(str(index))x = inner_block_module(x)o2.append(x)print(o2)

输出如下
在这里插入图片描述对同一深度的结果(o2)操作上采样以及相加,即:
注:此处方便理解,C代表代码中的o2,C2代表o2的下标2,所以有0,和论文中的不太一致
C3=P3
P3上采样+C2=P2
P2上采样+C1=P1
P1上采样+C0=P0

对P0-3分别做一次3x3的卷积,对P3做最大池化得pool
P0->3x3卷积=out(0)
P1->3x3卷积=out(1)
P2->3x3卷积=out(2)
P3->3x3卷积=out(3)
P3->maxpool=pool
代码简化示意如下:

 # 执行上采样以及合并操作,以及结果再次卷积o3 = list()# 最后一个直接丢到结果集上,作为p4last_inner = o2[-1]o3.append(last_inner)# 倒着遍历o2,从倒数第3个开始# 使用一个3x3的卷积核再次处理结果, 减少上采样的混叠效应layer_blocks = nn.ModuleList()for idx in range(len(o2) - 2, -1, -1):# 获取当前这个,以及形状inner_lateral = o2[idx]feat_shape = inner_lateral.shape[-2:]# 对上层的那个执行上采样inner_top_down = nn.functional.interpolate(last_inner, size=feat_shape)# 相加作为P3~P1last_inner = inner_lateral + inner_top_down# 使用一个3x3的卷积核再次处理结果,减少上采样的混叠效应layer_block_module = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=0)layer_blocks.append(layer_block_module)# 倒序存储到结果上o3.insert(0, layer_block_module(last_inner))# 取出最小特征图做一次池化,池化核1x1,步长2tm = nn.functional.max_pool2d(o3[-1], kernel_size=1, stride=2, padding=0)o3.append(tm)names = ["0", "1", "2", "3", "pool"]# make it back an OrderedDictout = OrderedDict([(k, v) for k, v in zip(names, o3)])print(o3)

在这里插入图片描述以上全部演示代码

import copy
from collections import OrderedDictimport torch
from PIL import Image
from torchvision.models import resnet50, ResNet50_Weights
from torchvision import transforms
from torchvision.ops import Conv2dNormActivation
from torch import nnif __name__ == '__main__':model = resnet50(weights=ResNet50_Weights.DEFAULT)original_img = Image.open("a.png").convert('RGB')ts = transforms.Compose([transforms.ToTensor()])img = ts(original_img)img = torch.unsqueeze(img, dim=0)model.eval()# 需要返回用以构建fpn层的名字return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}# 创建return_layers的副本return_layers_copy = copy.deepcopy(return_layers)# 存储有效的层layers = OrderedDict()# 提取所有return_layers最后一个层,即layer4之前的所有层,即抛弃掉无用的avgpool和fc层for name, module in model.named_children():layers[name] = moduleif name in return_layers_copy:del return_layers_copy[name]# 如果指示的层被删光了,说明遍历到最后一个了,跳出循环if not return_layers_copy:break# 创建结果集合out = OrderedDict()for name, module in layers.items():img = module(img)if name in return_layers:out_name = return_layers[name]out[out_name] = imgprint(out)in_channels_list = [256, 512, 1024, 2048]out_channels = 256# 创建1x1卷积,并执行卷积操作o2 = list()# 使用一个1x1的卷积核处理为同样深度的特征图inner_blocks = nn.ModuleList()for index, in_channels in enumerate(in_channels_list):# 用以执行处理同一深度的卷积核inner_block_module = nn.Conv2d(in_channels, out_channels, kernel_size=1, padding=0)inner_blocks.append(inner_blocks)# 等效于不设定激活函数和归一化层的Conv2d# inner_block_module2 = Conv2dNormActivation(in_channels, out_channels, kernel_size=1, padding=0,#                                            norm_layer=None,activation_layer=None)x = out.get(str(index))x = inner_block_module(x)o2.append(x)# 执行上采样以及合并操作,以及结果再次卷积o3 = list()# 最后一个直接丢到结果集上,作为p4last_inner = o2[-1]o3.append(last_inner)# 倒着遍历o2,从倒数第3个开始# 使用一个3x3的卷积核再次处理结果, 减少上采样的混叠效应layer_blocks = nn.ModuleList()for idx in range(len(o2) - 2, -1, -1):# 获取当前这个,以及形状inner_lateral = o2[idx]feat_shape = inner_lateral.shape[-2:]# 对上层的那个执行上采样inner_top_down = nn.functional.interpolate(last_inner, size=feat_shape)# 相加作为P3~P1last_inner = inner_lateral + inner_top_down# 使用一个3x3的卷积核再次处理结果,减少上采样的混叠效应layer_block_module = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=0)layer_blocks.append(layer_block_module)# 倒序存储到结果上o3.insert(0, layer_block_module(last_inner))# 取出最小特征图做一次池化,卷积核1x1,步长2tm = nn.functional.max_pool2d(o3[-1], kernel_size=1, stride=2, padding=0)o3.append(tm)names = ["0", "1", "2", "3", "pool"]# make it back an OrderedDictout = OrderedDict([(k, v) for k, v in zip(names, o3)])print(o3)

在这个过程中,可以学习的参数分布在
1.backbone网络,可以锁定一些层不更新,pytorch默认是更新3个层
2.处理特征图为同一深度的1x1核的卷积层
3.最后输出前的3x3的卷积层

2 构建RPN网络

上文我们获取了5张尺寸各异,深度为256的特征图,下面我们对他进行RPN即
(Region Proposal Network)区域生成网络构建.
注意 : 后面的原图,均指被transform处理过的图像,而不是真的原原本本的图像

        features = self.backbone(images.tensors)if isinstance(features, torch.Tensor):features = OrderedDict([("0", features)])proposals, proposal_losses = self.rpn(images, features, targets)detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)  # type: ignore[operator]

2.1 创建anchors

fpn创建了5张特征图(下图示例),我们取最大尺寸的为例,(其他的做法同理):
请添加图片描述

  1. 特征图尺寸为: 1x256x200x272 (batch_size=1) ->记作A
  2. 原始图像尺寸 800x1066 (实际尺寸为1848, 2464)->记作B
  3. 可以看出 A的尺寸是B的4倍(大约) .
  4. 做一个映射,一个A的点,映射到B上就是4个像素点.
  5. 我给A的每一个点,创建9个候选框,长宽比为(0.5,1,2).长为(16,32,64)
  6. 那么总计就是 200x272x9 = 489600个候选框.
  7. 下面计算出每一个候选框的实际坐标,按照(x1,y1,x2,y2)返回一个(489600,4)的tensor

2.1.1 基础cell_anchor构建

  1. 示例代码,计算出9个候选框的基础尺寸,其中scales代表是面积的开方,也可以理解为,在长宽比为1时,边长就是scales值.(注意实际使用的代码应该返回一个list,以适应5个特征图)
    调用栈
    GeneralizedRCNN.forward->
    RegionProposalNetwork.forward->
    AnchorGenerator.forward
import torch
from torch import Tensordef generate_anchors(scales,aspect_ratios,dtype: torch.dtype = torch.float32,device: torch.device = torch.device("cpu"),
) -> Tensor:scales = torch.as_tensor(scales, dtype=dtype, device=device)aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)h_ratios = torch.sqrt(aspect_ratios)w_ratios = 1 / h_ratiosws = (w_ratios[:, None] * scales[None, :]).view(-1)hs = (h_ratios[:, None] * scales[None, :]).view(-1)base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2return base_anchors.round()if __name__ == '__main__':size = (16, 32, 64)aspect_ratio = (0.5, 1.0, 2.0)print(generate_anchors(size, aspect_ratio))

输出结果

tensor([[-11.,  -6.,  11.,   6.],[-23., -11.,  23.,  11.],[-45., -23.,  45.,  23.],[ -8.,  -8.,   8.,   8.],[-16., -16.,  16.,  16.],[-32., -32.,  32.,  32.],[ -6., -11.,   6.,  11.],[-11., -23.,  11.,  23.],[-23., -45.,  23.,  45.]])

2.1.2 计算中心点相加cell_anchor

  1. 使用基础cell_anchor,A的所有点坐标,以及和原图的缩放关系,计算所有anchor.
    cell_anchor为(9x4),即A的每个点坐标都有9和候选框
    A尺寸为(200x272),即共有54400个坐标
    即最终结果应该是(54400x9x4) = (489600x4)的tensor
    其中4是由cell_anchor+缩放过比例的A坐标得到
    简化代码如下
import torchfrom test2 import generate_anchorsif __name__ == '__main__':grid_height = 200grid_width = 272# 和原图的缩放比例stride_height = torch.tensor(4)stride_width = torch.tensor(4)device = torch.device("cpu")# 依照缩放比例,即步幅,将特征图像素点缩放到原始图上shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_widthshifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height# 将(200x272)=54400个中心点数据(cx,cy) 变为54400x4的数据,即54400x(x1,y1,x2,y2)=(cx,cy,cx,cy)shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij")shift_x = shift_x.reshape(-1)shift_y = shift_y.reshape(-1)# shifts表示共有54400个中心点,每个中心点的坐标为(x1,y1,x2,y2);shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1)# 获取cell_anchors(9,4) 表示每个中心点都有9中可能,坐标距离(x1,y1,x2,y2)偏移分别是(a1,b1,a2,b2)(例如:[-11.,  -6.,  11.,   6.])size = (16, 32, 64)aspect_ratio = (0.5, 1.0, 2.0)cell_anchor = generate_anchors(size, aspect_ratio)# 只需要将shifts(54400x4) + cell_anchors(9x4)相加即可的得到结果(489600x4),即shifts,cell_anchors的第一维分别扩展9和54400倍即可anchor = shifts.view(-1, 1, 4) + cell_anchor.view(1, -1, 4)# 将 54400x9x4 转为 489600x4 ,代表共有489600的anchor,每个含1个坐标(x1,y1,x2,y2)anchor = anchor.view(-1, 4)print(anchor.shape)
  1. 对5个特征图执行相同操作,注意size的选用.在不同特征图上,size可以设置为不同形状的不同值,以适应在不同特征图尺寸的表现.
  2. 分辨率越大的特征图,缩放比例就越小,中心点间距小,故而size的设定就应越小
  3. 分辨率越小的特征图,缩放比例就越大,中心点间距大,故而size的设定就应越大
  4. 例如size可以设定为((16, 32, 64),(32, 64, 128),(64,128,256),(128,256,512),(256,512,1024)),当然也可以设定为一样的,看需求如何,同理aspect_ratio 也可以按照实际的需求自行设定,比如存在细长棍状的物体时,可以比例设置为(0.25, 0.5, 1.0, 2.0, 4.0)
  5. 按照每个scles=3.aspect_ratio =3来计算.总共获得个尺寸候选框分别为,最后加起来就好
    200 × 272 × 9 = 489600 100 × 136 × 9 = 122400 50 × 68 × 9 = 30600 25 × 34 × 9 = 7650 13 × 19 × 9 = 2223 s u m ( ) = 652473 \begin{align} 200 \times272 \times9&=489600\\ 100 \times136 \times9&=122400\\ 50 \times68 \times9&=30600\\ 25 \times34 \times9&=7650\\ 13 \times19 \times9&=2223\\ sum()&=652473 \end{align}\\ 200×272×9100×136×950×68×925×34×913×19×9sum()=489600=122400=30600=7650=2223=652473

2.2 计算每个anchor分类和回归值

这么多的候选框,首先进行一次判断,过绝大部分无用的anchor.
在这里插入图片描述

  1. 需要判断这个anchor是否保留,即判断他存在物体的可能性有多高,例如设定可能性大于70%即保留.
  2. 那这个存在物体就是一个二分类问题,即上图的2k scores
  3. 预测框和实际物体边框(GT)的差距有多少,就是一个回归问题.即上图的4k coordinates
  4. 注意,这个是需要对每一个候选框进行的操作

方案:
使用所有的特征图作为输入,创建一个模型RPNHead,计算预测,返回2个结果,分类结果与回归结果
即:使用一个3x3的卷积处理后分别接上分类卷积和回归卷积,输出通道数量应为每个点的可能的anchor数,即K,计算应得到2个结果

objectness(252473x1) = (
200x272x9x1+
100x136x9x1

)
pred_bbox_deltas (252473x4)= (
200x272x9x4+
100x136x9x4

)
注意 pred_bbox_deltas 并不是直接返回的直接边界值,而是和GT的偏差,因为图像尺寸不同原因,且是参数化后值,故有_deltas后缀
模型代码如下
调用栈
GeneralizedRCNN.forward->
RegionProposalNetwork.forward->
RPNHead.forward

class RPNHead(nn.Module):def __init__(self, in_channels: int, num_anchors: int, conv_depth=1) -> None:super().__init__()convs = []for _ in range(conv_depth):convs.append(Conv2dNormActivation(in_channels, in_channels, kernel_size=3, norm_layer=None))self.conv = nn.Sequential(*convs)self.cls_logits = nn.Conv2d(in_channels, num_anchors, kernel_size=1, stride=1)self.bbox_pred = nn.Conv2d(in_channels, num_anchors * 4, kernel_size=1, stride=1)for layer in self.modules():if isinstance(layer, nn.Conv2d):torch.nn.init.normal_(layer.weight, std=0.01)  # type: ignore[arg-type]if layer.bias is not None:torch.nn.init.constant_(layer.bias, 0)  # type: ignore[arg-type]# 省略若干方法def forward(self, x: List[Tensor]) -> Tuple[List[Tensor], List[Tensor]]:logits = []bbox_reg = []for feature in x:t = self.conv(feature)logits.append(self.cls_logits(t))bbox_reg.append(self.bbox_pred(t))return logits, bbox_reg

2.3过滤无用候选框

这篇关于pytorch中创建maskrcnn模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/945407

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多