百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

使用PyTorch实操分步指南:针对稻米进行分类

itomcoil 2024-12-28 13:34 11 浏览

在快节奏的农业世界中,能够快速准确地对不同水稻品种进行分类可能会改变游戏规则。但是,我们如何利用机器学习来完成像水稻分类这样小众的事情呢?好吧,这就是强大的深度学习库 PyTorch 发挥作用的地方。今天,我将指导您使用 PyTorch 创建卷积神经网络 (CNN),以根据图像对水稻品种进行分类。本动手教程适用于对 Python 有基本了解的任何人,我将引导您完成代码的每个步骤,以便您轻松跟上。

先决条件

在开始之前,请确保已安装必要的库。运行以下命令安装任何缺少的依赖项:

pip install torch torchvision pandas numpy seaborn matplotlib splitfolders tabulate termcolor scikit-learn

安装这些后,您就可以开始编码了!

设置数据集

我们将使用大米图像数据集来训练我们的模型。您可以在网上找到各种数据集,但为了简单起见和保持一致性,最好使用 Kaggle。如果您有 Kaggle 帐户,您可以直接将数据集导入笔记本,而无需在本地下载。

如果您在 Kaggle 笔记本中工作,只需确保将数据集直接上传到环境或使用 Kaggle 的内置数据集。对于本地用户,请下载数据集并将其解压到名为的文件夹中Rice_Image_Dataset

我将使用来自 kaggle 的数据集

www.kaggle.com 水稻图像数据集,五种不同的大米图像数据集。Arborio、Basmati、Ipsala、Jasmine、Karacadag。

代码分步解释

现在,让我们将代码分解为易于理解的部分,并看看每个部分的作用。

1. 导入库并设置随机种子

import warnings
warnings.filterwarnings('ignore')
import os    
import time
import torch 
import random 
import pathlib 
import torchvision     
import numpy as np  
import pandas as pd 
import splitfolders 
import torch.nn as nn   
import seaborn as sns   
import torch.utils.data
from tabulate import tabulate
import matplotlib.pyplot as plt  
from sklearn.metrics import confusion_matrix, classification_report
import torchvision.transforms as transforms
# Set random seeds for reproducibility
torch.manual_seed(42)
np.random.seed(42)
random.seed(42)

在这里,我们导入了数据处理、可视化和模型构建所需的所有库。我们还设置了随机种子,以确保每次运行代码时都能获得一致的结果。

2. 分割数据集

# 数据集概述
dir1 = 'Rice_Image_Dataset'
 splitfolders.ratio( input =dir1, output = 'imgs' , seed= 42 , ratio=( 0.7 , 0.15 , 0.15 )) 
dir2 = pathlib.Path( 'imgs' )

使用splitfolders,我们将数据分成训练、验证和测试集,比例为 70%、15% 和 15%。这有助于构建我们的数据集,以便有效地训练和测试我们的模型。您将看到创建了一个名为imgs 的文件夹,其中包含train、testval作为子目录。

3.定义数据转换

