编程语言   发布时间:2022-06-26  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了pytorch——VGG网络搭建大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

目录

🚗VGG介绍

🚓那VGG它到底厉害在哪里呢?

🚓那什么是感受野呢?

🚓计算公式

🚓问题一:

🚓问题二:

🚓网络图

🚗pytorch搭建VGG网络

🚓1. model.py

5;神奇处理之处

🚓2. Train.py

3. preDict.py

🚗注意


🚗VGG介绍

VGG 在2014年由牛津大学著名研究组 VGGVisual Geometry Group)提出࿰c;

(论文地址:https://arxiv.org/abs/1409.1556)

获得该年 ImageNet 竞赛中 Localization Task(定位任务)第一名和 Classification Task(分类任务)第二名。(可以说是非常的厉害)

🚓那VGG它到底厉害在哪里呢?

通过堆叠多个小卷积核来替代大尺度卷积核࿰c;可以减少训练参数࿰c;同时能保证相同的感受野

🚓那什么是感受野呢?

决定某一层输出结果中一个元素所对应的输入层的区域大小࿰c;被称作感受野receptive field

简单来说就是输出feature map上的一个单元 对应 输入层(上层)上的区域大小

pytorch——VGG网络搭建

🚗例如上图:maxpool1 感受野为2  (意思是上一层1格 对应 下一层2格)

                   conv1 感受野为5

🚓计算公式

我们的感受野的计算公式为:                                 

pytorch——VGG网络搭建

 

F ( i + 1) 为第 i +1 层感受野 Stride 为第 i 层的步距 Ksize 为 卷积核 或 池化核 尺寸  

🚓问题一:

堆叠两个3×3的卷积核替代5x5的卷积核࿰c;堆叠三个3×3的卷积核替代7x7的卷积核。

(VGG网络中卷积的Stride默认为1)

替代前后感受野是否相同呢?

根据公式

(第一层)Feature map: F(1) = 1 

(第二层)Conv3x3(3):pytorch——VGG网络搭建pytorch——VGG网络搭建

(第三层)Conv3x3(2):  pytorch——VGG网络搭建

(5×5卷积核感受野)

(第四层)Conv3x3(1): pytorch——VGG网络搭建

(7×7卷积核感受野)  

2个3×3的卷积核和一个5x5的卷积核感受野相同

证明可以通过堆叠两个3×3的卷积核替代5x5的卷积核࿰c;堆叠三个3×3的卷积核替代7x7的卷积核 

🚓问题二:

堆叠3×3卷积核后训练参数是否真的减少了? 

注:CNN参数个数 = 卷积核尺寸×卷积核深度 × 卷积核组数 = 卷积核尺寸 × 输入特征矩阵深度 × 输出特征矩阵深度 现假设 输入特征矩阵深度 = 输出特征矩阵深度 = C

使用7×7卷积核所需参数个数:

pytorch——VGG网络搭建

堆叠三个3×3的卷积核所需参数个数: 

pytorch——VGG网络搭建

很明显27小于49 

🚓网络图

VGG网络有多个版本࿰c;

 我们一般采用VGG16 (16的意思是16层=12层卷积层+4层全连接层

其网络结构如下如所示:

pytorch——VGG网络搭建

 看图和计算我们可以知道c;经3×3卷积的特征矩阵的尺寸是不改变的:

 out =(in −F+2p)/S+1=(in ​−3+2)/1+1= in 

out = in 大小一样

🚗pytorch搭建VGG网络

VGG网络分为 卷积层提取特征 和 全连接层进行分类 这两个模块

🚓1. model.py

import torch.nn as nn
import torch

class VGG(nn.ModulE):
    def __init__(self, features, num_classes=1000, init_weights=falsE):
        super(VGG, self).__init__()
        self.features = features			# 卷积层提取特征
        self.classifier = nn.Sequential(	# 全连接层进行分类
            nn.Dropout(p=0.5),
            nn.Linear(512*7*7, 2048),
            nn.ReLU(true),
            nn.Dropout(p=0.5),
            nn.Linear(2048, 2048),
            nn.ReLU(true),
            nn.Linear(2048, num_classes)
        )
        if init_weights:
            self._initialize_weights()  #初始化权重

    def forWARD(self, X):
        # N x 3 x 224 x 224
        x = self.features(X)
        # N x 512 x 7 x 7
        x = torch.flatten(x, start_dim=1)
        # N x 512*7*7
        x = self.classifier(X)
        return x

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                # nn.init.KaiR_520_11845@ing_normal_(m.weight, mode='fan_out', nonlinearity='Relu')
                nn.init.xavier_uniform_(m.weight)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                nn.init.xavier_uniform_(m.weight)
                # nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)  

5;神奇处理之处

pytorch——VGG网络搭建

# vgg网络模型配置列表࿰c;数字表示卷积核个数࿰c;'M'表示最大池化层
cfgs = {
    'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],											# 模型A
    'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],									# 模型B
    'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],					# 模型D
    'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 	# 模型E
}

# 卷积层提取特征
def make_features(cfg: list): # 传入的是具体某个模型的参数列表
    layers = []
    in_chAnnels = 3		# 输入的原始图像(rgb三通道)
    for v in cfg:
        # 如果是最大池化层࿰c;就进行池化
        if v == "M":
            layers += [nn.MaxPool2d(kernel_size=2, Stride=2)]
        # 不然就是卷积层
        else:
            conv2d = nn.Conv2d(in_chAnnels, v, kernel_size=3, padding=1)
            layers += [conv2d, nn.ReLU(true)]
            in_chAnnels = v
    return nn.Sequential(*layers)  # 单星号(*)将参数以元组(tuplE)的形式导入


def vgg(model_name="vgg16", **kwargs):  # 双星号(**)将参数以字典的形式导入
    try:
        cfg = cfgs[model_name]
    except:
        print("Warning: model number {} not in cfgs Dict!".format(model_Name))
        exit(-1)
    model = VGG(make_features(cfg), **kwargs) #**kwargs是你传入的字典数据
    return model

🚓2. Train.py

和pytorch——AlexNet——训练花分类数据集_heart_6662的博客-CSDN博客的一样(数据还是花的数据)

import os
import json

import torch
import torch.nn as nn
from torchvision import transforms, datasets
import torch.optim as optim
from tqdm import tqdm

from model import vgg


def main():
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("using {} device.".format(devicE))

    data_transform = {
        "Train": transforms.Compose([transforms.RandomResizedCrop(224),
                                     transforms.RandomHorizontalFlip(),
                                     transforms.ToTensor(),
                                     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
        "val": transforms.Compose([transforms.Resize((224, 224)),
                                   transforms.ToTensor(),
                                   transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}

    data_root = os.path.abspath(os.path.join(os.getcwd(), "../.."))  # get data root path
    image_path = os.path.join(data_root, "data_set", "flower_data")  # flower data set path
    assert os.path.exists(image_path), "{} path does not exist.".format(image_path)
    Train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "Train"),
                                         transform=data_transform["Train"])
    Train_num = len(Train_dataset)

    # {'daisy':0, 'dandelion':1, 'Roses':2, 'sunflower':3, 'tulips':4}
    flower_list = Train_dataset.class_to_idx
    cla_Dict = Dict((val, key) for key, val in flower_list.items())
    # write Dict into json file
    json_str = json.dumps(cla_Dict, indent=4)
    with open('class_inDices.json', 'w') as json_file:
        json_file.write(json_str)

    batch_size =32
    nw = min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])  # number of workers
    print('using {} dataloader workers every process'.format(nw))

    Train_loader = torch.utils.data.DataLoader(Train_dataset,
                                               batch_size=batch_size, shuffle=True,
                                               num_workers=0)

    validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"),
                                            transform=data_transform["val"])
    val_num = len(validate_dataset)
    validate_loader = torch.utils.data.DataLoader(validate_dataset,
                                                  batch_size=batch_size, shuffle=false,
                                                  num_workers=0)
    print("using {} images for Training, {} images for validation.".format(Train_num,
                                                                           val_num))

    # test_data_iter = iter(validate_loader)
    # test_image, test_label = test_data_iter.next()

    model_name = "vgg16"
    net = vgg(model_name=model_name, num_classes=5, init_weights=TruE)
    net.to(devicE)
    loss_function = nn.CrossEntropyLoss()
    optimizer = optim.Adam(net.parameters(), lr=0.0001)

    epochs = 30
    best_acc = 0.0
    save_path = './{}Net.pth'.format(model_Name)
    Train_steps = len(Train_loader)
    for epoch in range(epochs):
        # Train
        net.Train()
        running_loss = 0.0
        Train_bar = tqdm(Train_loader)
        for step, data in enumerate(Train_bar):
            images, labels = data
            optimizer.zero_grad()
            outputs = net(images.to(devicE))
            loss = loss_function(outputs, labels.to(devicE))
            loss.BACkWARD()
            optimizer.step()

            # print statistics
            running_loss += loss.item()

            Train_bar.desc = "Train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,
                                                                     epochs,
                                                                     loss)

        # validate
        net.eval()
        acc = 0.0  # accumulate accurate number / epoch
        with torch.no_grad():
            val_bar = tqdm(validate_loader)
            for val_data in val_bar:
                val_images, val_labels = val_data
                outputs = net(val_images.to(devicE))
                preDict_y = torch.max(outputs, dim=1)[1]
                acc += torch.eq(preDict_y, val_labels.to(devicE)).sum().item()

        val_accurate = acc / val_num
        print('[epoch %d] Train_loss: %.3f  val_accuracy: %.3f' %
              (epoch + 1, running_loss / Train_steps, val_accuratE))

        if val_accurate > best_acc:
            best_acc = val_accurate
            torch.save(net.state_Dict(), save_path)

    print('Finished Training')


