pytorch项目实战-分类模型李宏毅 21 机器学习第三次作业代码详解 CNN图片分类任务

请添加图片描述

CNN 卷积神经网络食物分类任务

  • 前言
  • 一、数据集介绍
  • 二、CNN模型整体框架
  • 三、卷积神经网络代码详解
    • 3.1 导入需要使用的包
    • 3.2 数据集,数据加载器,数据增强操作
      • 3.2.1 数据增强
      • 3.2.2 数据集构建
      • 3.2.3 加载器构建
    • 3.3 卷积神经网络构建
    • 3.4 训练代码
      • 3.4.1 半监督训练
      • 3.4.2 模型训练验证代码
    • 3.5 训练结果可视化
    • 3.6 训练结果可视化
  • 总结

前言

深度学习领域中,卷积神经网络(CNN)是一个绕不开的重要主题。本章节旨在深入探讨和实践CNN相关的概念和知识点,将依据李宏毅教授在2021年机器学习课程中的第三次作业代码作为例子。通过这一实例,读者将有机会加深对CNN的理解,并提升自己的实践技能。

需要指出的是,本章节中展示的代码并未直接采用课程提供的baseline示例。这是因为基础模型的性能有限,而且与传统的深度神经网络(DNN)代码相比,并不提供更多的学习内容。因此,自行选择了一套演示代码,旨在提供更深入的学习和探索机会。对于有兴趣进一步研究的读者,推荐参考原始代码。

通过本章节的学习,希望帮助读者不仅掌握卷积神经网络的理论基础,还能通过亲手实践,有效地加深对这一强大工具的理解和应用能力。

一、数据集介绍

请添加图片描述

  • 食物分类数据集
    • 图像来自被分为11类的food-11数据集。
    • 这里的数据集有所修改:
      • 训练集:280*11张有标签的图像 + 6786张无标签的图像
      • 验证集:60*11张有标签的图像
      • 测试集:3347张图像
        因为测试部分需要使用kaggle进行上传测试故此,本章节不会对测试代码进行讲解,具体感兴趣的同学可以移步Kaggle进行上传测试

为了规范化地访问数据,数据集被组织如下所示:同一类别的图片被放置在相同的文件夹内,同时测试集和验证集的图片也已被完整地分配到不同的文件夹中以便于调用:

请添加图片描述

二、CNN模型整体框架

借助之前章节的学习,读者对深度学习代码的整体框架已有充分的了解。因此,本章节的框架结构图仅对重要部分进行了简明划分。在随后的代码详解部分,将针对各个部分进行深入讲解。框架的整体布局是按照编码的逻辑顺序排列的。如果读者在详细分析各个部分时对整个流程感到困惑,可以回顾本节,以便更好地理解代码的整体逻辑。

在这里插入图片描述

三、卷积神经网络代码详解

3.1 导入需要使用的包

先来看下模型所需要的使用的库函数,本章节对之前文章中未出现的库函数进行讲解。

# 常规的库函数
import numpy as np 
import torch
import torch.nn as nn#针对当前部分引入新的库函数
import torchvision 
import torchvision.transforms as transforms
from PIL import Image# "ConcatDataset" and "Subset" are possibly useful when doing semi-supervised learning.
from torch.utils.data import ConcatDataset, DataLoader, Subset, Dataset
from torchvision.datasets import DatasetFolder
# 进度条
from tqdm.auto import tqdm

本章节出现了新的库函数如下:

import torchvision 

torchvision独立于pytorch,专门用来处理图像,通常用于计算机视觉领域。

import torchvision.transforms as transforms

transforms 是一个函数,主要作用就是对用于图像预处理和数据增强。transforms 通常与 transforms.Compose 配合使用,transforms.Compose 是一个组合类,它可以将多个图像变换操作组合在一起。
举个例子:

from torchvision import transforms# 定义图像预处理操作
transform = transforms.Compose([transforms.Resize(256),             # 缩放图像,使较短的边为256像素transforms.CenterCrop(224),         # 从图像中心裁剪出224*224大小的图像transforms.ToTensor(),              # 将图像转换为Tensor,归一化至[0,1]transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 标准化处理
])# 然后你可以使用这个 `transform` 来处理你的图像数据
# 例如:
# image = Image.open("path_to_your_image.jpg") 当前步骤实例化一个图像的对象,送入transform进行处理
# image = transform(image)
from PIL import Image

