【图像分类】实战——使用DenseNet实现识别秃头(pytorch)(1)

导入项目使用的库

========

import torch.optim as optim

import torch

import torch.nn as nn

import torch.nn.parallel

import torch.utils.data

import torch.utils.data.distributed

import torchvision.transforms as transforms

import torchvision.datasets as datasets

from torch.autograd import Variable

from torchvision.models import densenet121

设置全局参数

======

设置BatchSize、学习率和epochs,判断是否有cuda环境,如果没有设置为cpu

设置全局参数

modellr = 1e-4

BATCH_SIZE = 32

EPOCHS = 5

DEVICE = torch.device(‘cuda’ if torch.cuda.is_available() else ‘cpu’)

图像预处理

=====

在做图像与处理时,train数据集的transform和验证集的transform分开做,train的图像处理出了resize和归一化之外,还可以设置图像的增强,比如旋转、随机擦除等一系列的操作,验证集则不需要做图像增强,另外不要盲目的做增强,不合理的增强手段很可能会带来负作用,甚至出现Loss不收敛的情况。

数据预处理

transform = transforms.Compose([

transforms.Resize((224, 224)),

transforms.ToTensor(),

transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])

])

transform_test = transforms.Compose([

transforms.Resize((224, 224)),

transforms.ToTensor(),

transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])

])

读取数据

=====

这个数据集,作者已经做过调整,可以直接使用Python的默认方式读取数据。数据的目录如下图:

训练集中有1.6万张图片,其中有3千多个是秃头,验证集有2万多张,其中秃头是470张,数量差别太大我随机删了一部分。然后,写读取数据的代码。

dataset_train = datasets.ImageFolder(‘Dataset/Train’, transform)

dataset_test = datasets.ImageFolder(‘Dataset/Validation’,transform_test)

读取数据

print(dataset_train.imgs)

导入数据

train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=False)

设置模型

====

使用交叉熵作为loss,模型采用densenet121,建议使用预训练模型,我在调试的过程中,使用预训练模型可以快速得到收敛好的模型,使用预训练模型将pretrained设置为True即可。更改最后一层的全连接,将类别设置为2,然后将模型放到DEVICE。优化器选用Adam。

实例化模型并且移动到GPU

criterion = nn.CrossEntropyLoss()

model_ft = densenet121(pretrained=True)

num_ftrs = model_ft.classifier.in_features

model_ft.classifier = nn.Linear(num_ftrs, 2)

model_ft.to(DEVICE)

选择简单暴力的Adam优化器,学习率调低

optimizer = optim.Adam(model_ft.parameters(), lr=modellr)

def adjust_learning_rate(optimizer, epoch):

“”“Sets the learning rate to the initial LR decayed by 10 every 30 epochs”“”

modellrnew = modellr * (0.1 ** (epoch // 50))

print(“lr:”, modellrnew)

for param_group in optimizer.param_groups:

param_group[‘lr’] = modellrnew

设置训练和验证

=======

最外层是循环的是每个epochs,先训练,后验证。下面分别讲一下训练和验证的过程。

训练过程必须经历的步骤:

第一步:将输入input向前传播,进行运算后得到输出output,代码:output = model(data)

第二步:将output再输入loss函数,计算loss值(是个标量),代码:  loss = criterion(output, target)

第三步:将梯度反向传播到每个参数,代码:  loss.backward()

第四步:将参数的grad值初始化为0,代码: optimizer.zero_grad()

第五步:更新权重,代码: optimizer.step()

验证过程和训练过程基本相似。

定义训练过程

def train(model, device, train_loader, optimizer, epoch):

model.train()

sum_loss = 0

total_num = len(train_loader.dataset)

print(total_num, len(train_loader))

for batch_idx, (data, target) in enumerate(train_loader):

data, target = Variable(data).to(device), Variable(target).to(device)

output = model(data)

loss = criterion(output, target)

optimizer.zero_grad()

loss.backward()

optimizer.step()

print_loss = loss.data.item()

sum_loss += print_loss

if (batch_idx + 1) % 50 == 0:

print(‘Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}’.format(

epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),

    • (batch_idx + 1) / len(train_loader), loss.item()))