if __name__ == '__main__':
    main()

3. preDict.py

pytorch——AlexNet——训练花分类数据集_heart_6662的博客-CSDN博客与之前一样

import os
import json

import torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt

from model import vgg


def main():
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    data_transform = transforms.Compose(
        [transforms.Resize((224, 224)),
         transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    # load image
    img_path = "../tulip.jpg"
    assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)
    img = Image.open(img_path)
    plt.imshow(img)
    # [N, C, H, W]
    img = data_transform(img)
    # expand batch dimension
    img = torch.unsqueeze(img, dim=0)

    # read class_inDict
    json_path = './class_inDices.json'
    assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)

    json_file = open(json_path, "r")
    class_inDict = json.load(json_filE)
    
    # create model
    model = vgg(model_name="vgg16", num_classes=5).to(devicE)
    # load model weights
    weights_path = "./vgg16Net.pth"
    assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)
    model.load_state_Dict(torch.load(weights_path, map_LOCATIOn=devicE))

    model.eval()
    with torch.no_grad():
        # preDict class
        output = torch.squeeze(model(img.to(devicE))).cpu()
        preDict = torch.softmax(output, dim=0)
        preDict_cla = torch.argmax(preDict).numpy()

    print_res = "class: {}   prob: {:.3}".format(class_inDict[str(preDict_cla)],
                                                 preDict[preDict_cla].numpy())
    plt.title(print_res)
    for i in range(len(preDict)):
        print("class: {:10}   prob: {:.3}".format(class_inDict[str(i)],
                                                  preDict[i].numpy()))
    plt.show()


if __name__ == '__main__':
    main()

🚗注意

VGG网络模型深度较深࿰c;需要使用算力强大GPU进行训练(而且要内存大一点的GPU࿰c;我3050跑不动࿰c;pytorch会报错GPU内存不足)

你也可以试试改小batch_size

pytorch——VGG网络搭建

大佬总结

以上是大佬教程为你收集整理的pytorch——VGG网络搭建全部内容,希望文章能够帮你解决pytorch——VGG网络搭建所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。