当前位置: 首页 > news >正文

【计算机视觉基础CV】05 - 深入解析ResNet与GoogLeNet:从基础理论到实际应用

引言

在上一篇文章中,我们详细介绍了ResNet与GoogLeNet的网络结构、设计理念及其在图像分类中的应用。本文将继续深入探讨如何在实际项目中应用这些模型,特别是如何保存训练好的模型、加载模型以及使用模型进行新图像的预测。通过这些步骤,读者将能够完整地掌握从模型训练到部署的全过程。

ps:数据集已经发布~

目录:

  1. ResNet简介

  2. ResNet的网络结构

    • 残差块

    • ResNet模型架构

  3. GoogLeNet简介

  4. GoogLeNet的网络结构

    • Inception模块

    • GoogLeNet模型架构

  5. ResNet与GoogLeNet的对比

  6. 实际应用:利用ResNet进行图像分类

    • 数据准备与预处理

    • 模型实例化与参数设置

    • 模型训练与评估

    • 模型保存与加载

    • 新图像预测

    • 完整代码实现详解

  7. 总结与展望

  8. 参考文献


ResNet简介

随着深度神经网络层数的增加,模型的表达能力显著提升。然而,网络越深,训练过程中面临的梯度消失、梯度爆炸等问题也愈加严重,导致模型性能难以进一步提升。2015年,何凯明等人提出了残差网络(ResNet),通过引入“跳跃连接”(Shortcut Connections)有效缓解了深层网络训练中的退化问题,使得训练超过百层的深度网络成为可能。ResNet在2015年的ImageNet图像识别挑战赛中取得了显著成绩,极大地影响了后续深度神经网络的设计。

ResNet的网络结构

残差块

 

在传统的深层神经网络中,随着网络深度的增加,模型的训练误差往往呈现上升趋势,这被称为“退化问题”。ResNet通过引入残差块(Residual Block)解决了这一问题。

这种结构被称为“跳跃连接”(Shortcut Connection),它允许梯度直接在网络中传播,缓解了梯度消失的问题。基础残差块

输入 x|Conv3x3|BatchNorm|ReLU|Conv3x3|BatchNorm|+-----+|     |x     ||     |+-----+|ReLU|输出 H(x) = F(x) + x
瓶颈残差块

输入 x|Conv1x1|BatchNorm|ReLU|Conv3x3|BatchNorm|ReLU|Conv1x1|BatchNorm|+-----+|     |x     ||     |+-----+|ReLU|输出 H(x) = F(x) + x

ResNet模型架构

ResNet的整体架构由多个残差块堆叠而成,不同的ResNet版本(如ResNet-18、ResNet-34、ResNet-50、ResNet-101、ResNet-152)主要区别在于残差块的类型及其数量。以ResNet-50为例,其结构如下:

图2:ResNet-34架构图 来源

下图:ResNet 的常见版本架构

GoogLeNet简介

GoogLeNet,又称为Inception v1,是Google在2014年提出的一种深度卷积神经网络模型。与ResNet不同,GoogLeNet主要通过Inception模块的设计,实现了网络结构的深度和宽度的有效扩展,同时控制了计算复杂度。GoogLeNet在2014年的ImageNet挑战赛中取得了优异成绩,显著降低了参数数量。

图3:GoogLeNet架构图 来源

GoogLeNet的网络结构

Inception模块

Inception模块是GoogLeNet的核心创新,通过在同一层次上并行应用不同尺寸的卷积核和池化操作,捕捉多尺度的特征信息。具体来说,一个Inception模块通常包括以下几部分:

  1. 1x1卷积:用于减少维度,降低计算量。

  2. 3x3卷积:处理空间信息。

  3. 5x5卷积:处理更大范围的空间信息。

  4. 3x3最大池化:用于下采样,后接1x1卷积。

通过这些并行的操作,Inception模块能够同时捕捉到不同尺度的特征,提高了模型的表达能力。

GoogLeNet模型架构

图4:Inception模块示意图 来源

ResNet与GoogLeNet的对比

特性ResNetGoogLeNet
核心创新残差学习(Residual Learning)Inception模块
网络深度可扩展至超过100层22层,后续版本如Inception v2、v3更深
参数数量随层数增加显著通过Inception模块有效控制参数数量
训练难度残差块设计缓解深层网络的训练难题多路径结构复杂,需精心设计和训练
应用场景图像分类、目标检测、语义分割等多种任务主要用于图像分类,后续版本扩展至其他任务
计算效率残差块结构相对简单,计算效率高Inception模块复杂,但通过1x1卷积降低计算量

