动手造轮子:ResNet

【Resnet】Resnet代码详解(图+代码) 具体理论就不说了。直接看网络结构以及其代码就好。 1.先上网络整体结构。 如下图 分别放出来resnet18 resnet134resnet50resnet101 resnet152.文字注释应该写明白了大致的网络结构。 ... 阅读详情

自己写的版本:

class resBlock(x,):
    def __initial__:
        conv1=torch.nn.Conv2d(in_channels, out_channels, 1, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
        conv3=torch.nn.Conv2d(in_channels, out_channels, 3, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
        self.relu=torch.nn.relu();
        
    def forward(x):    
        orgi_x=x
        in_channels=x[1].size()
        out_channels=20
        x=self.conv1(x)
        x=self.conv3(x)
        x=self.conv1(x)
        x+=orgi_x
        x=self.relu(x)
        return x

存在的问题以及改进:

  1. 初始化函数也是需要输入输出的,类的第一个参数是self。
  2. 类名字括号是写,继承的父类。
  3. 写函数时,习惯使用带名字的初始化,stride=1,这样知道这个值的含义。

官网的实现:

def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
    """3x3 convolution with padding"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                     padding=dilation, groups=groups, bias=False, dilation=dilation)


def conv1x1(in_planes, out_planes, stride=1):
    """1x1 convolution"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)


class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
                 base_width=64, dilation=1, norm_layer=None):
        super(BasicBlock, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        if groups != 1 or base_width != 64:
            raise ValueError('BasicBlock only supports groups=1 and base_width=64')
        if dilation > 1:
            raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv3x3(inplanes, planes, stride)
        self.bn1 = norm_layer(planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = conv3x3(planes, planes)
        self.bn2 = norm_layer(planes)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out


class Bottleneck(nn.Module):
    # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2)
    # while original implementation places the stride at the first 1x1 convolution(self.conv1)
    # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385.
    # This variant is also known as ResNet V1.5 and improves accuracy according to
    # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch.

    expansion = 4

    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
                 base_width=64, dilation=1, norm_layer=None):
        super(Bottleneck, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        width = int(planes * (base_width / 64.)) * groups
        # Both self.conv2 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv1x1(inplanes, width)
        self.bn1 = norm_layer(width)
        self.conv2 = conv3x3(width, width, stride, groups, dilation)
        self.bn2 = norm_layer(width)
        self.conv3 = conv1x1(width, planes * self.expansion)
        self.bn3 = norm_layer(planes * self.expansion)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        out = self.conv3(out)
        out = self.bn3(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out


class ResNet(nn.Module):

    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,
                 groups=1, width_per_group=64, replace_stride_with_dilation=None,
                 norm_layer=None):
        super(ResNet, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        self._norm_layer = norm_layer

        self.inplanes = 64
        self.dilation = 1
        if replace_stride_with_dilation is None:
            # each element in the tuple indicates if we should replace
            # the 2x2 stride with a dilated convolution instead
            replace_stride_with_dilation = [False, False, False]
        if len(replace_stride_with_dilation) != 3:
            raise ValueError("replace_stride_with_dilation should be None "
                             "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
        self.groups = groups
        self.base_width = width_per_group
        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
                               bias=False)
        self.bn1 = norm_layer(self.inplanes)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
                                       dilate=replace_stride_with_dilation[0])
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
                                       dilate=replace_stride_with_dilation[1])
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
                                       dilate=replace_stride_with_dilation[2])
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512 * block.expansion, num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

        # Zero-initialize the last BN in each residual branch,
        # so that the residual branch starts with zeros, and each residual block behaves like an identity.
        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
        if zero_init_residual:
            for m in self.modules():
                if isinstance(m, Bottleneck):
                    nn.init.constant_(m.bn3.weight, 0)
                elif isinstance(m, BasicBlock):
                    nn.init.constant_(m.bn2.weight, 0)

    def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
        norm_layer = self._norm_layer
        downsample = None
        previous_dilation = self.dilation
        if dilate:
            self.dilation *= stride
            stride = 1
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                conv1x1(self.inplanes, planes * block.expansion, stride),
                norm_layer(planes * block.expansion),
            )

        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
                            self.base_width, previous_dilation, norm_layer))
        self.inplanes = planes * block.expansion
        for _ in range(1, blocks):
            layers.append(block(self.inplanes, planes, groups=self.groups,
                                base_width=self.base_width, dilation=self.dilation,
                                norm_layer=norm_layer))

        return nn.Sequential(*layers)

    def _forward_impl(self, x):
        # See note [TorchScript super()]
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)

        return x

    def forward(self, x):
        return self._forward_impl(x)

