当前位置: 首页 > wzjs >正文

网站建设合同要交印花吗seo站长助手

网站建设合同要交印花吗,seo站长助手,建站之星破解版下载,web前端框架一、前言 随着人工智能和深度学习技术的迅猛发展,卷积神经网络(Convolutional Neural Networks,CNN)已经成为计算机视觉领域中最为重要的工具之一。无论是在图像分类、目标检测,还是在人脸识别、自动驾驶等应用中&…

一、前言

随着人工智能和深度学习技术的迅猛发展,卷积神经网络(Convolutional Neural Networks,CNN)已经成为计算机视觉领域中最为重要的工具之一。无论是在图像分类、目标检测,还是在人脸识别、自动驾驶等应用中,CNN都展现出了其卓越的表现和广泛的应用前景。

本文旨在通过深入的实战案例,带领读者一步步理解并掌握CNN的核心原理及其在图片识别中的应用。我们将通过实际操作和代码演示,帮助读者将理论与实践相结合,全面提升在深度学习方向上的技能,为解决复杂的图像处理问题打下坚实的基础。

二、实战

2.1 下载Jupyter Notebook

# 切换成你想要的环境,这里我是默认base环境。
conda activate base
# 生成notebook的配置
jupyter notebook --generate-config
# 把这个配置打开并调整成你需要打开的默认文件 c.NotebookApp.notebook_dir = '/path/to/your/directory'
vim ~/.jupyter/jupyter_notebook_config.py
jupyter notebook

在这里插入图片描述

2.2 导入需要用到的工具包

# os 模块提供了一系列与操作系统交互的功能
import os
#  Python 中非常流行的绘图库 Matplotlib 的一个子模块,用于创建各种类型的图表和可视化。
import matplotlib.pyplot as plt
# 是一个 IPython 魔法命令(magic command),通常用于 Jupyter Notebook 中。它的作用是使得 Matplotlib 绘制的图表直接嵌入在 Notebook 的输出单元中,而不是弹出一个单独的窗口显示图表。
%matplotlib inline
# NumPy 是用于数值计算的强大库,主要用于处理多维数组、矩阵操作,以及提供了大量数学函数和工具,特别适合科学计算和数据处理。
import numpy as np
# torch 是一个用于深度学习的开源框架,由 Facebook 开发。PyTorch 具有强大的张量运算能力和自动微分功能,并且广泛应用于构建和训练神经网络模型,特别是在研究和生产中的深度学习任务中使用非常流行。
import torch
# 构建神经网络的工具
from torch import nn
# 导入 PyTorch 的优化器模块 torch.optim。该模块包含了多种优化算法,用于训练神经网络时更新模型的参数。常见的优化器包括随机梯度下降(SGD)、Adam、RMSprop 等。
import torch.optim as optim
# 它是 PyTorch 生态系统的一部分,专门为计算机视觉任务提供了便捷的工具和数据集。Torchvision 包含了预训练模型、数据集、数据预处理和数据增强等常用功能
import torchvision
# transforms 图像处理与数据增强模块,提供如裁剪、翻转、旋转、缩放等操作。
# models 提供多种经典的卷积神经网络架构,如 ResNet、VGG、AlexNet、MobileNet 等,且支持加载预训练模型。
# datasets 常见的数据集加载模块,支持的数据集包括 CIFAR-10、MNIST、COCO、ImageNet 等。 
from torchvision import transforms, models, datasets
# imageio 是一个用于读取和写入图像、视频、GIF 和其他多媒体文件的 Python 库,支持多种格式(如 PNG、JPEG、TIFF、GIF、MP4 等),并且具有简单易用的接口。
import imageio
# 提供时间相关的功能,如获取当前时间、延迟执行等。
import time
# 用于发出警告消息,通常用于提示用户程序的潜在问题或使用不推荐的功能。
import warnings
# 提供生成随机数的功能,包括整型、浮点型随机数以及随机选择等。
import random
# 提供对 Python 解释器和环境的访问,包括系统参数、模块路径等。
import sys
# 提供浅拷贝和深拷贝的功能,用于复制对象。
import copy
# 用于处理 JSON 数据的编码和解码。
import json
# 提供对图像的操作功能,包括打开、保存、转换图像格式等。PIL(Python Imaging Library)现在被 Pillow 取代,Pillow 是 PIL 的一个分支并提供了相同的接口。
from PIL import Image