主要的作用Image模块是Pillow库的核心模块,用于图像的加载、处理和保存。通过Image模块的对Image.open打开文件,实例化图片,通过对象的方法实现对图像的改变。

from PIL import Image# 加载图像文件
image = Image.open("example.jpg")# 显示图像
image.show()# 对图像进行一些处理
# 比如旋转90度
rotated_image = image.rotate(90)
# 或者将图像转换为灰度
greyscale_image = image.convert("L")
# 又或者调整图像的大小
resized_image = image.resize((300, 300))
from torch.utils.data import ConcatDataset, DataLoader, Subset, Dataset

ConcatDataset 是一个 PyTorch 数据集类,它用于组合多个具有相同的字段(如图像和标签)的数据集

dataset1 = CustomDataset('path/to/dataset1')
dataset2 = CustomDataset('path/to/dataset2')
# Concatenate datasets
combined_dataset = ConcatDataset([dataset1, dataset2])

Subset 类用于从一个大数据集中选取特定的子集。

# Assuming dataset is a large dataset and you want to select a subset of it
subset_indices = [10, 20, 30, 40, 50]  # Just as an example
subset = Subset(dataset, subset_indices)
from torchvision.datasets import DatasetFolder

torchvision.datasets.DatasetFolder 是 PyTorch torchvision 库中一个非常实用的类,它允许快速且轻松地按照特定的文件结构组织和加载数据集,针对那些已经以一定格式存放的数据集特别有用。 这种方式可以大大减少手动编写用于加载数据集的代码量,尤其是当数据集已经按照一定的目录结构组织时。

具体的格式如下:请添加图片描述
一目了然,就是将相同类别的数据存储到一个文件夹中,这样就能够使用该类进行数据集好的快速创建。

3.2 数据集,数据加载器,数据增强操作

3.2.1 数据增强

在深度学习特别是图像处理领域中,数据增强(Data Augmentation)是一个非常关键的技术,它可以增加数据集的多样性,减少模型对特定形式输入数据的依赖,从而提高模型的泛化能力
通过应用各种随机变换,数据增强能够从现有数据集生成新的训练样本,这些变换包括但不限于旋转、平移、缩放、裁剪、翻转、调整亮度/对比度等。transforms 模块提供了许多此类操作,可以方便地用于图像数据的增强。


# It is important to do data augmentation in training.train_tfm = transforms.Compose([transforms.RandomResizedCrop((128, 128)),# 随机从图中裁切一部分,并将裁减的部分的大小限定在128,128。增加随机行模型能够得到更多的训练样本transforms.RandomChoice( # 在下面的几种方式中随机选择一种进行
'''
简单点说就是在不同的数据集上得到的数据增强的技术:1. **`transforms.AutoAugment()`:使用默认的 AutoAugment 策略。如果不指定任何策略
2. ,那么将使用 ImageNet 数据集上实验确定的最佳增强策略。这是一种通用的增强策略,适用于多种图像分类任务。3. **`transforms.AutoAugment(transforms.AutoAugmentPolicy.CIFAR10)`**:
4. 使用为 CIFAR10 数据集特别设计的 AutoAugment 策略。CIFAR10 包含10个类别的小尺
5. 寸彩色图像(32x32像素)。为这个数据集定制的策略考虑到了其特定的特性,如图像尺寸和类型的多样性。6. **`transforms.AutoAugment(transforms.AutoAugmentPolicy.SVHN)`**:使用为
7. 街景门牌号(SVHN, Street View House Numbers)数据集特别设计的 AutoAugment 策略
8. 。SVHN 是现实世界的数字识别数据集,图像来源于谷歌街景的门牌号。因此,这项策略是针对识别数字类别的图像进行优化的。'''[transforms.AutoAugment(),transforms.AutoAugment(transforms.AutoAugmentPolicy.CIFAR10),transforms.AutoAugment(transforms.AutoAugmentPolicy.SVHN)]),transforms.RandomHorizontalFlip(p=0.5), #以 50% 的概率水平翻转图像。这种随机性增加了训练数据的多样性。transforms.ColorJitter(brightness=0.5), #随机改变图像亮度,亮度参数 brightness=0.5 提供了亮度变化的强度。transforms.RandomAffine(degrees=20, translate=(0.2, 0.2), scale=(0.7, 1.3)),# 应用随机仿射变换:
# degrees=20 表示随机旋转的角度范围为 [-20, 20] 度。
# translate=(0.2, 0.2) 允许平移至多达图像宽度和高度20%的大小。
# scale=(0.7, 1.3) 指定缩放比例范围,在原始大小的基础上进行放大或缩小。transforms.ToTensor(), #将 PIL 图像 FloatTensor,并将图像的像素值从 [0, 255] 范围缩放到 [0.0, 1.0] 范围。
])# 并不需要对测试和验证集的数据进行增强
# 需要将所有的图片的大小进行设定,并且转换成tensor类型
test_tfm = transforms.Compose([transforms.Resize((128, 128)),transforms.ToTensor(),
])

