【动手学深度学习】使用块的网络(VGG)的研究详情

目录

🌊1. 研究目的

🌊2. 研究准备

🌊3. 研究内容

🌍3.1 多层感知机模型选择、欠拟合和过拟合

🌍3.2 练习

🌊4. 研究体会


🌊1. 研究目的

  • 理解块的网络结构;
  • 比较块的网络与传统浅层网络的性能差异;
  • 探究块的网络深度与性能之间的关系;
  • 研究块的网络在不同任务上的适用性。

🌊2. 研究准备

  • 根据GPU安装pytorch版本实现GPU运行研究代码;
  • 配置环境用来运行 Python、Jupyter Notebook和相关库等相关库。

🌊3. 研究内容

启动jupyter notebook,使用新增的pytorch环境新建ipynb文件,为了检查环境配置是否合理,输入import torch以及torch.cuda.is_available() ,若返回TRUE则说明研究环境配置正确,若返回False但可以正确导入torch则说明pytorch配置成功,但研究运行是在CPU进行的,结果如下:


🌍3.1 使用块的网络(VGG)

(1)使用jupyter notebook新增的pytorch环境新建ipynb文件,完成基本数据操作的研究代码与练习结果如下:

VGG块

import torch
from torch import nn
from d2l import torch as d2l


def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels,
                                kernel_size=3, padding=1))
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
    return nn.Sequential(*layers)

VGG网络

conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))

def vgg(conv_arch):
    conv_blks = []
    in_channels = 1
    # 卷积层部分
    for (num_convs, out_channels) in conv_arch:
        conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
        in_channels = out_channels

    return nn.Sequential(
        *conv_blks, nn.Flatten(),
        # 全连接层部分
        nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(), nn.Dropout(0.5),
        nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5),
        nn.Linear(4096, 10))

net = vgg(conv_arch)

X = torch.randn(size=(1, 1, 224, 224))
for blk in net:
    X = blk(X)
    print(blk.__class__.__name__,'output shape:\t',X.shape)

训练模型

ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)

lr, num_epochs, batch_size = 0.05, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())


🌍3.2 练习

1.打印层的尺寸时,我们只看到8个结果,而不是11个结果。剩余的3层信息去哪了?

在VGG网络中,最后三个全连接层(nn.Linear)的输出尺寸没有被打印出来。这是因为在for循环中,只遍历了卷积层部分的模块,而没有遍历全连接层部分的模块。

为了打印出全连接层的输出尺寸,可以将全连接层的模块添加到一个列表中,然后在遍历网络的时候也打印出这些模块的输出尺寸。以下是修改后的代码:

import torch
import torch.nn as nn

# 定义 VGG 模型
def vgg(conv_arch):
    layers = []
    in_channels = 1
    for c, num_convs in conv_arch:
        layers.append(nn.Sequential(
            nn.Conv2d(in_channels, c, kernel_size=3, padding=1),
            nn.ReLU()
        ))
        in_channels = c
        for _ in range(num_convs - 1):
            layers.append(nn.Sequential(
                nn.Conv2d(c, c, kernel_size=3, padding=1),
                nn.ReLU()
            ))
        layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
    return nn.Sequential(*layers)

conv_arch = ((1, 1), (2, 2), (4, 2), (8, 2), (16, 2))

net = vgg(conv_arch)

X = torch.randn(size=(1, 1, 224, 224))
for blk in net:
    X = blk(X)
    print(blk.__class__.__name__, 'output shape:\t', X.shape)

# 获取卷积层的输出尺寸
_, channels, height, width = X.shape

# 添加全连接层模块到列表中
fc_layers = [
    nn.Flatten(),
    nn.Linear(channels * height * width, 4096),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(4096, 4096),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(4096, 10)
]

net = nn.Sequential(*net, *fc_layers)

# 打印全连接层的输出尺寸
for blk in fc_layers:
    X = blk(X)
    print(blk.__class__.__name__, 'output shape:\t', X.shape)

