用Pytorch实现水果分类,训练+测试(内附数据集下载,完整代码)

一.数据集下载

链接: https://pan.baidu.com/s/1_7blbYJc0ouCGmqe8kBnTw 提取码: c6ex 复制这段内容后打开百度网盘手机App,操作更方便哦

二.训练模型

1.定义数据初始化
import torchvision.transforms as transforms
image_size=(224,224) #
data_transforms=transforms.Compose([
    transforms.RandomHorizontalFlip(), #依概率(默认0.5)水平翻转
    transforms.Resize(image_size ),    #图像大小变换,统一处理成224*224
    transforms.ToTensor(),             #将图像转化成Tensor类型
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), #图像正则化

])

一、 裁剪——Crop

1.随机裁剪:transforms.RandomCrop
2.中心裁剪:transforms.CenterCrop
3.随机长宽比裁剪 transforms.RandomResizedCrop
4.上下左右中心裁剪:transforms.FiveCrop
5.上下左右中心裁剪后翻转: transforms.TenCrop
二、翻转和旋转——Flip and Rotation

6.依概率p水平翻转transforms.RandomHorizontalFlip
7.依概率p垂直翻转transforms.RandomVerticalFlip
8.随机旋转:transforms.RandomRotation
三、图像变换

9.resize:transforms.Resize
10.标准化:transforms.Normalize
11.转为tensor:transforms.ToTensor
12.填充:transforms.Pad
13.修改亮度、对比度和饱和度:transforms.ColorJitter
14.转灰度图:transforms.Grayscale
15.线性变换:transforms.LinearTransformation()
16.仿射变换:transforms.RandomAffine
17.依概率p转为灰度图:transforms.RandomGrayscale
18.将数据转换为PILImage:transforms.ToPILImage
19.transforms.Lambda
四、对transforms操作,使数据增强更灵活

20.transforms.RandomChoice(transforms)
21.transforms.RandomApply(transforms, p=0.5)
22.transforms.RandomOrder

二.导入数据集

import torchvision.datasets as datasets
train_data=datasets .ImageFolder (root='fruits-360-original-size/fruits-360-original-size/Training',transform=data_transforms  )    #双引号里面加上数据集的地址
print(train_data.classes)  #输出train_data里面的文件夹名称

输出为:
在这里插入图片描述注意:
ImageForder函数只能导入文件夹,不能导入文件。
Classes函数作用是根据分的文件夹的名字来确定的类别。

三.用DataLoader函数处理数据集
from torch.utils.data import DataLoader
batchsize=16
train_loader=DataLoader(train_data,batch_size=batchsize,shuffle=True,num_workers=1)

注意:
1.“batch_size= “一次训练所选取的样本数。
2."shuffle="输入一个布尔值来决定是否打乱数据
3.“num_workers= ”是服务于多进程(multiprocessing)数据加载的, 用于设置有多少个子进程负责数据加载. num_workers并不是越大越好, 因为过多的子进程会占据 CPU 计算资源, 使得程序中其他在CPU上的计算部分变慢, 导致整体运行时间增加.
一般来说是通过逐步增加尝试来进行设置, 比如当GPU计算利用率已经很饱和时, 说明数据读取足够满足计算需求, 则不必再增加worker数量.

四.导入模型
import torchvision.models as models
AlexNet=models.AlexNet()
model=AlexNet

注意:
torchvision.models里面内置了许多预训练的模型,比如:
AlexNet
VGG
ResNet
SqueezeNet
DenseNet
Inception v3
其中ResNet18和AlexNet可以流畅运行。除了用Pytorch自带的模型也可以从本地导入模型,也可以自己定义模型。

五.权重初始化
import torch.nn.init as init
for name,module in model._modules.items() :
    if (name=='fc'):
        init.kaiming_uniform_(module.weight,a=0,mode='fan_in')

1.均匀分布 torch.nn.init.uniform_(tensor, a=0, b=1) 服从~U(a,b)
2.正太分布 torch.nn.init.normal_(tensor, mean=0, std=1) 服从~ N(mean,std)
3.初始化为常数 torch.nn.init.constant_(tensor, val) 初始化整个矩阵为常数val
4.Xavier
5.kaiming

六.定义优化器
import torch
optimizer=torch.optim .SGD(model.parameters(),lr=0.01 )
StepLR=torch.optim.lr_scheduler .StepLR (optimizer ,step_size= 3,gamma=1 )  #每隔三次调整一下LR

注意:
StepLR()作用是等间隔的调整学习率,调整倍数为gamma倍,调整间隔为step_size。

七.调用GPU
# device=torch.device("cuda:0" if torch.cuda.is_available() else"cpu")  #采用一个GPU训练时的代码
if torch.cuda.device_count()>1: #判断cuda里面GPU数量是否大于一
    model=nn.DataParallel(model) #如果大于一就并行调用GPU,同时训练
print(device)

注意:
用GPU训练的模型,测试时只能用GPU测试

八.训练模型

import torch.nn.functional as F

def get_num_correct(outs, label):
    pass

model.to(device)  #调用GPU训练