实际应用:利用ResNet进行图像分类

本文将以ResNet-18为例,演示如何在PyTorch框架下构建、训练和评估一个图像分类模型。以鲜花种类识别为案例,读者可以通过本文的步骤,掌握从数据准备到模型训练、保存、加载及预测的完整流程。

数据准备与预处理

首先,确保已下载并整理好鲜花数据集。数据集通常分为训练集和测试集,分别存放在不同的文件夹中。为了适应ResNet-18的输入要求,需要将图像尺寸调整为224x224。

from torchvision import transforms
from torch.utils.data import DataLoader
from torchvision.datasets import ImageFolder
​
# 指定批次大小
batch_size = 16
​
# 指定数据集路径
flower_train_path = './dataset/flower_datas/train/'
flower_test_path = './dataset/flower_datas/val/'
​
# 数据预处理:调整图像大小并转换为Tensor
dataset_transform = transforms.Compose([transforms.Resize((224, 224)),  # 调整图像大小为224x224transforms.ToTensor()           # 将图像转换为Tensor
])
​
# 加载训练集和测试集
flower_train = ImageFolder(flower_train_path, transform=dataset_transform)
flower_test = ImageFolder(flower_test_path, transform=dataset_transform)
​
# 创建数据加载器
train_loader = DataLoader(dataset=flower_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=flower_test, batch_size=batch_size, shuffle=False)

说明

  • 使用transforms.Resize将图像调整为224x224,以匹配ResNet的输入要求。

  • 使用ImageFolder加载数据集,确保数据集目录结构符合PyTorch的要求(每个类别一个文件夹)。

  • 使用DataLoader创建训练和测试数据加载器,设置批次大小和是否打乱数据。

模型实例化与参数设置

使用PyTorch内置的ResNet-18模型,并根据任务需要调整输出类别数。

import torch
import torchvision.models as models
​
# 实例化ResNet-18模型,调整输出类别数为5
model = models.resnet18(num_classes=5)
​
# 设置训练设备为GPU(如果可用)否则为CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
​
# 定义优化器(Adam)和损失函数(交叉熵损失)
learning_rate = 1e-3
num_epochs = 25
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_fn = torch.nn.CrossEntropyLoss()

说明

  • models.resnet18(num_classes=5):加载ResNet-18模型,并将最后的全连接层调整为输出5个类别。

  • device:自动检测是否有GPU可用,并将模型移动到对应设备以加速训练。

  • optimizer:选择Adam优化器,并设置学习率。

  • loss_fn:使用交叉熵损失函数,适用于多分类任务。

模型训练与评估

定义训练和评估函数,逐步训练模型并监控其性能。

import matplotlib.pyplot as plt
​
# 评估模型准确率
def evaluate_accuracy(data_iter, model):model.eval()  # 设置模型为评估模式correct = 0total = 0with torch.no_grad():  # 不计算梯度for images, labels in data_iter:images, labels = images.to(device), labels.to(device)outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()return correct / total
​
# 训练模型
def train_model(model, train_loader, test_loader, optimizer, loss_fn, num_epochs):train_losses = []train_accuracies = []test_accuracies = []for epoch in range(num_epochs):model.train()  # 设置模型为训练模式running_loss = 0.0correct = 0total = 0for images, labels in train_loader:images, labels = images.to(device), labels.to(device)# 前向传播outputs = model(images)loss = loss_fn(outputs, labels)# 反向传播和优化optimizer.zero_grad()  # 清除之前的梯度loss.backward()        # 反向传播计算梯度optimizer.step()       # 更新参数# 统计损失和准确率running_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()# 计算平均损失和准确率epoch_loss = running_loss / len(train_loader)epoch_acc = correct / totaltest_acc = evaluate_accuracy(test_loader, model)train_losses.append(epoch_loss)train_accuracies.append(epoch_acc)test_accuracies.append(test_acc)print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}, 'f'Train Acc: {epoch_acc:.3f}, Test Acc: {test_acc:.3f}')print('训练完成')# 绘制损失和准确率曲线epochs = range(1, num_epochs+1)plt.figure(figsize=(12,5))# 绘制训练损失曲线plt.subplot(1,2,1)plt.plot(epochs, train_losses, 'r', label='训练损失')plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('训练损失曲线')plt.legend()# 绘制训练和测试准确率曲线plt.subplot(1,2,2)plt.plot(epochs, train_accuracies, 'g', label='训练准确率')plt.plot(epochs, test_accuracies, 'b', label='测试准确率')plt.xlabel('Epoch')plt.ylabel('Accuracy')plt.title('准确率曲线')plt.legend()plt.show()