2.3 数据读取与预处理操作

# 获取当前工作目录
current_directory = os.getcwd()
# 使用相对路径拼接文件路径
relative_path = 'flower_data/'
data_dir = os.path.join(current_directory, relative_path)
train_dir = data_dir + '/train'
valid_dir = data_dir + '/valid'

2.4 制作好数据源

  • data_transforms中指定了所有图像预处理操作
  • ImageFolder假设所有的文件按文件夹保存好,每个文件夹下面存贮同一类别的图片,文件夹的名字为分类的名字。
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=Btransforms.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])]),
}
batch_size = 8image_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

可以看看他们的结果集:

在这里插入图片描述

2.5 读取标签对应的实际名字

current_directory = os.getcwd()
relative_path = 'cat_to_name.json'
file_path = os.path.join(current_directory, relative_path)with open(file_path, 'r') as f:cat_to_name = json.load(f)

2.6 展示下数据

  • 注意tensor的数据需要转换成numpy的格式,而且还需要还原回标准化的结果。
def im_convert(tensor):""" 将 Tensor 转换为可展示的图像 """# 将 Tensor 转到 CPU 并复制一份,同时切断与计算图的关系image = tensor.to("cpu").clone().detach()# 转换为 NumPy 数组并去掉批次维度image = image.numpy().squeeze()# 转置维度以匹配 (H, W, C) 格式image = image.transpose(1,2,0)# 反归一化图像image = image * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406))# 将像素值限制在 [0, 1] 之间image = image.clip(0, 1)return image

为了创建一个包含 8 张图像(2 行 4 列)的网格,显示从 dataloaders[‘valid’] 中获取的图像, 并在每个图像上方显示相应的标题。这是常用于深度学习中的数据可视化步骤,比如在 PyTorch 中查看图像和对应的分类标签。

# 创建一个图像,大小为 20x12 英寸
fig=plt.figure(figsize=(20, 12))
# 设置列数为 4
columns = 4
# 设置行数为 2
rows = 2
# 获取数据加载器的迭代器
dataiter = iter(dataloaders['valid'])
# 获取下一批数据 (inputs 是图像, classes 是对应的标签)
inputs, classes = dataiter.next()# 共8张图片
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()

跑一下结果:
在这里插入图片描述

2.7 加载models中提供的模型,并且直接用训练好的权重当做初始化参数

  • 第一次执行需要下载,可能会比较慢,我会提供给大家一份下载好的,可以直接放到相应路径
# 可选的比较多 ['resnet', 'alexnet', 'vgg', 'squeezenet', 'densenet', 'inception']
model_name = 'resnet'  
# 是否用人家训练好的特征来做
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")

set_parameter_requires_grad 函数用于设置模型的参数是否需要计算梯度,通常用于迁移学习中的 特征提取(feature extraction)。如果 feature_extracting 参数为 True,函数会将模型的所有参数的 requires_grad 属性设为 False,意味着这些参数在反向传播时不会被更新。

def set_parameter_requires_grad(model, feature_extracting):if feature_extracting:for param in model.parameters():param.requires_grad = False

使用场景:

当你做迁移学习时,如果你只想更新模型的最后几层,而保持其他层的权重不变,可以使用这个函数将不需要更新的层冻结。例如在使用预训练的卷积神经网络(如 ResNet)进行图像分类时,常会冻结卷积层,只更新最后的全连接层。

老周这里在 CPU 上训练深度学习模型,尤其是像 ResNet-152 这样的大型模型,速度会非常慢,因为 ResNet-152 是一个非常深的网络,有 152 层卷积层和残差块,非常适合在 GPU 上运行。而 CPU 在处理深度神经网络时,特别是在大型数据集和复杂模型上,性能会明显下降。我这里选择 ResNet-18。

  • 参数量:约 11M 参数。
  • 特点:相比 ResNet-152,ResNet-18 要浅很多,只有 18 层,但依然保留了 ResNet 的优点——残差连接结构。如果你需要一个比 ResNet-152 更轻量的网络,并且愿意牺牲部分性能,ResNet-18 是一个不错的选择。
  • 使用场景:小型数据集或需要在 CPU 上训练的场景。