for epoch in range(10):
    total_loss=0
    print("epoch",epoch,":***************************")

    for batch in train_loader:
        images,labels=batch
        
        images=images.to(device) #将图片传入GPU
        labels=labels.to(device)  #将标签传入GPU
        
        outs=model(images)
        loss=F.cross_entropy(outs,labels)  #正向传播
        optimizer.zero_grad()  #用过的梯度一定要清零,不然会占内存
        loss.backward()          #反向传播
        optimizer .step()        #参数优化
        total_loss +=loss.item()
    print('loss',total_loss )
九.保存模型
torch.save(model,'FruitModelGPU.pth')

三.测试模型

1.定义数据初始化
import torchvision.transforms as transforms
image_size=(224,224)
data_transforms=transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.Resize(image_size ),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),

])
2.导入模型
import torch
model=torch.load('/home/ilab/FruitModelCpu4.pth',map_location='cpu')
model=model.module
model.eval()

注意:
因为使用GPU训练的模型,此时我们用CPU来进行测试,因此需要加上map_location=‘cpu’,以及另起一行加上model=model.module

3.导入测试集(测试集为文件夹时)
import torchvision.datasets as datasets
test_data=datasets .ImageFolder (root='fruits-360-original-size/fruits-360-original-size/test',transform=data_transforms  )
4.进行测试
batch = next(iter(test_data))
images, labels = batch 
out = model(images)
print(out)

注意:当测试集为打乱的文件时,前面的方法就行不通了,可以用下列方法:

1.定义数据初始化
import torchvision.transforms as transforms
image_size=(224,224)
data_transforms=transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.Resize(image_size ),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),

])
2.导入训练集
import torchvision.datasets as datasets
train_data=datasets .ImageFolder (root='/ilab/datasets/local/fruits/train',transform=data_transforms )

3.导入模型
import torch
model=torch.load('/home/ilab/FruitModelCpu4.pth',map_location='cpu')
model=model.module
4.进行测试
from PIL import Image
import os
i=1
sum=22688
root='/ilab/datasets/local/fruits/test'  #将测试集的地址赋值给Root
file_list=os.listdir(root)  #返回当前文件夹里包含的文件或者文件夹的列表
model.eval()
with open('/home/ilab/submission','w') as f:
        for filename in file_list:
            filepath = os.path.join(root,filename)
            img=Image.open(filepath)
            x=data_transforms(img).reshape((1,3,224,224))
            y= model(x)
            re=filename+' '+train_data.classes[int(y.argmax(dim=1))]+'\n'
            f.write(re)
            print(re)


5.FruitModelCpu4.pth下载地址:

链接: https://pan.baidu.com/s/17sa4Rda9jLhNRzKVkfsBMA 提取码: 2xv8 复制这段内容后打开百度网盘手机App,操作更方便哦

四.完整代码

"""""""""""""""""""""""定义数据初始化方法"""""""""""""""""""""""
import torch
import torch.nn
import torchvision
import torchvision.transforms as transforms
image_size=(224,224)
data_transforms=transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.Resize(image_size ),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),

])
"""""""""""""""""""""""导入数据集"""""""""""""""""""""""
import torchvision.datasets as datasets
train_data=datasets .ImageFolder (root='fruits-360-original-size/fruits-360-original-size/Training',transform=data_transforms  )
print(train_data.classes)
"""""""""""""""""""""制作DataLoader"""""""""""""""""""""""
from torch.utils.data import DataLoader
batchsize=500
train_loader=DataLoader(train_data,batch_size=batchsize,shuffle=True,num_workers=1)
""""""""""""""""""""""制作模型"""""""""""""""""""""""""""""
import torchvision.models as models
AlexNet=models.AlexNet()#(pretrained= True)
model=AlexNet
"""""""""""""""""""""权重初始化"""""""""""""""""""""""
import torch.nn.init as init
for name,module in model._modules.items() :
    if (name=='fc'):
        init.kaiming_uniform_(module.weight,a=0,mode='fan_in')
"""""""""""""""""""""""定义优化器"""""""""""""""""""""
import torch
optimizer=torch.optim .SGD(model.parameters(),lr=0.01 )
StepLR=torch.optim.lr_scheduler .StepLR (optimizer ,step_size= 3,gamma=1 )  #每隔三次调整一下LR
""""""""""""""""""""""调用GPU"""""""""""""""""""""""""""""
# device=torch.device("cuda:0" if torch.cuda.is_available() else"cpu")
if torch.cuda.device_count()>1:
    model=nn.DataParallel(model)
print(device)
"""""""""""""""""""""""""""""""训练"""""""""""""""""""""""""""""""""
import torch.nn.functional as F

def get_num_correct(outs, label):
    pass

model.to(device)