说明

  • evaluate_accuracy函数用于评估模型在测试集上的准确率,设置模型为评估模式,避免梯度计算。

  • train_model函数负责整个训练过程,包括前向传播、计算损失、反向传播、优化参数,以及记录和绘制损失与准确率曲线。

  • 在每个epoch结束后,输出当前epoch的损失、训练准确率和测试准确率。

输出: 

模型保存与加载

在完成模型训练后,保存训练好的模型是非常重要的步骤。保存模型不仅可以避免重复训练,还可以在需要时加载模型进行预测或进一步训练。

1. 保存模型

使用PyTorch的torch.save函数可以方便地保存模型的参数(state_dict)或整个模型。

# 保存模型参数
torch.save(model.state_dict(), 'resnet18_flower.pth')
print("模型已保存为 resnet18_flower.pth")

说明

  • model.state_dict():获取模型的所有参数。

  • torch.save:将参数保存到指定路径。

  • 推荐保存模型的参数而不是整个模型,因为保存参数更加灵活,适用于不同的应用场景。

2. 加载模型

在需要使用保存的模型时,可以通过加载模型参数来恢复模型。

# 实例化模型结构
model_loaded = models.resnet18(num_classes=5)
​
# 加载模型参数
model_loaded.load_state_dict(torch.load('resnet18_flower.pth'))
​
# 设置模型为评估模式
model_loaded.eval()
​
# 将模型移动到对应设备
model_loaded = model_loaded.to(device)
print("模型已加载并准备就绪")

说明

  • 实例化与保存时相同结构的模型。

  • 使用load_state_dict加载保存的参数。

  • 设置模型为评估模式,避免在推理时启用训练模式的行为(如Dropout)。

  • 将模型移动到相应设备(GPU或CPU)。

新图像预测

完成模型的加载后,可以使用模型对新图像进行预测。以下步骤展示了如何加载新图像、进行预处理、并使用模型进行预测。

from PIL import Image
import numpy as np
​
# 定义类别标签(根据实际数据集调整)
class_names = ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
​
# 图像预处理函数
def preprocess_image(image_path):# 定义与训练时相同的预处理步骤transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor()])# 打开图像image = Image.open(image_path).convert('RGB')# 应用预处理image = transform(image)# 增加批次维度image = image.unsqueeze(0)return image
​
# 预测函数
def predict(image_path, model, class_names):# 预处理图像image = preprocess_image(image_path)image = image.to(device)# 进行预测model.eval()with torch.no_grad():outputs = model(image)_, predicted = torch.max(outputs.data, 1)# 获取预测结果predicted_class = class_names[predicted.item()]return predicted_class
​
# 示例:预测新图像
new_image_path = './dataset/flower_datas/test/daisy/daisy_001.jpg'  # 替换为实际图像路径
predicted_label = predict(new_image_path, model_loaded, class_names)
print(f"预测结果:{predicted_label}")

说明

  • preprocess_image函数:加载并预处理新图像,使其符合模型输入要求。

  • predict函数:加载预处理后的图像,使用模型进行前向传播,获取预测结果。

  • class_names:根据实际数据集定义类别标签。

  • 示例中替换new_image_path为实际需要预测的图像路径。

完整代码实现详解

以下是完整的代码实现,包括数据准备、模型定义、训练、保存、加载及新图像预测。代码中包含详细注释,帮助您理解每一步的具体操作。

