首页 > 其他分享 >VGG16

VGG16

时间:2024-10-28 20:21:18浏览次数:3  
标签:nn VGG16 torch 卷积 Shape Output 512

1️⃣ VGG介绍

  Alexnet证明了神经网络变深是有效的,因此网络能不能更深更大?
  VGG(visual geometry group)是由牛津大学提出的使用“块思想”的网络,通过使用循环和子程序可以很容易地在任何现代深度学习框架的代码中实现这些重复的架构。
  VGG在2014ImageNet图像分类与定位挑战赛 ILSVRC-2014中取得在分类任务第二,定位任务第一的优异成绩。


2️⃣ 创新

  • LeNet(1995)
    • 2卷积+池化层
    • 2全连接层
  • AlexNet(2012)
    • 更大更深
    • ReLu,Dropout,数据增强
  • VGG(2014)
    • 相比Alexnet ,VGG使用了更小的卷积核,更深的网络结构,是一个利用小卷积核不断加深网络的一次尝试。

3️⃣ 网络结构

在这里插入图片描述
在这里插入图片描述
注意:上面这张图最后fc4096应该是fc1000,画错了

总的来说,VGG16由13个卷积层和3个全连接层组成,一共16层(池化层不算层数,因为不包含需要学习的权重和偏置)。

其中的13个卷积层可以分成5个VGG块:

  • 输入层:图片大小为3×224×224
  • 第1块:2个conv3-64组成(con3-64中3代表卷积核大小为3×3,64代表64个卷积核)
    • 第一个卷积:64个3×3卷积核,padding=1,stride=1
      输入:3×224×224
      输出:64×224×224
      再经过ReLu激活函数
    • 第二个卷积:64个3×3卷积核,padding=1,stride=1
      输入:64×224×224
      输出:64×224×224
      再经过ReLu激活函数
    • 最大池化:2×2,stride=2,padding=0
      输入:64×224×224
      输出:64×112×112
  • 第2块:2个conv3-128组成
    • 第一个卷积:128个3×3卷积核,padding=1,stride=1
      输入:64×112×112
      输出:128×112×112
      再经过ReLu激活函数
    • 第二个卷积:128个3×3卷积核,padding=1,stride=1
      输入:128×112×112
      输出:128×112×112
      再经过ReLu激活函数
    • 最大池化:2×2,stride=2,padding=0
      输入:128×112×112
      输出:128×56×56
  • 第3块:3个conv3-256组成
    • 第一个卷积:256个3×3卷积核,padding=1,stride=1
      输入:128×56×56
      输出:256×56×56
      再经过ReLu激活函数
    • 第二个卷积:256个3×3卷积核,padding=1,stride=1
      输入:256×56×56
      输出:256×56×56
      再经过ReLu激活函数
    • 第三个卷积:256个3×3卷积核,padding=1,stride=1
      输入:256×56×56
      输出:256×56×56
      再经过ReLu激活函数
    • 最大池化:2×2,stride=2,padding=0
      输入:256×56×56
      输出:256×28×28
  • 第4块:3个conv3-512组成
    • 第一个卷积:512个3×3卷积核,padding=1,stride=1
      输入:256×28×28
      输出:512×28×28
      再经过ReLu激活函数
    • 第二个卷积:512个3×3卷积核,padding=1,stride=1
      输入:512×28×28
      输出:512×28×28
      再经过ReLu激活函数
    • 第三个卷积:512个3×3卷积核,padding=1,stride=1
      输入:512×28×28
      输出:512×28×28
      再经过ReLu激活函数
    • 最大池化:2×2,stride=2,padding=0
      输入:512×28×28
      输出:512×14×14
  • 第5块:3个conv3-512组成
    • 第一个卷积:512个3×3卷积核,padding=1,stride=1
      输入:512×14×14
      输出:512×14×14
      再经过ReLu激活函数
    • 第二个卷积:512个3×3卷积核,padding=1,stride=1
      输入:512×14×14
      输出:512×14×14
      再经过ReLu激活函数
    • 第三个卷积:512个3×3卷积核,padding=1,stride=1
      输入:512×14×14
      输出:512×14×14
      再经过ReLu激活函数
    • 最大池化:2×2,stride=2,padding=0
      输入:512×14×14
      输出:512×7×7
  • 全连接层1:先通过nn.Flatten()将512×7×7展开到25088
    输入:25088
    输出:4096
    再经过ReLu激活函数
    再经过dropout=0.5
  • 全连接层2:
    输入:4096
    输出:4096
    再经过ReLu激活函数
    再经过dropout=0.5
  • 全连接层3
    输入:4096
    输出:1000
  • 最终输出层:
    输入:1000
    输出:2(将 1000 维映射到 2 维,二分类任务:猫和狗)