参考:
pytorch-resnet

PyTorch实战:从VGG到ResNet,手把手搭建经典CNN网络 卷积神经网络(CNN)是计算机视觉领域的核心架构,其通过卷积层自动提取图像特征,为图像识别、目标检测等任务奠定了基础。其核心原理在于利用局部连接和权值共享,高效处理网格状数据(如图像)。随着网络深度增加,模型表征能力增强,但也会引发梯度消失和网络退化等问题。VGG网络通过堆叠小型卷积核,在增加深度的同时保持了参数效率;ResNet则创新性地引入残差连接,通过恒等映射解决了深度网络的优化难题,使训练数百层的网络成为可能。这些经典架构在图像分类、目标检测等场景中广泛应用。本文将以PyTorch为工具,深入解析V 阅读详情

相关推荐

实战解析:为YOLOv5 7.0定制ResNet骨干网络的完整流程与避坑指南

本文详细解析了为YOLOv5 7.0定制ResNet骨干网络的完整流程与关键避坑点。针对高分辨率输入下CSPDarknet53的局限性,指南从配置文件设计、模型前向传播改造、核心代码整合到预训练权重加载,提供了手把手的实战方案,并重点解决了特征层对齐与尺度不匹配等核心难题,帮助开发者构建高性能的YOLOv5-ResNet混合模型。

weixin_29269441的博客 611

Pytorch intermediate(二) ResNet

layer2:输入通道:16,输出通道:32,padding = 0, stride = 2。由于输入不等于输出通道数,增加了一层卷积层,并且带有对应的stride。可以看到在残差块中有一个判断,就是判断输入数据是否被向下采样,也就是形状是否变化,如果变化就进行上述处理。layer1:输入通道:16,输出通道:16,padding = 0,stride = 0。conv3x3:将输入数据进行一次卷积,将数据转换成为,残差块需要的shape大小。layer3:输入通道:32,输出通道:64,其余同上。

青山渺渺 1005

从零手动搭建ResNet18:PyTorch实现与训练全流程详解

卷积神经网络是计算机视觉领域的核心架构,通过卷积、池化等操作自动提取图像特征。其核心原理在于利用局部连接和权值共享,有效减少参数数量并保留空间信息。残差网络通过引入捷径连接,解决了深层网络训练中的梯度消失和网络退化问题,显著提升了模型性能与训练稳定性。在图像分类、目标检测等实际应用场景中,ResNet因其优异的性能成为基准模型。本文以ResNet18为例,详细解析其基础残差块与整体架构,并提供完整的PyTorch实现代码,涵盖环境配置、模型搭建、训练循环及推理部署全流程,帮助读者深入理解模型内部机制。

weixin_34391445的博客 371

ResNet 几大变体的github地址

ResNet 几大变体的github地址

zchang81的博客 1万+

从零手动搭建ResNet18:PyTorch实战与CNN架构深度解析

卷积神经网络(CNN)是计算机视觉领域的核心架构,其通过卷积层、池化层等模块自动提取图像特征。ResNet(残差网络)通过引入残差连接(Residual Connection)这一关键创新,有效解决了深层网络中的梯度消失问题,使网络深度得以大幅增加,成为现代深度学习模型的基石。这一技术显著提升了模型在图像分类、目标检测等任务上的性能,被广泛应用于工业界和学术界。本文聚焦于ResNet18这一经典轻量级网络,通过PyTorch框架从零开始手动实现其完整结构,涵盖BasicBlock模块设计、维度匹配、权重初始