# 导入相关的工具包
import torch
import torchvision.models as models
from torchvision import transforms
from torch.utils.data import DataLoader
from torchvision.datasets import ImageFolder
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
​
# 指定批次大小
batch_size = 16
​
# 指定数据集路径
flower_train_path = './dataset/flower_datas/train/'
flower_test_path = './dataset/flower_datas/val/'
​
# 数据预处理:调整图像大小并转换为Tensor
dataset_transform = transforms.Compose([transforms.Resize((224, 224)),  # 调整图像大小为224x224transforms.ToTensor()           # 将图像转换为Tensor
])
​
# 加载训练集和测试集
flower_train = ImageFolder(flower_train_path, transform=dataset_transform)
flower_test = ImageFolder(flower_test_path, transform=dataset_transform)
​
# 创建数据加载器
train_loader = DataLoader(dataset=flower_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=flower_test, batch_size=batch_size, shuffle=False)
​
# 实例化ResNet-18模型,调整输出类别数为5
model = models.resnet18(num_classes=5)
​
# 设置训练设备为GPU(如果可用)否则为CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
​
# 定义优化器(Adam)和损失函数(交叉熵损失)
learning_rate = 1e-3
num_epochs = 25
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_fn = torch.nn.CrossEntropyLoss()
​
# 评估模型准确率
def evaluate_accuracy(data_iter, model):model.eval()  # 设置模型为评估模式correct = 0total = 0with torch.no_grad():  # 不计算梯度for images, labels in data_iter:images, labels = images.to(device), labels.to(device)outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()return correct / total
​
# 训练模型
def train_model(model, train_loader, test_loader, optimizer, loss_fn, num_epochs):train_losses = []train_accuracies = []test_accuracies = []for epoch in range(num_epochs):model.train()  # 设置模型为训练模式running_loss = 0.0correct = 0total = 0for images, labels in train_loader:images, labels = images.to(device), labels.to(device)# 前向传播outputs = model(images)loss = loss_fn(outputs, labels)# 反向传播和优化optimizer.zero_grad()  # 清除之前的梯度loss.backward()        # 反向传播计算梯度optimizer.step()       # 更新参数# 统计损失和准确率running_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()# 计算平均损失和准确率epoch_loss = running_loss / len(train_loader)epoch_acc = correct / totaltest_acc = evaluate_accuracy(test_loader, model)train_losses.append(epoch_loss)train_accuracies.append(epoch_acc)test_accuracies.append(test_acc)print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}, 'f'Train Acc: {epoch_acc:.3f}, Test Acc: {test_acc:.3f}')print('训练完成')# 绘制损失和准确率曲线epochs = range(1, num_epochs+1)plt.figure(figsize=(12,5))# 绘制训练损失曲线plt.subplot(1,2,1)plt.plot(epochs, train_losses, 'r', label='训练损失')plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('训练损失曲线')plt.legend()# 绘制训练和测试准确率曲线plt.subplot(1,2,2)plt.plot(epochs, train_accuracies, 'g', label='训练准确率')plt.plot(epochs, test_accuracies, 'b', label='测试准确率')plt.xlabel('Epoch')plt.ylabel('Accuracy')plt.title('准确率曲线')plt.legend()plt.show()
​
# 保存模型参数
def save_model(model, path='resnet18_flower.pth'):torch.save(model.state_dict(), path)print(f"模型已保存为 {path}")
​
# 加载模型参数
def load_model(path='resnet18_flower.pth'):model_loaded = models.resnet18(num_classes=5)model_loaded.load_state_dict(torch.load(path))model_loaded = model_loaded.to(device)model_loaded.eval()print("模型已加载并准备就绪")return model_loaded
​
# 图像预处理函数
def preprocess_image(image_path):# 定义与训练时相同的预处理步骤transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor()])# 打开图像image = Image.open(image_path).convert('RGB')# 应用预处理image = transform(image)# 增加批次维度image = image.unsqueeze(0)return image
​
# 预测函数
def predict(image_path, model, class_names):# 预处理图像image = preprocess_image(image_path)image = image.to(device)# 进行预测model.eval()with torch.no_grad():outputs = model(image)_, predicted = torch.max(outputs.data, 1)# 获取预测结果predicted_class = class_names[predicted.item()]return predicted_class
​
# 定义类别标签(根据实际数据集调整)
class_names = ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
​
# 开始训练
train_model(model, train_loader, test_loader, optimizer, loss_fn, num_epochs)
​
# 保存训练好的模型
save_model(model, 'resnet18_flower.pth')
​
# 加载保存的模型
model_loaded = load_model('resnet18_flower.pth')
​
# 示例:预测新图像
new_image_path = './dataset/flower_datas/test/daisy/daisy_001.jpg'  # 替换为实际图像路径
predicted_label = predict(new_image_path, model_loaded, class_names)
print(f"预测结果:{predicted_label}")