transform = transforms.Compose([
    transforms.Resize((250, 250)),
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

我们定义一系列变换来预处理图像。这里:

  • Resize((250, 250))将每个图像的大小调整为 250x250 像素。
  • ToTensor()将图像转换为 PyTorch 张量。
  • Normalize()缩放像素值以使模型训练更加稳定。

4.加载数据

batch_size = 32
 train_ds = torchvision.datasets.ImageFolder(os.path.join(dir2,'train' ), transform =transform) 
val_ds = torchvision.datasets.ImageFolder(os.path.join(dir2,'val'),transform=transform)
test_ds = torchvision.datasets.ImageFolder(os.path.join(dir2,'test'),transform=transform)
train_loader = torch.utils.data.DataLoader(train_ds, batch_size=batch_size, shuffle=True)
val_loader = torch.utils.data.DataLoader(val_ds, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_ds, batch_size=batch_size, shuffle=True)

我们在应用转换后加载数据集,并分批准备进行训练、验证和测试。批处理有助于提高模型训练期间的内存效率。

5. 可视化数据分布

class_counts = [0] * len(train_ds.classes)
for _, label in train_ds:
    class_counts[label] += 1
class_distribution = pd.DataFrame({
    'Class': train_ds.classes,
    'Count': class_counts
})
plt.figure(figsize=(10, 6))
sns.barplot(x='Class', y='Count', data=class_distribution)
plt.title('Class Distribution in Training Dataset')
plt.xticks(rotation=45)
plt.ylabel('Number of Images')
plt.xlabel('Classes')
plt.show()

这部分代码绘制了图像在各个类别中的分布情况,让我们可以快速检查类别平衡情况。这在分类问题中至关重要,因为它会影响模型的泛化能力。

6.定义 CNN 模型

class CNN(nn.Module):
    def __init__(self, unique_classes):
        super(CNN, self).__init__()
        self.conv_layers = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(32, 64, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(64, 128, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        self.dense_layers = nn.Sequential(
            nn.Linear(128 * 29 * 29, 128),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(128, unique_classes)
        )
    
    def forward(self, X):
        out = self.conv_layers(X)
        out = out.view(out.size(0), -1)
        out = self.dense_layers(out)
        return out

我们的 CNN 模型由用于特征提取的卷积层和用于分类的密集层组成。每个卷积层后面都有 ReLU 激活和最大池化以降低维度。最后,全连接层预测每幅图像的类别。

7.训练模型

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
num_epochs = 5

num_epochs = 5
train_losses, val_losses, train_accs, val_accs = [], [], [], []

for epoch in range(num_epochs):
    model.train()
    train_loss, n_correct_train, n_total_train = 0, 0, 0
    
    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)
        optimizer.zero_grad()
        y_pred = model(images)
        loss = criterion(y_pred, labels)
        loss.backward()
        optimizer.step()
        
        train_loss += loss.item()
        _, predicted_labels = torch.max(y_pred, 1)
        n_correct_train += (predicted_labels == labels).sum().item()
        n_total_train += labels.size(0)

    train_losses.append(train_loss / len(train_loader))
    train_accs.append(n_correct_train / n_total_train)
    
    # Validation phase
    model.eval()
    val_loss, n_correct_val, n_total_val = 0, 0, 0
    with torch.no_grad():
        for images, labels in val_loader:
            images, labels = images.to(device), labels.to(device)
            y_pred = model(images)
            loss = criterion(y_pred, labels)
            val_loss += loss.item()
            _, predicted_labels = torch.max(y_pred, 1)
            n_correct_val += (predicted_labels == labels).sum().item()
            n_total_val += labels.size(0)

    val_losses.append(val_loss / len(val_loader))
    val_accs.append(n_correct_val / n_total_val)

    # Print metrics for the current epoch
    print(f'Epoch [{epoch+1}/{num_epochs}]')
    print('-' * 50)
    print(f'Train Loss: {train_losses[-1]:.4f} | Train Accuracy: {train_accs[-1]:.4f}')
    print(f'Validation Loss: {val_losses[-1]:.4f} | Validation Accuracy: {val_accs[-1]:.4f}')
    print('-' * 50)

我们定义了训练循环来帮助模型从数据中学习并在每个时期提高其性能。

  1. 损失函数和优化器:我们首先设置nn.CrossEntropyLoss()损失函数,它非常适合多类分类任务。优化器torch.optim.Adam根据反向传播期间计算的梯度更新模型的参数,使用学习率为0.001
  2. 时期和跟踪:我们将训练时期(整个数据集上的迭代次数)的数量指定为num_epochs = 5。我们还初始化列表以跟踪训练和验证损失和准确度随时间的变化。
  3. 训练阶段:在主循环中,模型设置为train模式,这允许它调整其权重。对于每一批图像:
  • 我们用optimizer.zero_grad() 重置梯度。
  • 将图像传递给模型以获得预测(y_pred)。
  • 通过将预测与真实标签进行比较来计算损失。
  • 反向传播损失(loss.backward())并用optimizer.step()更新模型的权重。
  • 跟踪当前时期的累积训练损失和准确度。

4.验证阶段:在当前时期进行训练后,我们在验证集上评估模型(不更新权重):

  • 该模型设置为eval模式以禁用dropout和批量标准化层。
  • 我们计算每个批次的验证损失和准确度,类似于训练循环,但没有反向传播(使用torch.no_grad())。

5. 记录结果:在每个时期结束时,我们都会打印训练和验证损失和准确率,以监控模型的进度。这有助于我们了解模型是否正在改进或是否存在过度拟合的可能性。

每个时期都会让我们了解模型的学习效果,记录的结果可以帮助我们在必要时对模型进行微调。

8.评估模型性能

model.eval()
test_loss, total_correct, total_samples = 0, 0, 0
with torch.no_grad():
    for images, labels in test_loader:
        images, labels = images.to(device), labels.to(device)
        predictions = model(images)
        loss = criterion(predictions, labels)
        test_loss += loss.item()
        _, predicted_classes = torch.max(predictions, 1)
        total_correct += (predicted_classes == labels).sum().item()
        total_samples += labels.size(0)

avg_test_loss = test_loss / len(test_loader)
test_accuracy = total_correct / total_samples
print(f'Test Loss: {avg_test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}')

训练完模型后,必须评估其在测试集(由未见过的数据组成)上的表现。此步骤可让我们更好地了解模型在训练和验证数据之外的泛化能力。

以下是评估代码的细目:

  1. 将模型设置为评估模式:通过调用model.eval(),我们将模型设置为评估模式。这将停用某些层(如 dropout),确保输出一致且测试结果可靠。
  2. 初始化跟踪变量:我们将test_losstotal_correct和初始化total_samples为零。这些变量将帮助我们计算所有批次的总体测试损失和准确度。
  3. 禁用梯度计算:通过torch.no_grad(),我们禁用梯度计算,这可以减少内存使用并加快进程,因为我们在测试期间不会更新任何模型参数。
  4. 循环测试数据:针对每个批次test_loader
  • 将图像和标签移动到设备(GPU 或 CPU)。
  • 将图像传递给模型以获得预测。
  • 计算预测和真实标签之间的损失,并将其添加到test_loss
  • 用于torch.max(predictions, 1)获取预测的类别标签。
  • predicted_classes通过与真实值进行比较来计算正确的预测labels,并将结果添加到total_correct
  • 增加total_samples当前批次中的图像数量,以跟踪测试样本的总数。

5.计算平均测试损失和准确率

  • avg_test_loss是通过将累计test_loss除以批次数(len(test_loader))来计算的。
  • test_accuracy计算为total_correct预测值与total_samples的比率,给出模型在测试集上的整体准确度。

6. 打印结果:最后,我们打印测试损失和准确率,总结模型在未见数据上的表现。此指标可以帮助您判断模型是否已准备好部署或是否需要进一步调整。

9.保存模型

model_save_path = 'cnn_rice_classifier.pth'
torch.save(model.state_dict(), model_save_path)
print(f'Model saved to {model_save_path}')

最后,我们保存模型,以便可以重复使用而无需重新训练。

总结

就这样!您已成功在 PyTorch 中构建并训练了一个 CNN 模型来对水稻品种进行分类。此过程涵盖了数据预处理、构建 CNN、训练和评估模型。只需进行一些调整,您就可以调整此模型来对其他类型的图像进行分类。祝您编码愉快!

相关推荐

PS小技巧 调整命令,让人物肤色变得更加白皙 #后期修图

我们来看一下如何去将人物的皮肤变得更加的白皙。·首先选中图层,Ctrl键加J键复制一层。·打开这里的属性面板,选择快速操作删除背景,这样就会将人物进行单独的抠取。·接下来在上方去添加一个黑白调整图层,...

把人物肤色提亮的方法和技巧

PS后期调白肤色提亮照片的方法。一白遮百丑,所以对于Photoshop后期来说把人物肤色调白是一项非常重要的任务。就拿这张素材图片来说,这张素材图片人脸的肤色主要偏红、偏黄,也不够白皙,该怎样对它进行...

《Photoshop教程》把美女图片调成清爽色彩及润肤技巧

关注PS精品教程,每天不断更新~~室内人物图片一般会偏暗,人物脸部、肤色及背景会出现一些杂点。处理之前需要认真的给人物磨皮及美白,然后再整体润色。最终效果原图一、用修补工具及图章工具简单去除大一点的黑...

PS后期对皮肤进行美白的技巧

PS后期进行皮肤美白的技巧。PS后期对皮肤进行美白的技巧:·打开素材图片之后直接复制原图。·接下来直接点击上方的图像,选择应用图像命令。·在通道这里直接选择红通道,混合这里直接选择柔光,然后点击确定。...

493 [PS调色]调模特通透肤色

效果对比:效果图吧:1、光位图:2、拍摄参数:·快门:160;光圈:8;ISO:1003、步骤分解图:用曲线调整图层调出基本色调。用可选颜色调整图层调整红色、黄色、白色和灰色4种颜色的混合比例。用色彩...

先选肤色再涂面部,卡戴珊的摄影师透露:为明星拍完照后怎么修图

据英国媒体12月17日报道,真人秀明星金·卡戴珊终于承认,她把女儿小北P进了家族的圣诞贺卡,怪不得粉丝们都表示这张贺卡照得非常失败。上周,这位39岁的女星遭到了一些粉丝针对这张照片的批评,她于当地时间...

如何在PS中运用曲线复制另一张照片的色调

怎样把另一张作品的外观感觉,套用到自己的照片上?单靠肉眼来猜,可能很不容易,而来自BenSecret的教学,关键是在PS使用了两个工具,让你可以准确比较两张照片的曝光、色调与饱和度,方便你调整及复制...

PS在LAB模式下调出水嫩肤色的美女

本PS教程主要使用Photoshop使用LAB模式调出水嫩肤色的美女,教程调色比较独特。作者比较注重图片高光部分的颜色,增加质感及肤色调红润等都是在高光区域完成。尤其在Lab模式下,用高光选区调色后图...

在Photoshop图像后期处理中如何将人物皮肤处理得白皙通透

我们在人像后期处理中,需要将人物皮肤处理的白皙通透,处理方法很多,大多数都喜欢使用曲线、磨皮等进行调整,可以达到亮但是不透,最终效果往往不是很好,今天就教大家一种如何将任务皮肤处理得白皙通透,希望能帮...

PS调色自学教程:宝宝照片快速调通透,简单实用!

PS调色自学教程:宝宝照片快速调通透。·首先复制图层,然后选择进入ACR滤镜,选择曲线锁定照片的亮部,也就高光位置,其他部位补亮一点,尤其是阴影的部位补亮多一些,让画面的层次均匀一点。·然后回到基本项...

【干货】如何利用PS进行人物美化

人物图像美化在Photoshop中非常常用,Photoshop作为一款功能强大的图像处理软件,不仅可以对人像进行基本的调色、美化和修复等处理,还可以改变人物的线条和幅度,如调整脸部器官和脸型的大小、调...

教大家一种可以快速把肤色处理均匀的方法@抖音短视频

快速把肤色处理均匀的方法。今天教大家一种可以快速把肤色处理均匀的方法。像这张照片整体肤色走紫红色,但是局部偏黄缘处理起来非常的麻烦。其实我们只需要新建空白图层,图层混合模式更改为颜色,再选择画笔工具把...

PS调色教程 利用RAW调出干净通透的肤色

要么不发,要么干货。后期教程来噜~用RAW调出干净通透的肤色。这次终于不会原片比PS后好看了吧。如果你依然这么觉得,请不要残忍的告诉我这个事实,泪谢TAT)附送拍摄花絮,感谢各位的支持更多风格请关注m...

photoshop后期皮肤变白的技巧

PS后期皮肤变白的技巧。1.PS后期让皮肤变白的方法有很多种,接下来教你一种非常简单容易上手的方法。2.打开素材图片之后,直接在小太极下拉框的位置添加一个纯色调整图层,颜色设置一个纯白色,点击...

Photoshop调出人物的淡雅粉嫩肤色教程

本教程主要使用Photoshop调出人物的淡雅粉嫩肤色教程,最终的效果非常的通透迷人,下面让我们一起来学习.出自:86ps效果图:原图:1、打开原图复制一层。2、用Topaz滤镜磨皮(点此下载)。3、...