model_ft = models.resnet18()
model_ft

在这里插入图片描述
2.8 参考pytorch官网例子

根据指定的模型名称初始化不同的预训练模型,同时可以选择是否进行特征提取(即冻结部分参数)和更改最后的分类层,以适应不同的分类任务。这个函数涵盖了多种经典的卷积神经网络架构,比如 ResNet、AlexNet、VGG、SqueezeNet、DenseNet 和 Inception。

def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True):# 选择合适的模型,不同模型的初始化方法稍微有点区别model_ft = Noneinput_size = 0# Resnet152if model_name == "resnet":model_ft = models.resnet152(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.fc.in_featuresmodel_ft.fc = nn.Sequential(nn.Linear(num_ftrs, 102),nn.LogSoftmax(dim=1))input_size = 224# Alexnetelif model_name == "alexnet":model_ft = models.alexnet(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.classifier[6].in_featuresmodel_ft.classifier[6] = nn.Linear(num_ftrs,num_classes)input_size = 224# VGG11_bnelif model_name == "vgg":model_ft = models.vgg16(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.classifier[6].in_featuresmodel_ft.classifier[6] = nn.Linear(num_ftrs,num_classes)input_size = 224# Squeezenetelif model_name == "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_classesinput_size = 224# Densenetelif model_name == "densenet":model_ft = models.densenet121(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.classifier.in_featuresmodel_ft.classifier = nn.Linear(num_ftrs, num_classes)input_size = 224# Inception v3 (Be careful, expects (299,299) sized images and has auxiliary output)elif model_name == "inception": model_ft = models.inception_v3(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)# Handle the auxilary netnum_ftrs = model_ft.AuxLogits.fc.in_featuresmodel_ft.AuxLogits.fc = nn.Linear(num_ftrs, num_classes)# Handle the primary netnum_ftrs = model_ft.fc.in_featuresmodel_ft.fc = nn.Linear(num_ftrs,num_classes)input_size = 299else:print("Invalid model name, exiting...")exit()return model_ft, input_size

2.9 设置哪些层需要训练

# 初始化模型
model_ft, input_size = initialize_model(model_name, 102, feature_extract, use_pretrained=True)# GPU计算
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model_ft = model_ft.to(device)# 设置要训练的参数
params_to_update = model_ft.parameters()
print("Params to learn:")# 如果 feature_extract=True,意味着你只会训练最后的分类层,之前的层保持冻结,避免更新权重。
if feature_extract:params_to_update = []for name, param in model_ft.named_parameters():if param.requires_grad:params_to_update.append(param)print("\t", name)
# 如果 feature_extract=False,则意味着你希望训练所有层,因此无需修改 params_to_update。
else:for name, param in model_ft.named_parameters():if param.requires_grad:print("\t", name)

在这里插入图片描述
在这里插入图片描述

2.10 优化器设置

# 优化器设置(使用 Adam 优化器,并设置了较高的学习率 1e-2)
optimizer_ft = optim.Adam(params_to_update, lr=1e-2)
# 学习率调度器(用了 StepLR 学习率调度器,每 7 个 epoch 后学习率衰减到原来的 1/10。)
# 这种策略有助于在训练过程中逐步减小学习率,防止过拟合,同时也能让模型更稳定地收敛。
scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)
# 最后一层已经LogSoftmax()了,所以不能nn.CrossEntropyLoss()来计算了,nn.CrossEntropyLoss()相当于logSoftmax()和nn.NLLLoss()整合
# 这是针对对数概率分布的负对数似然损失函数:
criterion = nn.NLLLoss()

2.11 训练模块

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.0running_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# resnet执行的是这里else: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() - sinceprint('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_accbest_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() - sinceprint('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 

2.12 开始训练

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"))

在这里插入图片描述
两轮Epoch花了1个多钟,因为我这里是CPU训练的,比较慢。我这里调整下num_epochs为2.

2.13 再继续训练所有层

for param in model_ft.parameters():param.requires_grad = True# 再继续训练所有的参数,学习率调小一点
optimizer = optim.Adam(params_to_update, lr=1e-4)
# # 确保optimizer使用的是所有参数
scheduler = optim.lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)# 损失函数,确保最后一层是 LogSoftmax
criterion = nn.NLLLoss()
# 加载检查点
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, val_acc_history, train_acc_history, valid_losses, train_losses, LRs  = train_model(model_ft, dataloaders, criterion, optimizer, num_epochs=2, is_inception=(model_name=="inception"))

