(5)catanddong_用resnet18迁移学习分类和测试

1、数据集制作

 (1)将从kaggle下载的数据集中的train目录下的图片分类为cat和dog文件夹,每个文件夹下12500张图片

(2)使用教程1的方法进行数据的划分

 (1)数据集的划分_chencaw的博客-CSDN博客

2、使用resnet18的预训练模型迁移训练

(1)使用了dqtm查看进度

参考了tqdm介绍及常用方法_GZKPeng的博客-CSDN博客_tqdm函数

(2)使用summary()清晰打印网络结果

参考了

PyTorch 打印网络模型结构-pudn.com

1)安装

pip install torchinfo
或者
conda install -c conda-forge torchinfo

2)使用方法

from    torchinfo import summary
............
...........
model = simpleNet()
batch_size = 64
summary(model, input_size=(batch_size, 3, 32, 32))

(3)使用多张显卡

1)查看显卡

print("cuda:") 
print(torch.cuda.is_available())
print(torch.cuda.device_count())
print(torch.cuda.current_device()) 
print(torch.cuda.get_device_name(0)) 

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
或者
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

2)对模型训练使用多张显卡

#一机多卡设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1,2,3'#设置所有可以使用的显卡,共计四块
device_ids = [0,1]#选中其中两块
model = nn.DataParallel(model, device_ids=device_ids)#并行使用两块
#model = torch.nn.Dataparallel(model)  # 默认使用所有的device_ids
model = model.cuda()

(4)完整代码如下

import  torch
from    torch import optim, nn
# import  visdom
# from tensorboardX import SummaryWriter  #(1)引入tensorboardX
from torch.utils.tensorboard import SummaryWriter

# import  torchvision
from    torch.utils.data import DataLoader
from    torchvision import transforms, datasets, models
# from    utils import Flatten

# from    pokemon import Pokemon
# from    resnet import ResNet18
from    torchvision.models import resnet18
from    PIL import Image
from    tqdm import tqdm
from    torchinfo import summary
import  os


# batchsz = 32
batch_size = 128
lr = 1e-3
epochs = 10
img_resize = 224

# print("cuda:") 
# print(torch.cuda.is_available())
# print(torch.cuda.device_count())
# print(torch.cuda.current_device()) 
# print(torch.cuda.get_device_name(0)) 

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# device = torch.device('cpu')
torch.manual_seed(1234)

# tf = transforms.Compose([
#                      transforms.Resize((224,224)),
#                      transforms.ToTensor(),
#      ])
#输入应该是PIL.Image类型
tf = transforms.Compose([
    #匿名函数
    # lambda x:Image.open(x).convert('RGB'), # string path= > image data
    transforms.Resize((int(img_resize*1.25), int(img_resize*1.25))),
    transforms.RandomRotation(15),
    transforms.CenterCrop(img_resize),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                            std=[0.229, 0.224, 0.225])
])
# db = torchvision.datasets.ImageFolder(root='pokemon', transform=tf)
train_db = datasets.ImageFolder(root='/home/chen/chen_deep/data/cat_dog/train', transform=tf)
print(train_db.class_to_idx)
print("个数",len(train_db))
val_db = datasets.ImageFolder(root='/home/chen/chen_deep/data/cat_dog/val', transform=tf)
test_db = datasets.ImageFolder(root='/home/chen/chen_deep/data/cat_dog/test', transform=tf)


# train_db = Pokemon('pokemon', 224, mode='train')
# val_db = Pokemon('pokemon', 224, mode='val')
# test_db = Pokemon('pokemon', 224, mode='test')
# train_loader = DataLoader(train_db, batch_size=batchsz, shuffle=True,
#                           num_workers=4)
# val_loader = DataLoader(val_db, batch_size=batchsz, num_workers=2)
# test_loader = DataLoader(test_db, batch_size=batchsz, num_workers=2)
train_loader = DataLoader(train_db, batch_size = batch_size, shuffle=True)
val_loader = DataLoader(val_db, batch_size = batch_size)
test_loader = DataLoader(test_db, batch_size = batch_size)


# viz = visdom.Visdom()
#(2)初始化,注意可以给定路径
writer = SummaryWriter('runs/chen_cat_dog_test1')
# pip install tensorboard
# tensorboard --logdir=runs
# http://localhost:6006

def evalute(model, loader):
    model.eval()
    
    correct = 0
    total = len(loader.dataset)

    for x,y in loader:
        x,y = x.to(device), y.to(device)
        with torch.no_grad():
            logits = model(x)
            pred = logits.argmax(dim=1)
        correct += torch.eq(pred, y).sum().float().item()

    return correct / total