代码注释详解

  1. 数据准备

    • 使用transforms.Resize将图像调整为224x224,以匹配ResNet的输入要求。

    • 使用ImageFolder加载数据集,确保每个类别的图像存放在单独的文件夹中。

    • 使用DataLoader创建训练和测试数据加载器,设置批次大小和是否打乱数据。

  2. 模型实例化与参数设置

    • 使用models.resnet18加载ResNet-18模型,并将最后的全连接层调整为5个输出类别。

    • 检测是否有GPU可用,并将模型移动到对应设备以加速训练。

    • 定义优化器(Adam)和损失函数(交叉熵损失),设置学习率和训练轮数。

  3. 训练与评估

    • 定义evaluate_accuracy函数,用于在测试集上评估模型的准确率,设置模型为评估模式,避免梯度计算。

    • 定义

      train_model

      函数,包含整个训练过程:

      • 设置模型为训练模式。

      • 遍历每个epoch和每个batch,进行前向传播、计算损失、反向传播和优化参数。

      • 记录每个epoch的损失和准确率。

      • 在每个epoch结束后,评估模型在测试集上的准确率。

      • 绘制训练损失和准确率曲线,直观展示模型的训练过程。

  4. 模型保存与加载

    • 定义save_model函数,使用torch.save将模型的参数保存到指定路径。

    • 定义load_model函数,实例化相同结构的模型,并使用load_state_dict加载保存的参数。设置模型为评估模式,并移动到对应设备。

  5. 新图像预测

    • 定义preprocess_image函数,加载并预处理新图像,使其符合模型输入要求。

    • 定义predict函数,加载预处理后的图像,使用模型进行前向传播,获取预测结果。

    • 示例中替换new_image_path为实际需要预测的图像路径,打印预测结果。

完整流程说明

  1. 数据准备:加载并预处理数据集,包括图像尺寸调整和格式转换。

  2. 模型定义与参数设置:实例化ResNet-18模型,定义优化器和损失函数,并将模型移动到训练设备。

  3. 模型训练与评估:通过训练函数,迭代训练模型,并在每个epoch后评估模型性能。

  4. 模型保存:训练完成后,使用torch.save保存模型的参数。

  5. 模型加载:在需要使用模型时,实例化相同结构的模型,并加载保存的参数。

  6. 新图像预测:加载并预处理新图像,使用加载的模型进行预测,输出预测结果。

示例运行结果

训练过程的输出如下:

Epoch [1/25], Loss: 1.3775, Train Acc: 0.442, Test Acc: 0.516
Epoch [2/25], Loss: 1.1998, Train Acc: 0.528, Test Acc: 0.552
...
Epoch [25/25], Loss: 0.7376, Train Acc: 0.730, Test Acc: 0.684
训练完成
模型已保存为 resnet18_flower.pth
模型已加载并准备就绪
预测结果:daisy

通过绘制的损失和准确率曲线,可以直观地观察模型的训练过程和性能提升情况。

总结与展望

本文详细介绍了ResNet与GoogLeNet两种经典深度卷积神经网络的结构与设计理念,并通过实际案例演示了如何在PyTorch框架下应用ResNet进行图像分类任务。特别是通过增加模型保存、加载和新图像预测的步骤,展示了完整的从训练到部署的流程。

关键总结

  • ResNet通过引入残差块有效解决了深层网络的训练难题,使得训练超过100层的深度网络成为可能。

  • GoogLeNet通过Inception模块实现了网络深度和宽度的有效扩展,同时控制了计算复杂度,适用于计算资源有限的场景。

  • 实际应用中,选择适当的网络结构和参数设置对于提升模型性能至关重要。

  • 模型的保存与加载是深度学习项目中重要的步骤,确保训练成果能够被复用和部署。

未来展望

随着深度学习技术的不断发展,更多高效的网络架构不断涌现,如DenseNet、EfficientNet等。结合更先进的优化算法和硬件加速技术,深度神经网络将在计算机视觉、自然语言处理等领域发挥更大的作用。此外,模型压缩与加速技术的发展,也将推动深度学习模型在移动设备和边缘计算中的广泛应用。