迷彩风情 399

从AlexNet到ResNet:深度卷积网络演进与PyTorch实战指南

卷积神经网络(CNN)是深度学习最核心的技术之一,它通过局部连接与参数共享自动从数据中学习特征,取代了传统手工特征工程。从AlexNet引入ReLU与Dropout实现深度训练突破,到VGG、GoogLeNet、ResNet等经典网络不断优化结构,CNN在图像分类、目标检测、语义分割等任务中展现出强大的技术价值。在工程实践中,借助PyTorch框架可以快速搭建和训练CNN模型,结合数据增强与迁移学习,有效解决小数据集下的过拟合与精度问题。本文从CNN基本原理出发,系统梳理深度卷积网络的演进脉络,并提供可落地

weixin_34236869的博客 482

ResNet代码理解

ResNet代码理解

w12345815856_的博客 3288

基于ResNet50与余弦相似度构建辣椒榕图像识别系统

图像识别是计算机视觉领域的核心技术,其原理在于通过深度学习模型提取图像的高维特征向量,将其转化为可计算的“数字指纹”。这项技术的核心价值在于能够自动化、客观地处理海量视觉信息,极大地提升了分类、检索和比对的效率。在工程实践中,预训练模型(如ResNet50)因其强大的通用特征提取能力,常被用于解决特定领域的图像识别问题,例如在农业、生物分类或商品检索等场景中。本文以辣椒榕品种识别为具体案例,详细阐述了如何利用ResNet50模型提取特征,并结合余弦相似度计算,构建一个从后端Python处理到前端Vue展示的

weixin_34111790的博客 380

conv2d参数_Day238:ResNet中3*3卷积模板中参数的介绍

