Pytorch | 从零构建MobileNet对CIFAR10进行分类
Pytorch | 从零构建MobileNet对CIFAR10进行分类
- CIFAR10数据集
- MobileNet
- 设计理念
- 网络结构
- 技术优势
- 应用领域
- MobileNet结构代码详解
- 结构代码
- 代码详解
- DepthwiseSeparableConv 类
- 初始化方法
- 前向传播 forward 方法
- MobileNet 类
- 初始化方法
- 前向传播 forward 方法
- 训练过程和测试结果
- 代码汇总
- mobilenet.py
- train.py
- test.py
前面文章我们构建了AlexNet、Vgg、GoogleNet对CIFAR10进行分类:
Pytorch | 从零构建AlexNet对CIFAR10进行分类
Pytorch | 从零构建Vgg对CIFAR10进行分类
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
Pytorch | 从零构建ResNet对CIFAR10进行分类
这篇文章我们来构建MobileNet.
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个不同的类别,这些类别都是现实世界中常见的物体,具有一定的代表性。
下面是一些示例样本:
MobileNet
MobileNet是由谷歌在2017年提出的一种轻量级卷积神经网络,主要用于移动端和嵌入式设备等资源受限的环境中进行图像识别和分类任务,以下是对其的详细介绍:
设计理念
- 深度可分离卷积:其核心创新是采用了深度可分离卷积(Depthwise Separable Convolution)来替代传统的卷积操作。深度可分离卷积将标准卷积分解为一个深度卷积(Depthwise Convolution)和一个逐点卷积(Pointwise Convolution),大大减少了计算量和模型参数,同时保持了较好的性能。
网络结构
- 标准卷积层:输入层为3通道的彩色图像,首先经过一个普通的卷积层
conv1
,将通道数从3变为32,同时进行了步长为2的下采样操作,以减小图像尺寸。 - 深度可分离卷积层:包含了一系列的深度可分离卷积层
dsconv1
至dsconv13
,这些层按照一定的规律进行排列,通道数逐渐增加,同时通过不同的步长进行下采样,以提取不同层次的特征。 - 池化层和全连接层:在深度可分离卷积层之后,通过一个自适应平均池化层
avgpool
将特征图转换为1x1的大小,然后通过一个全连接层fc
将特征映射到指定的类别数,完成分类任务。
技术优势
- 模型轻量化:通过深度可分离卷积的使用,大大减少了模型的参数量和计算量,使得模型更加轻量化,适合在移动设备和嵌入式设备上运行。
- 计算效率高:由于减少了计算量,MobileNet在推理时具有较高的计算效率,可以快速地对图像进行分类和识别,满足实时性要求较高的应用场景。
- 性能表现较好:尽管模型轻量化,但MobileNet在图像识别任务上仍然具有较好的性能表现,能够在保持较高准确率的同时,大大降低模型的复杂度。
应用领域
- 移动端视觉任务:广泛应用于各种移动端设备,如智能手机、平板电脑等,用于图像分类、目标检测、人脸识别等视觉任务。
- 嵌入式设备视觉:在嵌入式设备,如智能摄像头、自动驾驶汽车等领域,MobileNet可以为这些设备提供高效的视觉处理能力,实现实时的图像分析和决策。
- 物联网视觉应用:在物联网设备中,MobileNet可以帮助实现对图像数据的快速处理和分析,为智能家居、智能安防等应用提供支持。
MobileNet结构代码详解
结构代码
import torch
import torch.nn as nnclass DepthwiseSeparableConv(nn.Module):def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False):super(DepthwiseSeparableConv, self).__init__()self.depthwise = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, groups=in_channels, bias=bias)self.bn1 = nn.BatchNorm2d(in_channels)self.relu1 = nn.ReLU6(inplace=True)self.pointwise = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=bias)self.bn2 = nn.BatchNorm2d(out_channels)self.relu2 = nn.ReLU6(inplace=True)def forward(self, x):out = self.depthwise(x)out = self.bn1(out)out = self.relu1(out)out = self.pointwise(out)out = self.bn2(out)out = self.relu2(out)return outclass MobileNet(nn.Module):def __init__(self, num_classes):super(MobileNet, self).__init__()self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1, bias=False)self.bn1 = nn.BatchNorm2d(32)self.relu = nn.ReLU6(inplace=True)self.dsconv1 = DepthwiseSeparableConv(32, 64, stride=1)self.dsconv2 = DepthwiseSeparableConv(64, 128, stride=2)self.dsconv3 = DepthwiseSeparableConv(128, 128, stride=1)self.dsconv4 = DepthwiseSeparableConv(128, 256, stride=2)self.dsconv5 = DepthwiseSeparableConv(256, 256, stride=1)self.dsconv6 = DepthwiseSeparableConv(256, 512, stride=2)self.dsconv7 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv8 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv9 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv10 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv11 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv12 = DepthwiseSeparableConv(512, 1024, stride=2)self.dsconv13 = DepthwiseSeparableConv(1024, 1024, stride=1)self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(1024, num_classes)def forward(self, x):out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.dsconv1(out)out = self.dsconv2(out)out = self.dsconv3(out)out = self.dsconv4(out)out = self.dsconv5(out)out = self.dsconv6(out)out = self.dsconv7(out)out = self.dsconv8(out)out = self.dsconv9(out)out = self.dsconv10(out)out = self.dsconv11(out)out = self.dsconv12(out)out = self.dsconv13(out)out = self.avgpool(out)out = out.view(out.size(0), -1)out = self.fc(out)return out
代码详解
以下是对上述代码的详细解释:
DepthwiseSeparableConv 类
这是一个自定义的深度可分离卷积层类,继承自 nn.Module
。
初始化方法
- 参数说明:
in_channels
:输入通道数,指定输入数据的通道数量。out_channels
:输出通道数,即卷积操作后输出特征图的通道数量。kernel_size
:卷积核大小,默认为3,用于定义卷积操作中卷积核的尺寸。stride
:步长,默认为1,控制卷积核在输入特征图上滑动的步长。padding
:填充大小,默认为1,在输入特征图周围添加的填充像素数量,以保持特征图尺寸在卷积过程中合适变化。bias
:是否使用偏置,默认为False
,决定卷积层是否添加偏置项。
- 构建的层及作用:
self.depthwise
:这是一个深度卷积层(nn.Conv2d
),通过设置groups=in_channels
,实现了深度可分离卷积中的深度卷积部分,它对每个输入通道分别进行卷积操作,有效地减少了计算量。self.bn1
:批归一化层(nn.BatchNorm2d
),用于对深度卷积后的输出进行归一化处理,加速模型收敛并提升模型的泛化能力。self.relu1
:激活函数层(nn.ReLU6
),采用ReLU6
激活函数(输出值限定在0到6之间),并且设置inplace=True
,意味着直接在输入的张量上进行修改,节省内存空间,增加非线性特性。self.pointwise
:逐点卷积层(nn.Conv2d
),卷积核大小为1,用于将深度卷积后的特征图在通道维度上进行融合,改变通道数到指定的out_channels
。self.bn2
:又是一个批归一化层,对逐点卷积后的输出进行归一化处理。self.relu2
:同样是ReLU6
激活函数层,进一步增加非线性,处理逐点卷积归一化后的结果。
前向传播 forward 方法
定义了数据在该层的前向传播过程:
- 首先将输入
x
通过深度卷积层self.depthwise
进行深度卷积操作,得到输出特征图。 - 然后将深度卷积的输出依次经过批归一化层
self.bn1
和激活函数层self.relu1
。 - 接着把经过处理后的特征图通过逐点卷积层
self.pointwise
进行逐点卷积,改变通道数等特征。 - 最后再经过批归一化层
self.bn2
和激活函数层self.relu2
,并返回最终的输出结果。
MobileNet 类
这是定义的 MobileNet 网络模型类,同样继承自 nn.Module
。
初始化方法
- 参数说明:
num_classes
:分类的类别数量,用于最后全连接层输出对应类别数的预测结果。
- 构建的层及作用:
self.conv1
:普通的二维卷积层(nn.Conv2d
),输入通道数为3(通常对应RGB图像的三个通道),输出通道数为32,卷积核大小为3,步长为2,用于对输入图像进行初步的特征提取和下采样,减少特征图尺寸同时增加通道数。self.bn1
:批归一化层,对conv1
卷积后的输出进行归一化。self.relu
:激活函数层,采用ReLU6
激活函数给特征图增加非线性。- 一系列的
self.dsconv
层(从dsconv1
到dsconv13
):都是前面定义的深度可分离卷积层DepthwiseSeparableConv
的实例,它们逐步对特征图进行更精细的特征提取、通道变换以及下采样等操作,不同的dsconv
层有着不同的输入输出通道数以及步长设置,以此构建出 MobileNet 网络的主体结构,不断提取和融合特征,逐步降低特征图尺寸并增加通道数来获取更高级、更抽象的特征表示。 self.avgpool
:自适应平均池化层(nn.AdaptiveAvgPool2d
),将输入特征图转换为指定大小(1, 1)
的输出,起到全局平均池化的作用,进一步压缩特征图信息,同时保持特征图的维度一致性,方便后续全连接层处理。self.fc
:全连接层(nn.Linear
),输入维度为1024(与前面网络结构最终输出的特征维度对应),输出维度为num_classes
,用于将经过前面卷积和池化等操作得到的特征向量映射到对应类别数量的预测分数上,实现分类任务。
前向传播 forward 方法
定义了 MobileNet 模型整体的前向传播流程:
- 首先将输入
x
通过conv1
进行初始卷积、bn1
进行归一化以及relu
激活。 - 然后依次通过各个深度可分离卷积层(
dsconv1
到dsconv13
),逐步提取和变换特征。 - 接着经过自适应平均池化层
self.avgpool
,将特征图压缩为(1, 1)
大小。 - 再通过
out.view(out.size(0), -1)
操作将特征图展平为一维向量(其中out.size(0)
表示批量大小,-1
表示自动计算剩余维度大小使其展平)。 - 最后将展平后的特征向量通过全连接层
self.fc
得到最终的分类预测结果并返回。
训练过程和测试结果
训练过程损失函数变化曲线:
训练过程准确率变化曲线:
测试结果:
代码汇总
项目github地址
项目结构:
|--data
|--models|--__init__.py|-mobilenet.py|--...
|--results
|--weights
|--train.py
|--test.py
mobilenet.py
import torch
import torch.nn as nnclass DepthwiseSeparableConv(nn.Module):def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False):super(DepthwiseSeparableConv, self).__init__()self.depthwise = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, groups=in_channels, bias=bias)self.bn1 = nn.BatchNorm2d(in_channels)self.relu1 = nn.ReLU6(inplace=True)self.pointwise = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=bias)self.bn2 = nn.BatchNorm2d(out_channels)self.relu2 = nn.ReLU6(inplace=True)def forward(self, x):out = self.depthwise(x)out = self.bn1(out)out = self.relu1(out)out = self.pointwise(out)out = self.bn2(out)out = self.relu2(out)return outclass MobileNet(nn.Module):def __init__(self, num_classes):super(MobileNet, self).__init__()self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1, bias=False)self.bn1 = nn.BatchNorm2d(32)self.relu = nn.ReLU6(inplace=True)self.dsconv1 = DepthwiseSeparableConv(32, 64, stride=1)self.dsconv2 = DepthwiseSeparableConv(64, 128, stride=2)self.dsconv3 = DepthwiseSeparableConv(128, 128, stride=1)self.dsconv4 = DepthwiseSeparableConv(128, 256, stride=2)self.dsconv5 = DepthwiseSeparableConv(256, 256, stride=1)self.dsconv6 = DepthwiseSeparableConv(256, 512, stride=2)self.dsconv7 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv8 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv9 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv10 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv11 = DepthwiseSeparableConv(512, 512, stride=1)self.dsconv12 = DepthwiseSeparableConv(512, 1024, stride=2)self.dsconv13 = DepthwiseSeparableConv(1024, 1024, stride=1)self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(1024, num_classes)def forward(self, x):out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.dsconv1(out)out = self.dsconv2(out)out = self.dsconv3(out)out = self.dsconv4(out)out = self.dsconv5(out)out = self.dsconv6(out)out = self.dsconv7(out)out = self.dsconv8(out)out = self.dsconv9(out)out = self.dsconv10(out)out = self.dsconv11(out)out = self.dsconv12(out)out = self.dsconv13(out)out = self.avgpool(out)out = out.view(out.size(0), -1)out = self.fc(out)return out
train.py
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from models import *
import matplotlib.pyplot as pltimport ssl
ssl._create_default_https_context = ssl._create_unverified_context# 定义数据预处理操作
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.491, 0.482, 0.446), (0.247, 0.243, 0.261))])# 加载CIFAR10训练集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=False, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128,shuffle=True, num_workers=2)# 定义设备(GPU优先,若可用)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")# 实例化模型
model_name = 'MobileNet'
if model_name == 'AlexNet':model = AlexNet(num_classes=10).to(device)
elif model_name == 'Vgg_A':model = Vgg(cfg_vgg='A', num_classes=10).to(device)
elif model_name == 'Vgg_A-LRN':model = Vgg(cfg_vgg='A-LRN', num_classes=10).to(device)
elif model_name == 'Vgg_B':model = Vgg(cfg_vgg='B', num_classes=10).to(device)
elif model_name == 'Vgg_C':model = Vgg(cfg_vgg='C', num_classes=10).to(device)
elif model_name == 'Vgg_D':model = Vgg(cfg_vgg='D', num_classes=10).to(device)
elif model_name == 'Vgg_E':model = Vgg(cfg_vgg='E', num_classes=10).to(device)
elif model_name == 'GoogleNet':model = GoogleNet(num_classes=10).to(device)
elif model_name == 'ResNet18':model = ResNet18(num_classes=10).to(device)
elif model_name == 'ResNet34':model = ResNet34(num_classes=10).to(device)
elif model_name == 'ResNet50':model = ResNet50(num_classes=10).to(device)
elif model_name == 'ResNet101':model = ResNet101(num_classes=10).to(device)
elif model_name == 'ResNet152':model = ResNet152(num_classes=10).to(device)
elif model_name == 'MobileNet':model = MobileNet(num_classes=10).to(device)criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练轮次
epochs = 15def train(model, trainloader, criterion, optimizer, device):model.train()running_loss = 0.0correct = 0total = 0for i, data in enumerate(trainloader, 0):inputs, labels = data[0].to(device), data[1].to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()_, predicted = outputs.max(1)total += labels.size(0)correct += predicted.eq(labels).sum().item()epoch_loss = running_loss / len(trainloader)epoch_acc = 100. * correct / totalreturn epoch_loss, epoch_accif __name__ == "__main__":loss_history, acc_history = [], []for epoch in range(epochs):train_loss, train_acc = train(model, trainloader, criterion, optimizer, device)print(f'Epoch {epoch + 1}: Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}%')loss_history.append(train_loss)acc_history.append(train_acc)# 保存模型权重,每5轮次保存到weights文件夹下if (epoch + 1) % 5 == 0:torch.save(model.state_dict(), f'weights/{model_name}_epoch_{epoch + 1}.pth')# 绘制损失曲线plt.plot(range(1, epochs+1), loss_history, label='Loss', marker='o')plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('Training Loss Curve')plt.legend()plt.savefig(f'results\\{model_name}_train_loss_curve.png')plt.close()# 绘制准确率曲线plt.plot(range(1, epochs+1), acc_history, label='Accuracy', marker='o')plt.xlabel('Epoch')plt.ylabel('Accuracy (%)')plt.title('Training Accuracy Curve')plt.legend()plt.savefig(f'results\\{model_name}_train_acc_curve.png')plt.close()
test.py
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from models import *import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 定义数据预处理操作
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.491, 0.482, 0.446), (0.247, 0.243, 0.261))])# 加载CIFAR10测试集
testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=128,shuffle=False, num_workers=2)# 定义设备(GPU优先,若可用)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")# 实例化模型
model_name = 'MobileNet'
if model_name == 'AlexNet':model = AlexNet(num_classes=10).to(device)
elif model_name == 'Vgg_A':model = Vgg(cfg_vgg='A', num_classes=10).to(device)
elif model_name == 'Vgg_A-LRN':model = Vgg(cfg_vgg='A-LRN', num_classes=10).to(device)
elif model_name == 'Vgg_B':model = Vgg(cfg_vgg='B', num_classes=10).to(device)
elif model_name == 'Vgg_C':model = Vgg(cfg_vgg='C', num_classes=10).to(device)
elif model_name == 'Vgg_D':model = Vgg(cfg_vgg='D', num_classes=10).to(device)
elif model_name == 'Vgg_E':model = Vgg(cfg_vgg='E', num_classes=10).to(device)
elif model_name == 'GoogleNet':model = GoogleNet(num_classes=10).to(device)
elif model_name == 'ResNet18':model = ResNet18(num_classes=10).to(device)
elif model_name == 'ResNet34':model = ResNet34(num_classes=10).to(device)
elif model_name == 'ResNet50':model = ResNet50(num_classes=10).to(device)
elif model_name == 'ResNet101':model = ResNet101(num_classes=10).to(device)
elif model_name == 'ResNet152':model = ResNet152(num_classes=10).to(device)
elif model_name == 'MobileNet':model = MobileNet(num_classes=10).to(device)criterion = nn.CrossEntropyLoss()# 加载模型权重
weights_path = f"weights/{model_name}_epoch_15.pth"
model.load_state_dict(torch.load(weights_path, map_location=device))def test(model, testloader, criterion, device):model.eval()running_loss = 0.0correct = 0total = 0with torch.no_grad():for data in testloader:inputs, labels = data[0].to(device), data[1].to(device)outputs = model(inputs)loss = criterion(outputs, labels)running_loss += loss.item()_, predicted = outputs.max(1)total += labels.size(0)correct += predicted.eq(labels).sum().item()epoch_loss = running_loss / len(testloader)epoch_acc = 100. * correct / totalreturn epoch_loss, epoch_accif __name__ == "__main__":test_loss, test_acc = test(model, testloader, criterion, device)print(f"================{model_name} Test================")print(f"Load Model Weights From: {weights_path}")print(f'Test Loss: {test_loss:.4f}, Test Acc: {test_acc:.2f}%')
相关文章:
Pytorch | 从零构建MobileNet对CIFAR10进行分类
Pytorch | 从零构建MobileNet对CIFAR10进行分类 CIFAR10数据集MobileNet设计理念网络结构技术优势应用领域 MobileNet结构代码详解结构代码代码详解DepthwiseSeparableConv 类初始化方法前向传播 forward 方法 MobileNet 类初始化方法前向传播 forward 方法 训练过程和测试结果…...
冯诺依曼架构与哈佛架构的对比与应用
冯诺依曼架构(Von Neumann Architecture),也称为 冯诺依曼模型,是由著名数学家和计算机科学家约翰冯诺依曼(John von Neumann)在1945年提出的。冯诺依曼架构为现代计算机奠定了基础,几乎所有现代…...
【Java基础面试题032】Java中的字节码是什么?
回答重点 Java字节码是Java编译器将Java源代码编译后生成的 位于Java源代码与JVM执行的执行的机器码之间。 Java字节码由JVM解释或即时编译(JIT)为机器码执行 扩展知识 Java字节码的关键点 1)字节码结构: Java字节码是与平…...
K8s ConfigMap的基础功能介绍
在 Kubernetes 中,ConfigMap 是一种用于管理配置信息的资源对象,它允许你将 配置信息与代码解耦,方便管理和更新应用配置,而无需重新构建镜像或重启服务。 ConfigMap 的功能 存储配置信息: 可以以 键值对 的形式存储配…...
stm32制作CAN适配器4--WinUsb的使用
前面使用STM32G474芯片的USB模块做了一个CANFD程序,当时用的是HID模式,在实际使用时发现HID模块的通讯速率太慢了,只能1ms传输一帧,就会造成有些掉帧现象。 现在就把HID模块改为在Window下同样免驱的WinUsb来实现CANFD数据的传输。…...
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组 在 Java 编程中,ArrayList 和 List 是最常用的集合类之一。它们帮助我们管理动态数据,支持按索引访问、增加、删除元素等操作。尤其在使用泛型时,理解它们之间的关系及应用…...
[react 3种方法] 获取ant组件ref用ts如何定义?
获取ant的轮播图组件, 我用ts如何定义? Strongly Type useRef with ElementRef | Total TypeScript import React, { ElementRef } from react; const lunboRef useRef<ElementRef<typeof Carousel>>(null); <Carousel autoplay ref{lunboRef}> 这样就…...
VS Code Copilot 与 Cursor 对比
选手简介 VS Code Copilot:算是“老牌”编程助手了,虽然Copilot在别的编辑器上也有扩展,不过体验最好的还是VS Code,毕竟都是微软家的所以功能集成更好一些;主要提供的是Complete和Chat能力,也就是代码补全…...
华为IPD流程6大阶段370个流程活动详解_第一阶段:概念阶段 — 81个活动
华为IPD流程涵盖了产品从概念到上市的完整过程,各阶段活动明确且相互衔接。在概念启动阶段,产品经理和项目经理分析可行性,PAC评审后成立PDT。概念阶段则包括产品描述、市场定位、投资期望等内容的确定,同时组建PDT核心组并准备项目环境。团队培训涵盖团队建设、流程、业务…...
Vue3组件封装技巧与心得
摘要: 日常开发中,用Vue组件进行业务拆分,代码解耦是一个很好的选择; 今天就来分享一下我在使用Vue3进行组件封装的一些技巧和心得,希望能够帮助到大家; 1. 组件特性: 在Vue中组件是一个独立的…...
15.初识接口1 C#
这是一个用于实验接口的代码 适合初认识接口的人 【CSDN开头介绍】(文心一言AI生成) 在C#编程世界中,接口(Interface)扮演着至关重要的角色,它定义了一组方法,但不提供这些方法的实现。它要求所…...
渗透测试-前端加密分析之RSA加密登录(密钥来源本地)
本文是高级前端加解密与验签实战的第5篇文章,本系列文章实验靶场为Yakit里自带的Vulinbox靶场,本文讲述的是绕过前端RSA加密来爆破登录。 分析 generateKey函数用来生成随机的RSA公私钥 加密的格式如下: {"username":"admin…...
题海拾贝:力扣 86.分隔链表
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞,关注! 1、题…...
《Mycat核心技术》第06章:Mycat问题处理总结
作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 星球项目地址:https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀,…...
前端实现图片压缩
前端实现图片压缩的主要方法有: 使用 HTML5 的 API 利用 canvas 将图片绘制到画布上,然后通过 toDataURL 方法获取压缩后的图片数据。 使用第三方库 借助 compressorjs、browser-image-compression 等开源库,快速实现高质量的图片压缩功能。…...
Python OCR 文字识别
一.引言 文字识别,也称为光学字符识别(Optical Character Recognition, OCR),是一种将不同形式的文档(如扫描的纸质文档、PDF文件或数字相机拍摄的图片)中的文字转换成可编辑和可搜索的数据的技术。随着技…...
怿星科技联合赛力斯举办workshop活动,进一步推动双方合作
12月18日,由怿星科技与赛力斯汽车联合举办的workshop活动在赛力斯五云湖总部展开,双方嘉宾围绕智能汽车发展趋势、行业前沿技术、汽车电子网络与功能测试等核心议题展开了深度对话与交流,并现场参观演示了多套前沿产品。怿星科技CEO潘凯、汽车…...
Vue.js前端框架教程1:Vue应用启动和Vue组件
文章目录 Vue 应用Vue 应用的主要组成部分:启动 Vue 应用:Vue组件基础组件组件注册父子组件组件插槽(Slots)动态组件和 `keep-alive`Vue 应用 Vue 应用由几个主要部分组成,每个部分都有其特定的角色和职责。以下是 Vue 应用的主要组成部分以及如何启动一个 Vue 应用的介绍…...
LabVIEW深海气密采水器测控系统
LabVIEW的深海气密采水器测控系统通过高性价比的硬件选择与自主开发的软件,实现了高精度的温度、盐度和深度测量,并在实际海上试验中得到了有效验证。 项目背景 深海气密采水器是进行海底科学研究的关键工具,用LabVIEW开发了一套测控系统&am…...
SpringBoot 启动类 SpringApplication 二 run方法
配置 在Program arguments配置2个参数:--server.port8081 --spring.profiles.activedev。 run方法 run方法执行结束代表SpringBoot启动完成,即完成加载bean。 // ConfigurableApplicationContext 是IOC容器 public ConfigurableApplicationContext ru…...
【java基础系列】实现一个简单的猜数字小游戏
主要是用的java中的键盘录入和随机数两个api,实现这种人机交互的小游戏,可以用来锻炼基础算法思维 实现效果 实现代码 package com.gaofeng.day10;import java.util.Random; import java.util.Scanner;/*** author gaofeng* date 2024-12-22 - 9:21*/ …...
Liveweb视频融合共享平台在果园农场等项目中的视频监控系统搭建方案
一、背景介绍 在我国的大江南北遍布着各种各样的果园,针对这些地处偏僻的果园及农场等环境,较为传统的安全防范方式是建立围墙,但是仅靠围墙仍然无法阻挡不法分子的有意入侵和破坏,因此为了及时发现和处理一些难以察觉的问题&…...
clickhouse-题库
1、clickhouse介绍以及架构 clickhouse一个分布式列式存储数据库,主要用于在线分析查询 2、列式存储和行式存储有什么区别? 行式存储: 1)、数据是按行存储的 2)、没有建立索引的查询消耗很大的IO 3)、建…...
kafka常用命令
安装kafka注意事项 修改 、vim kafka/config/server.properties 三个地方①brokerId ②logs地址③指定节点 一、创建主题 (必须指定分区,指定副本) #在kafka bin目录下执行以下命令 #①连接hadoop01 创建主题为TEST 分区1 副本3个 bin/ka…...
在 Django 中使用 SMTP 发送邮件是一个常见的需求
在 Django 中使用 SMTP 发送邮件是一个常见的需求,通常用于发送用户注册确认邮件、密码重置邮件等。下面是一个简单的示例,展示了如何在 Django 中配置 SMTP 发送邮件,并创建一个包含表单、路由和视图的界面来发送邮件。 1. 配置 Django 项目…...
JS中的原型与原型链
1. 基本概念 原型(Prototype):每个对象都有一个内部属性 [[Prototype]],通常通过 __proto__ 访问(非标准,但广泛支持)。 原型链(Prototype Chain):对象通过原…...
STM32F407 | Embedded IDE01 - vscode搭建Embedded IDE开发环境(支持JLINK、STLINK、DAPLINK)
导言 Embedded IDE官网:https://em-ide.com/docs/intro 我猜肯定有部分人使用SI Keil开发STM32项目,也有vscode Keil开发STM32程序。SI或vscode编写代码,然后切换Keil编译、下载、调试程序。有一段时间,我也是这么干的。但是,程…...
放弃机器学习框架,如何用Python做物体检测?
每当我们听说“物体检测”时,就会想到机器学习和各种不同的框架。但实际上,我们可以在不使用机器学习或任何其他框架的情况下进行物体检测。在本文中,我将向你展示如何仅使用Python进行操作。 首先,我们定义一个模板图像…...
基于langchain的Agent(实现实时查询天气)
心血来潮,玩一下Agent,实现了多轮对话功能 import requests, jsonfrom langchain.agents import load_tools from langchain.agents import initialize_agent from langchain_community.llms.tongyi import Tongyi from langchain.memory import Conver…...
OB删除1.5亿数据耗费2小时
目录 回顾:mysql是怎么删除数据的? 删除方案 代码实现 执行结果 结论 本篇是实际操作 批量处理数据以及线程池线程数设置 记录学习 背景:有一张用户标签表,存储数据量达4个亿,使用OceanBase存储,由于…...
深度学习之目标检测——RCNN
Selective Search 背景:事先不知道需要检测哪个类别,且候选目标存在层级关系与尺度关系 常规解决方法:穷举法,在原始图片上进行不同尺度不同大小的滑窗,获取每个可能的位置 弊端:计算量大,且尺度不能兼顾 Selective …...
Vue.js前端框架教程7:Vue计算属性和moment.js
文章目录 计算属性(Computed Properties)基本用法缓存机制计算属性 vs 方法使用场景计算属性的 setter 和 getter结论Moment.js 进行时间处理1. 安装 Moment.js2. 在 Vue 组件中引入 Moment.js3. 在全局使用 Moment.js4. 使用 Vue 插件的方式引入 Moment.js5. 常用日期格式化…...
了解RPC
本文来自智谱清言 --------- RPC(Remote Procedure Call,远程过程调用)是一种允许程序调用位于远程计算机上的子程序或服务的技术。这种技术使得构建分布式计算变得更加容易,因为它提供了强大的远程调用能力,同时保持…...
【Go】Go数据类型详解—指针
1. 前言 在我看来,一门编程语言语法的核心就在于数据类型。而各类编程语言的基本数据类型大致相同:int整型、float浮点型、string字符串类型、bool布尔类型,但是在一些进阶数据类型上就有所不同了。本文将会介绍Go语言当中核心的数据类型——…...
C++ 中的智能指针与内存管理:从基础到进阶
在 C 中,内存管理是一个至关重要的课题,尤其是当程序复杂度逐渐增加时。传统的手动内存管理方式(使用 new 和 delete)容易引发内存泄漏、悬挂指针等问题。为了简化内存管理,C11 引入了智能指针(std::unique…...
二、使用langchain搭建RAG:金融问答机器人--数据清洗和切片
选择金融领域的专业文档作为源文件 这里选择 《博金大模型挑战赛-金融千问14b数据集》,这个数据集包含若干公司的年报,我们将利用这个年报搭建金融问答机器人。 具体下载地址 这里 git clone https://www.modelscope.cn/datasets/BJQW14B/bs_challenge_…...
R 语言 | 绘图的文字格式(绘制上标、下标、斜体、文字标注等)
1. 上下标 # 注意y轴标签文字 library(ggplot2) ggplot(mtcars, aes(mpg, cyl))geom_point()ylab(label bquote(O[3]~(ug / m^3)))2. 希腊字母,如alpha ggplot(mtcars, aes(mpg, cyl))geom_point()ylab(label bquote(O[3]~(ug / m^3)))ggtitle(expression(alpha))…...
版本更新导致前端网站资源加载失败:Failed to fetch dynamically imported module
前端网站在维护过程中经常有版本更新和重新部署,而这会导致一些问题,其中某些问题会导致更新时,正在网站中的用户无法正常使用。 异常 Failed to fetch dynamically imported module 的诱发原因之一就是版本更新:在用户访问网站的…...
CentOS 7 安装、测试和部署FastDFS
目录 FastDFS环境搭建 安装 libfastcommon 库 安装FastDFS 查看编译后的文件 FastDFS配置 FastDFS启动 启动tracker服务 启动storage服务 查看storage是否已经注册到了tracker下 查看存储文件的目录 FastDFS重启 FastDFS关闭 使用fdfs_test进行测试 修改client.co…...
elasticache备份
Elasticsearch 本地快照操作流程 配置快照存储路径 在 elasticsearch.yml 文件中配置以下字段以指定数据、日志和快照存储路径:path:data: /data/data # 数据存储路径logs: /data/log # 日志存储路径repo: /data/snapshot # 快照存储路径确保路径 /dat…...
wordpress调用指定分类ID下 相同标签的内容
要在WordPress中调用分类ID为1、3、7的分类下,具有相同标签的前10个内容,可以使用自定义的WordPress查询(WP_Query)。以下是实现此功能的步骤和示例代码: 步骤: 确定共同标签: 首先,你需要确定分类1、3、…...
Spring Security 6 系列之五 - 授权管理
之所以想写这一系列,是因为之前工作过程中使用Spring Security,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级为6.3.0,关键是其风…...
贪心算法求解跳跃游戏
跳跃游戏1: 代码随想录链接:代码随想录 思路: 求解是否能够跳到数组的最后一个位置,关键在于跳跃的覆盖范围 因此设置一个变量表示每次移动时能够覆盖的范围,该变量的初始值为0 因为坐标的位置受到覆盖范围的限制,因此只能遍历覆盖范围内…...
4大应用场景揭秘:AI视频监控在养老院中的智能化管理与安全保障
随着人口老龄化的加剧,养老院的管理面临着越来越多的挑战。传统的人工巡查方式不仅难以做到全天候监控,而且存在响应迟缓、效率低下等问题。为了解决这些问题,AI视频监控系统,利用人工智能技术提供了一种高效、智能化的解决方案。…...
构建简洁之美:我的第一个前端页面
实现界面效果 1. HTML示例代码 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><link rel"stylesheet…...
重拾设计模式--备忘录模式
文章目录 备忘录模式(Memento Pattern)概述定义: 作用:实现状态的保存与恢复支持撤销 / 恢复操作 备忘录模式UML图备忘录模式的结构原发器(Originator):备忘录(Memento)&…...
联通光猫怎么自己改桥接模式?
环境: 联通光猫 ZXHN F677V9 硬件版本号 V9.0 软件版本号 V9.0.0P1T3 问题描述: 联通光猫怎么自己改桥接模式 家里用的是ZXHN F677V9 光猫,最近又搞了个软路由,想改桥接模式 解决方案: 1.拿到最新超级密码&…...
UITableView实现通讯录效果
// // TableViewIndexViewController.m // study2024 // // Created by figo zhu on 2024/12/22. //#import "TableViewIndexViewController.h" //实现协议UITableViewDelegate,UITableViewDataSource interface TableViewIndexViewController ()<UITableView…...
Pytorch | 利用NI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用NI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集NI-FGSM介绍背景算法流程 NI-FGSM代码实现NI-FGSM算法实现攻击效果 代码汇总nifgsm.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器: Pytorch | 从零构建AlexNet对CIFAR10进行…...
【Matlab】绘制混淆矩阵示意图+colormap调整方法
主代码 %https://blog.csdn.net/weixin_42943114/article/details/81811556 %https://blog.csdn.net/Mark711/article/details/141144280 clc clear close all warning off %% 原始数据 % 假设groundTruth和predictions是已经定义好的向量 TrueLabels [1 2 1 3 2 3 1 3 2 1 4…...