位置: IT常识 - 正文

PyTorch 之 基于经典网络架构训练图像分类模型(pytorch csdn)

编辑:rootadmin
PyTorch 之 基于经典网络架构训练图像分类模型 文章目录一、 模块简单介绍1. 数据预处理部分2. 网络模块设置3. 网络模型保存与测试二、数据读取与预处理操作1. 制作数据源2. 读取标签对应的实际名字3. 展示数据三、模型构建与实现1. 加载 models 中提供的模型,并且直接用训练的好权重当做初始化参数2. 参考 pytorch 官网例子3. 设置哪些层需要训练4. 优化器设置5. 训练模块6. 测试模型效果

推荐整理分享PyTorch 之 基于经典网络架构训练图像分类模型(pytorch csdn),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:pytorch讲解,pytorch csdn,pytorch optimizer.step,pytorch optimizer.step,pytorch regularization,pytorch基础,pytorch jit,pytorch jit,内容如对您有帮助,希望把文章链接给更多的朋友!

本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052

一、 模块简单介绍我们可以进入 pytorch 的官方网站,对模型的基本架构和训练好的参数进行直接调用,具体链接如下 https://pytorch.org/。1. 数据预处理部分(1) 数据增强通过 torchvision 中 transforms 模块的自带功能实现,比较实用。(2) 数据预处理通过 torchvision 中 transforms 也帮我们实现好了,直接调用即可。(3) DataLoader 模块可以直接读取 batch 数据。2. 网络模块设置(1) 加载预训练模型,torchvision 中有很多经典网络架构,调用起来十分方便,并且可以用人家训练好的权重参数来继续训练,也就是所谓的迁移学习。(2) 需要注意的是别人训练好的任务跟咱们的可不是完全一样,需要把最后的 head 层改一改,一般也就是最后的全连接层,改成咱们自己的任务。(3) 训练时可以全部重头训练,也可以只训练最后咱们任务的层,因为前几层都是做特征提取的,本质任务目标是一致的。3. 网络模型保存与测试(1) 模型保存的时候可以带有选择性,例如在验证集中如果当前效果好则保存。(2) 读取模型进行实际测试。

import osimport matplotlib.pyplot as plt%matplotlib inlineimport numpy as npimport torchfrom torch import nnimport torch.optim as optimimport torchvision#pip install torchvisionfrom torchvision import transforms, models, datasets#https://pytorch.org/docs/stable/torchvision/index.htmlimport imageioimport timeimport warningsimport randomimport sysimport copyimport jsonfrom PIL import Image二、数据读取与预处理操作在最开始,我们先进行训练集和测试集的数据读取。data_dir = './flower_data/'train_dir = data_dir + '/train'valid_dir = data_dir + '/valid'1. 制作数据源由于整体数据集较少,因此,我们通过 data_transforms 进行数据增强,指定所有图像预处理操作,包括旋转,裁剪,水平翻转、垂直翻转等等。需要注意的是,这里分为训练集和数据集两部分。data_transforms = { 'train': transforms.Compose([transforms.RandomRotation(45),#随机旋转,-45到45度之间随机选 transforms.CenterCrop(224),#从中心开始裁剪 transforms.RandomHorizontalFlip(p=0.5),#随机水平翻转 选择一个概率概率 transforms.RandomVerticalFlip(p=0.5),#随机垂直翻转 transforms.ColorJitter(brightness=0.2, contrast=0.1, saturation=0.1, hue=0.1),#参数1为亮度,参数2为对比度,参数3为饱和度,参数4为色相 transforms.RandomGrayscale(p=0.025),#概率转换成灰度率,3通道就是R=G=B transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])#均值,标准差 ]), 'valid': transforms.Compose([transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]),}在数据加强完后,我们将单次传递给程序用以训练的数据也就是样本的个数设置为 8。在传入数据集的时候,第一个参数是我们原始数据的路径,第二个参数是我们的数据增强方法。batch_size = 8​image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'valid']}dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True) for x in ['train', 'valid']}dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'valid']}class_names = image_datasets['train'].classes接下来,我们读取数据集的基本信息,包括训练集中的数据个数,存储路径等等信息,测试集也是相同的。image_datasets#{'train': Dataset ImageFolder# Number of datapoints: 6552# Root location: ./flower_data/train# StandardTransform# Transform: Compose(# RandomRotation(degrees=(-45, 45), resample=False, expand=False)# CenterCrop(size=(224, 224))# RandomHorizontalFlip(p=0.5)# RandomVerticalFlip(p=0.5)# ColorJitter(brightness=[0.8, 1.2], contrast=[0.9, 1.1], saturation=[0.9, 1.1], #hue=[-0.1, 0.1])# RandomGrayscale(p=0.025)# ToTensor()# Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])# ), 'valid': Dataset ImageFolder# Number of datapoints: 818# Root location: ./flower_data/valid# StandardTransform# Transform: Compose(# Resize(size=256, interpolation=PIL.Image.BILINEAR)# CenterCrop(size=(224, 224))# ToTensor()# Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])# )}我们也可以打印 dataloaders 中的信息,包含训练集和测试集两个。dataloaders#{'train': <torch.utils.data.dataloader.DataLoader at 0x21c5388b2b0>,# 'valid': <torch.utils.data.dataloader.DataLoader at 0x21c539a80b8>}查看 dataset 中的数据数量,其中训练集包含 6552 个样本,测试集中包含 818 个样本。dataset_sizes#{'train': 6552, 'valid': 818}2. 读取标签对应的实际名字在我们的文件当中,包含一个 json 文件,这中间包含了基本的标签信息,每个数字对应一种花的种类,在此,我们对这些信息进行读取。