通过各种各样的手段对数据进行处理,从而在有限的数据集上能够提供更多的样本给模型进行训练,从而提升模型的性能。

3.2.2 数据集构建

 DatasetFolder("food-11/training/labeled", loader=lambda x: Image.open(x), extensions="jpg", transform=train_tfm)

当前主要是针对DatasetFolder这个类实现进行实例化,创建数据集,前提是按照上文中描述的数据集的格式是按照DatasetFolder类的要求进行创建的。

举个例子解释一下,要创建数据集首先就要知道数据集的位置,故此第一个参数是数据集的根目录,然后就是读取数据文件,使用Image.open(x)方法进行打开,而loader作为加载器是会接收到位置信息的,故此这个匿名函数lambda就可以正常运行,为了防止访问到其他非图片数据因此要限定访问数据的格式,在得到了数据对象后,应用上文讲解的数据增强技术对数据进行处理,最终得到数据集对象。由此也可以看到torchvision.Composs和DataFolder的配套使用的。

train_set = DatasetFolder("food-11/training/labeled", loader=lambda x: Image.open(x), extensions="jpg", transform=train_tfm)
valid_set = DatasetFolder("food-11/validation", loader=lambda x: Image.open(x), extensions="jpg", transform=test_tfm)
unlabeled_set = DatasetFolder("food-11/training/unlabeled", loader=lambda x: Image.open(x), extensions="jpg", transform=train_tfm)
test_set = DatasetFolder("food-11/testing", loader=lambda x: Image.open(x), extensions="jpg", transform=test_tfm)

3.2.3 加载器构建

# Construct data loaders.
train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True, num_workers=2, pin_memory=True)
valid_loader = DataLoader(valid_set, batch_size=batch_size, shuffle=True, num_workers=2, pin_memory=True)
test_loader = DataLoader(test_set, batch_size=batch_size, shuffle=False)
# 和前文一样故此不在过多赘述,值得注意就是测试集不打乱数据

3.3 卷积神经网络构建

class Classifier(nn.Module):def __init__(self):super(Classifier, self).__init__()# torch.nn.Conv2d(in_channels输入通道个数, out_channels输出通道个数, kernel_size卷积核大小, stride步长, padding是否填充)# torch.nn.MaxPool2d(kernel_size通道数, stride步长, padding填充)# input image size: [3, 128, 128]self.cnn_layers = nn.Sequential(nn.Conv2d(3, 64, 3, 1), # 卷积层nn.BatchNorm2d(64), # 批归一化nn.ReLU(),# 激活nn.MaxPool2d(2, 2, 0),# 池化层nn.Conv2d(64, 128, 3, 1),nn.BatchNorm2d(128),nn.ReLU(),nn.MaxPool2d(2, 2, 0),nn.Conv2d(128, 256, 3, 1),nn.BatchNorm2d(256),nn.ReLU(),nn.MaxPool2d(2, 2, 0),nn.Conv2d(256, 512, 3, 1),nn.BatchNorm2d(512),nn.ReLU(),nn.MaxPool2d(2, 2, 0),nn.Conv2d(512, 1024, 3, 1),nn.BatchNorm2d(1024),nn.ReLU(),nn.MaxPool2d(2, 2, 0))self.fc_layers = nn.Sequential(nn.Linear(4096, 1024),nn.BatchNorm1d(1024),nn.ReLU(),nn.Dropout(0.6),nn.Linear(1024, 256),nn.BatchNorm1d(256),nn.ReLU(),nn.Dropout(0.4),nn.Linear(256, 11))def forward(self, x):# input (x): [batch_size, 3, 128, 128]# output: [batch_size, 11]x = self.cnn_layers(x)x = x.flatten(1)x = self.fc_layers(x)return x