在这里插入图片描述
2.14 加载训练好的模型

# 初始化模型
model_ft, input_size = initialize_model(model_name, 102, feature_extract, use_pretrained=True)
# GPU模式
model_ft = model_ft.to(device)
# 保存文件的名字
filename = 'checkpoint.pth'
# 加载模型
checkpoint = torch.load(filename)
# 恢复最好的验证准确率
best_acc = checkpoint['best_acc']
# 加载模型权重
model_ft.load_state_dict(checkpoint['state_dict'])

2.15 测试数据预处理

  • 测试数据处理方法需要跟训练时一致才可以
  • 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)/2bottom_margin = (img.height-224)/2right_margin = left_margin + 224top_margin = bottom_margin + 224img = img.crop((left_margin, bottom_margin, right_margin,   top_margin))# 相同的预处理方法img = np.array(img)/255mean = np.array([0.485, 0.456, 0.406]) #provided meanstd = np.array([0.229, 0.224, 0.225]) #provided stdimg = (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()# 颜色通道还原 (H, W, C)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# 确保数值在 [0, 1] 之间image = np.clip(image, 0, 1)# 显示图像ax.imshow(image)ax.set_title(title)# 隐藏坐标轴ax.axis('off')  return ax
image_path = 'image_06621.jpg'
img = process_image(image_path)
imshow(img)

在这里插入图片描述

# 从验证集获取一个batch的数据
dataiter = iter(dataloaders['valid'])
images, labels = next(dataiter)  # 模型切换到评估模式
model_ft.eval()# 将输入传到模型
if train_on_gpu:# 如果在GPU上训练,输入数据也要搬到GPU上output = model_ft(images.cuda())
else:output = model_ft(images)

output表示对一个batch中每一个数据得到其属于各个类别的可能性

output.shape
torch.Size([2, 102])

2.16 得到概率最大的那个

# 获取预测的类别索引
_, preds_tensor = torch.max(output, 1)# 将张量移回 CPU 并转换为 NumPy 数组
if train_on_gpu:preds = preds_tensor.cpu().numpy()
else:preds = preds_tensor.numpy()# 使用 np.squeeze() 去掉单个批次维度(将预测的结果去掉单一维度,保持数据维度的整洁。)
preds = np.squeeze(preds)# 打印预测
print(preds)
[71 89]

2.17 展示预测结果

fig = plt.figure(figsize=(20, 20))
columns = 2
rows = 1for idx in range(columns * rows):ax = fig.add_subplot(rows, columns, idx+1, xticks=[], yticks=[])# 显示图像plt.imshow(im_convert(images[idx]))# 获取预测类别和真实类别的名称pred_label = cat_to_name[str(preds[idx])]true_label = cat_to_name[str(labels[idx].item())]# 设置标题,颜色标记是否正确ax.set_title("{} ({})".format(pred_label, true_label),color=("green" if pred_label == true_label else "red"))plt.show()

在这里插入图片描述
2.18 小结

可以看出上诉两张图片识别错误,这也很正常,老周这里只跑了两个批次batch_size,训练所有层的时候我把num_epochs=20调整成2,调整成2都跑了3个钟,所以训练模型还得拿GPU来跑!!!

三、论文解读

上诉代码可以看出,老周这里用的是resnet18的一个网络模型,只有18层,因为我这里用的CPU跑的,层数太深我这边跑不动,需要换GPU。

看其它网络模型,给我的直观感觉就是层数越多表现的效果越好,卷积越多越好吗?不一定,我们还是来看下论文里实践跑的效果。

在这里插入图片描述
论文地址:Deep Residual Learning for Image Recognition

可以看出,红色线是一个56层的网络,黄色线是一个20层的网络,从20层延伸到56层我们可以看到无论是 training error、test error,20层的都比56层的要好。所以,在神经网络当中,越深的神经网络没有我们想象的那么好,即网络层数也不能无限做深下去。我能不能把网络层数做多一些并且效果还很好的,这样网络层数更多并且效果要比浅层神经网络更好是我们的目标,那下面来看看作者是怎么设计的?