with open('cat_to_name.json', 'r') as f: cat_to_name = json.load(f)cat_to_namePyTorch 之 基于经典网络架构训练图像分类模型(pytorch csdn)

3. 展示数据在展示数据时,需要注意 tensor 的数据需要转换成 numpy 的格式,而且还需要还原回标准化的结果。由于现在的数据都是已经处理完成后的数据,因此,如果我们想要展示的话需要对这些数据进行还原。def im_convert(tensor): """ 展示数据""" image = tensor.to("cpu").clone().detach() image = image.numpy().squeeze() image = image.transpose(1,2,0) image = image * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406)) image = image.clip(0, 1)​ return image在还原完成后,我们只需要对其中的数据进行读取即可,这里展示 8 个数据为例。fig=plt.figure(figsize=(20, 12))columns = 4rows = 2​dataiter = iter(dataloaders['valid'])inputs, classes = dataiter.next()​for idx in range (columns*rows): ax = fig.add_subplot(rows, columns, idx+1, xticks=[], yticks=[]) ax.set_title(cat_to_name[str(int(class_names[classes[idx]]))]) plt.imshow(im_convert(inputs[idx]))plt.show()

三、模型构建与实现1. 加载 models 中提供的模型,并且直接用训练的好权重当做初始化参数第一次执行需要下载,可能会比较慢,大家不必担心。model_name = 'resnet' #可选的比较多 ['resnet', 'alexnet', 'vgg', 'squeezenet', 'densenet', 'inception']在下载完成后,通过设置 feature_extract 为 True 或 False,决定是否用人家训练好的特征来做,这里直接使用人家训练好的特征,也就是设置为 True。feature_extract = True之后,我们决定是否用 GPU 进行训练。train_on_gpu = torch.cuda.is_available()​if not train_on_gpu: print('CUDA is not available. Training on CPU ...')else: print('CUDA is available! Training on GPU ...')device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")#CUDA is available! Training on GPU ...进行模型架构的打印。def set_parameter_requires_grad(model, feature_extracting): if feature_extracting: for param in model.parameters(): param.requires_grad = Falsemodel_ft = models.resnet152()model_ft

