Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类
Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类
- CIFAR10数据集
- ParNet
- 架构特点
- 优势
- 应用
- ParNet结构代码详解
- 结构代码
- 代码详解
- SSE
- ParNetBlock 类
- DownsamplingBlock 类
- FusionBlock 类
- ParNet 类
- 训练过程和测试结果
- 代码汇总
- parnet.py
- train.py
- test.py
前面文章我们构建了AlexNet、Vgg、GoogleNet、ResNet、MobileNet、EfficientNet对CIFAR10进行分类:
Pytorch | 从零构建AlexNet对CIFAR10进行分类
Pytorch | 从零构建Vgg对CIFAR10进行分类
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
Pytorch | 从零构建ResNet对CIFAR10进行分类
Pytorch | 从零构建MobileNet对CIFAR10进行分类
Pytorch | 从零构建EfficientNet对CIFAR10进行分类
这篇文章我们来构建ParNet(Non-Deep Networks).
CIFAR10数据集
CIFAR-10数据集是由加拿大高级研究所(CIFAR)收集整理的用于图像识别研究的常用数据集,基本信息如下:
- 数据规模:该数据集包含60,000张彩色图像,分为10个不同的类别,每个类别有6,000张图像。通常将其中50,000张作为训练集,用于模型的训练;10,000张作为测试集,用于评估模型的性能。
- 图像尺寸:所有图像的尺寸均为32×32像素,这相对较小的尺寸使得模型在处理该数据集时能够相对快速地进行训练和推理,但也增加了图像分类的难度。
- 类别内容:涵盖了飞机(plane)、汽车(car)、鸟(bird)、猫(cat)、鹿(deer)、狗(dog)、青蛙(frog)、马(horse)、船(ship)、卡车(truck)这10个不同的类别,这些类别都是现实世界中常见的物体,具有一定的代表性。
下面是一些示例样本:

ParNet
ParNet是一种高效的深度学习网络架构由谷歌研究人员于2021年提出,以下从其架构特点、优势及应用等方面进行详细介绍:
架构特点
- 并行子结构:ParNet的核心在于其并行的子结构设计。它由多个并行的分支组成,每个分支都包含一系列的卷积层和池化层等操作。这些分支在网络中同时进行计算,就像多条并行的道路同时运输信息一样,大大提高了信息处理的效率。
- 多尺度特征融合:不同分支在不同的尺度上对输入图像进行处理,然后将这些多尺度的特征进行融合。例如,一个分支可能专注于提取图像中的局部细节特征,而另一个分支则更擅长捕捉图像的全局上下文信息。通过融合这些不同尺度的特征,ParNet能够更全面、更准确地理解图像内容。
- 深度可分离卷积:在网络的卷积操作中,大量使用了深度可分离卷积。这种卷积方式将传统的卷积操作分解为深度卷积和逐点卷积两个步骤,大大减少了计算量,同时提高了模型的运行速度,使其更适合在移动设备等资源受限的环境中应用。