def main():






    #(1)如用anaconda激活你自己的环境
    # conda env list
    # conda activate chentorch_cp310
    #(2)安装
    # pip install visdom
    #(3)使用
    # python -m visdom.server
    # http://localhost:8097/

    # model = ResNet18(5).to(device)

    # model = ResNet18(5).to(device)
    #The current behavior is equivalent to passing `weights=ResNet18_Weights.IMAGENET1K_V1`.
    #  You can also use `weights=ResNet18_Weights.DEFAULT`
    # trained_model = resnet18(pretrained=True)
    trained_model = resnet18(weights=models.ResNet18_Weights.DEFAULT)
    model = nn.Sequential(*list(trained_model.children())[:-1], #[b, 512, 1, 1]
                        #   Flatten(), # [b, 512, 1, 1] => [b, 512]
                          nn.Flatten(),
                        #   nn.Linear(512, 5)
                          nn.Linear(512, 2)
                          ).to(device)
    # x = torch.randn(2, 3, 224, 224)
    # print(model(x).shape)

    #一机多卡设置
    # os.environ['CUDA_VISIBLE_DEVICES'] = '0,1,2,3'#设置所有可以使用的显卡,共计四块
    os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'#设置所有可以使用的显卡,共计四块
    device_ids = [0,1]#选中其中两块
    model = nn.DataParallel(model, device_ids=device_ids)#并行使用两块
    #model = torch.nn.Dataparallel(model)  # 默认使用所有的device_ids


    batch_size = 64
    summary(model, input_size=(batch_size, 3, 224, 224))
    # print(model)
    
    optimizer = optim.Adam(model.parameters(), lr=lr)
    criteon = nn.CrossEntropyLoss()


    best_acc, best_epoch = 0, 0
    global_step = 0
    # viz.line([0], [-1], win='loss', opts=dict(title='loss'))
    # viz.line([0], [-1], win='val_acc', opts=dict(title='val_acc'))
    for epoch in tqdm(range(epochs)):

        for step, (x,y) in tqdm(enumerate(train_loader)):

            # x: [b, 3, 224, 224], y: [b]
            x, y = x.to(device), y.to(device)
            
            model.train()
            logits = model(x)
            loss = criteon(logits, y)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            # viz.line([loss.item()], [global_step], win='loss', update='append')
            #(3)将batch中TrainLoss添加到tensorboardX中
            writer.add_scalar('TrainLoss', loss.item(), global_step=global_step)
            global_step += 1

        if epoch % 1 == 0:

            val_acc = evalute(model, val_loader)
            if val_acc> best_acc:
                best_epoch = epoch
                best_acc = val_acc

                torch.save(model.state_dict(), 'best_cat_dong_transfer.mdl')

                # viz.line([val_acc], [global_step], win='val_acc', update='append')
                #(4)将epoch中TestAcc添加到tensorboardX中
                writer.add_scalar('TestAcc', val_acc, global_step=epoch) 


    print('best acc:', best_acc, 'best epoch:', best_epoch)

    model.load_state_dict(torch.load('best_cat_dong_transfer.mdl'))
    print('loaded from ckpt!')

    test_acc = evalute(model, test_loader)
    print('test acc:', test_acc)

    #(5)关闭writer
    writer.close()
    


if __name__ == '__main__':
    main()

3、单张图片测试

    发现使用state_dict保存时如果是多GPU
    测试的时候也要多GPU

import  torch
from    torch import optim, nn
 
from    torch.utils.data import DataLoader
from    torchvision import transforms,datasets ,models
 
# from    resnet import ResNet18
from    torchvision.models import resnet18
from    PIL import Image
# from    utils import Flatten
import  os

img_resize = 224
mean=[0.485, 0.456, 0.406]
std=[0.229, 0.224, 0.225]
 
# device = torch.device('cuda')
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# device = torch.device('cpu')
 
 
tf = transforms.Compose([
    #匿名函数
    lambda x:Image.open(x).convert('RGB'), # string path= > image data
    transforms.Resize((img_resize, img_resize)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                            std=[0.229, 0.224, 0.225])
])
 
"""
    函数说明: 根据训练结果对模型进行测试
    :param    img_test: 待测试的图片
    :return:  y: 测试结果,分类序号
 """
def model_test_img(model,img_test):
    model.eval()
    # img = Image.open(img_test).convert('RGB') 
    # resize = transforms.Resize([224,224])
    # x = transforms.Resize([img_resize,img_resize])(img)
    # x = transforms.ToTensor()(x)
    x =tf(img_test)
    x = x.to(device)
    x = x.unsqueeze(0)
    # x = transforms.Normalize(mean,std)(x)
    # print(x.shape)
    with torch.no_grad():
        logits = model(x)
        pred = logits.argmax(dim=1)
    return pred
 
 
def main():
 
    #(1)如用anaconda激活你自己的环境
    # conda env list
    # conda activate chentorch_cp310
 
    #分类名称
    class_name = ['cat', 'dog']
    # image_file = "D:/pytorch_learning2022/data/pokeman/train/bulbasaur/00000002.jpg"
    # image_file = "/home/chen/chen_deep/data/cat_dog/test/cat/cat.21.jpg"  #出错
    # image_file = "/home/chen/chen_deep/data/cat_dog/test/cat/cat.20.jpg"  #出错
    image_file = "/home/chen/chen_deep/data/cat_dog/test/cat/cat.10.jpg"    #出错
    # image_file = "/home/chen/chen_deep/data/cat_dog/test/cat/cat.285.jpg"
    # image_file = "/home/chen/chen_deep/data/cat_dog/test/cat/cat.576.jpg"


    # trained_model = resnet18(pretrained=True)
    trained_model = resnet18(weights = models.ResNet18_Weights.DEFAULT)

    model = nn.Sequential(*list(trained_model.children())[:-1], #[b, 512, 1, 1]
                          nn.Flatten(),
                        #   Flatten(), # [b, 512, 1, 1] => [b, 512]
                          nn.Linear(512, 2)
                          ).to(device)
    #发现使用state_dict保存时如果是多GPU
    #测试的时候也要多GPU
    os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'#设置所有可以使用的显卡,共计四块
    device_ids = [0,1]#选中其中两块
    model = nn.DataParallel(model, device_ids=device_ids)#并行使用两块

    model.load_state_dict(torch.load('old_best_cat_dog_transfer.mdl'))
    y = model_test_img(model,image_file)
    print(y)
 
    print("detect result is: ",class_name[y])
 
 
 
if __name__ == '__main__':
    main()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值