2. 参考 pytorch 官网例子选择合适的模型,不同模型的初始化方法稍微有点区别,具体的代码如下所示。def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True): model_ft = None input_size = 0​ if model_name == "resnet": """ Resnet152 """ model_ft = models.resnet152(pretrained=use_pretrained) set_parameter_requires_grad(model_ft, feature_extract) num_ftrs = model_ft.fc.in_features model_ft.fc = nn.Sequential(nn.Linear(num_ftrs, 102), nn.LogSoftmax(dim=1)) input_size = 224​ elif model_name == "alexnet": """ Alexnet """ model_ft = models.alexnet(pretrained=use_pretrained) set_parameter_requires_grad(model_ft, feature_extract) num_ftrs = model_ft.classifier[6].in_features model_ft.classifier[6] = nn.Linear(num_ftrs,num_classes) input_size = 224​ elif model_name == "vgg": """ VGG11_bn """ model_ft = models.vgg16(pretrained=use_pretrained) set_parameter_requires_grad(model_ft, feature_extract) num_ftrs = model_ft.classifier[6].in_features model_ft.classifier[6] = nn.Linear(num_ftrs,num_classes) input_size = 224​ elif model_name == "squeezenet": """ Squeezenet """ model_ft = models.squeezenet1_0(pretrained=use_pretrained) set_parameter_requires_grad(model_ft, feature_extract) model_ft.classifier[1] = nn.Conv2d(512, num_classes, kernel_size=(1,1), stride=(1,1)) model_ft.num_classes = num_classes input_size = 224​ elif model_name == "densenet": """ Densenet """ model_ft = models.densenet121(pretrained=use_pretrained) set_parameter_requires_grad(model_ft, feature_extract) num_ftrs = model_ft.classifier.in_features model_ft.classifier = nn.Linear(num_ftrs, num_classes) input_size = 224​ elif model_name == "inception": """ Inception v3 Be careful, expects (299,299) sized images and has auxiliary output """ model_ft = models.inception_v3(pretrained=use_pretrained) set_parameter_requires_grad(model_ft, feature_extract) # Handle the auxilary net num_ftrs = model_ft.AuxLogits.fc.in_features model_ft.AuxLogits.fc = nn.Linear(num_ftrs, num_classes) # Handle the primary net num_ftrs = model_ft.fc.in_features model_ft.fc = nn.Linear(num_ftrs,num_classes) input_size = 299​ else: print("Invalid model name, exiting...") exit()​ return model_ft, input_size3. 设置哪些层需要训练在关于哪些层需要训练,首先导入模型的名字,把最终的输出结果 102 导入进去,然后选择是否动那些层,是否使用人家的模型参数。model_ft, input_size = initialize_model(model_name, 102, feature_extract, use_pretrained=True)使用 GPU 进行计算。model_ft = model_ft.to(device)将我们训练完成后的模型保存到指定路径之下。​filename='checkpoint.pth'是否训练所有层。params_to_update = model_ft.parameters()print("Params to learn:")if feature_extract: params_to_update = [] for name,param in model_ft.named_parameters(): if param.requires_grad == True: params_to_update.append(param) print("\t",name)else: for name,param in model_ft.named_parameters(): if param.requires_grad == True: print("\t",name)#Params to learn:# fc.0.weight# fc.0.bias#model_ft

4. 优化器设置进行学习率衰减。optimizer_ft = optim.Adam(params_to_update, lr=1e-2)scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)#学习率每7个epoch衰减成原来的1/10#最后一层已经LogSoftmax()了,所以不能nn.CrossEntropyLoss()来计算了,nn.CrossEntropyLoss()相当于logSoftmax()和nn.NLLLoss()整合criterion = nn.NLLLoss()5. 训练模块def train_model(model, dataloaders, criterion, optimizer, num_epochs=25, is_inception=False,filename=filename): since = time.time() best_acc = 0 """ checkpoint = torch.load(filename) best_acc = checkpoint['best_acc'] model.load_state_dict(checkpoint['state_dict']) optimizer.load_state_dict(checkpoint['optimizer']) model.class_to_idx = checkpoint['mapping'] """ model.to(device)​ val_acc_history = [] train_acc_history = [] train_losses = [] valid_losses = [] LRs = [optimizer.param_groups[0]['lr']]​ best_model_wts = copy.deepcopy(model.state_dict())​ for epoch in range(num_epochs): print('Epoch {}/{}'.format(epoch, num_epochs - 1)) print('-' * 10)​ # 训练和验证 for phase in ['train', 'valid']: 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'): if is_inception and phase == 'train': outputs, aux_outputs = model(inputs) loss1 = criterion(outputs, labels) loss2 = criterion(aux_outputs, labels) loss = loss1 + 0.4*loss2 else:#resnet执行的是这里 outputs = model(inputs) loss = criterion(outputs, labels)​ _, preds = torch.max(outputs, 1)​ # 训练阶段更新权重 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 / len(dataloaders[phase].dataset) epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset) time_elapsed = time.time() - since print('Time elapsed {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60)) print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))​ # 得到最好那次的模型 if phase == 'valid' and epoch_acc > best_acc: best_acc = epoch_acc best_model_wts = copy.deepcopy(model.state_dict()) state = { 'state_dict': model.state_dict(), 'best_acc': best_acc, 'optimizer' : optimizer.state_dict(), } torch.save(state, filename) if phase == 'valid': val_acc_history.append(epoch_acc) valid_losses.append(epoch_loss) scheduler.step(epoch_loss) if phase == 'train': train_acc_history.append(epoch_acc) train_losses.append(epoch_loss) print('Optimizer learning rate : {:.7f}'.format(optimizer.param_groups[0]['lr'])) LRs.append(optimizer.param_groups[0]['lr']) 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, val_acc_history, train_acc_history, valid_losses, train_losses, LRs model_ft, val_acc_history, train_acc_history, valid_losses, train_losses, LRs = train_model(model_ft, dataloaders, criterion, optimizer_ft, num_epochs=20, is_inception=(model_name=="inception"))