2.与AlexNet相比,VGG的计算要慢得多,而且它还需要更多的显存。分析出现这种情况的原因。
VGG相对于AlexNet而言,计算速度更慢、显存需求更高的主要原因如下:

  • 更深的网络结构: VGG网络相比AlexNet更深,它使用了更多的卷积层和全连接层。VGG的网络结构包含了多个连续的卷积层,导致了参数的数量增加和计算量的增加。相对于AlexNet的8层网络,VGG网络有16或19层,这导致了更多的计算和内存消耗。
  • 小尺寸的卷积核: VGG网络使用了较小的卷积核(3x3大小),而AlexNet则使用了更大的卷积核(11x11和5x5大小)。较小的卷积核意味着每个卷积层需要进行更多次的卷积运算来覆盖相同的感受野,从而增加了计算量。
  • 更多的参数: VGG网络具有更多的参数量。由于每个卷积层都使用了较小的卷积核,导致了更多的卷积核参数。此外,由于网络更深,全连接层的参数数量也更多。更多的参数需要更多的内存来存储,并且在计算过程中需要更多的计算量。
  • 更高的内存需求: VGG网络的深度和参数量的增加导致了更高的内存需求。在训练过程中,需要存储每一层的输出、梯度和参数,这会消耗大量的显存。较大的显存需求可能导致无法一次性加载更多的数据和模型,从而导致更多的显存读写操作和内存碎片化,进而影响计算速度。

3.尝试将Fashion-MNIST数据集图像的高度和宽度从224改为96。这对实验有什么影响?
将Fashion-MNIST数据集图像的高度和宽度从224改为96会对实验产生以下影响:

  • 模型性能下降: 缩小图像尺寸会导致图像的信息丢失和细节损失。VGG网络在设计时使用了较大的输入尺寸,以便更好地捕捉图像的细节和纹理。通过将图像尺寸缩小为96x96,模型可能无法有效地捕捉到原始图像中的细微特征,从而导致性能下降。
  • 空间分辨率减小: 图像尺寸从224x224缩小到96x96会导致空间分辨率的减小。较小的图像尺寸意味着每个像素代表的区域更大,图像中的细节信息被压缩。这可能会导致模型在进行物体边界检测、纹理识别等任务时表现不佳。
  • 减少计算和内存需求: 缩小图像尺寸可以减少模型的计算和内存需求。较小的输入图像尺寸意味着每个卷积层的特征图大小也会减小,从而减少了参数数量和计算量。此外,由于特征图大小减小,模型所需的内存也会相应减少。
  • 训练速度加快: 缩小图像尺寸可以加快训练速度。较小的输入图像尺寸意味着每个批次的数据量减少,从而减少了每个训练步骤的计算量和内存消耗。这可能导致更快的训练速度和更高的训练效率。
import torch
from torch import nn
from torchvision.transforms import ToTensor
from torchvision.datasets import FashionMNIST
from torch.utils.data import DataLoader

# 定义VGG块
def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
    return nn.Sequential(*layers)

# 定义VGG网络
class VGG(nn.Module):
    def __init__(self, conv_arch):
        super(VGG, self).__init__()
        self.conv_blocks = nn.Sequential()
        in_channels = 1
        for i, (num_convs, out_channels) in enumerate(conv_arch):
            self.conv_blocks.add_module(f'vgg_block{i+1}', vgg_block(num_convs, in_channels, out_channels))
            in_channels = out_channels
        self.fc_layers = nn.Sequential(
            nn.Linear(out_channels * 3 * 3, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 10)
        )

    def forward(self, x):
        x = self.conv_blocks(x)
        x = torch.flatten(x, start_dim=1)
        x = self.fc_layers(x)
        return x

# 将Fashion-MNIST图像尺寸缩小为96x96
transform = ToTensor()
train_dataset = FashionMNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = FashionMNIST(root='./data', train=False, download=True, transform=transform)

# 创建数据加载器
batch_size = 128
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 定义VGG网络结构
conv_arch = [(1, 64), (1, 128), (2, 256), (2, 512), (2, 512)]
model = VGG(conv_arch)

# 训练和测试
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.05)
criterion = nn.CrossEntropyLoss()

def train(model, train_loader, optimizer, criterion, device):
    model.train()
    train_loss = 0.0
    train_acc = 0.0
    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        train_loss += loss.item() * images.size(0)
        _, preds = torch.max(outputs, 1)
        train_acc += torch.sum(preds == labels.data).item()

    train_loss /= len(train_loader.dataset)
    train_acc /= len(train_loader.dataset)
    return train_loss, train_acc