4️⃣ 代码

1. 分割数据,创建一个名为split_data.py的文件

需要数据集的话请私信我

import os
from shutil import copy
import random
from tqdm import tqdm


def mkfile(file):
    if not os.path.exists(file):
        os.makedirs(file)


folder_path = "D:\\code\\AI_ladder\\2_VGG"


# orig_data_path="D:\\code\\AI_ladder\\2_VGG\\data_origin"
orig_data_path = os.path.join(folder_path + '\\data_origin')
pet_class = [cla for cla in os.listdir(orig_data_path)]

mkfile(folder_path + '\\data\\train')
mkfile(folder_path + '\\data\\val')

for cla in pet_class:
    mkfile(folder_path + '\\data\\train\\' + cla)
    mkfile(folder_path + '\\data\\val\\' + cla)

split_rate = 0.2

# pet_class=['cat','dog']
for cla in pet_class:
    # D:\\code\\AI_ladder\\2_VGG\\data_origin\\cat\\
    # D:\\code\\AI_ladder\\2_VGG\\data_origin\\dog\\
    cla_path = orig_data_path + '\\' + cla + '\\'
    # cla_path路径下的所有图片文件名
    images = os.listdir(cla_path)
    # 统计数量
    num = len(images)
    eval_index = random.sample(images, k=int(num * split_rate))
    # enumerate(images),它会遍历 images 列表中的每个图片文件,同时生成一个 (index, image) 对,
    # 其中 index 是当前图片的索引,image 是当前图片的名称
    # 例如,假设 images = ['img1.jpg', 'img2.jpg', 'img3.jpg'],那么 enumerate(images) 将会生成:
    # (0, 'img1.jpg')
    # (1, 'img2.jpg')
    # (2, 'img3.jpg')

    # tqdm 接受一个迭代对象作为参数,并为这个迭代对象创建一个进度条显示。
    # 在这里,tqdm 接收 enumerate(images) 作为迭代对象
    # tqdm 会自动更新进度条,每次从 enumerate(images) 中获取一个新的 (index, image) 时,进度条会自动增加
    # total=len(images) 总共需要处理的图片数量,指定进度条的总长度
    loop = tqdm(enumerate(images),total=len(images))
    # 设置进度条的前缀描述信息
    loop.set_description(f'[{cla}]')
    for index, image in loop:
        # 验证集
        if image in eval_index:
            image_path = cla_path + image
            new_path = folder_path + '\\data\\val\\' + cla
            copy(image_path, new_path)
        # 训练集
        else:
            image_path = cla_path + image
            new_path = folder_path + '\\data\\train\\' + cla
            copy(image_path, new_path)

print("\nprocessing done")

2.网络结构,创建一个名为network.py的文件

# 导入pytorch库
import torch
# 引入了神经网络模块nn
from torch import nn

