深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18

0. 往期内容 [一]深度学习Pytorch-张量定义与张量创建
[二]深度学习Pytorch-张量的操作:拼接、切分、索引和变换
[三]深度学习Pytorch-张量数学运算
[四]深度学习Pytorch-线性回归
[五]深度学习Pytorch-计算图与动态图机制
[六]深度学习Pytorch-autograd与逻辑回归
[七]深度学习Pytorch-DataLoader与Dataset(含人民币二分类实战)
[八]深度学习Pytorch-图像预处理transforms
[九]深度学习Pytorch-transforms图像增强(剪裁、翻转、旋转)
[十]深度学习Pytorch-transforms图像操作及自定义方法
[十一]深度学习Pytorch-模型创建与nn.Module
[十二]深度学习Pytorch-模型容器与AlexNet构建
[十三]深度学习Pytorch-卷积层(1D/2D/3D卷积、卷积nn.Conv2d、转置卷积nn.ConvTranspose)
[十四]深度学习Pytorch-池化层、线性层、激活函数层
[十五]深度学习Pytorch-权值初始化
[十六]深度学习Pytorch-18种损失函数loss function
[十七]深度学习Pytorch-优化器Optimizer
[十八]深度学习Pytorch-学习率Learning Rate调整策略
[十九]深度学习Pytorch-可视化工具TensorBoard
[二十]深度学习Pytorch-Hook函数与CAM算法
[二十一]深度学习Pytorch-正则化Regularization之weight decay
[二十二]深度学习Pytorch-正则化Regularization之dropout
[二十三]深度学习Pytorch-批量归一化Batch Normalization
[二十四]深度学习Pytorch-BN、LN(Layer Normalization)、IN(Instance Normalization)、GN(Group Normalization)
[二十五]深度学习Pytorch-模型保存与加载
[二十六]深度学习Pytorch-模型微调Finetune
[二十七]深度学习Pytorch-GPU的使用
[二十八]深度学习Pytorch-图像分类Resnet18

深度学习Pytorch-图像分类Resnet18

  • 0. 往期内容
  • 1. 模型是如何将图像分类的?
  • 2. Resnet18模型inference
  • 3. resnet18结构分析

1. 模型是如何将图像分类的? 深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片
深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片
深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片

2. Resnet18模型inference 深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片

代码示例:
resnet_inference.py
# -*- coding: utf-8 -*- """ # @file name: resnet_inference.py # @brief: inference demo """import os import time import torch.nn as nn import torch import torchvision.transforms as transforms from PIL import Image from matplotlib import pyplot as plt import torchvision.models as models BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # device = torch.device("cuda" if torch.cuda.is_available() else "cpu") device = torch.device("cpu")# config vis = True # vis = False vis_row = 4norm_mean = [0.485, 0.456, 0.406] norm_std = [0.229, 0.224, 0.225]#transform要与validate时的transform一致 inference_transform = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(norm_mean, norm_std), ])classes = ["ants", "bees"]def img_transform(img_rgb, transform=None): """ 将数据转换为模型读取的形式 :param img_rgb: PIL Image :param transform: torchvision.transform :return: tensor """if transform is None: raise ValueError("找不到transform!必须有transform对img进行处理")img_t = transform(img_rgb) return img_tdef get_img_name(img_dir, format="jpg"): """ 获取文件夹下format格式的文件名 :param img_dir: str :param format: str :return: list """ file_names = os.listdir(img_dir) img_names = list(filter(lambda x: x.endswith(format), file_names))if len(img_names) < 1: raise ValueError("{}下找不到{}格式数据".format(img_dir, format)) return img_namesdef get_model(m_path, vis_model=False):resnet18 = models.resnet18() num_ftrs = resnet18.fc.in_features resnet18.fc = nn.Linear(num_ftrs, 2)checkpoint = torch.load(m_path) resnet18.load_state_dict(checkpoint['model_state_dict'])if vis_model: from torchsummary import summary summary(resnet18, input_size=(3, 224, 224), device="cpu")return resnet18if __name__ == "__main__":img_dir = os.path.join("..", "..", "data/hymenoptera_data/val/bees") model_path = "./checkpoint_14_epoch.pkl" time_total = 0 img_list, img_pred = list(), list()# 1. data img_names = get_img_name(img_dir) num_img = len(img_names)# 2. model resnet18 = get_model(model_path, True) resnet18.to(device) resnet18.eval() #设置eval状态,不是训练状态#告诉pytorch下面所有的计算都不需要计算梯度,减少内存的消耗 with torch.no_grad(): #每次读取一张图片 for idx, img_name in enumerate(img_names): path_img = os.path.join(img_dir, img_name)# step 1/4 : path --> img img_rgb = Image.open(path_img).convert('RGB')# step 2/4 : img --> tensor img_tensor = img_transform(img_rgb, inference_transform) #3D img_tensor.unsqueeze_(0) #4D img_tensor = img_tensor.to(device) #张量的to操作不会进行inplace操作,需要用等号进行赋值# step 3/4 : tensor --> vector time_tic = time.time() outputs = resnet18(img_tensor) time_toc = time.time()# step 4/4 : visualization _, pred_int = torch.max(outputs.data, 1) #torch.max(a,1) 返回每一行中最大值的那个元素,且返回其索引 pred_str = classes[int(pred_int)]if vis: img_list.append(img_rgb) img_pred.append(pred_str)if (idx+1) % (vis_row*vis_row) == 0 or num_img == idx+1: for i in range(len(img_list)): plt.subplot(vis_row, vis_row, i+1).imshow(img_list[i]) plt.title("predict:{}".format(img_pred[i])) plt.show() plt.close() img_list, img_pred = list(), list()time_s = time_toc-time_tic time_total += time_sprint('{:d}/{:d}: {} {:.3f}s '.format(idx + 1, num_img, img_name, time_s))print("\ndevice:{} total time:{:.1f}s mean:{:.3f}s". format(device, time_total, time_total/num_img)) if torch.cuda.is_available(): print("GPU name:{}".format(torch.cuda.get_device_name()))

3. resnet18结构分析 深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片
深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片

(1)输入是224*224,经过conv1(步长为2)后输出为112*112,再经过pool(步长为2)后输出为56*56,再经过conv3_x(layer2)的第一个卷积层(步长为2)后输出为28*28,然后再进行conv3_x(layer2)的第二个卷积层,再经过conv4_x(layer3)的第一个卷积层(步长为2)后输出为14*14,然后再进行conv4_x(layer3)的第二个卷积层,最后经过池化层后输出为1*1,然后再经过全连接层进行输出,最后用softmax将输出转换成概率分布。
(2)Resnet-18中的18是指网络中带有weight权值的网络层的个数,conv1带有1个权值,conv2_x、conv3_x、conv4_x、conv5_x中每个有两个basic block,每个basic block中有两个卷积层,所以这4layer2*2*4=16个权值,fc层有1个权值,所以总共18个权值。
(3)50-layer往后每个block称为瓶颈层。
【深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18】深度学习Pyrotch|[二十八]深度学习Pytorch-图像分类Resnet18
文章图片

    推荐阅读