优势
- 高效性:由于其并行结构和深度可分离卷积的使用,ParNet在计算效率上具有很大的优势。它可以在保证模型性能的前提下,大大减少模型的参数量和计算量,从而实现快速的推理和训练。
- 灵活性:ParNet的并行子结构和多尺度特征融合方式使其具有很强的灵活性。它可以根据不同的任务和数据集进行调整和优化,轻松适应各种图像识别和处理任务。
- 可扩展性:该网络架构具有良好的可扩展性,可以方便地增加或减少分支的数量和深度,以满足不同的性能需求。
应用
- 图像分类:在图像分类任务中,ParNet能够快速准确地对图像中的物体进行分类。例如,在CIFAR-10和ImageNet等标准图像分类数据集上,ParNet取得了与现有先进模型相当的准确率,同时具有更快的推理速度。
- 目标检测:在目标检测任务中,ParNet可以有效地检测出图像中的目标物体,并确定其位置和类别。通过对多尺度特征的融合和利用,ParNet能够更好地处理不同大小和形状的目标物体,提高检测的准确率和召回率。
- 语义分割:在语义分割任务中,ParNet能够对图像中的每个像素进行分类,将图像分割成不同的语义区域。其多尺度特征融合的特点使得它在处理复杂的场景和物体边界时具有更好的效果,能够生成更准确的分割结果。
ParNet结构代码详解
结构代码
import torch
import torch.nn as nn
import torch.nn.functional as Fclass SSE(nn.Module):def __init__(self, in_channels):super(SSE, self).__init__()self.global_avgpool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Linear(in_channels, in_channels)def forward(self, x):out = self.global_avgpool(x)out = out.view(out.size(0), -1)out = self.fc(out)out = torch.sigmoid(out)out = out.view(out.size(0), out.size(1), 1, 1)return x * outclass ParNetBlock(nn.Module):def __init__(self, in_channels, out_channels):super(ParNetBlock, self).__init__()self.branch1x1 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.branch3x3 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.sse = SSE(out_channels)def forward(self, x):branch1x1 = self.branch1x1(x)branch3x3 = self.branch3x3(x)out = branch1x1 + branch3x3out = self.sse(out)out = F.silu(out)return outclass DownsamplingBlock(nn.Module):def __init__(self, in_channels, out_channels):super(DownsamplingBlock, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=2, padding=1, bias=False)self.bn = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.se = SSE(out_channels)def forward(self, x):out = self.conv(x)out = self.bn(out)out = self.relu(out)out = self.se(out)return outclass FusionBlock(nn.Module):def __init__(self, in_channels, out_channels):super(FusionBlock, self).__init__()self.conv1x1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=2, bias=False)self.bn = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.se = SSE(out_channels)self.concat = nn.Conv2d(out_channels * 2, out_channels, kernel_size=1, bias=False)def forward(self, x1, x2):x1, x2 = self.conv1x1(x1), self.conv1x1(x2)x1, x2 = self.bn(x1), self.bn(x2)x1, x2 = self.relu(x1), self.relu(x2)x1, x2 = self.se(x1), self.se(x2)out = torch.cat([x1, x2], dim=1)out = self.concat(out)return outclass ParNet(nn.Module):def __init__(self, num_classes):super(ParNet, self).__init__()self.downsampling_blocks = nn.ModuleList([DownsamplingBlock(3, 64),DownsamplingBlock(64, 128),DownsamplingBlock(128, 256),])self.streams = nn.ModuleList([nn.Sequential(ParNetBlock(64, 64),ParNetBlock(64, 64),ParNetBlock(64, 64),DownsamplingBlock(64, 128)),nn.Sequential(ParNetBlock(128, 128),ParNetBlock(128, 128),ParNetBlock(128, 128),ParNetBlock(128, 128)),nn.Sequential(ParNetBlock(256, 256),ParNetBlock(256, 256),ParNetBlock(256, 256),ParNetBlock(256, 256))])self.fusion_blocks = nn.ModuleList([FusionBlock(128, 256),FusionBlock(256, 256)])self.final_downsampling = DownsamplingBlock(256, 1024)self.fc = nn.Linear(1024, num_classes)def forward(self, x):downsampled_features = []for i, downsampling_block in enumerate(self.downsampling_blocks):x = downsampling_block(x)downsampled_features.append(x)stream_features = []for i, stream in enumerate(self.streams):stream_feature = stream(downsampled_features[i])stream_features.append(stream_feature)fused_features = stream_features[0]for i in range(1, len(stream_features)):fused_features = self.fusion_blocks[i - 1](fused_features, stream_features[i])x = self.final_downsampling(fused_features)x = F.adaptive_avg_pool2d(x, (1, 1))x = x.view(x.size(0), -1)x = self.fc(x)return x
代码详解
以下是对上述提供的ParNet代码的详细解释,这段代码使用PyTorch框架构建了一个名为ParNet的神经网络模型,整体结构符合ParNet网络架构的特点,下面从不同模块依次进行分析:
SSE
class SSE(nn.Module):def __init__(self, in_channels):super(SSE, self).__init__()self.global_avgpool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Linear(in_channels, in_channels)def forward(self, x):out = self.global_avgpool(x)out = out.view(out.size(0), -1)out = self.fc(out)out = torch.sigmoid(out)out = out.view(out.size(0), out.size(1), 1, 1)return x * out
-
功能概述:
这个类实现了类似Squeeze-and-Excitation(SE)模块的功能,旨在对输入特征进行通道维度的重加权,突出重要的通道特征,抑制相对不重要的通道特征。 -
__init__方法:- 首先通过
nn.AdaptiveAvgPool2d(1)创建了一个自适应平均池化层,它可以将输入特征图在空间维度上压缩为大小为(1, 1)的特征图,也就是将每个通道的特征进行全局平均池化,得到通道维度上的统计信息,无论输入特征图的尺寸是多少都可以自适应处理。 - 接着创建了一个全连接层
nn.Linear(in_channels, in_channels),其输入和输出维度都是in_channels,目的是学习通道维度上的变换权重。
- 首先通过
-
forward方法:- 先将输入
x经过全局平均池化层得到压缩后的特征表示out,然后通过view操作将其维度调整为二维形式(批次大小,通道数),方便后续全连接层处理。 - 接着将这个特征送入全连接层进行线性变换,再经过
sigmoid激活函数,将输出值映射到(0, 1)区间,得到每个通道对应的权重。 - 最后将权重的维度调整回四维(批次大小,通道数,1,1),并与原始输入
x进行逐元素相乘,实现对不同通道特征的重加权。
- 先将输入
ParNetBlock 类
class ParNetBlock(nn.Module):def __init__(self, in_channels, out_channels):super(ParNetBlock, self).__init__()self.branch1x1 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.branch3x3 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.sse = SSE(out_channels)def forward(self, x):branch1x1 = self.branch1x1(x)branch3x3 = self.branch3x3(x)out = branch1x1 + branch3x3out = self.sse(out)out = F.silu(out)return out
-
功能概述:
该类定义了ParNet中的一个基础并行块结构,包含两个并行分支(1x1卷积分支和3x3卷积分支)以及一个SSE模块,用于提取和融合特征,并进行通道重加权和非线性激活。 -
__init__方法:- 构建了两个并行分支,
branch1x1是一个由1x1卷积层、批归一化层和ReLU激活函数组成的序列,1x1卷积主要用于调整通道维度,同时可以融合不同通道间的信息,且计算量相对较小。 branch3x3同样是由3x3卷积层(带有合适的填充保证特征图尺寸不变)、批归一化层和ReLU激活函数组成,3x3卷积能够捕捉局部空间特征信息。- 最后实例化了一个
SSE模块,用于后续对融合后的特征进行通道维度的重加权。
- 构建了两个并行分支,
-
forward方法:- 首先将输入
x分别送入两个并行分支进行处理,得到两个分支的输出branch1x1和branch3x3,然后将它们对应元素相加进行特征融合。 - 接着把融合后的特征送入
SSE模块进行通道重加权,最后使用F.silu(也就是swish函数)激活函数对结果进行非线性激活,并返回处理后的特征。
- 首先将输入
DownsamplingBlock 类
class DownsamplingBlock(nn.Module):def __init__(self, in_channels, out_channels):super(DownsamplingBlock, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=2, padding=1, bias=False)self.bn = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.se = SSE(out_channels)def forward(self, x):out = self.conv(x)out = self.bn(out)out = self.relu(out)out = self.se(out)return out
-
功能概述:
用于对输入特征图进行下采样操作,同时融合了批归一化、非线性激活以及类似SE的通道重加权功能,以减少特征图的空间尺寸并提取更抽象的特征。 -
__init__方法:
创建了一个3x3卷积层,其步长设置为2,配合合适的填充,在进行卷积操作时可以实现特征图在空间维度上长宽各减半的下采样效果,同时调整通道维度到out_channels。还定义了批归一化层、ReLU激活函数以及一个SSE模块。 -
forward方法:
按照顺序依次将输入x经过卷积层、批归一化层、ReLU激活函数进行处理,然后再通过SSE模块进行通道重加权,最终返回下采样并处理后的特征图。
FusionBlock 类
class FusionBlock(nn.Module):def __init__(self, in_channels, out_channels):super(FusionBlock, self).__init__()self.conv1x1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=2, bias=False)self.bn = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.se = SSE(out_channels)self.concat = nn.Conv2d(out_channels * 2, out_channels, kernel_size=1, bias=False)def forward(self, x1, x2):x1, x2 = self.conv1x1(x1), self.conv1x1(x2)x1, x2 = self.bn(x1), self.bn(x2)x1, x2 = self.relu(x1), self.relu(x2)x1, x2 = self.se(x1), self.se(x2)out = torch.cat([x1, x2], dim=1)out = self.concat(out)return out
-
功能概述:
该类用于融合不同分支或不同阶段的特征,通过一系列操作包括调整通道维度、批归一化、激活以及通道重加权,然后将两个特征在通道维度上进行拼接并进一步融合。 -
__init__方法:- 首先创建了
1x1卷积层,步长设置为2,用于对输入的两个特征分别进行通道维度调整以及下采样操作(特征图空间尺寸减半)。 - 接着定义了批归一化层、
ReLU激活函数以及SSE模块,用于对下采样后的特征进行处理。还创建了一个1x1卷积层concat,用于将拼接后的特征进一步融合为指定的通道维度。
- 首先创建了
-
forward方法:
分别对输入的两个特征x1和x2依次进行1x1卷积、批归一化、ReLU激活以及SSE模块的处理,然后将它们在通道维度上进行拼接(torch.cat操作,维度dim=1表示按通道维度拼接),最后通过concat卷积层将拼接后的特征融合为指定的通道维度,并返回融合后的特征。
ParNet 类
class ParNet(nn.Module):def __init__(self, num_classes):super(ParNet, self).__init__()self.downsampling_blocks = nn.ModuleList([DownsamplingBlock(3, 64),DownsamplingBlock(64, 128),DownsamplingBlock(128, 256),])self.streams = nn.ModuleList([nn.Sequential(ParNetBlock(64, 64),ParNetBlock(64, 64),ParNetBlock(64, 64),DownsamplingBlock(64, 128)),nn.Sequential(ParNetBlock(128, 128),ParNetBlock(128, 128),ParNetBlock(128, 128),ParNetBlock(128, 128)),nn.Sequential(ParNetBlock(256, 256),ParNetBlock(256, 256),ParNetBlock(256, 256),ParNetBlock(256, 256))])self.fusion_blocks = nn.ModuleList([FusionBlock(128, 256),FusionBlock(256, 256)])self.final_downsampling = DownsamplingBlock(256, 1024)self.fc = nn.Linear(1024, num_classes)def forward(self, x):downsampled_features = []for i, downsampling_block in enumerate(self.downsampling_blocks):x = downsampling_block(x)downsampled_features.append(x)stream_features = []for i, stream in enumerate(self.streams):stream_feature = stream(downsampled_features[i])stream_features.append(stream_feature)fused_features = stream_features[0]for i in range(1, len(stream_features)):fused_features = self.fusion_blocks[i - 1](fused_features, stream_features[i])x = self.final_downsampling(fused_features)x = F.adaptive_avg_pool2d(x, (1, 1))x = x.view(x.size(0), -1)x = self.fc(x)return x
-
功能概述:
这是整个ParNet网络的定义类,整合了前面定义的各个模块,构建出完整的网络结构,包括下采样、并行分支处理、特征融合以及最后的分类全连接层等部分,能够接收输入图像数据并输出对应的分类预测结果。 -
__init__方法:downsampling_blocks:通过nn.ModuleList创建了一个包含三个下采样块的列表,用于对输入图像依次进行下采样,将图像的空间尺寸逐步缩小,同时增加通道数,从最初的3通道(对应RGB图像)逐步变为64、128、256通道。streams:同样是nn.ModuleList,定义了三个并行的流(stream),每个流由多个ParNetBlock和一个DownsamplingBlock组成,不同流在不同的特征图尺度和通道维度上进行特征提取和处理,每个流内部的ParNetBlock用于提取和融合局部特征,最后的DownsamplingBlock用于进一步下采样。fusion_blocks:也是nn.ModuleList,包含两个特征融合块,用于融合不同流的特征,将各个流提取到的不同层次的特征进行融合,以综合利用多尺度信息。final_downsampling:定义了一个下采样块,用于对融合后的特征再进行一次下采样,将通道数提升到1024,进一步提取更抽象的全局特征。fc:创建了一个全连接层,用于将最终提取到的特征映射到指定的类别数量num_classes,实现图像分类任务的输出。
-
forward方法:- 首先,通过循环将输入
x依次经过各个下采样块进行下采样,并将每次下采样后的特征保存到downsampled_features列表中,得到不同阶段下采样后的特征图。 - 接着,针对每个流,将对应的下采样后的特征图送入流中进行处理,每个流内部的模块会进一步提取和融合特征,得到每个流输出的特征,并保存在
stream_features列表中。 - 然后,先取第一个流的特征作为初始的融合特征,再通过循环依次使用特征融合块将其他流的特征与已有的融合特征进行融合,不断更新融合特征。
- 之后,将融合后的特征送入最后的下采样块进行进一步下采样处理。
- 再通过自适应平均池化
F.adaptive_avg_pool2d将特征图在空间维度上压缩为(1, 1)大小,然后使用view操作将其展平为二维向量。 - 最后将展平后的特征送入全连接层进行分类预测,返回最终的分类结果。
- 首先,通过循环将输入
总体而言,这段代码构建了一个符合ParNet架构特点的神经网络模型,通过多个模块的组合实现了高效的特征提取、融合以及分类功能,可应用于图像分类等相关任务。
训练过程和测试结果
训练过程损失函数变化曲线:

训练过程准确率变化曲线:

测试结果:

代码汇总
项目github地址
项目结构:
|--data
|--models|--__init__.py|-parnet.py|--...
|--results
|--weights
|--train.py
|--test.py
parnet.py
import torch
import torch.nn as nn
import torch.nn.functional as Fclass SSE(nn.Module):def __init__(self, in_channels):super(SSE, self).__init__()self.global_avgpool = nn.AdaptiveAvgPool2d(1)self.fc = nn.Linear(in_channels, in_channels)def forward(self, x):out = self.global_avgpool(x)out = out.view(out.size(0), -1)out = self.fc(out)out = torch.sigmoid(out)out = out.view(out.size(0), out.size(1), 1, 1)return x * outclass ParNetBlock(nn.Module):def __init__(self, in_channels, out_channels):super(ParNetBlock, self).__init__()self.branch1x1 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.branch3x3 = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, bias=False),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))self.sse = SSE(out_channels)def forward(self, x):branch1x1 = self.branch1x1(x)branch3x3 = self.branch3x3(x)out = branch1x1 + branch3x3out = self.sse(out)out = F.silu(out)return outclass DownsamplingBlock(nn.Module):def __init__(self, in_channels, out_channels):super(DownsamplingBlock, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=2, padding=1, bias=False)self.bn = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.se = SSE(out_channels)def forward(self, x):out = self.conv(x)out = self.bn(out)out = self.relu(out)out = self.se(out)return outclass FusionBlock(nn.Module):def __init__(self, in_channels, out_channels):super(FusionBlock, self).__init__()self.conv1x1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=2, bias=False)self.bn = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.se = SSE(out_channels)self.concat = nn.Conv2d(out_channels * 2, out_channels, kernel_size=1, bias=False)def forward(self, x1, x2):x1, x2 = self.conv1x1(x1), self.conv1x1(x2)x1, x2 = self.bn(x1), self.bn(x2)x1, x2 = self.relu(x1), self.relu(x2)x1, x2 = self.se(x1), self.se(x2)out = torch.cat([x1, x2], dim=1)out = self.concat(out)return outclass ParNet(nn.Module):def __init__(self, num_classes):super(ParNet, self).__init__()self.downsampling_blocks = nn.ModuleList([DownsamplingBlock(3, 64),DownsamplingBlock(64, 128),DownsamplingBlock(128, 256),])self.streams = nn.ModuleList([nn.Sequential(ParNetBlock(64, 64),ParNetBlock(64, 64),ParNetBlock(64, 64),DownsamplingBlock(64, 128)),nn.Sequential(ParNetBlock(128, 128),ParNetBlock(128, 128),ParNetBlock(128, 128),ParNetBlock(128, 128)),nn.Sequential(ParNetBlock(256, 256),ParNetBlock(256, 256),ParNetBlock(256, 256),ParNetBlock(256, 256))])self.fusion_blocks = nn.ModuleList([FusionBlock(128, 256),FusionBlock(256, 256)])self.final_downsampling = DownsamplingBlock(256, 1024)self.fc = nn.Linear(1024, num_classes)def forward(self, x):downsampled_features = []for i, downsampling_block in enumerate(self.downsampling_blocks):x = downsampling_block(x)downsampled_features.append(x)stream_features = []for i, stream in enumerate(self.streams):stream_feature = stream(downsampled_features[i])stream_features.append(stream_feature)fused_features = stream_features[0]for i in range(1, len(stream_features)):fused_features = self.fusion_blocks[i - 1](fused_features, stream_features[i])x = self.final_downsampling(fused_features)x = F.adaptive_avg_pool2d(x, (1, 1))x = x.view(x.size(0), -1)x = self.fc(x)return x
train.py
test.py
相关文章:
Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类
Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类 CIFAR10数据集ParNet架构特点优势应用 ParNet结构代码详解结构代码代码详解SSEParNetBlock 类DownsamplingBlock 类FusionBlock 类ParNet 类 训练过程和测试结果代码汇总parnet.pytrain.pytest.py 前面文章我们构…...
验证 Dijkstra 算法程序输出的奥秘
一、引言 Dijkstra 算法作为解决图中单源最短路径问题的经典算法,在网络路由、交通规划、资源分配等众多领域有着广泛应用。其通过不断选择距离源节点最近的未访问节点,逐步更新邻居节点的最短路径信息,以求得从源节点到其他所有节点的最短路径。在实际应用中,确保 Dijkst…...
二叉树的最小深度
最小深度思路解析: 与求最大深度相比,求最小深度就要简单很多,从上向下访问,只要访问到一个叶节点,证明已经到达了与根节点距离最近的叶节点处,此叶节点的深度即为最小深度.借助队列,如果当前节点为叶节点,则返回该节点的深度为最终结果;如果当前节点不满足上述判断且不为空节…...
C#+OpenCv深度学习开发(常用模型汇总)
在使用 OpenCvSharp 结合深度学习进行机器视觉开发时,有许多现成的模型可以使用。以下是一些常用的深度学习模型,适用于不同的机器视觉任务,包括物体检测、图像分类和分割等。 使用示例 在 OpenCvSharp 中加载和使用这些模型的基本示例&…...
什么样的LabVIEW控制算自动控制?
自动控制是指系统通过预先设计的算法和逻辑,在无人工干预的情况下对被控对象的状态进行实时监测、决策和调整,达到预期目标的过程。LabVIEW作为一种图形化编程工具,非常适合开发自动控制系统。那么,什么样的LabVIEW控制算作“自动…...
Linux系统编程——理解系统内核中的信号捕获
目录 一、sigaction() 使用 信号捕捉技巧 二、可重入函数 三、volatile关键字 四、SIGCHLD信号 在信号这一篇中我们已经学习到了一种信号捕捉的调用接口:signal(),为了深入理解操作系统内核中的信号捕获机制,我们今天再来看一个接口:si…...
《Java 与 OpenAI 协同:开启智能编程新范式》
在当今科技飞速发展的时代,人工智能已成为推动各领域创新变革的核心力量。OpenAI 作为人工智能领域的领军者,其开发的一系列强大模型,如 GPT 系列,为自然语言处理等诸多任务带来了前所未有的突破。而 Java,作为一种广泛…...
基于Python大数据的电影可视化分析系统
标题:基于 Python 大数据的电影可视化分析系统 内容:1.摘要 本文介绍了一个基于 Python 大数据的电影可视化分析系统。该系统通过收集和分析大量电影数据,提供了对电影市场的深入洞察。文章首先介绍了系统的背景和目的,然后详细描述了系统的架构和功能。…...
【杂谈】-为什么Python是AI的首选语言
为什么Python是AI的首选语言 文章目录 为什么Python是AI的首选语言1、为何 Python 引领人工智能发展1.1 可用性和生态系统1.2 用户群和用例1.3 效率辅助 2、AI项目对Python开发人员的要求3、如何开启你的 AI 学习之旅 人工智能的广泛应用正在软件工程领域引发范式转变。Python凭…...
(高可用版本)Kubeadm+Containerd+keepalived部署高可用k8s(v1.28.2)集群
KubeadmContainerdkeepalived部署高可用k8s(v1.28.2)集群 一.环境准备,二.容器运行时Containerd安装请参照前文。KubeadmContainerd部署k8s(v1.28.2)集群(非高可用版)-CSDN博客 文章目录 KubeadmContainerdkeepalived部署高可用k8s(v1.28.2)集…...
单片机:实现自动关机电路(附带源码)
单片机实现自动关机电路 在许多嵌入式系统或便携式设备中,自动关机功能非常重要,尤其是在电池供电的设备中,防止设备长时间开启以节省电能。自动关机电路的基本功能是检测设备是否处于待机状态,若一定时间内未收到用户操作信号或…...
【YashanDB知识库】ycm-YashanDB列表有数据库显示故障排除步骤
本文内容来自YashanDB官网,原文内容请见 https://www.yashandb.com/newsinfo/7802959.html?templateId1718516 数据库状态 正常 异常 1、查看告警列表 例如:告警显示实例无法连接,一般是数据库实例服务掉了,需要尽快联系系统…...
高级的SQL查询技巧有哪些?
成长路上不孤单😊😊😊😊😊😊 【14后😊///C爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于高级SQL查询技巧方面的相关内容…...
使用 UniApp 在微信小程序中实现 SSE 流式响应
概述 服务端发送事件(Server-Sent Events, SSE)是一种允许服务器向客户端推送实时更新的技术。SSE 提供了一种单向的通信通道,服务器可以持续地向客户端发送数据,而不需要客户端频繁发起请求。这对于需要实时更新的应用场景非常有…...
transformer用作分类任务
系列博客目录 文章目录 系列博客目录1、在手写数字图像这个数据集上进行分类1. 数据准备2. 将图像转化为适合Transformer的输入3. 位置编码4. Transformer编码器5. 池化操作6. 分类头7. 训练8. 评估总结流程:相关模型: 1、在手写数字图像这个数据集上进行…...
【枚举】假币问题
题目描述: 有12枚硬币。其中有11枚真币和1枚假币。假币和真币重量不同,但不知道假币比真币轻还是重。现在,用一架天平称了这些币三次,告诉你称的结果,请你找出假币并且确定假币是轻是重(数据保证一定能找出…...
easyExcel导出大数据量EXCEL文件,前端实现进度条或者遮罩层
需求:页面点击导出,先按照页面条件去数据库查询,然后将查询到的数据导出。 问题:由于查询特别耗时,所以点击之后页面会看上去没有反应 方案1:就在点击之后在页面增加了一个进度条,等待后端查询…...
Java模拟Mqtt客户端连接Mqtt Broker
Java模拟Mqtt客户端基本流程 引入Paho MQTT客户端库 <dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.mqttv5.client</artifactId><version>1.2.5</version> </dependency>设置mqtt配置数据 …...
【电商搜索】文档的信息论生成聚类
【电商搜索】文档的信息论生成聚类 目录 文章目录 【电商搜索】文档的信息论生成聚类目录文章信息概览研究背景技术挑战如何破局技术应用主要相关工作与参考文献后续优化方向 后记 文章信息 https://arxiv.org/pdf/2412.13534 概览 本文提出了一种基于信息论的生成聚类&#…...
在福昕(pdf)阅读器中导航到上次阅读页面的方法
文章目录 在福昕(pdf)阅读器中导航到上次阅读页面的方法概述笔记用书签的方法来导航用导航按钮的方法来导航 备注END 在福昕(pdf)阅读器中导航到上次阅读页面的方法 概述 喜欢用福昕(pdf)阅读器来看pdf文件。 但是有个小问题困扰了我好久。 e.g. 300页的pdf看了一半ÿ…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