ResNet分类及框架结构3*3的卷积模板卷积步长 stride=1,扩张大小 dilation=1(也就是 padding),in_planes 和 out_planes 分别是输入和输出的通道数,groups 是分组卷积参数,这里 groups=1 相当于没有分组分组卷积参考:卷积神经网络中十大拍案叫绝的操作PyTorch中groups函数的作用def conv3x3(in_planes, o...

weixin_39565021的博客 2000

PyTorch人脸表情识别实战:CNN、VGG与ResNet选型与优化

卷积神经网络(CNN)是图像识别的基础架构,通过局部感受野与权值共享高效提取视觉特征;VGG与ResNet则通过加深网络层次或引入残差连接进一步提升模型表征能力。在人脸表情识别这类细粒度视觉任务中,模型选型、数据划分与类别不平衡处理直接决定最终落地效果。PyTorch作为灵活的深度学习框架,支持快速原型搭建与迁移学习,借助ImageNet预训练权重可显著缓解小数据集下的过拟合问题。从FER2013数据预处理到模型训练、权重保存与单张图片推理,每一步都有影响精度的关键细节。文章系统梳理了CNN基线、VGG简化

weixin_32487557的博客 219

3D ResNet视频动作识别实战:基于PyTorch的开源项目全解析

视频理解是计算机视觉的重要方向,动作识别作为其核心任务,需要模型同时捕捉空间外观与时间运动信息。传统2D卷积仅处理单帧图像,难以建模帧间动态,而3D卷积通过在时间维度上进行卷积操作,能够有效融合时空特征。3D ResNet作为经典的动作识别基线模型,将ResNet架构扩展至3D卷积,在UCF101、HMDB51等基准数据集上表现稳健,成为视频分类任务的首选方案。本文围绕一个基于PyTorch的开源3D-ResNets项目,详细介绍其环境配置、数据预处理、模型结构与训练调优技巧,并分享实际使用中的常见问题与解

weixin_29070861的博客 274

深度学习入门:从机器学习范式迁移到动手实践的核心指南

机器学习旨在从数据中学习规律,而深度学习作为其重要分支,带来了根本性的范式迁移。其核心原理在于通过多层神经网络自动学习数据的层次化特征表示,从而将传统机器学习中繁重的特征工程很大程度上自动化。这一技术价值在于极大地提升了模型处理原始数据(如图像、文本)的能力,推动了计算机视觉、自然语言处理等领域的突破。在实际应用场景中,理解从机器学习到深度学习的转变,掌握数据、算法、算力三大驱动力,并践行“动手”实践,是构建扎实AI工程能力的基础。本文以《动手学深度学习》为脉络,结合特征工程、过拟合等关键概念,深入解析如何

weixin_30628077的博客 335

基于pyQt的图像语义分割GUI:支持mobilenet、resnet50等8个模型切换

图像语义分割是计算机视觉的核心任务,通过深度学习模型实现像素级分类。其原理是利用骨干网络提取特征,分割头逐像素预测类别。技术价值在于将复杂模型封装为易用工具,提升算法验证与业务演示效率。在街景分析、遥感解译、工业质检等场景中,需要快速切换不同算力档位的模型。本文围绕pyQt构建的GUI框架,支持mobilenet、resnet50等8个骨干网络,实现模型推理、结果叠加与导出,并解决权重加载、线程阻塞等工程问题,提供完整源码与文档说明。

weixin_29071809的博客 236

PaddlePaddle-v3.3实战:ResNet50模型剪枝,精度损失不到1%

本文介绍了如何在星图GPU平台上自动化部署PaddlePaddle-v3.3镜像,并利用其内置的PaddleSlim工具包对ResNet50模型进行结构化剪枝。通过实战演示,在CIFAR-10数据集上实现模型体积减半、推理加速的同时,精度损失控制在1%以内,有效满足了边缘设备部署等轻量化AI应用需求。

weixin_42350014的博客 112

人工智能导论教案设计:模块化教学与动手实践全解析

人工智能作为计算机科学的前沿领域,正深刻改变着技术生态与产业格局。在高校教育中,如何让初学者从庞杂的概念中建立系统认知,成为课程设计的核心难题。本文基于人工智能导论课程的教学实践,提出一种以“可动手验证的科学”为导向的教案设计思路:通过机器学习、深度学习、计算机视觉、自然语言处理等核心模块的有机串联,配合生活化类比与课堂实验,帮助学习者理解算法原理、数据价值与模型能力。同时,课程融入AI伦理与职业发展视角,回应人工智能训练师等新兴岗位的技能需求。这种从概念到原理、从技术到应用的教学框架,不仅适合本科低年级学

weixin_33868027的博客 175

ResNet18从零训练Cifar10:PyTorch实现与95.46%准确率调参指南

深度学习中的卷积神经网络(CNN)凭借残差结构有效缓解深层网络退化问题,ResNet18作为经典轻量级骨干模型,在图像分类任务中应用广泛。Cifar10数据集是评估模型泛化能力的常用基准,从零训练而非加载预训练权重,能真实反映网络设计与超参调优的水平。通过PyTorch构建残差块、配合SGD优化器、数据增强与学习率调度,模型可在不借助预训练权重的情况下将测试准确率提升至95.46%。从环境配置、数据管线到训练策略,结合工程实践提供可复现的从零训练范式,并剖析常见踩坑案例,适合希望深入理解卷积神经网络训练细节

weixin_28223453的博客 308

本科深度学习需要从零开始训练模型吗?

本科阶段搞深度学习,无论是课设、比赛还是毕业设计,99%的场景都是应用,不是科研。你加载一个预训练的ViT,改改分类头,用自己数据微调几个epoch,一样能讲明白自注意力机制怎么工作的。而且说实话,面试的时候面试官更关心你怎么处理数据、怎么调参、怎么解决过拟合,不会问你“手写过几次反向传播”。你花一个月从零训模型,人家用CLIP的API十分钟搞定,准确率还比你高。四步走完,一个像模像样的深度学习项目就诞生了,耗时可能就一周。这一步你就在做“创新”了,虽然技术底层没变,但应用场景变了,课设老师就吃这套。

Michael_Jay的博客 200

Python-使用Python和keras进行股票预测

使用Python和keras进行股票预测

上一篇: 每天一kernel:正太概率图
下一篇: 动手造轮子:DenseNet
dlvector
博客等级 码龄10年 85粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值