再次继续训练所有层。for param in model_ft.parameters(): param.requires_grad = True​#再继续训练所有的参数,学习率调小一点optimizer = optim.Adam(params_to_update, lr=1e-4)scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)​#损失函数criterion = nn.NLLLoss()#Load the checkpoint​checkpoint = torch.load(filename)best_acc = checkpoint['best_acc']model_ft.load_state_dict(checkpoint['state_dict'])optimizer.load_state_dict(checkpoint['optimizer'])#model_ft.class_to_idx = checkpoint['mapping']model_ft, val_acc_history, train_acc_history, valid_losses, train_losses, LRs = train_model(model_ft, dataloaders, criterion, optimizer, num_epochs=10, is_inception=(model_name=="inception"))

6. 测试模型效果输入一张测试图像,看看网络的返回结果:probs, classes = predict(image_path, model)print(probs)print(classes)#[ 0.01558163 0.01541934 0.01452626 0.01443549 0.01407339]#['70', '3', '45', '62', '55']这里需要注意的是,预处理方法需相同。然后,我们加载训练好的模型。model_ft, input_size = initialize_model(model_name, 102, feature_extract, use_pretrained=True)​#GPU模式model_ft = model_ft.to(device)​#保存文件的名字filename='seriouscheckpoint.pth'​#加载模型checkpoint = torch.load(filename)best_acc = checkpoint['best_acc']model_ft.load_state_dict(checkpoint['state_dict'])测试数据处理方法需要跟训练时一直才可以。crop 操作的目的是保证输入的大小是一致的。标准化操作也是必须的,用跟训练数据相同的 mean 和 std,但是需要注意一点训练数据是在 0-1 上进行标准化,所以测试数据也需要先归一化。PyTorch 中颜色通道是第一个维度,跟很多工具包都不一样,需要转换。def process_image(image_path): # 读取测试数据 img = Image.open(image_path) # Resize,thumbnail方法只能进行缩小,所以进行了判断 if img.size[0] > img.size[1]: img.thumbnail((10000, 256)) else: img.thumbnail((256, 10000)) # Crop操作 left_margin = (img.width-224)/2 bottom_margin = (img.height-224)/2 right_margin = left_margin + 224 top_margin = bottom_margin + 224 img = img.crop((left_margin, bottom_margin, right_margin, top_margin)) # 相同的预处理方法 img = np.array(img)/255 mean = np.array([0.485, 0.456, 0.406]) #provided mean std = np.array([0.229, 0.224, 0.225]) #provided std img = (img - mean)/std # 注意颜色通道应该放在第一个位置 img = img.transpose((2, 0, 1)) return img在数据测试完成后,我们需要对测试数据进行展示,也就是需要进行还原操作。def imshow(image, ax=None, title=None): """展示数据""" if ax is None: fig, ax = plt.subplots() # 颜色通道还原 image = np.array(image).transpose((1, 2, 0)) # 预处理还原 mean = np.array([0.485, 0.456, 0.406]) std = np.array([0.229, 0.224, 0.225]) image = std * image + mean image = np.clip(image, 0, 1) ax.imshow(image) ax.set_title(title) return aximage_path = 'image_06621.jpg'img = process_image(image_path)imshow(img)