def test(model, test_loader, criterion, device):
    model.eval()
    test_loss = 0.0
    test_acc = 0.0
    with torch.no_grad():
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)

            outputs = model(images)
            loss = criterion(outputs, labels)

            test_loss += loss.item() * images.size(0)
            _, preds = torch.max(outputs, 1)
            test_acc += torch.sum(preds == labels.data).item()

    test_loss /= len(test_loader.dataset)
    test_acc /= len(test_loader.dataset)
    return test_loss, test_acc

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    train_loss, train_acc = train(model, train_loader, optimizer, criterion, device)
    test_loss, test_acc = test(model, test_loader, criterion, device)

    print(f'Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.4f}, '
          f'Test Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.4f}')

# 输出样例
print("Sample outputs:")
model.eval()
with torch.no_grad():
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)
        _, preds = torch.max(outputs, 1)

        for i in range(images.size(0)):
            print(f"Predicted: {preds[i].item()}, Ground Truth: {labels[i].item()}")
        break  # 只输出一个批次的样例结果

在上面的代码中,定义了VGG网络结构,并在Fashion-MNIST数据集上进行了训练和测试。通过将图像尺寸从224缩小为96,可以看到模型的训练和推理速度可能会加快,但模型的性能可能会下降,因为图像的细节被压缩。这里使用了SGD优化器和交叉熵损失函数来训练模型,并输出了训练和测试的损失和准确率。最后输出了一个样例的预测结果,以查看模型的输出效果。请注意,实际训练过程可能需要更多的迭代次数和调整超参数以获得更好的性能。

4.请参考VGG论文 (Simonyan and Zisserman, 2014)中的表1构建其他常见模型,如VGG-16或VGG-19。
VGG-16:

import torch
from torch import nn
from torchvision.transforms import ToTensor
from torchvision.datasets import FashionMNIST
from torch.utils.data import DataLoader

# 定义VGG块
def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
    return nn.Sequential(*layers)

# 定义VGG-16网络
class VGG16(nn.Module):
    def __init__(self):
        super(VGG16, self).__init__()
        self.conv_blocks = nn.Sequential(
            vgg_block(2, 3, 64),
            vgg_block(2, 64, 128),
            vgg_block(3, 128, 256),
            vgg_block(3, 256, 512),
            vgg_block(3, 512, 512)
        )
        self.fc_layers = nn.Sequential(
            nn.Linear(512 * 7 * 7, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 10)
        )

    def forward(self, x):
        x = self.conv_blocks(x)
        x = torch.flatten(x, start_dim=1)
        x = self.fc_layers(x)
        return x

# 将Fashion-MNIST图像转换为Tensor,并进行数据加载
transform = ToTensor()
train_dataset = FashionMNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = FashionMNIST(root='./data', train=False, download=True, transform=transform)

# 创建数据加载器
batch_size = 128
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 创建VGG-16模型实例
model = VGG16()

# 定义优化器和损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.05)
criterion = nn.CrossEntropyLoss()

# 将模型移动到GPU(如果可用)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    train_loss = 0.0
    train_acc = 0.0
    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        train_loss += loss.item() * images.size(0)
        _, preds = torch.max(outputs, 1)
        train_acc += torch.sum(preds == labels.data).item()

    train_loss /= len(train_loader.dataset)
    train_acc /= len(train_loader.dataset)

    # 在测试集上评估模型
    model.eval()
    test_loss = 0.0
    test_acc = 0.0
    with torch.no_grad():
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)

            outputs = model(images)
            loss = criterion(outputs, labels)

            test_loss += loss.item() * images.size(0)
            _, preds = torch.max(outputs, 1)
            test_acc += torch.sum(preds == labels.data).item()

    test_loss /= len(test_loader.dataset)
    test_acc /= len(test_loader.dataset)

    print(f'Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.4f}, '
          f'Test Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.4f}')

# 输出样例
print("Sample outputs:")
model.eval()
with torch.no_grad():
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)
        _, preds = torch.max(outputs, 1)

        for i in range(images.size(0)):
            print(f"Predicted: {preds[i].item()}, Ground Truth: {labels[i].item()}")
        break  # 只输出一个批次的样例结果