在这里插入图片描述
我们可以看到经过了一个卷积以后得到了一个结果,右边还有一条线直接拿过来。刚才我们上面说了卷积神经网络层数越多效果可能不好,在越多的时候其中那两层可能效果不好,右边那个直接拿过来就是以防那两层卷积效果不好,再不好的情况下直接拿上一层的效果最好的值。理解了这一点,我们再来看整体架构就简单了。

在这里插入图片描述
VGG-19我们就不看,我们来对比 34-layer plain(正常网络) 和 34-layer residua(残差网络),感觉没啥区别,参数都是一致的,但是右边的那个传参网络多了一条一条线,在整个神经网络中都加上一个个的小模块,每一层都是通过一个小模块相连的,这样的话就保证了一点,网络架构不会比原来更差的。不知道你有没有注意到,不同颜色连接处是用虚线连接的,不通颜色之间有啥不同?显而易见是特征图的个数不一样,虚线的作用就是做了一个1×1的卷积(把我们的特征图的个数进行翻倍)。

在这里插入图片描述

结论:右边残差网络34层比18层效果要更好,左边的普通网络没有呈现34层比18层效果要更好的趋势。

四、Resnet网络架构

在这里插入图片描述
从左到右看,input输入数据,再到ZERO PAD,也就是边缘上加几层0,让边界点利用的更加充分。我们再看stage 1,conv、Batch Norm、ReLU、MAX POOL,总之进行正常的卷积池化操作。主要来看下stage2(3、4、5一样),这些就是上面论文中介绍的一个模块,这一个个模块做了残差网络当中最核心的计算。

蓝色的是卷积模块,红色的是映射模块。如下图:

在这里插入图片描述
这里解释下identity_block模块,输入的特征图的大小以及个数(如:[32,32,64])与下面经过了三次卷积完成之后的特征图的大小以及个数(如:[32,32,64])要一致,这样才能进行相加操作。

我们再来看convolution_block模块,如果一直让特征图保持一样,那特征就没那么丰富了。比如第一个是[32,32,64],第二个是[32,32,64],第三个是[32,32,256],那要想进行相加,上面那条线就得进行[1,1,256]的卷积得到[32,32,256],这样才能和下面第三个的[32,32,256]进行相加。

理解了这两个模块,那残差网络架构的核心你也就知道了。

http://www.dtcms.com/wzjs/280570.html

相关文章:

  • 中企动力 集团网站百度软件应用市场
  • 学网站开发跟那个专业最相近seo专员的工作内容
  • 微网站如何做微信支付宝支付关键词推广技巧
  • 网站制作与网站建设企业营销策略分析论文
  • 网站文章做排名营销策略是什么
  • 金融行业网站制作论述搜索引擎优化的具体措施
  • wordpress主体seo对网店推广的作用有哪些
  • 网站访问次数受限十个有创意的线上活动
  • 网站中的表单怎么做合肥今日头条新闻
  • 吉林疫情最新消息青岛百度关键词优化
  • 企业网站模板建立流程seo整站优化更能准确获得客户
  • 宁波电信网站备案搜索引擎优化特点
  • 专门做nba评论的网站百度推广账号
  • wordpress注册没有密码福州搜索引擎优化公司
  • 淘宝宝贝链接怎么做相关网站海南seo快速排名优化多少钱
  • 卖信息的网站网站关键字优化公司
  • 沈丘做网站去哪里精准营销的成功案例
  • 加速器免费加速优化设计官方电子版
  • 腾讯企业邮箱扫码登录北京seo经理
  • 网站建设公司苏州百度推广在哪里能看到
  • 西安竞价托管seo81
  • 汇鑫网站建设方便社交网络的推广方法有哪些
  • 平面设计赚钱网站关闭站长工具seo综合查询
  • 学网站制作多少钱水果网络营销策划书
  • 厦门 网站设计2021最火营销方案
  • 网站建设丿找vx cp5173google chrome
  • 建筑网站的设计与实现的论文百度客户端下载
  • 趣快排seo是什么百度seo引流怎么做
  • 淄博北京网站建设公司公司想建个网站怎么弄
  • 网站建设seo优化培训吉林seo技术交流