【计算机视觉基础CV-图像分类】05 - 深入解析ResNet与GoogLeNet:从基础理论到实际应用
引言
在上一篇文章中,我们详细介绍了ResNet与GoogLeNet的网络结构、设计理念及其在图像分类中的应用。本文将继续深入探讨如何在实际项目中应用这些模型,特别是如何保存训练好的模型、加载模型以及使用模型进行新图像的预测。通过这些步骤,读者将能够完整地掌握从模型训练到部署的全过程。
ps:数据集已经发布~
目录:
-
ResNet简介
-
ResNet的网络结构
-
残差块
-
ResNet模型架构
-
-
GoogLeNet简介
-
GoogLeNet的网络结构
-
Inception模块
-
GoogLeNet模型架构
-
-
ResNet与GoogLeNet的对比
-
实际应用:利用ResNet进行图像分类
-
数据准备与预处理
-
模型实例化与参数设置
-
模型训练与评估
-
模型保存与加载
-
新图像预测
-
完整代码实现详解
-
-
总结与展望
-
参考文献
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模块通常包括以下几部分:
-
1x1卷积:用于减少维度,降低计算量。
-
3x3卷积:处理空间信息。
-
5x5卷积:处理更大范围的空间信息。
-
3x3最大池化:用于下采样,后接1x1卷积。
通过这些并行的操作,Inception模块能够同时捕捉到不同尺度的特征,提高了模型的表达能力。
GoogLeNet模型架构
图4:Inception模块示意图 来源
ResNet与GoogLeNet的对比
特性 | ResNet | GoogLeNet |
---|---|---|
核心创新 | 残差学习(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}")
代码注释详解:
-
数据准备:
-
使用
transforms.Resize
将图像调整为224x224,以匹配ResNet的输入要求。 -
使用
ImageFolder
加载数据集,确保每个类别的图像存放在单独的文件夹中。 -
使用
DataLoader
创建训练和测试数据加载器,设置批次大小和是否打乱数据。
-
-
模型实例化与参数设置:
-
使用
models.resnet18
加载ResNet-18模型,并将最后的全连接层调整为5个输出类别。 -
检测是否有GPU可用,并将模型移动到对应设备以加速训练。
-
定义优化器(Adam)和损失函数(交叉熵损失),设置学习率和训练轮数。
-
-
训练与评估:
-
定义
evaluate_accuracy
函数,用于在测试集上评估模型的准确率,设置模型为评估模式,避免梯度计算。 -
定义
train_model
函数,包含整个训练过程:
-
设置模型为训练模式。
-
遍历每个epoch和每个batch,进行前向传播、计算损失、反向传播和优化参数。
-
记录每个epoch的损失和准确率。
-
在每个epoch结束后,评估模型在测试集上的准确率。
-
绘制训练损失和准确率曲线,直观展示模型的训练过程。
-
-
-
模型保存与加载:
-
定义
save_model
函数,使用torch.save
将模型的参数保存到指定路径。 -
定义
load_model
函数,实例化相同结构的模型,并使用load_state_dict
加载保存的参数。设置模型为评估模式,并移动到对应设备。
-
-
新图像预测:
-
定义
preprocess_image
函数,加载并预处理新图像,使其符合模型输入要求。 -
定义
predict
函数,加载预处理后的图像,使用模型进行前向传播,获取预测结果。 -
示例中替换
new_image_path
为实际需要预测的图像路径,打印预测结果。
-
完整流程说明:
-
数据准备:加载并预处理数据集,包括图像尺寸调整和格式转换。
-
模型定义与参数设置:实例化ResNet-18模型,定义优化器和损失函数,并将模型移动到训练设备。
-
模型训练与评估:通过训练函数,迭代训练模型,并在每个epoch后评估模型性能。
-
模型保存:训练完成后,使用
torch.save
保存模型的参数。 -
模型加载:在需要使用模型时,实例化相同结构的模型,并加载保存的参数。
-
新图像预测:加载并预处理新图像,使用加载的模型进行预测,输出预测结果。
示例运行结果
训练过程的输出如下:
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等。结合更先进的优化算法和硬件加速技术,深度神经网络将在计算机视觉、自然语言处理等领域发挥更大的作用。此外,模型压缩与加速技术的发展,也将推动深度学习模型在移动设备和边缘计算中的广泛应用。
参考文献
-
He, K., Zhang, X., Ren, S., & Sun, J. (2016). Deep Residual Learning for Image Recognition. arXiv preprint arXiv:1512.03385.
-
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.
-
He, K., Zhang, X., Ren, S., & Sun, J. (2016). Identity Mappings in Deep Residual Networks. European Conference on Computer Vision (ECCV).
-
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的网络结构、设计理念及其在图像分类中的应用。本文将继续深入探讨如何在实际项目中应用这些模型,特别是如何保存训练好的模型、加载模型以及使用模型进行新图像的预测。通过这些步骤,读…...
WPF+MVVM案例实战与特效(四十五)- 打造优雅交互:ListBox 的高级定制与行为触发(侧边菜单交互面板)
文章目录 1、引言2、案例效果3、案例实现1、依赖安装2、文件创建3、代码实现1、依赖引用与上下文2、个性化视觉效果:自定义 ItemContainerStyle3、页面样式与布局完整代码4、ViewModel 逻辑实现5、子界面代码:3、实现效果4、源代码获取5、总结1、引言 在WPF应用程序开发中,…...
Git进阶:本地或远程仓库如何回滚到之前的某个commit
在Git的使用过程中,我们经常会遇到需要回滚到之前某个commit的情况。无论是为了修复错误、撤销更改,还是为了重新组织代码,回滚到特定commit都是一个非常有用的技能。本文将介绍几种常用的回滚方法,帮助读者更好地掌握Git版本控制…...
Django 后端数据传给前端
Step 1 创建一个数据库 Step 2 在Django中点击数据库连接 Step 3 连接成功 Step 4 settings中找DATABASES Step 5 将数据库挂上面 将数据库引擎和数据库名改成自己的 Step 6 在_init_.py中加上数据库的支持语句 import pymysql pymysql.install_as_MySQLdb()Step7 简单创建两列…...
Docker 技术系列之安装多版本Mysql5.6和Mysql5.7
image 大家好,后面的就不是关于MAC专有的内容,基本是跟Java环境,基础技术方面有关。所以这个教程对于在linux系统还是macOS都是通用的,不用担心。 上一篇,我们安装好对应的Docker之后,感受到了它的便利。接…...
C# 范围判断函数
封装范围函数 public static class CommonUtil {/// <summary>/// 范围判断函数,检查给定的值是否在指定的最小值和最大值之间。/// 例如,可以用来判断当前日期是否在开始日期和结束日期之间。/// 该方法适用于任何实现了 IComparable 接口的类型…...
技术速递|使用 Dependabot 管理 .NET SDK 更新
作者:Jamie Magee - 高级软件工程师 排版:Alan Wang 保持 .NET SDK 版本的更新对于维护安全高效的应用程序至关重要。现在 Dependabot 可以在 global.json 中更新 .NET SDK 版本,这使您可以比以往更轻松地确保自己的应用程序始终运行最新的安…...
笔记本通过HDMI转VGA线连接戴尔显示器,wifi不可用或网速变慢
早上开开心心的来使用我的分屏显示器,结果winP开拓展,我的wifi就断掉了,琢磨了好一阵我以为是wifi的问题,发现不进行拓展,网络又好了,一上午就研究这个了,说是hdmi信号干扰了wifi信号啥的额&…...
Excel中match()函数
函数功能概述 MATCH 函数是 Excel 中用于在指定区域中查找特定值的位置的函数。它返回指定数值在指定数组区域中的位置。这个位置是相对于查找区域的相对位置,而不是绝对的单元格位置。语法结构 MATCH(lookup_value, lookup_array, match_type)lookup_value…...
ACl访问控制列表
ACL的原理 ACL也称为访问控制列表,主要有包过滤的功能,同时也是包过滤防火前的本质 其方式主要是定立规则,这些规则控制着数据包的允许或者通过 ACL的场景 如下图,在全网互通的情况下,控制特定的数据包走向 例如控…...
android 用户空间切换流程
在Android开发中,创建和切换用户是一个重要的功能,特别是在需要多用户支持的应用中,下面讲述一下用户切换的流程。 一、CarUserManager.java 准备创建新用户,可以减少真正创建用户的时间 @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,Manifest.permis…...
突破续航瓶颈:数字样机技术引领新能源汽车复合制动新方向
随着我国经济快速发展和人民生活水平不断提升,汽车保有量截至2023年9月底就已达到了3.3亿,同比增长6.32%。庞大的汽车保有量对我国的环境和能源都产生了巨大的压力,具备节能环保优势的新能源汽车对于有效解决环境恶化和能源危机问题具有重要意…...
51单片机仿真摇号抽奖机源程序 12864液晶显示
资料下载地址:51单片机仿真摇号抽奖机源程序12864液晶显示仿真程序 一、功能介绍 单片机连接12864(st7920)液晶显示器和1个按键接INT0,模拟一个抽奖机。 实现效果: 1、液晶初始显示“祝你好运!”ÿ…...
路由器的原理
✍作者:柒烨带你飞 💪格言:生活的情况越艰难,我越感到自己更坚强;我这个人走得很慢,但我从不后退。 📜系列专栏:网路安全入门系列 目录 路由器的原理一,路由器基础及相关…...
Vue(四)
1.Vuex 1.1 Vuex是什么 Vuex 是一个插件,可以帮我们管理 Vue 通用的数据。例如:购物车数据、个人信息数据。 1.2 vuex的使用 1.安装 vuex 安装 vuex 与 vue-router 类似,vuex 是一个独立存在的插件,如果脚手架初始化没有选 v…...
今日总结 2024-12-23
项目初始化 拉取代码与环境配置: 难点:Git 命令不熟悉,依赖文件定位不准,启动脚本含义不明。解决办法:系统学习 Git 基础操作,如通过官方文档、优质的 Git 教程视频,反复练习克隆、分支切换等常…...
Vue常用指令
1. 插值表达式 {{}} <script setup> let msg="hello vue!" </script> <template> <h1>{{ msg }}--{{ 1+1 }}--{{ msg+sb }}</h1> </template> 2. Vue 常用指令 (以v- 开头) 2.1 v-html 替换标签元素内容,包含标签…...
欢乐力扣1-10
文章目录 前言1、合并两个有序数组1.1.描述 2、移除元素2.1.描述2.2.思路 3、删除有序数组中的重复元素3.1.描述3.2.思路 4、输出有序数组中的重复项二4.1.描述4.2.思路 5、多数元素5.1.描述5.2.思路 6、轮转数组6.1.描述6.2.思路 7、买卖股票最佳时机一7.1.思路 8、买卖股票最…...
[创业之路-204]:《华为战略管理法-DSTE实战体系》- 5-平衡记分卡绩效管理
目录 一、平衡计分卡概述 1、平衡计分卡的基本概念 2、平衡计分卡的发展阶段 3、平衡计分卡在华为的应用 4、平衡计分卡的优缺点 五、财务(股东)、顾客(用户)、内部运营(内部)及学习与发展࿰…...
算法设计期末复习
文章目录 1. 什么是算法,算法有哪些特征,算法设计的基本步骤,算法的时间复杂度的确定2. 什么是算法分析,算法分析的主要内容是什么?怎么确定算法的时间复杂度?3. 什么是分治算法,分治算法通常用…...
芝法酱学习笔记(2.2)——sql性能优化2
一、前言 在上一节中,我们使用实验的方式,验证了销售单报表的一些sql性能优化的猜想。但实验结果出乎我们的意料,首先是时间查询使用char和datetime相比,char可能更快,使用bigint(转为秒)和cha…...
Linux 安装 nvm
Linux 安装 nvm 网上用curl命令安装的方式都下载不成功,直接使用压缩包安装 ####### wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.39.1.tar.gz mkdir -p /root/.nvm tar xvf nvm-0.39.1.tar.gz -C /root/.nvm#######vi ~/.bashrc,在~/.bashrc的末尾…...
图像处理基础 | 查看两张图像的亮度差异,Y通道相减
两张图像的Y通道相减通常用于图像差异分析或比较,尤其是在亮度方面。具体来说,这一操作是基于YCbCr颜色空间中的Y通道进行的,其中Y通道代表图像的亮度信息(亮度成分),而Cb和Cr通道分别代表色度成分…...
机器学习-43-可解释性机器学习库LIME
文章目录 1 LIME1.1 LIME的特点1.2 LIME的步骤2 应用LIME2.1 分类模型2.1.1 创建模型和解释器2.1.2 解释样本2.2 回归模型2.2.1 创建模型和解释器2.2.2 解释样本2.3 文本模型2.3.1 创建模型和解释器2.3.2 解释样本2.4 图像模型2.4.1 创建模型和解释器2.4.2 解释样本3 附录3.1 l…...
RestTemplate关于https的使用详解
RestTemplate关于https的使用详解 一、restTemplate注入到bean里面。 Configuration public class RestTempleConfig {BeanPrimarypublic RestTemplate restTemplate() {return new RestTemplate();}/*** https 请求的 restTemplate* return* throws Exception*/Beanpublic R…...
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
Hiヽ(゜▽゜ )-欢迎来到蓝染Aizen的CSDN博客~ 🔥 博客主页: 【✨蓝染 の Blog😘】 💖感谢大家点赞👍 收藏⭐ 评论✍ 文章目录 行为型模式1、模板方法模式(1)概述(2&…...
CNN、RNN、LSTM和Transformer之间的区别和联系
文章目录 CNN、RNN、LSTM和Transformer之间的区别和联系前言CNN(卷积神经网络)RNN(循环神经网络)LSTM(长短期记忆网络)Transformer四者之间的联系与区别Yolo算法简介Yolo和CNN的关系YOLO各版本 CNN、RNN、L…...
sqlite3,一个轻量级的 C++ 数据库库!
宝子们,今天咱来唠唠 sqlite3 这个超棒的轻量级 C 数据库库。它就像是一个小巧但功能齐全的“数据仓库”,能帮咱们轻松地存储、查询和管理数据,无论是开发小型的桌面应用,还是做一些简单的数据处理程序,它都能派上大用…...
重温设计模式--观察者模式
文章目录 观察者模式(Observer Pattern)概述观察者模式UML图作用:实现对象间的解耦支持一对多的依赖关系易于维护和扩展 观察者模式的结构抽象主题(Subject):具体主题(Concrete Subject…...
基于Java+Swing+Mysql的超市客户关系管理系统
基于JavaSwingMysql的超市客户关系管理系统 一、系统介绍二、效果展示三、其他系统实现四、获取源码 一、系统介绍 系统实现管理员对客户信息进行增删改查,信息包括客户编号,姓名,手机号,会员评级;可以对客户消费记录…...
JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化
目录 1. 背景2. 实现2.1 pom.xml2.2 FruitController.java2.3 DispatcherServlet.java2.4 applicationContext.xml 3. 测试 1. 背景 前面我们做了Servlet的一个案例。但是存在很多问题,现在我们要做优化,优化的步骤如下: 每个Fruit请求都需…...
基础I/O -> 如何谈文件与文件系统?
文件的基础理解 空文件也要在磁盘上占据空间。文件 文件内容文件属性。文件操作 对内容的操作 对属性的操作或者是对内容和属性的操作。标定一个文件,必须使用:文件路径 文件名(具有唯一性)。如果没有指明对应的文件路径&…...
安装配置git
1、下载git:https://git-scm.com 2、配置git,进入git bash #配置用户名 git config-global user.name "petter7226" #配置邮箱 git config-global user.email "894266014qq.com" 3、配置ssh免密登录 可参考这个文档 https://gitee.com/help/article…...
cad学习 day4 day5
平面布置 客厅平面布置 端景柜: 一般玄关区域、走廊、过道尽头做造型端景柜,可以组展示、柜体、艺术品陈设窗帘盒 200mm 电动窗帘盒 250mm, 镜像命令: MI 做对称使用沙发: 归类FF - 移动家私木门: 归类FF - 平面内门地台床: 使用bo快速生成, 绘制后外围偏移O 50mm pl连接作为灯…...
Java的基础概念(一)
一、注释 **注意!:**注释内容不会参与编译和运行,仅仅是对代码的解释说明。 Java支持单行注释、多行注释、文档注释。 单行注释 以//开头 ,格式【 //注释内容 】 例子如下: 多行注释 格式【 / 注释内容 / 】 例…...
Qt5 cmake引用private头文件
Qt5 cmake引用private头文件 如何引用Qt的qzipreader_p.h头文件 、xlsxzipreader_p.h头文件 使用 target_include_directories target_include_directories(TestQtXlsx PRIVATE${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS}${Qt${QT_VERSION_MAJOR}Xlsx_PRIVATE_INCLUD…...
重温设计模式--代理、中介者、适配器模式的异同
文章目录 1、相同点2、不同点 1、相同点 目的都是为了更好地处理对象之间的关系:这三种模式都是在软件设计中用于处理对象之间的关联和交互,以达到优化系统结构、增强可维护性等目的。它们都在一定程度上隐藏了对象之间的某些细节或者复杂性,…...
拦截器魔法:Spring MVC中的防重放守护者
目录 简介HandlerInterceptorAdapter vs HandlerInterceptor创建一个防重放拦截器注册拦截器路径模式匹配适配器模式的魅力总结 简介 在构建安全可靠的Web应用程序时,防止请求重放攻击是一项关键任务。当用户或系统发出的请求被恶意第三方捕获并重复发送给服务器…...
MVC 发布
关于MVC发布,我为您整理了以下信息: SpringMVC发布:SpringMVC是Spring框架的一部分,它基于MVC架构,具有解耦合、轻量级和对注解的广泛支持等优点。发布SpringMVC项目通常涉及配置中央调度器、编写控制器类和设置视图解…...
AI在传统周公解梦中的技术实践与应用
本文深入探讨了人工智能在传统周公解梦领域的技术实践与应用。首先介绍了传统周公解梦的背景与局限性,随后详细阐述了 AI 技术如何应用于梦境数据的采集、整理与分析,包括自然语言处理技术对梦境描述的理解,机器学习算法构建解梦模型以及深度…...
Go怎么做性能优化工具篇之基准测试
一、什么是基准测试(Benchmark) 在 Go 中,基准测试是通过创建以 Benchmark 开头的函数,并接收一个 *testing.B 类型的参数来实现的。testing.B 提供了控制基准测试执行的接口,比如设置测试执行的次数、记录每次执行的…...
社区管理系统:实现社区信息数字化管理的实践
3.1可行性分析 开发者在进行开发系统之前,都需要进行可行性分析,保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该社区管理系统所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识,同…...
Java设计模式 —— 【结构型模式】外观模式详解
文章目录 概述结构案例实现优缺点 概述 外观模式又名门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这…...
基于 Python 的二手电子设备交易平台
标题:基于 Python 的二手电子设备交易平台 内容:1.摘要 基于 Python 的二手电子设备交易平台的摘要:本文介绍了一个基于 Python 的二手电子设备交易平台。该平台旨在为用户提供一个便捷、安全的交易环境,促进二手电子设备的流通和再利用。文章首先介绍了…...
Vue.js组件开发-插槽(Slots)的使用
插槽(Slots)是 Vue.js 中一个非常强大的特性,允许在组件内部指定可重用的内容片段,这些内容片段可以由父组件动态地填充。它能够让父组件决定组件内部应该渲染什么内容。 默认插槽 默认插槽是最简单的插槽类型。在子组件的模板中…...
python:面向对象简单示例
编写 se2ball.py 如下 # -*- coding: utf-8 -*- """ python 面向对象简单示例 """ import randomclass Random_ball(object):""" 随机选双色球 """def __init__(self, reds33, blues16):""" 初始…...
Stealthy Attack on Large Language Model based Recommendation
传统RS依赖id信息进行推荐,攻击:生成虚假用户,这些用户对特定目标物体给于高评价,从而影响模型的训练。 基于llm的RS:llm利用语义理解,将用户兴趣转化为语义向量,通过计算用户兴趣向量与物品向…...
云原生周刊:利用 eBPF 增强 K8s
开源项目推荐 Slurm-operator Slurm-operator 是一个高效可扩展的框架,用于在 K8s 环境中部署和运行 Slurm 工作负载。 它结合了 Slurm 的可靠性和 Kubernetes 的灵活性,支持快速部署 Slurm 集群、动态扩展 HPC 工作负载,并提供高度灵活的定…...
Ubuntu20.04安装openMVS<成功>.colmap<成功>和openMVG<失败(已成功)>
一、安装openMVS 官方文档:https://github.com/cdcseacave/openMVS/wiki/Building sudo apt-get -y install git mercurial cmake libpng-dev libjpeg-dev libtiff-dev libglu1-mesa-dev eigen git clone https://gitlab.com/libeigen/eigen --branch 3.4 mkdi…...
第22天:信息收集-Web应用各语言框架安全组件联动系统数据特征人工分析识别项目
#知识点 1、信息收集-Web应用-开发框架-识别安全 2、信息收集-Web应用-安全组件-特征分析 一、ICO图标: 1、某个应用系统的标示,如若依系统有自己特点的图标;一旦该系统出问题,使用该系统的网站都会受到影响; 2、某个公…...