以上代码展示了包含数据加载和训练的完整代码,使用VGG-16模型对Fashion-MNIST数据集进行了训练和测试。训练过程中,模型在每个epoch中进行了训练和验证,并输出了训练和验证集上的损失和准确率。最后,展示了一个样例输出,显示了模型在测试集上的预测结果。

VGG-19:

import torch
from torch import nn
from torchvision.transforms import ToTensor
from torchvision.datasets import FashionMNIST
from torch.utils.data import DataLoader

# 定义VGG块
def vgg_block(num_convs, in_channels, out_channels):
    layers = []
    for _ in range(num_convs):
        layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
        layers.append(nn.ReLU())
        in_channels = out_channels
    layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
    return nn.Sequential(*layers)

# 定义VGG-19网络
class VGG19(nn.Module):
    def __init__(self):
        super(VGG19, self).__init__()
        self.conv_blocks = nn.Sequential(
            vgg_block(2, 3, 64),
            vgg_block(2, 64, 128),
            vgg_block(4, 128, 256),
            vgg_block(4, 256, 512),
            vgg_block(4, 512, 512)
        )
        self.fc_layers = nn.Sequential(
            nn.Linear(512 * 7 * 7, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 10)
        )

    def forward(self, x):
        x = self.conv_blocks(x)
        x = torch.flatten(x, start_dim=1)
        x = self.fc_layers(x)
        return x

# 将Fashion-MNIST图像转换为Tensor,并进行数据加载
transform = ToTensor()
train_dataset = FashionMNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = FashionMNIST(root='./data', train=False, download=True, transform=transform)

# 创建数据加载器
batch_size = 128
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 创建VGG-19模型实例
model = VGG19()

# 定义优化器和损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.05)
criterion = nn.CrossEntropyLoss()

# 将模型移动到GPU(如果可用)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    train_loss = 0.0
    train_acc = 0.0
    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        train_loss += loss.item() * images.size(0)
        _, preds = torch.max(outputs, 1)
        train_acc += torch.sum(preds == labels.data).item()

    train_loss /= len(train_loader.dataset)
    train_acc /= len(train_loader.dataset)

    # 在测试集上评估模型
    model.eval()
    test_loss = 0.0
    test_acc = 0.0
    with torch.no_grad():
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)

            outputs = model(images)
            loss = criterion(outputs, labels)

            test_loss += loss.item() * images.size(0)
            _, preds = torch.max(outputs, 1)
            test_acc += torch.sum(preds == labels.data).item()

    test_loss /= len(test_loader.dataset)
    test_acc /= len(test_loader.dataset)

    print(f'Epoch {epoch+1}/{num_epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.4f}, '
          f'Test Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.4f}')

# 输出样例
print("Sample outputs:")
model.eval()
with torch.no_grad():
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)
        _, preds = torch.max(outputs, 1)

        for i in range(images.size(0)):
            print(f"Predicted: {preds[i].item()}, Ground Truth: {labels[i].item()}")
        break  # 只输出一个批次的样例结果


🌊4. 研究体会

在本次实验中,我采用了块的网络结构,具体来说是VGG(Visual Geometry Group)网络,进行了深入的研究和分析。通过实验,我对使用块的网络的性能和优势有了更深刻的理解,并在不同任务上的适用性方面进行了探索。

首先,块的网络结构给予了深度神经网络更强大的特征提取能力。通过将多个卷积层和池化层堆叠在一起形成块的方式,块的网络能够逐层地提取出越来越抽象的特征信息。这种层次化的特征提取过程有助于网络更好地理解和表示输入数据,提高模型的分类准确率。在实验中的结果表明,相比传统的浅层网络,块的网络在处理复杂的视觉任务时表现出更好的性能。

其次,通过实验发现,块的网络的深度与性能之间存在一定的关系。逐渐增加块的数量可以增加网络的深度,但并不意味着性能一定会线性提升。实验中,我逐步增加了VGG网络的块数,并观察了模型的性能变化。结果显示,在增加块的数量初期,性能得到了显著提升,但随着深度继续增加,性能的改善趋于平缓,甚至有时会出现性能下降的情况。这表明网络深度的增加并不是无限制地提高性能的唯一因素,适当的模型复杂度和正则化方法也需要考虑。对块的网络在不同任务上的适用性进行了研究。通过在不同的数据集上进行训练和测试,我发现块的网络在图像分类、目标检测和语义分割等多个视觉任务中都表现出很好的性能。这表明块的网络具有较强的泛化能力和适应性,能够应用于多个领域和应用场景。这对于深度学习的研究和应用具有重要的启示意义,也为实际应用中的图像分析和理解提供了有力支持。