3.4 训练代码

3.4.1 半监督训练

简单的说,半监督训练本质上就是通过训练到一定程度的模型,对无标签数据进行标注,按照置信度判断是否作为训练数据,实现对训练数据的补充,从而依托更多的训练数据期望模型的性能上升。

在半监督训练框架下,模型首先使用少量的标记数据进行训练。一旦模型达到一定的性能水平,它就可以对未标记的数据进行预测,并给出每个样本的标签及其对应的置信度。然后,根据预先设定的置信度阈值,选择置信度高的预测结果将这些未标记的数据(现在带有预测标签)作为新的训练样本。通过这种方式,模型可以利用更多的数据,包括原始的标记数据和添加的预测标记数据,进行进一步的训练。这个循环可以按需重复进行,每一轮都可能提升模型对数据的理解和预测能力。

在实践中,这种方法的有效性很大程度上依赖于模型的初始性能以及如何选择置信度阈值来决定哪些未标记的样本被认为是可靠的训练数据。如果模型的初始预测准确性很高,那么利用未标记数据所带来的性能提升可能会更明显。相反,如果模型的初始预测性能较差,错误地标记大量未标记的数据可能会引起错误传播,进而影响模型的整体性能。
此外,半监督训练能够有效地缓解标记数据不足的问题,这在许多实际应用中是非常有价值的,因为手动标记大量数据往往是昂贵和耗时的。通过合理地利用未标记数据,半监督学习为学习更丰富和更泛化的模型提供了一条可行的路径。

代码部分