参考文献

  1. He, K., Zhang, X., Ren, S., & Sun, J. (2016). Deep Residual Learning for Image Recognition. arXiv preprint arXiv:1512.03385.

  2. Szegedy, C., Liu, W., Jia, Y., Sermanet, P., Reed, S., Anguelov, D., ... & Rabinovich, A. (2015). Going deeper with convolutions. Proceedings of the IEEE conference on computer vision and pattern recognition.

  3. He, K., Zhang, X., Ren, S., & Sun, J. (2016). Identity Mappings in Deep Residual Networks. European Conference on Computer Vision (ECCV).

  4. Ioffe, S., & Szegedy, C. (2015). Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. International Conference on Machine Learning (ICML).


本文内容结合了公开的学术论文与实践经验,旨在为读者提供清晰、系统的ResNet与GoogLeNet解析。如有任何问题或建议,欢迎在评论区交流讨论。

相关文章:

【计算机视觉基础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命令启动,但是放到国产信创系统上就是报错&#xf…...

【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的研究历程 ② 分词…...

uniapp blob格式转换为video .mp4文件使用ffmpeg工具

前言 介绍一下这三种对象使用场景 您前端一旦涉及到文件或图片上传Q到服务器,就势必离不了 Blob/File /base64 三种主流的类型它们之间 互转 也成了常态 Blob - FileBlob -Base64Base64 - BlobFile-Base64Base64 _ File uniapp 上传文件 现在已获取到了blob格式的…...

【无标题】 [蓝桥杯 2024 省 B] 好数

[蓝桥杯 2024 省 B] 好数 好数 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。 给定一…...

Leecode刷题C语言之同位字符串连接的最小长度

执行结果:通过 执行用时和内存消耗如下&#xff1a; bool check(char *s, int m) {int n strlen(s), count0[26] {0};for (int j 0; j < n; j m) {int count1[26] {0};for (int k j; k < j m; k) {count1[s[k] - a];}if (j > 0 && memcmp(count0, cou…...

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集BIM介绍基本原理算法流程特点应用场景 BIM代码实现BIM算法实现攻击效果 代码汇总bim.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对CIFAR1…...

音频进阶学习八——傅里叶变换的介绍

文章目录 前言一、傅里叶变换1.傅里叶变换的发展2.常见的傅里叶变换3.频域 二、欧拉公式1.实数、虚数、复数2.对虚数和复数的理解3.复平面4.复数和三角函数5.复数的运算6.欧拉公式 三、积分运算1.定积分2.不定积分3.基本的积分公式4.积分规则线性替换法分部积分法 5.定积分计算…...

将4G太阳能无线监控的视频接入电子监控大屏,要考虑哪些方面?

随着科技的飞速发展&#xff0c;4G太阳能无线监控系统以其独特的优势在远程监控领域脱颖而出。这种系统结合了太阳能供电的环保特性和4G无线传输的便捷性&#xff0c;为各种环境尤其是无电或电网不稳定的地区提供了一种高效、可靠的视频监控解决方案。将这些视频流接入大屏显示…...

使用docker拉取镜像很慢或者总是超时的问题

在拉取镜像的时候比如说mysql镜像&#xff0c;在拉取 时总是失败&#xff1a; 像这种就是网络的原因&#xff0c;因为你是连接到了外网去进行下载的&#xff0c;这个时候可以添加你的访问镜像源。也就是daemon.json文件&#xff0c;如果你没有这个文件可以输入 vim /etc/dock…...

Redis数据库笔记

Spring cache 缓存的介绍 在springboot中如何使用redis的缓存 1、使用Cacheable的例子【一般都是在查询的方法上】 /*** 移动端的套餐查询* value 就是缓存的名称* key 就是缓存id &#xff0c;就是一个缓存名称下有多个缓存&#xff0c;根据id来区分* 这个id一般就是多个查询…...

U盘出现USBC乱码文件的全面解析与恢复指南

一、乱码现象初探&#xff1a;USBC乱码文件的神秘面纱 在数字时代&#xff0c;U盘已成为我们日常生活中不可或缺的数据存储工具。然而&#xff0c;当U盘中的文件突然变成乱码&#xff0c;且文件名前缀显示为“USBC”时&#xff0c;这无疑给用户带来了极大的困扰。这些乱码文件…...

多线程 - 自旋锁

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 多线程 - 自旋锁 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 概述 原理 优点与…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...