# 定义VGG类
class VGG(nn.Module):
    # conv_arch是VGG中每个块的配置参数,包含两部分:卷积层个数和输出通道数
    def __init__(self, conv_arch):
        super(VGG, self).__init__() 
        self.conv_arch=conv_arch

        # 创建VGG块
        self.conv_blks = self.make_vgg_blocks(conv_arch)
        
        # 创建三个全连接层
        # 先nn.Flatten 将输入展平为一维张量,以便传入线性层
        # 全连接层1:第一个线性层的输入大小为 25088,输出大小为 4096,再经过ReLu和dropout
        # 全连接层2:第二个线性层的输入大小为 4096,输出大小为 4096,再经过ReLu和dropout
        # 全连接层3:第三个线性层的输入大小为 4096,输出大小为 10,
        # 二分类:最终输出层nn.Linear(1000, 2)
        self.fc = nn.Sequential(
            nn.Flatten(),
            nn.Linear(25088, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 1000),
            nn.Linear(1000, 2)
        )


    def make_vgg_blocks(self, conv_arch):
        # 定义了一个空列表blocks,用于存储生成的VGG块
        blocks = []
        # 输入通道维度
        in_channels = 3
        # 遍历 conv_arch
        # num_convs:卷积层个数
        # out_channels:输出通道数
        for (num_convs, out_channels) in conv_arch:
            # 创建VGG块
            blocks.append(self.vgg_block(num_convs, in_channels, out_channels))
            # 在块与块之间,下一个块的输入通道数等于上一个块的输出通道数
            in_channels = out_channels
        return nn.Sequential(*blocks)
    
    # 静态方法,调用时不需要传递 self 参数,也就是说,这个方法不会直接访问实例属性
    @staticmethod
    def vgg_block(num_convs, in_channels, out_channels):
        # 定义了一个空列表layers,用于存储VGG块中的所有层
        layers = []
        # 遍历 卷积层个数
        for _ in range(num_convs):
            # VGG中所有的卷积核的大小都是3×3,padding=1,stride=1
            layers.append(
                nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, padding=1))
            # 激活函数
            layers.append(nn.ReLU())
            # 在同一个块中,下一层卷积的输入通道数等于上一层输出的卷积通道数
            in_channels = out_channels
        # 最大池化,2×2,stride=2,padding=0
        layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
        # 使用星号 * 对列表进行解包,将 layers 中的每个元素作为 nn.Sequential 的参数传递
        return nn.Sequential(*layers)
    
    def forward(self, x):
        feature = self.conv_blks(x)
        output = self.fc(feature)
        return output
    

def register_hooks(model):
    # 定义钩子函数 hook:这是一个内部函数,它会被注册为模型每一层的钩子。
    # 在前向传播过程中,当每一层执行完毕时,这个钩子函数会被触发

    # module:表示当前被钩子的模块(层)。例如,它可以是卷积层、池化层、全连接层等。
    # input:是传入当前模块的输入张量,形状与输入数据的形状一致(通常是元组形式)。
    # output:是从当前模块得到的输出张量
    def hook(module, input, output):
        # 获取当前层的类名,例如 Conv2d、ReLU、MaxPool2d 等
        class_name = module.__class__.__name__
        # 打印当前层的类名和其输出张量的形状
        print(f"{class_name} Output Shape: {output.shape}")

    # 注册钩子函数
    for layer in model.modules():
        # 排除 nn.Sequential:nn.Sequential 是一个包含多个层的容器类,我们通常希望钩子直接注册到具体的层,而不是容器本身。
        # 排除 nn.ModuleList:nn.ModuleList 是另一种容器类,通常用于将多个模块按列表存储。
        # 排除顶级的模型类本身:检查 (layer == model) 以确保不会在整个模型对象上注册钩子
        if not isinstance(layer, nn.Sequential) and not isinstance(layer, nn.ModuleList) and not (layer == model):
            # 对于通过检查的每一个 layer,调用 register_forward_hook 方法,将之前定义的 hook 函数注册到该层上
            layer.register_forward_hook(hook)


if __name__=='__main__':
    # conv_arch是VGG中每个块的配置参数,包含两部分:卷积层个数和输出通道数
    # VGG中的卷积包含padding,因此不改变高宽,卷积的作用是改变输出通道数
    # 对于VGG16来说,由5个块组成
    # 第1块:2个conv3-64组成(con3-64中3代表卷积核大小为3×3,64代表64个卷积核)
    # 第2块:2个conv3-128组成
    # 第3块:3个conv3-256组成
    # 第4块:3个conv3-512组成
    # 第5块:3个conv3-512组成
    conv_arch = ((2, 64), (2, 128), (3, 256), (3, 512), (3, 512))
    # 创建输入张量 X,其大小为 (1, 3, 224, 224),表示批次大小为 1、三通道、尺寸为 224x224
    X = torch.randn(size=(1, 3, 224, 224))
    # 实例化 VGG 模型 net
    net = VGG(conv_arch)
    # 注册钩子以打印每层的输出尺寸
    register_hooks(net)
    # 进行一次前向传播,输出最终结果
    y = net(X)
    print('Final output:\t', y)