之后进行预测结果的展示。fig=plt.figure(figsize=(20, 20))columns =4rows = 2​for idx in range (columns*rows): ax = fig.add_subplot(rows, columns, idx+1, xticks=[], yticks=[]) plt.imshow(im_convert(images[idx])) ax.set_title("{} ({})".format(cat_to_name[str(preds[idx])], cat_to_name[str(labels[idx].item())]), color=("green" if cat_to_name[str(preds[idx])]==cat_to_name[str(labels[idx].item())] else "red"))plt.show()

本文链接地址:https://www.jiuchutong.com/zhishi/300419.html 转载请保留说明!

上一篇:Vue中 provide、inject 详解及使用

下一篇:IDEA 2022专业版创建Java Web项目(保姆式小白讲义,强烈建议入手!)

  • 基本户和一般户的用途
  • 污水处理税收优惠政策
  • 城市基础设施配套有哪些
  • 安装服务费发票需要备注地址吗
  • 房产继承是不是谁照顾谁的
  • 多交的增值税怎么退
  • 红字发票怎么勾选认证
  • 仪器检测费发票哪一类
  • 已经计提的坏账准备可以转回吗
  • 别人给的发票一直不开
  • 企业会议费发票可否抵扣?
  • 营改增后手写发票还能用吗
  • 物业管理公司代收水电费如何开票
  • 个人两处以上所得经营所得怎么申报
  • 固定资产原值变更当月计提折旧
  • 预付账款后期如何冲销
  • 低值易耗品怎么结转
  • 再生资源会计科目
  • win10windows资源管理器怎么打开
  • window10锁屏壁纸图片在哪
  • 高新技术产业研究院有限公司
  • 投资性房地产期末公允价值大于账面价值
  • au_.exe是什么进程
  • loaddriver.exe是什么病毒
  • php如何上传1个g以上的文件
  • php二维码解码
  • 生产型企业出口外购货物可以退税吗
  • Access-Control-Expose-Headers 响应报头、跨域 公开响应头
  • vue笔记项目
  • 自动化工具 业务有哪些
  • 如何认识软件测试
  • point network
  • 语音语言
  • 纳税人在工作
  • 预付账款后收到货物会计分录
  • 电子承兑对方拒绝签收多久能到账
  • 企业原材料成本占比
  • mysql 局域网访问权限
  • 外购商品发放给员工 进项税额能不能抵扣
  • 金税四期一般纳税人开票先票后款行吗
  • 工会经费与残保金属于什么
  • 建筑业营改增的主要内容
  • 道路货物运输服务税率
  • 人力资源公司劳务外包
  • 红字冲销怎么做账
  • 房屋估价需要准备什么
  • 增值税达不到税负怎么办
  • 同一客户有应收应付可以相互抵消吗
  • 销项发票怎么导出的是压缩包怎么打开
  • 一般纳税人提供劳务税率是多少
  • 工伤 保险赔付
  • 苗木设计方案
  • 套现给现金还是转账好
  • 库存数据不准确
  • 养老服务机构有住房租赁贷款需求吗
  • 不开票收据可以盖章吗
  • 虚拟机linux端mysql数据库无法远程访问的解决办法
  • mysql 5.7.17 64bit安装配置方法图文教程
  • Windows任务计划程序服务
  • win10怎么更改磁盘空间分配
  • macbook备忘录字数统计
  • culauncherexe是什么进程
  • linux软件类型
  • 解决Android Studio下载gradle慢
  • 详细分析我国针对疫情的国防动员举措
  • linux sar文件路径
  • python的理解
  • Python读取Excel文件需要什么
  • python 进阶
  • 详解linux设备
  • shell脚本实现文件管理
  • linux怎么ssh远程
  • 用python发邮件
  • jquery返回顶部代码
  • 在windows中快捷键的作用
  • 增值税纳税申报表附列资料(三)
  • 云南省昆明市官渡区矣六街道
  • 安康国税局电话号码
  • 西北地区的沙尘暴
  • 出口退税函调不予退税的后果
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设