class PseudoDataset(Dataset): # 应用Dataset()类,构建数据集,可以通过,实例化过程中使用的都是模型预测的结果作为y,x就是图数据def __init__(self, x, y):self.x = xself.y = ydef __getitem__(self, id): # 构建索引和数据之间的联系return self.x[id][0], self.y[id]def __len__(self):return len(self.y)def get_pseudo_labels(dataset, model, threshold=0.9): # 当前函数调用PseudoDataset生成无标签的数据集device = "cuda" if torch.cuda.is_available() else "cpu" data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=False) # 导入无标签的数据集生成数据加载器model.eval() # 模型开始评估模式softmax = nn.Softmax(dim=-1) '''
"torch的交叉熵损失函数本身就是具备softmax功能" 在使用交叉熵损失计算梯度时不需要再单独加 softmax 层,
但在预测类别时需要使用 softmax 来获取概率分布。'''idx = [] # 存放数据的索引,用于取出来数据labels = [] # 预测的结果作为标签for i, batch in enumerate(data_loader): # 数据分批导入img, _ = batch # 当前部分的全部类别都是00,有疑问可以看下数据集with torch.no_grad(): # 不会计算梯度logits = model(img.to(device)) # 送入模型预测probs = softmax(logits) #接入softmax层for j, x in enumerate(probs): # 对所有的预测结果进行编码,j是序号而x是预测结果if torch.max(x) > threshold: #比较向量中最大的值是否大于置信度idx.append(i * batch_size + j) # 这个就是索引信息,batchsize就是批次个数乘i就会得到每一个批次的第一个数值的索引编号加上j就是真实的索引信息。labels.append(int(torch.argmax(x))) # 这个就是类别最大的索引信息,x是一个向量取最大位置数值的索引作为真实标签model.train() # 模型开始训练模式print ("\nNew data: {:5d}\n".format(len(idx)))dataset = PseudoDataset(Subset(dataset, idx), labels)  #  Subset 是按照idx提供的索引列表,从dataset中选出部分数据形成新的数据集。return dataset

上述部分可以是本节最重要的内容,其他的其实都和之前的网络无太大差异

3.4.2 模型训练验证代码

这一部分的流程遵循了传统的模型训练与验证步骤,其核心目标是通过迭代更新参数以优化模型性能。在此过程中,模型首先在训练集上学习,然后通过验证集检验其泛化能力。不同的是,在这一阶段我们考虑了一种扩展策略:即是否引入半监督学习,也就是利用未标记数据来进一步增强模型的性能。

在这个上文中,半监督训练的实施为模型训练带来了新的维度。通过利用之前生成的带有伪标签的数据集,不仅使用了原始的有标记数据,还加入了额外的未标记数据,这些数据被模型预测并选择出高置信度的部分作为新的训练样本。这样的策略有助于模型从更多样化的数据中学习,尤其是在可用的标记数据较少时,这种方法尤为有价值。最终,半监督训练旨在通过扩大训练数据集的规模,提升模型对未见样本的识别能力。

通过这种灵活的训练策略,可以充分利用可用数据资源,进而朝着更加准确和鲁棒的模型性能迈进。综合使用传统训练方法和半监督训练策略,可为模型优化提供更全面的支持,从而在多个层面上提升模型性能。

device = "cuda" if torch.cuda.is_available() else "cpu"# Initialize a model, and put it on the device specified.
model = Classifier().to(device) # 实例化模型送入设备上
model.device = devicefrom torchsummary import summary
summary(model, input_size=(3, 128, 128), device=device)
#通过提供模型实例和输入数据的尺寸,summary 函数允许你快速了解模型的构造和大小
#这在设计、调整网络结构时非常有用。criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0003, weight_decay=1e-5)
# optimizer = torch.optim.SGD(model.parameters(), lr=0.0003, momentum=0.9, weight_decay=1e-5)n_epochs = 500
do_semi = True # 是否使用半监督
model_path = "model.ckpt"best_acc = 0.0 
train_loss_record = []
valid_loss_record = []
train_acc_record = []
valid_acc_record = []for epoch in range(n_epochs):if do_semi and best_acc > 0.7 and epoch % 5 == 0: # 使用半监督进行增强训练的条件pseudo_set = get_pseudo_labels(unlabeled_set, model) # 调用半监督函数 创建无标签数据集concat_dataset = ConcatDataset([train_set, pseudo_set]) # 将两个数据集进行拼接train_loader = DataLoader(concat_dataset, batch_size=batch_size, shuffle=True, num_workers=2, pin_memory=True, drop_last=True) # 得到新的数据集后构建增强数据集的加载器(原始训练集合加上无标签数据集)# ---------- Train ----------model.train()train_loss = []train_accs = []# for batch in tqdm(train_loader):for batch in train_loader:imgs, labels = batchlogits = model(imgs.to(device)) #模型预测loss = criterion(logits, labels.to(device)) #计算损失optimizer.zero_grad() #梯度清0loss.backward()# 计算梯度信息grad_norm = nn.utils.clip_grad_norm_(model.parameters(), max_norm=10)'''可以被视作一种梯度归一化的技术。它确保模型中所有参数的梯度范数不超过一个特定的最大阈值。如果梯度范数已经超过了这个阈值,那么会将梯度按比例缩小,以使得整体梯度的范数恰好等于最大阈值,这个过程也被称为梯度裁剪。通过这种方式,它可以防止在训练期间出现梯度爆炸问题,有助于保持训练过程的稳定性。在某些情况下,当模型极度复杂或是训练数据包含异常值时,梯度可能会变得极大,导致模型参数的大幅更新,从而影响模型的学习效果。通过梯度裁剪,可以限制梯度更新的步幅,使得每次参数更新更加温和,从而有助于稳定训练过程,提高模型的训练效率和最终性能。简而言之,梯度裁剪通过对梯度的大小进行限制,以实现对模型训练过程的一种归一化控制,帮助防止梯度过大导致的训练不稳定问题。'''optimizer.step() #按学习率更新acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()
# 本身就是一个二维的数据,因此要在最后一个维度找到最大值并取出索引(logits.argmax(dim=-1) ,和真实标签比对,计算均值作为准确率train_loss.append(loss.item())train_accs.append(acc)train_loss = sum(train_loss) / len(train_loss)train_acc = sum(train_accs) / len(train_accs)print(f"[ Train | {epoch + 1:03d} / {n_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}")# ---------- Validation ---------- 验证部分model.eval()valid_loss = []valid_accs = []# for batch in tqdm(valid_loader):for batch in valid_loader:imgs, labels = batchwith torch.no_grad():logits = model(imgs.to(device))loss = criterion(logits, labels.to(device))acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()valid_loss.append(loss.item())valid_accs.append(acc)valid_loss = sum(valid_loss) / len(valid_loss)valid_acc = sum(valid_accs) / len(valid_accs)print(f"[ Valid | {epoch + 1:03d} / {n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")# ---------- Record ----------if valid_acc > best_acc: # 在最好的准确率下保存模型用于测试best_acc = valid_acctorch.save(model.state_dict(), model_path)train_loss_record.append(train_loss)valid_loss_record.append(valid_loss)train_acc_record.append(train_acc)valid_acc_record.append(valid_acc)

3.5 训练结果可视化

import matplotlib.pyplot as plt  # 导入matplotlib.pyplot模块用于绘图x = np.arange(len(train_acc_record))  # 创建一个与训练准确率记录长度相同的序列作为横坐标plt.plot(x, train_acc_record, color="blue", label="Train")  # 以蓝色线条绘制训练准确率变化趋势,添加标签"Train"
plt.plot(x, valid_acc_record, color="red", label="Valid")   # 以红色线条绘制验证准确率变化趋势,添加标签"Valid"
plt.legend(loc="upper right")  # 显示图例,并将其放置在图的右上角
plt.show()  # 显示图像

3.6 训练结果可视化

测试阶段代码,将结果保存一个文档。

model.eval()predictions = []for batch in test_loader:imgs, labels = batchwith torch.no_grad():logits = model(imgs.to(device))predictions.extend(logits.argmax(dim=-1).cpu().numpy().tolist())with open("predict.csv", "w") as f:  # 保存预测结果f.write("Id,Category\n")for i, pred in  enumerate(predictions):f.write(f"{i},{pred}\n")

总结

本章节深入浅出地探讨了使用PyTorch框架进行深度学习模型构建与训练的全流程,旨在帮助读者系统掌握从数据预处理、模型搭建、训练策略到验证评估的每一个环节。通过食物分类任务的实例,结合半监督学习这一高级训练策略,展示了提升模型性能的可能路径。这些内容的覆盖,旨在为读者搭建一个坚实的知识框架,让大家在深度学习的过程中稳健前行,还能灵活应对各种挑战。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jmeter多用户登录并退出教程

有时候为了模拟更真实的场景,在项目中需要多用户登录并退出操作,大致参考如下 多用户登录前面已经实现:参考博文 多用户登录并退出jmx文件:百度网盘 提取码:0000 一、多用户退出操作 添加一个setUp线程组&#xff0…

Perplexity 搜索引擎刚刚推出了新的页面功能——维基百科可以扔了

Perplexity 允许用户根据搜索结果创建自定义页面 人工智能搜索引擎初创公司 Perplexity 推出了一项新功能,使其结果更具粘性,允许用户将研究转变为易于共享的页面。页面建立在 Perplexity 中现有的人工智能驱动的搜索功能之上,该功能使用与 …

云服务(ECS)Docker安装vulhub安装详解

本文以xshell进行远程控制 1.以ssh连接云服务器 ssh 服务器名公网ip [D:\~]$ ssh root47.99.138.9 在弹框中输入密码 2.安装docker curl -s http://get.docker.com/ | sh rootiZbp1fm14idjlfp53akni8Z:~# curl -s https://get.docker.com/ | sh # Executing docker insta…

万字长文,小白新手怎么开始做YOLO实验,从零开始教!整体思路在这里,科研指南针!

最近专栏来了很多的新手小白,对科研实验的过程感到困惑和无从下手,这篇文章就来讲解一下整体的科研流程,从选择数据集到发表论文的各个步骤,并针对大家在实验中常犯的错误进行解答。并且为大家提供通向我其他相关博客的指引&#…

激光焊接机作为一种高效、精密的焊接设备

激光焊接机是一种用于材料加工时激光焊接的机器,以下是对其的详细介绍: 1. 定义与别称: 激光焊接机,又常称为激光焊机、镭射焊机,是材料加工激光焊接时用的机器。 2. 工作原理: 激光焊接是利用高能量…

【计算机毕业设计】345大学生心理健康测评管理系统小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

【数据结构与算法 | 二叉树篇】二叉树的前中后序遍历(递归版本)

1. 二叉树的概念 (1). 二叉树的结构 借用了一下力扣的模板 public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left left;this.righ…

Linux下的Git应用

1、卸载 2、安装 3、创建并初始化 4、配置 (附加删除语句) 5、查看(tree .git/) 6、增加和提交 7、打印日志 8、验证已操作工作

公告:公众号铁粉粉丝介绍以及说明

大家好,我是公众号博主--夏目 机械电气电机杂谈是我个人建立,为分享机械,电气,电机知识为主,闲谈杂聊社会时事,职场见闻,生活琐事,成长趣事,学习心得,读书观影…

C#WPF数字大屏项目实战06--报警信息

1、ItemsControl 简介 ItemsControl 是用来表示一些条目集合的控件,所以它叫条目控件,它的成员是一些其它控件的集合,其继承关系如下: 其常用的派生控件为:ListBox、ListView、ComboBox,为ItemsCo…

充电宝怎么选?充电宝目前什么牌子质量好耐用?盘点好用充电宝

充电宝怎么选?是不是很多朋友在选充电宝上非常的纠结?在买充电宝上面还是非常有讲究的!市面上的充电宝虽然多,但是不排除很多存在安全隐患的,如果稍微没有挑选好充电宝的话,买来的充电宝极大可能是存在非常…

在 Kubesphere 中开启新一代云原生数仓 Databend

上周六,由 KubeSphere 社区联合 Databend 社区以及纵目科技共同组织的云原生 Meetup 北京站在北京圆满落幕。本次 Meetup 活动邀请到了 SkyWalking PMC 成员、青云科技架构及可观测性团队负责人、江苏纵目科技 APM 研发总监、青云科技容器产品经理、数元灵科技 CTO …

[线程与网络] 网络编程与通信原理(四):深入理解传输层UDP与TCP协议

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

Java——类型转换

一、类型转换 1、介绍 类型转换分为自动类型转换和强制类型转换。 2、自动类型转换 自动类型转换是指在表达式中,当两种不同的数据类型组合在一起时,较小的数据类型会自动转换为较大的数据类型,这个过程是自动的,无需编程者手…

Linux---用户及权限配置

文章目录 目录 文章目录 前言 一.基本概念 二.用户管理 创建用户 修改用户属性 用户组管理 用户授权 前言 用户在操作系统中是非常重要的,我们登录系统,访问共享文件夹等都需要用户进行验证。所以,掌握管理用户的知识非常有必要的 一.基…

笔墨挥毫如游龙 最是经典铁线篆——记著名书法家王子彬

真正的书法大家,必是经历了日积月累的求索磨炼,毕竟书法从来都不是一蹴而就的艺术,因此但凡是急功近利者,其人也是远远无法达到书入臻境的创作高度。而纵观当代书坛界内,其中王子彬先生的艺术声誉可谓是广为人知,作为一名深具传统功底的实力派书法大家,王子彬先生的取法历途无疑…

深度学习入门到放弃系列 - Jupyter Notebook添加虚拟环境

当使用conda创建完虚拟环境以后,terminal进入虚拟环境很简单,如何将虚拟环境添加到Notebook呢,这次把相关的命令记录一下。 Notebook未添加虚拟环境 添加完虚拟环境后 步骤如下: 安装ipykernel的命令如下: # 查看虚拟…

BioVendor—Surfactant Protein D Human ELISA

人表面活性剂蛋白D是糖蛋白和钙依赖凝集素胶原亚家族的一员。SP-D是一种同源三聚体蛋白,由三个43kDa单元组成,这些单元在它们的中间结合。大多数SP-D主要含有十二聚体(四个三聚体亚单位),但也观察到更高的多聚体。每个单元由至少四个离散的结…

解决:写路由文件时引入页面路径没有提示

1、首先安装插件: Path Autocomplete 2、配置settings.json 文件 复制下面代码到settings.json配置文件中: "path-autocomplete.pathMappings": {"": "${folder}/src/","views": "${folder}/src/views/&…

mysql大表的深度分页慢sql案例(跳页分页)-2

1 背景 有一张大表,内容是费用明细表,数据量约700万级, 普通B树索引KEY idx_fk_fymx_qybh_xfsj (qybh,xfsj)。 1.1 原始深度分页sql select t.* from fk_fymx t where t.qybh XXXXXXX limit 100000,100; 深度分页会导致加载数据行过多1000001…