Coggle 30 Days of ML 打卡任务二:苹果病害数据加载与数据增强

简介: Coggle 30 Days of ML 打卡任务二:苹果病害数据加载与数据增强

任务二:苹果病害数据加载与数据增强

  • 难度/分值:中/2

打卡内容:

  1. 参赛选手名称:AppleDoctor
  2. 完成日期:2023.6.9
  3. 任务完成情况
  • 使用的编程语言:Python,Pytorch
  • 实现的功能:
  • 使用OpenCV或者PIL加载数据集
  • 使用torchvision或者OpenCV实现图像分类任务的数据增强

背景介绍

本次打卡任务是 Coggle 30 Days of ML 中的第二项任务,要求完成苹果病害数据加载与数据增强。数据加载阶段,参赛选手需要编写代码来读取和处理提供的图像数据。数据增强阶段,选手可以使用各种图像处理技术和方法,如旋转、缩放、翻转、亮度调整等,来增强数据集的多样性和数量。

image.png

数据集准备

首先报名并下载数据集,以下是实践比赛地址:

  • 赛题1:苹果病害图像识别
  • 赛题2:建筑物变化检测

自定义数据集

首先,使用PyTorch作为示例,需要自定义数据集。为此,我定义了一个名为AppleDataset的类。

# 定义Apple数据集的类
class AppleDataset(Dataset):
    def __init__(self, img_path, transform=None):
        """
        构造函数,初始化数据集的路径和数据增强操作
        Args:
            - img_path: list类型,存储数据集中图像的路径
            - transform: torchvision.transforms类型,数据增强操作
        """
        self.img_path = img_path
        self.transform = transform
    def __getitem__(self, index):
        """
        获取一个样本
        Args:
            - index: 数据集中的索引
        Returns:
            - img: Tensor类型,经过处理后的图像
            - label: Tensor类型,标签
        """
        img = Image.open(self.img_path[index])
        if self.transform is not None:
            img = self.transform(img)
        # 将类别名转换为数字标签
        class_name = self.img_path[index].split('/')[-2]
        if class_name in ['d1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9']:
            label = ['d1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9'].index(class_name)
        else:
            label = -1
        return img, torch.from_numpy(np.array(label))
    def __len__(self):
        """
        获取数据集的大小
        Returns:
            - size: int类型,数据集的大小
        """
        return len(self.img_path)

然后,我们可以使用这个自定义数据集类来加载数据。

np.random.shuffle(train_path)
train_data = AppleDataset(train_path,)
valid_data = AppleDataset(val_path,)
print("类别: {}".format(classes_name))
print("训练集: {}".format(len(train_data)))

可以看到,训练集大约有1万张图片,这个信息在第一次打卡中已经提到过。

类别: ['d1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9']
训练集: 10211

数据增强及可视化

接下来,让我们进行数据增强和可视化。

import matplotlib.pyplot as plt
import torchvision.transforms.functional as TF
# 定义一系列的图像增强操作
transformations = [
    transforms.Resize((224, 224)), # 将图像大小调整为224*224
    transforms.RandomHorizontalFlip(), # 以0.5的概率对图像进行水平翻转
    transforms.RandomVerticalFlip(), # 以0.5的概率对图像进行垂直翻转
    transforms.GaussianBlur(kernel_size=3), # 对图像进行高斯模糊,卷积核大小为3
    transforms.ColorJitter(brightness=0.9), # 调整图像的亮度,亮度因子的范围为[0.1, 1.9]
    transforms.ColorJitter(contrast=0.9), # 调整图像的对比度,对比度因子的范围为[0.1, 1.9]
    transforms.ColorJitter(saturation=0.9), # 调整图像的饱和度,饱和度因子的范围为[0.1, 1.9]
]
# 定义每个转换操作的标题
transformations_title = ['Resize', 
                         'RandomHorizontalFlip', 
                         'RandomVerticalFlip', 
                         'RandomGaussianBlur', 
                         'ColorJitter(brightness)', 
                         'ColorJitter(contrast)', 
                         'ColorJitter(saturation)',
                        ]
num_images = 5
# 可视化训练集的图像转换结果
fig, axes = plt.subplots(nrows=1, ncols=num_images, figsize=(12, 2))
# 显示原始图像
for i in range(num_images):
    img, label = train_data[i]
    ax = axes[i]
    ax.imshow(img)
    ax.set_title(f"Original d{label+1}")
    ax.axis('off')