ave_loss = sum_loss / len(train_loader)

print(‘epoch:{},loss:{}’.format(epoch, ave_loss))

验证过程

def val(model, device, test_loader):

model.eval()

test_loss = 0

correct = 0

total_num = len(test_loader.dataset)

print(total_num, len(test_loader))

with torch.no_grad():

for data, target in test_loader:

data, target = Variable(data).to(device), Variable(target).to(device)

output = model(data)

loss = criterion(output, target)

_, pred = torch.max(output.data, 1)

correct += torch.sum(pred == target)

print_loss = loss.data.item()

test_loss += print_loss

correct = correct.data.item()

acc = correct / total_num

avgloss = test_loss / len(test_loader)

print(‘\nVal set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n’.format(

avgloss, correct, len(test_loader.dataset), 100 * acc))

训练

for epoch in range(1, EPOCHS + 1):

adjust_learning_rate(optimizer, epoch)

train(model_ft, DEVICE, train_loader, optimizer, epoch)

val(model_ft, DEVICE, test_loader)

torch.save(model_ft, ‘model.pth’)

完成后就可以run了,运行结果如下:

测试

==

测试集存放的目录如下图:

第一步 定义类别,这个类别的顺序和训练时的类别顺序对应,一定不要改变顺序!!!!我们在训练时,Bald类别是0,NoBald类别是1,所以我定义classes为(‘Bald’,‘NoBald’)。

第二步 定义transforms,transforms和验证集的transforms一样即可,别做数据增强。

第三步 加载model,并将模型放在DEVICE里,

第四步 读取图片并预测图片的类别,在这里注意,读取图片用PIL库的Image。不要用cv2,transforms不支持。

import torch.utils.data.distributed

import torchvision.transforms as transforms

from PIL import Image

from torch.autograd import Variable

import os

classes=(‘Bald’,‘NoBald’)

transform_test = transforms.Compose([

transforms.Resize((224, 224)),

transforms.ToTensor(),

transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])

])

DEVICE = torch.device(“cuda:0” if torch.cuda.is_available() else “cpu”)

model = torch.load(“model.pth”)

model.eval()

model.to(DEVICE)

path=‘Dataset/Test/Bald/’

testList=os.listdir(path)

for file in testList:

img=Image.open(path+file)

img=transform_test(img)

img.unsqueeze_(0)

img = Variable(img).to(DEVICE)

out=model(img)

Predict

_, pred = torch.max(out.data, 1)

print(‘Image Name:{},predict:{}’.format(file,classes[pred.data.item()]))

运行结果如下:

第二种方法可以使用pytorch默认加载数据集的方法。

import torch.utils.data.distributed

import torchvision.transforms as transforms

import torchvision.datasets as datasets

from torch.autograd import Variable

classes=(‘Bald’,‘NoBald’)

transform_test = transforms.Compose([

transforms.Resize((224, 224)),

transforms.ToTensor(),

transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])

])

DEVICE = torch.device(“cuda:0” if torch.cuda.is_available() else “cpu”)

model = torch.load(“model.pth”)

model.eval()

model.to(DEVICE)

dataset_test = datasets.ImageFolder(‘Dataset/Test’,transform_test)

print(len(dataset_test))

对应文件夹的label

for index in range(len(dataset_test)):

item = dataset_test[index]

img, label = item

img.unsqueeze_(0)

data = Variable(img).to(DEVICE)

output = model(data)

_, pred = torch.max(output.data, 1)

print(‘Image Name:{},predict:{}’.format(dataset_test.imgs[index], classes[pred.data.item()]))

index += 1

运行结果:

完整代码

====

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-sDQqt9lH-1712969598623)]

[外链图片转存中…(img-XKICMapi-1712969598623)]

[外链图片转存中…(img-3SJXrgLG-1712969598624)]

[外链图片转存中…(img-qTofnpdo-1712969598624)]

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

img
  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值