这里打印了每一层的输出大小,和前面通过公式计算得到的结果一致:

输入[1,3,224,224]
第一个VGG块
Conv2d Output Shape: torch.Size([1, 64, 224, 224])
ReLU Output Shape: torch.Size([1, 64, 224, 224])
Conv2d Output Shape: torch.Size([1, 64, 224, 224])
ReLU Output Shape: torch.Size([1, 64, 224, 224])
MaxPool2d Output Shape: torch.Size([1, 64, 112, 112])
第二个VGG块
Conv2d Output Shape: torch.Size([1, 128, 112, 112])
ReLU Output Shape: torch.Size([1, 128, 112, 112])
Conv2d Output Shape: torch.Size([1, 128, 112, 112])
ReLU Output Shape: torch.Size([1, 128, 112, 112])
MaxPool2d Output Shape: torch.Size([1, 128, 56, 56])
第三个VGG块
Conv2d Output Shape: torch.Size([1, 256, 56, 56])
ReLU Output Shape: torch.Size([1, 256, 56, 56])
Conv2d Output Shape: torch.Size([1, 256, 56, 56])
ReLU Output Shape: torch.Size([1, 256, 56, 56])
Conv2d Output Shape: torch.Size([1, 256, 56, 56])
ReLU Output Shape: torch.Size([1, 256, 56, 56])
MaxPool2d Output Shape: torch.Size([1, 256, 28, 28])
第四个VGG块
Conv2d Output Shape: torch.Size([1, 512, 28, 28])
ReLU Output Shape: torch.Size([1, 512, 28, 28])
Conv2d Output Shape: torch.Size([1, 512, 28, 28])
ReLU Output Shape: torch.Size([1, 512, 28, 28])
Conv2d Output Shape: torch.Size([1, 512, 28, 28])
ReLU Output Shape: torch.Size([1, 512, 28, 28])
MaxPool2d Output Shape: torch.Size([1, 512, 14, 14])
第五个VGG块
Conv2d Output Shape: torch.Size([1, 512, 14, 14])
ReLU Output Shape: torch.Size([1, 512, 14, 14])
Conv2d Output Shape: torch.Size([1, 512, 14, 14])
ReLU Output Shape: torch.Size([1, 512, 14, 14])
Conv2d Output Shape: torch.Size([1, 512, 14, 14])
ReLU Output Shape: torch.Size([1, 512, 14, 14])
MaxPool2d Output Shape: torch.Size([1, 512, 7, 7])
全连接层1
Flatten Output Shape: torch.Size([1, 25088])
Linear Output Shape: torch.Size([1, 4096])
ReLU Output Shape: torch.Size([1, 4096])
Dropout Output Shape: torch.Size([1, 4096])
全连接层2
Linear Output Shape: torch.Size([1, 4096])
ReLU Output Shape: torch.Size([1, 4096])
Dropout Output Shape: torch.Size([1, 4096])
全连接层3
Linear Output Shape: torch.Size([1, 1000])
最终输出层
Linear Output Shape: torch.Size([1, 2])

3.训练网络,创建一个名为train.py的文件

# 导入pytorch库
import torch
# 引入了神经网络模块nn
from torch import nn