实验发现块的网络结构具有良好的模块化和复用性,使得网络的设计和调整变得更加灵活和高效。通过将相同的卷积层和池化层堆叠在一起形成块,我可以轻松地调整网络的深度和宽度,而不需要对每一层都进行单独设计和调整。这种模块化的结构使得网络的搭建和调试更加高效,节省了大量的时间和资源。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux基础 (十四):socket网络编程

我们用户是处在应用层的,根据不同的场景和业务需求,传输层就要为我们应用层提供不同的传输协议,常见的就是TCP协议和UDP协议,二者各自有不同的特点,网络中的数据的传输其实就是两个进程间的通信,两个进程在…

activiti用法随记

案例&#xff1a; 摘抄于官网&#xff0c;假设我们有如下流程&#xff1a; 流程对应的bpmn文件如下&#xff1a; <definitions xmlns:activiti"http://activiti.org/bpmn" xmlns:bpmndi"http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc&quo…

configuration_auto.py in getitem raise KeyError(key) KeyError: ‘llama‘解决方案

运行LLaMA-7b模型有时候会报错“configuration_auto.py in getitem raise KeyError(key) KeyError:llama”如下所示&#xff1a; 解决办法升级安装transformer库即可&#xff0c;如下所示&#xff1a; pip install transformers4.30.0

vue3设置全局变量并获取 全局响应式变量 窗口大小