plt.show()
# 显示每个转换操作的结果
for i, transform in enumerate(transformations):
    # 可视化训练集的图像转换结果
    fig, axes = plt.subplots(nrows=1, ncols=num_images, figsize=(12, 2))
    for j in range(num_images):
        img, label = train_data[j]
        ax = axes[j]
        transformed_img = transform(img)
        ax.imshow(transformed_img)
        ax.set_title(f"{transformations_title[i]}")
        ax.axis('off')
    plt.tight_layout()
    plt.show()

通过上述代码,我们定义了一系列的数据增强操作,并进行了可视化。可以看到,在不同的数据增强操作下,图像发生了变化。

在代码中,我们使用了以下数据增强操作:

调整图像大小:使用 transforms.Resize((224, 224)) 将图像大小调整为 224x224 像素。

随机水平翻转:使用 transforms.RandomHorizontalFlip() 以 0.5 的概率对图像进行水平翻转。

随机垂直翻转:使用 transforms.RandomVerticalFlip() 以 0.5 的概率对图像进行垂直翻转。

高斯模糊:使用 transforms.GaussianBlur(kernel_size=3) 对图像进行高斯模糊,卷积核大小为 3。

调整亮度:使用 transforms.ColorJitter(brightness=0.9) 调整图像的亮度,亮度因子的范围为 [0.1, 1.9]。

调整对比度:使用 transforms.ColorJitter(contrast=0.9) 调整图像的对比度,对比度因子的范围为 [0.1, 1.9]。

调整饱和度:使用 transforms.ColorJitter(saturation=0.9) 调整图像的饱和度,饱和度因子的范围为 [0.1, 1.9]。

以上操作使得图像在进行数据增强时产生了多样的变化效果。

数据加载+数据增强

下面是将数据增强操作应用于数据集的代码:

# 定义图像预处理的参数
image_mean = [0.4940, 0.4187, 0.3855]
image_std = [0.2048, 0.1941, 0.1932]
# 定义训练集的数据增强操作
transform_train = transforms.Compose([
    transforms.Resize((224,224)), # 将图像大小调整为224*224
    transforms.RandomHorizontalFlip(), # 以0.5的概率对图像进行水平翻转
    transforms.RandomVerticalFlip(), # 以0.5的概率对图像进行垂直翻转
    transforms.RandomApply([transforms.GaussianBlur(kernel_size=3)], p=0.1), # 以0.1的概率对图像进行高斯模糊,卷积核大小为3
    transforms.RandomApply([transforms.ColorJitter(brightness=0.9)],p=0.5), # 以0.5的概率调整图像的亮度,亮度因子的范围为[0.1, 1.9]
    transforms.RandomApply([transforms.ColorJitter(contrast=0.9)],p=0.5), # 以0.5的概率调整图像的对比度,对比度因子的范围为[0.1, 1.9]
    transforms.RandomApply([transforms.ColorJitter(saturation=0.9),],p=0.5), # 以0.5的概率调整图像的饱和度,饱和度因子的范围为[0.1, 1.9]
    transforms.ToTensor(), # 将图像转换成张量
    transforms.Normalize(image_mean, image_std), # 对图像进行标准化处理
])
# 定义验证集的数据预处理操作
transform_valid = transforms.Compose([
    transforms.Resize((224,224)), # 将图像大小调整为224*224
    transforms.ToTensor(), # 将图像转换成张量
    transforms.Normalize(image_mean, image_std), # 对图像进行标准化处理
])

在上述代码中,我们定义了训练集和验证集的数据增强操作。transform_train 是训练集的数据增强操作,其中包括图像大小调整、水平翻转、垂直翻转、高斯模糊、亮度调整、对比度调整和饱和度调整等操作。transform_valid 是验证集的数据预处理操作,其中包括图像大小调整。

接下来,我们可以可视化经过数据增强操作后的图像。