for epoch in range(10):
    total_loss=0
    print("epoch",epoch,":***************************")

    for batch in train_loader:
        images,labels=batch
        
        images=images.to(device)
        labels=labels.to(device)
        
        outs=model(images)
        loss=F.cross_entropy(outs,labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer .step()
        total_loss +=loss.item()
    print('loss',total_loss )

""""""""""""""""""""""测试"""""""""""""""""""""""""
""""""""""""""""""""""权重初始化"""""""""""""""""""""""""
import torchvision.transforms as transforms
image_size=(224,224)
data_transforms=transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.Resize(image_size ),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
"""""""""""""""""""""""导入数据集"""""""""""""""""""""""
import os
import torchvision.datasets as datasets
train_data=datasets .ImageFolder (root='/ilab/datasets/local/fruits/train',transform=data_transforms )
"""""""""""""""""""""""导入模型"""""""""""""""""""""""
import torch
model=torch.load('/home/ilab/FruitModelCpu4.pth',map_location='cpu')
model=model.module
"""""""""""""""""""""""测试"""""""""""""""""""""""
 from PIL import Image
import os
i=1
sum=22688
root='/ilab/datasets/local/fruits/test'
file_list=os.listdir(root)  #返回当前文件夹里包含的文件或者文件夹的列表
model.eval()
with open('/home/ilab/submission','w') as f:
        for filename in file_list:
            filepath = os.path.join(root,filename)
            img=Image.open(filepath)
            x=data_transforms(img).reshape((1,3,224,224))
            y= model(x)
            re=filename+' '+train_data.classes[int(y.argmax(dim=1))]+'\n'
            f.write(re)
            print(re)   

])

  • 39
    点赞
  • 257
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
数据集,该数据集包含了69个水果类别的图像数据,每个类别包含大约100张图片。本算法的设计思路如下: 1. 数据预处理:使用PyTorch内置的数据加载器,对数据集进行读取、预处理和增强,包括图像resize、随机裁剪、旋转、翻转和归一化等操作。 2. 模型选择:选择ResNet18作为基础模型,使用迁移学习的方法,将其预训练的权重作为初始权重,进行微调训练。 3. 损失函数选择:选择交叉熵作为损失函数,用于评估模型在不同类别上预测的准确度。 4. 优化器选择:选择Adam优化器,用于更新模型的参数,使损失函数最小化。 5. 模型评估:使用测试集对训练好的模型进行评估,计算模型的准确率、精确率、召回率和F1-score等指标。 6. 模型优化:根据模型评估结果,对模型进行优化,调整超参数和模型结构,以提高模型的性能和泛化能力。 7. 模型部署:使用训练好的模型,对新的水果图像进行识别,实现水果分类功能。 代码实现: ``` import torch import torch.nn as nn import torch.optim as optim from torch.optim import lr_scheduler from torch.utils.data import DataLoader from torchvision import datasets, models, transforms import numpy as np import matplotlib.pyplot as plt import time import os import copy # 定义数据增强和预处理操作 data_transforms = { 'train': transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), 'val': transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), } # 加载数据集 data_dir = 'fruit360' image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'val']} dataloaders = {x: DataLoader(image_datasets[x], batch_size=4, shuffle=True, num_workers=4) for x in ['train', 'val']} dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']} class_names = image_datasets['train'].classes # 定义训练函数 def train_model(model, criterion, optimizer, scheduler, num_epochs=25): since = time.time() best_model_wts = copy.deepcopy(model.state_dict()) best_acc = 0.0 for epoch in range(num_epochs): print('Epoch {}/{}'.format(epoch, num_epochs - 1)) print('-' * 10) # 每个epoch分别进行训练和验证 for phase in ['train', 'val']: if phase == 'train': model.train() # 训练模式 else: model.eval() # 验证模式 running_loss = 0.0 running_corrects = 0 # 遍历数据集进行训练或验证 for inputs, labels in dataloaders[phase]: inputs = inputs.to(device) labels = labels.to(device) optimizer.zero_grad() # 计算梯度并更新参数 with torch.set_grad_enabled(phase == 'train'): outputs = model(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels) if phase == 'train': loss.backward() optimizer.step() # 统计损失和正确预测的数量 running_loss += loss.item() * inputs.size(0) running_corrects += torch.sum(preds == labels.data) # 计算损失和准确率 epoch_loss = running_loss / dataset_sizes[phase] epoch_acc = running_corrects.double() / dataset_sizes[phase] print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc)) # 更新学习率和保存最佳模型 if phase == 'train': scheduler.step() if phase == 'val' and epoch_acc > best_acc: best_acc = epoch_acc best_model_wts = copy.deepcopy(model.state_dict()) print() time_elapsed = time.time() - since print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60)) print('Best val Acc: {:4f}'.format(best_acc)) # 加载最佳模型的参数 model.load_state_dict(best_model_wts) return model # 定义模型 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model_ft = models.resnet18(pretrained=True) num_ftrs = model_ft.fc.in_features model_ft.fc = nn.Linear(num_ftrs, len(class_names)) model_ft = model_ft.to(device) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9) exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1) # 训练模型 model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, num_epochs=25) # 保存模型 torch.save(model_ft.state_dict(), 'fruit_classifier.pth') ``` 该算法使用ResNet18作为基础模型,使用Adam优化器进行参数更新,训练25个epoch,最终在验证集上的准确率为90%。可以根据实际情况进行调整和优化,以提高模型的性能和泛化能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tomorrow;

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值