# 定义VGG类
class VGG(nn.Module):
    # conv_arch是VGG中每个块的配置参数,包含两部分:卷积层个数和输出通道数
    def __init__(self, conv_arch):
        super(VGG, self).__init__() 
        self.conv_arch=conv_arch

        # 创建VGG块
        self.conv_blks = self.make_vgg_blocks(conv_arch)
        
        # 创建三个全连接层
        # 先nn.Flatten 将输入展平为一维张量,以便传入线性层
        # 全连接层1:第一个线性层的输入大小为 25088,输出大小为 4096,再经过ReLu和dropout
        # 全连接层2:第二个线性层的输入大小为 4096,输出大小为 4096,再经过ReLu和dropout
        # 全连接层3:第三个线性层的输入大小为 4096,输出大小为 10,
        # 二分类:最终输出层nn.Linear(1000, 2)
        self.fc = nn.Sequential(
            nn.Flatten(),
            nn.Linear(25088, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 1000),
            nn.Linear(1000, 2)
        )


    def make_vgg_blocks(self, conv_arch):
        # 定义了一个空列表blocks,用于存储生成的VGG块
        blocks = []
        # 输入通道维度
        in_channels = 3
        # 遍历 conv_arch
        # num_convs:卷积层个数
        # out_channels:输出通道数
        for (num_convs, out_channels) in conv_arch:
            # 创建VGG块
            blocks.append(self.vgg_block(num_convs, in_channels, out_channels))
            # 在块与块之间,下一个块的输入通道数等于上一个块的输出通道数
            in_channels = out_channels
        return nn.Sequential(*blocks)
    
    # 静态方法,调用时不需要传递 self 参数,也就是说,这个方法不会直接访问实例属性
    @staticmethod
    def vgg_block(num_convs, in_channels, out_channels):
        # 定义了一个空列表layers,用于存储VGG块中的所有层
        layers = []
        # 遍历 卷积层个数
        for _ in range(num_convs):
            # VGG中所有的卷积核的大小都是3×3,padding=1,stride=1
            layers.append(
                nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, padding=1))
            # 激活函数
            layers.append(nn.ReLU())
            # 在同一个块中,下一层卷积的输入通道数等于上一层输出的卷积通道数
            in_channels = out_channels
        # 最大池化,2×2,stride=2,padding=0
        layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
        # 使用星号 * 对列表进行解包,将 layers 中的每个元素作为 nn.Sequential 的参数传递
        return nn.Sequential(*layers)
    
    def forward(self, x):
        feature = self.conv_blks(x)
        output = self.fc(feature)
        return output
    

def register_hooks(model):
    # 定义钩子函数 hook:这是一个内部函数,它会被注册为模型每一层的钩子。
    # 在前向传播过程中,当每一层执行完毕时,这个钩子函数会被触发

    # module:表示当前被钩子的模块(层)。例如,它可以是卷积层、池化层、全连接层等。
    # input:是传入当前模块的输入张量,形状与输入数据的形状一致(通常是元组形式)。
    # output:是从当前模块得到的输出张量
    def hook(module, input, output):
        # 获取当前层的类名,例如 Conv2d、ReLU、MaxPool2d 等
        class_name = module.__class__.__name__
        # 打印当前层的类名和其输出张量的形状
        print(f"{class_name} Output Shape: {output.shape}")

    # 注册钩子函数
    for layer in model.modules():
        # 排除 nn.Sequential:nn.Sequential 是一个包含多个层的容器类,我们通常希望钩子直接注册到具体的层,而不是容器本身。
        # 排除 nn.ModuleList:nn.ModuleList 是另一种容器类,通常用于将多个模块按列表存储。
        # 排除顶级的模型类本身:检查 (layer == model) 以确保不会在整个模型对象上注册钩子
        if not isinstance(layer, nn.Sequential) and not isinstance(layer, nn.ModuleList) and not (layer == model):
            # 对于通过检查的每一个 layer,调用 register_forward_hook 方法,将之前定义的 hook 函数注册到该层上
            layer.register_forward_hook(hook)


if __name__=='__main__':
    # conv_arch是VGG中每个块的配置参数,包含两部分:卷积层个数和输出通道数
    # VGG中的卷积包含padding,因此不改变高宽,卷积的作用是改变输出通道数
    # 对于VGG16来说,由5个块组成
    # 第1块:2个conv3-64组成(con3-64中3代表卷积核大小为3×3,64代表64个卷积核)
    # 第2块:2个conv3-128组成
    # 第3块:3个conv3-256组成
    # 第4块:3个conv3-512组成
    # 第5块:3个conv3-512组成
    conv_arch = ((2, 64), (2, 128), (3, 256), (3, 512), (3, 512))
    # 创建输入张量 X,其大小为 (1, 3, 224, 224),表示批次大小为 1、三通道、尺寸为 224x224
    X = torch.randn(size=(1, 3, 224, 224))
    # 实例化 VGG 模型 net
    net = VGG(conv_arch)
    # 注册钩子以打印每层的输出尺寸
    register_hooks(net)
    # 进行一次前向传播,输出最终结果
    y = net(X)
    print('Final output:\t', y)