# 可视化训练集
fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(10, 4))
for i in range(10):
    img, label = train_data[i]
    ax = axes[i // 5, i % 5]
    ax.imshow(img.permute(1, 2, 0))
    ax.set_title(classes_name[label.item()])
    ax.axis('off')
plt.tight_layout()
plt.show()

以上代码会显示经过数据增强后的训练集图像,但是我进行标准化,所以会看的非常奇怪

为了查看进行了哪些操作,我们可以进行反标准化操作:

def denormalize(img, mean, std):
    mean = torch.tensor(mean).reshape(3, 1, 1)
    std = torch.tensor(std).reshape(3, 1, 1)
    return img * std + mean
# 可视化训练集
fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(10, 4))
for i in range(10):
    img, label = train_data[i]
    ax = axes[i // 5, i % 5]
    ax.imshow( denormalize(img, image_mean, image_std).permute(1, 2, 0))
    ax.set_title(classes_name[label.item()])
    ax.axis('off')
plt.tight_layout()
plt.show()

以上代码会显示经过反标准化操作后的训练集图像,以查看进行了哪些数据增强操作。

Mixup数据增强

接下来我们实现了Mixup数据增强方法。

首先,我们定义了一个Mixup类,它接受alpha和beta作为参数,这些参数用于定义Beta分布。Mixup类有一个__call__方法,用于执行Mixup操作。给定图像数据x和标签y,该方法将返回混合后的图像mixed_image、两个标签y1和y2以及混合系数lambd。

# 定义Mixup类
class Mixup:
    def __init__(self, alpha=1.5, beta=1.5):
        """
        构造函数,初始化Mixup的参数
        Args:
        - alpha: float类型,beta分布的参数alpha
        - beta: float类型,beta分布的参数beta
        Returns:
        - None
        """
        self.alpha = alpha
        self.beta = beta
    def __call__(self, x, y):
        """
        实现Mixup的操作
        Args:
        - x: Tensor类型,图像数据
        - y: Tensor类型,标签
        Returns:
        - mixed_image: Tensor类型,混合后的图像数据
        - y1: Tensor类型,标签1
        - y2: Tensor类型,标签2
        - lambd: Tensor类型,混合系数
        """
        image, label = x, y
        batch_size = image.size(0)
        # 生成混合系数
        lambd = torch.Tensor([random.betavariate(self.alpha, self.beta)]).to(image.device)
        # 生成随机索引
        index = torch.randperm(batch_size).to(image.device)
        # 进行Mixup操作
        mixed_image = lambd * image + (1 - lambd) * image[index, :]
        # 生成对应的标签
        y1, y2 = label, label[index]
        return mixed_image, y1, y2, lambd
# 初始化Mixup的参数
mixup = Mixup(alpha=1.5, beta=1.5)

接下来,我们从训练集中获取一个batch的数据,并应用Mixup数据增强。

# 使用PyTorch的DataLoader加载训练集数据
train_loader = torch.utils.data.DataLoader(
        train_data, batch_size=8, shuffle=True, num_workers=0, pin_memory = True)
# 获取一个batch的数据
images, labels = next(iter(train_loader))
# 进行数据混合
mixed_image, y1, y2, lambd = mixup(images,labels)


然后,我们对混合后的图像进行反标准化,并可视化结果。你可以观察到图像实际上是两张图像的混合。

# 反标准化混合图像
denorm_mixed_images = denormalize(mixed_image, image_mean, image_std)
# 创建图像网格
num_images = len(denorm_mixed_images)
fig, axes = plt.subplots(nrows=2, ncols=num_images//2, figsize=(12, 6))
# 显示混合图像
for i, ax in enumerate(axes.flatten()):
    mixed_img = TF.to_pil_image(denorm_mixed_images[i])
    ax.imshow(mixed_img)
    ax.set_title(f"Mixed Image {i+1}")
    ax.axis('off')
plt.tight_layout()
plt.show()

最后,需要注意的是,经过Mixup数据增强后,损失函数也需要进行相应的调整。以下是一个模板示例,展示了如何在训练批次中应用Mixup。

# 在每个训练批次中应用Mixup
inputs, labels = data  # 获取训练数据及其标签
inputs, labels_a, labels_b, lam = mixup(inputs, labels)
# 将数据和标签输入模型进行训练
outputs = model(inputs)
loss = lam * criterion(outputs, labels_a) + (1 - lam) * criterion(outputs, labels_b)
optimizer.zero_grad()
loss.backward()
optimizer.step()


在上述代码中,inputs 是训练数据,labels 是对应的标签。通过调用 mixup 函数,我们将输入数据进行Mixup操作,生成混合的输入数据 mixed_inputs,同时生成对应的标签 labels_a 和 labels_b。在训练过程中,我们使用混合数据 mixed_inputs 和相应的标签进行模型训练,并计算损失函数。注意,损失函数使用了Mixup系数 lam 进行加权计算。通过这种方式,你可以在训练过程中应用Mixup数据增强,并调整损失函数以适应混合图像的训练。

Mixup数据增强的核心思想是将两个样本按照一定的比例进行线性插值,生成一个新的样本,并将对应的标签也按照相同的比例进行插值。这种数据增强方法可以提升模型的鲁棒性和泛化能力,并且有助于防止过拟合。


相关文章
|
1月前
|
机器学习/深度学习 人工智能 算法
基于YOLOV8的口罩佩戴实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
本文介绍了基于YOLOv8算法的口罩佩戴实时检测系统,该系统通过7959张训练图片训练出有效识别模型,开发了带GUI界面的系统,支持图片、视频和摄像头实时检测口罩佩戴情况,提高疫情防控效率。
49 3
基于YOLOV8的口罩佩戴实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
1月前
|
机器学习/深度学习 人工智能 算法
基于YOLOv8的钢铁缺陷实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
基于YOLOv8的钢铁缺陷实时检测系统,通过1800张图片训练,开发了带GUI界面的检测系统,支持图片、视频和摄像头实时检测,提高生产效率和产品质量。系统基于Python和Pyside6开发,具备模型权重导入、检测置信度调节等功能。项目代码、数据集可通过特定链接获取。
58 1
基于YOLOv8的钢铁缺陷实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
1月前
|
机器学习/深度学习 人工智能 算法
基于YOLOv8的工业安全帽实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
基于YOLOv8的工业安全帽实时检测系统,通过7581张图片训练,实现工作场所安全帽佩戴检测,降低工伤事故。系统支持图片、视频和摄像头实时检测,具备GUI界面,易于操作。使用Python和Pyside6开发,提供模型训练、评估和推理功能。
73 1
基于YOLOv8的工业安全帽实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
1月前
|
机器学习/深度学习 人工智能 算法
基于YOLOv8的人员抽烟实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
基于YOLOv8的人员抽烟实时检测系统,旨在通过2472张图片训练出有效模型,维护无烟环境,预防火灾,保护公众健康。系统支持图片、视频和摄像头检测,具备GUI界面,易于操作。使用Python和Pyside6开发,具备模型权重导入、检测置信度调节等功能。
51 1
基于YOLOv8的人员抽烟实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
1月前
|
机器学习/深度学习 人工智能 算法
基于YOLOV10的反光衣头盔佩戴实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
基于YOLOv10的反光衣头盔佩戴实时检测系统,使用4409张工业场景图片训练,能检测未穿反光衣、穿反光衣、未佩戴头盔、佩戴头盔四种情况,确保工人安全。系统支持更换背景标题、模型选择、图片视频检测等功能,基于Python和Pyside6开发。
68 1
基于YOLOV10的反光衣头盔佩戴实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
1月前
|
机器学习/深度学习 人工智能 算法
基于YOLOv8的人员跌倒实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
本文介绍了基于YOLOv8算法的人员跌倒实时检测系统,通过4978张图片训练出有效模型,并开发了带GUI界面的系统,支持图片、视频和摄像头实时检测,具备更换背景、标题,调节检测置信度等功能。
43 0
基于YOLOv8的人员跌倒实时检测系统【训练和系统源码+Pyside6+数据集+包运行】
|
3月前
|
人工智能 安全 机器人
LLM对齐数据全自动合成!UW华人博士生提出Magpie方法,Macbook Air即可运行
【8月更文挑战第11天】在AI领域,大型语言模型(LLM)的行为对齐一直是个挑战。华盛顿大学研究人员提出名为Magpie的新方法,能自动高效生成高质量指令数据,减少人工干预,提升LLM的对齐效果。通过输入模板,Magpie利用已对齐LLM生成能力自动生成指令数据,仅需少量GPU资源即可创建大规模数据集。实验显示,使用Magpie数据集微调的模型性能媲美传统监督方法。尽管如此,Magpie仍需进一步优化以生成特定领域指令并确保数据安全性。[论文](https://arxiv.org/abs/2406.08464)
164 60
|
6月前
|
机器学习/深度学习 编解码 人工智能
SAM-Med | 英伟达基于SAM提出医学图像标注效率神器
SAM-Med | 英伟达基于SAM提出医学图像标注效率神器
336 0
|
6月前
|
机器学习/深度学习 PyTorch 算法框架/工具
Coggle 30 Days of ML 打卡任务三:苹果病害模型训练与预测
Coggle 30 Days of ML 打卡任务三:苹果病害模型训练与预测
|
6月前
|
机器学习/深度学习 自然语言处理 算法
Coggle 30 Days of ML(23年7月)任务三:使用TFIDF提取文本特征
Coggle 30 Days of ML(23年7月)任务三:使用TFIDF提取文本特征