通过训练植物分类数据集 如何构建基于深度学习的植物图像分类系统
数据集描述:
47类室内植物种类图像,可用于图像分类
该植物图像数据集由 14,790 张图像组成,分为 47 个不同的植物物种类别。图像总数:14,790,品种数量: 47
每个类的图像数量差异很大,从 66 张 (Yucca) 到 547 张 (Monstera Deliciosa) 不等。
一些代表性较强的类包括中国常青树(514 张图像)、哑杖(541 张图像)和 Monstera Deliciosa(547 张图像)。
图像较少的类包括 Yucca(66 张图像)、Kalanchoe(130 张图像)和 Asparagus Fern(169 张图像)。
图像的质量和分辨率各不相同。
该数据集包括整个植物的图像和特定植物部分的特写。
植物放置在室内和室外
对于每个植物类别,图像被组织到单独的文件夹中。
非洲紫罗兰 (Saintpaulia ionantha)
芦荟
鳳梨花 (Anthurium andraeanum)
鹿角棕榈 (Dypsis lutescens)
龙须草 (Asparagus setaceus)
秋海棠 (Begonia spp
天堂鸟 (Strelitzia reginae)
鸟巢蕨 (Asplenium nidus)
波士顿蕨 (Nephrolepis exaltata)
花叶万年青 (Calathea)
铁树 (Aspidistra elatior)
钱树 (Pilea peperomioides)
中国常青藤 (Aglaonema)
圣诞仙人掌 (Schlumbergera bridgesii)
菊花
鳞片草 (Ctenanthe)
水仙 (Narcissus spp
龙血树 (Dracaena)
哑巴草 (Dieffenbachia spp
大耳朵 (Alocasia spp
英国常春藤 (Hedera helix)
风信子 (Hyacinthus orientalis)
铁十字秋海棠 (Begonia masoniana)
等
建立一个深度学习植物分类系统,47类室内植物图像数据集进行模型训练、验证和测试。下面是一个简化的流程,包括如何准备数据、定义模型、训练模型以及评估模型性能。
数据准备
首先,确保你的数据集按照类别组织在不同的文件夹中。每个文件夹代表一个特定的植物种类,并且包含属于该类的所有图片。
环境设置
安装必要的库:
pip install torch torchvision scikit-learn matplotlib tqdm
数据加载与预处理
创建一个脚本来加载和预处理数据集。这通常涉及到图像的缩放、裁剪、归一化等操作。
from torchvision import transforms, datasets
from torch.utils.data import DataLoader, random_split
# 定义图像变换
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 加载数据集
data_dir = 'path_to_your_dataset'
dataset = datasets.ImageFolder(data_dir, transform=transform)
# 划分数据集
train_size = int(0.8 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
# 创建DataLoader
batch_size = 32
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
模型定义
选择合适的深度学习模型,如ResNet、VGG等,并根据需要调整输出层以适应47个类别。
import torch.nn as nn
from torchvision import models
def create_model():
model = models.resnet18(pretrained=True)
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 47) # 修改最后的全连接层以适应47个类别
return model
训练模型
定义训练循环,包括前向传播、计算损失、反向传播以及参数更新。
import torch.optim as optim
from tqdm import tqdm
model = create_model()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
num_epochs = 25
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for inputs, labels in tqdm(train_loader):
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
print(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_dataset)}")
模型评估
在验证集上评估模型性能。
model.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in val_loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"Accuracy on validation set: {100 * correct / total}%")
为了进一步优化你的植物图像分类系统,我们可以从模型架构、超参数调整和数据增强策略几个方面进行改进。下面我将详细说明每个部分,并附上相应的代码示例。
1. 模型架构
在选择模型架构时,可以考虑使用预训练模型(如ResNet, VGG, DenseNet等),并根据任务需求进行微调。这里以ResNet50为例:
import torch.nn as nn
from torchvision import models
def create_model(arch='resnet50', num_classes=47, pretrained=True):
model = models.__dict__[arch](pretrained=pretrained)
if hasattr(model, 'fc'): # ResNet-like architectures
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, num_classes)
elif hasattr(model, 'classifier'): # VGG, DenseNet-like architectures
num_ftrs = model.classifier[-1].in_features
model.classifier[-1] = nn.Linear(num_ftrs, num_classes)
return model
2. 超参数调整
包括学习率、批量大小、训练周期数等。可以通过网格搜索或随机搜索来找到最佳超参数组合。这里提供一个简单的超参数配置:
learning_rate = 0.001
batch_size = 32
num_epochs = 50
3. 数据增强策略
通过数据增强可以增加训练样本的多样性,从而提高模型的泛化能力。以下是一个包含多种变换的数据增强策略:
from torchvision import transforms
train_transforms = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(20),
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
val_transforms = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
完整流程代码示例
结合以上内容,完整的训练流程如下:
import os
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, random_split
import torch
import torch.nn as nn
import torch.optim as optim
from tqdm import tqdm
# 数据加载与预处理
data_dir = 'path_to_your_dataset'
train_transforms = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(20),
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
val_transforms = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
dataset = datasets.ImageFolder(data_dir, transform=train_transforms)
train_size = int(0.8 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)
# 创建模型
model = create_model()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练模型
num_epochs = 50
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for inputs, labels in tqdm(train_loader):
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
print(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_dataset)}")
# 模型评估
model.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in val_loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"Accuracy on validation set: {100 * correct / total}%")
以上文字及代码仅供参考学习使用。