标签:nn,VGG16,torch,卷积,Shape,Output,512
From: https://blog.csdn.net/qq_42980908/article/details/143302345

相关文章

  • 使用vgg16 ————对乳腺超声图像进行分类(两种方法)
    文章目录一、对乳腺超声图像进行分类的重要性二、原始数据三、详细代码解释(方法1)导入库数据预处理和展示读取数据和标签数据集划分创建目录结构复制图像文件统计和显示各个数据集中不同类别的图像数量显示训练集中每个类别的样本图像使用ImageFolder创建训练、验证和测......
  • 基于VGG16特征提取与聚类优化的苹果分类系统开发与性能提升
    数据集链接:https://pan.baidu.com/s/1qQglNzAIkBNxdrwND0NLNQ?pwd=data 提取码:data1.目的任务:根据original_data样本数据,建立模型,对test的图片进行普通/其他苹果判断 1.数据增强,扩充确认为普通苹果的样本数量 2.特征提取,使用VGG16模型提取特征 3.图片批量处理 ......
  • 使用VGG16和MLP实现猫狗图像识别
    数据集数据集可以参考我之前那篇文章,取一部分数据每个300条即可:基于卷积神经网络(CNN)的猫狗图像分类系统实现-CSDN博客1.目的使用VGG16的结构提取图像特征,再根据特征建立MLP模型,实现猫狗图像识别。训练/测试数据:data 1.对数据进行分离、计算测试数据准确率 2.使用VGG1......
  • 图像识别算法--VGG16
    前言:人类科技就是不断烧开水(发电)、丢石头(航天等)。深度学习就是一个不断解方程的过程(参数量格外大的方程)本文内容:1、介绍VGG16基本原理2、VGG16pytorch复现图像识别算法--VGG16目录图像识别算法--VGG161、参考文献2、VGG16理论2.1VGG16优点2.2VGG16网络结构图2.2.1复现代......
  • 解决 keras 首次装载预训练模型VGG16 时下载失败问题
    解决:Exception:URLfetchfailureonhttps://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5:None--[Errno104]Connectionresetbypeer解决方案:1、先将数据集单独下载下来:models/vgg16_weights_tf_d......
  • 基于Vgg16和Vgg19深度学习网络的步态识别系统matlab仿真
    1.算法运行效果图预览  2.算法运行软件版本MATLAB2022A 3.算法理论概述       步态识别作为生物特征识别领域的一个重要分支,在人体运动分析、身份验证、健康监测等方面具有广泛的应用前景。步态能量图(GaitEnergyImage,简称GEI)是一种有效的步态表示方法,通过......
  • 基于VGG16深度学习网络的目标识别matlab仿真,并结合ROC指标衡量识别性能
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要根据卷积核大小和卷积层数,VGG共有6中配置,分别为A,A-LRN,B,C,D,E,其中D和E两种最为常用,即i我们所说的VGG16和VGG19。具体为:卷积-卷积-池化-卷积-卷积-池化-卷积-卷积-卷积-池化-卷积-卷积-卷积-池化-卷积-卷积-......
  • 基于VGG16深度学习网络的目标识别matlab仿真,并结合ROC指标衡量识别性能
    1.算法仿真效果matlab2022a仿真结果如下:   2.算法涉及理论知识概要         根据卷积核大小和卷积层数,VGG共有6中配置,分别为A,A-LRN,B,C,D,E,其中D和E两种最为常用,即i我们所说的VGG16和VGG19。 具体为: 1.卷积-卷积-池化-卷积-卷积-池化-卷积-卷积-卷积-......
  • VGG16模型-tensorflow实现的架构
    importtensorflowastffromtensorflow.keras.modelsimportSequentialfromtensorflow.keras.layersimportInputLayer,Dense,Flatten,Conv2D,MaxPooling2Dfromtensorflow.keras.optimizersimportAdamdefbuild_vgg16(input_shape,num_classes):model......
  • VGG16模型
    VGG16模型,权重由ImageNet训练而来该模型可同时构建于channels_first(通道,高度,宽度)和channels_last(高度,宽度,通道)两种输入维度顺序。模型的默认输入尺寸是224x224(一)模型参数keras.applications.vgg16.VGG16(include_top=True,#是否保留顶层的3个全连接网络weights='im......