设置 js文件统一管理全局变量 方法1 app provide() 全局提供变量 通过inject()使用 方法2 app实例配置全局变量 获取 通过 getCurrentInstance.appContext.config.globalProperties.$innerWidth访问到 code import { ref } from vue export const useGlobalState () > {c…

新型AI编程语言Mojo来了!比Python快68000倍! 坚持每天写代码,真的能提高编程水平吗?

2024 年 3 月 29 日&#xff0c;Modular Inc. 宣布开源 Mojo 的核心组件。 Mojo语言是一种新的编程语言&#xff0c;由 Chris Lattner&#xff08;LLVM 和 Swift 语言的创始人&#xff09;创建的 Modular AI 公司开发。 它结合了Python的易用性和C的性能&#xff0c;旨在为人…

二说springboot3的自动配置机制

大家好&#xff0c;这里是教授.F 目录 SpringBootApplication&#xff1a; EableAutoConfiguration&#xff1a; 上一篇文章粗略的讲了自动配置机制&#xff0c;二说系列将从源码的角度进行讲解。 SpringBootApplication&#xff1a; 首先我们还是得从SpringBootApplication…

电商APP用户体验提升技巧:一个实战案例

随着网络和移动技术的快速发展&#xff0c;加上全球疫情的影响&#xff0c;电子商务应用程序改变了人们的购物方式&#xff0c;积累了大量的用户群体。如今&#xff0c;一个成功的电子商务应用程序&#xff0c;除了网站用户界面的美&#xff0c;电子商务用户体验的设计&#xf…

图片格式怎么转成pdf,简单的方法

在现代数字化时代&#xff0c;图片格式转换成PDF已经成为许多人的日常需求。无论是为了存档、分享还是打印&#xff0c;将图片转换为PDF都是一项非常实用的技能。本文将详细介绍如何将图片格式转换成PDF的方法。 用浏览器打开 "轻云处理pdf官网&#xff0c;上传图片。 图…

SpringBoot 请求响应

SpringBoot 请求响应 来源于黑马程序员JavaWeb课程&#xff0c;总结笔记 1.ApiFox Apifox快速入门教程 2.基本参数 简单参数&#xff1a;在向服务器发起请求时&#xff0c;向服务器传递的是一些普通的请求数据。 //RequestController.java import jakarta.servlet.http.Htt…

一线教师教学工具汇总

亲爱的教师们&#xff01;我们的教学工具箱里也该更新换代啦&#xff01;今天&#xff0c;就让我来给大家安利一波超实用的教学神器&#xff1a; 百度文库小程序 —— 在线图书馆 百度文库&#xff0c;一个宝藏级的在线文档分享平台&#xff01;在这里&#xff0c;你可以找到海…

康谋技术 | 自动驾驶:揭秘高精度时间同步技术(二)

在自动驾驶中&#xff0c;对车辆外界环境进行感知需要用到很多传感器的数据&#xff08;Lidar&#xff0c;Camera&#xff0c;GPS/IMU&#xff09;&#xff0c;如果计算中心接收到的各传感器消息时间不统一&#xff0c;则会造成例如障碍物识别不准等问题。 为了对各类传感器进…

VSCode插件EditorConfig for VS Code

1. 安装 2. 配置 # http://editorconfig.orgroot true[*] # 表示所有文件适用 charset utf-8 # 设置文件字符集为 utf-8 indent_style space # 缩进风格&#xff08;tab | space&#xff09; indent_size 4 # 缩进大小 end_of_line lf # 控制换行类型(lf | cr | crlf) tr…

鸿蒙低代码开发一个高频问题

在版本是DevEco Studio 3.1.1 Release&#xff0c;SDK是3.1.0(API9)。 创建和设计的visual文件经常会遇到无法渲染的情况&#xff0c;或者自定义组件在Custom列表中突然不见了的情况。 有以下报错信息的&#xff1a; JSON schema validation error: data/visualModel/value/…

Face Forgery Detection by 3D Decomposition

文章目录 Face Forgery Detection by 3D Decomposition研究背景研究目标创新点方法提出问题研究过程技术贡献实验结果未来工作Face Forgery Detection by 3D Decomposition 会议:CVPR2021 作者: 研究背景 面部伪造引发关注传统面部伪造检测主要关注原始RGB图像

React权限管理系统实现

目录 一、需求 二、逻辑 三、实现 &#xff08;一&#xff09;代码 &#xff08;二&#xff09;解释 1. 获取权限对照数组 (queryReferencePermissionsInfo) 2. 获取处理对照数组 (queryDisposePermissionsInfo) 3. 获取权限映射表信息并处理 (queryPermissionsInfo) 4…

【分享】两种方法设置PDF“打开密码”

想要保护PDF文件的私密性&#xff0c;只允许特定人查看&#xff0c;我们可以给PDF设置“打开密码”&#xff0c;这样只有知道密码的人才可以打开文件。如果小伙伴们不知道如何设置&#xff0c;就一起看看以下两种方法吧&#xff01; 方法1&#xff1a;使用PDF编辑器 大部分PD…

【异常检测】MVTec LOCO AD 数据集

every blog every motto: There’s only one corner of the universe you can be sure of improving, and that’s your own self. https://blog.csdn.net/weixin_39190382?spm1010.2135.3001.5343 0. 前言 MVTec LOCO AD 数据集介绍 相比MVTec AD 增加了逻辑异常 1. 正文…

【grafana】创建多变量table

这个普罗米修斯的指标啊&#xff0c;大多数都是键值对&#xff0c;而且笔者如果没记错&#xff0c;他这个值还必须是浮点。少数可以设成离散值&#xff08;Enum&#xff09;&#xff0c;但本质还是一个带翻译功能的键值对 这样的好处是&#xff0c;做起来非常简单&#xff0c;…

Java环境配置(超详细)

Java环境配置&#xff08;超详细&#xff09; 引言1、安装 JDK1.1、下载安装JDK1.2、配置环境变量&#xff1a;JAVA_HOME1.3、将JAVA_HOME添加到Path中 2、安装 Maven2.1、下载安装Maven2.2、配置maven的环境变量: M2_HOME2.3、将Maven变量添加到Path中 引言 Java开发环境的配…

智能水位监测识别报警摄像机:保障水域安全的重要利器

随着城市化进程的加速和气候变化的影响&#xff0c;对水域安全的关注日益增加。为了及时监测水位变化并采取相应措施&#xff0c;智能水位监测识别报警摄像机应运而生。本文将介绍这一创新技术的应用和优势。 传统的水位监测方法通常依赖于传感器&#xff0c;但其存在着安装位置…