从原理到实践:一文详解残差网络
在深度学习的发展历程中,神经网络的深度一直是提升模型性能的关键因素之一。随着网络层数的增加,模型理论上可以学习到更复杂、更抽象的特征表示。然而,在实际训练过程中,研究人员发现,当网络深度达到一定程度后,模型的性能不仅没有提升,反而出现了下降,这就是困扰深度学习领域已久的梯度消失、梯度爆炸以及网络退化问题。残差网络(Residual Network,ResNet)的出现,成功打破了这一僵局,为深度学习的发展开辟了新的道路。本文将从残差网络的诞生背景、结构原理、代码实现以及实际应用等方面,带大家深入了解这一经典模型。
一、深度学习网络训练难题
在深度学习中,神经网络通过不断调整网络参数,最小化损失函数来学习数据中的模式和规律。在反向传播算法中,梯度用于指导参数更新的方向和步长。但当网络层数过多时,梯度在反向传播过程中会逐渐变小(梯度消失)或变得过大(梯度爆炸)。梯度消失使得网络参数难以更新,模型无法学习;梯度爆炸则会导致参数值过大,模型训练不稳定。
除了梯度问题,网络退化现象也不容忽视。研究发现,在训练过程中,当网络层数增加时,模型在训练集和测试集上的错误率反而会上升。这并非是过拟合导致的,因为即使在训练集上,更深的网络也无法达到较浅网络的训练精度。这表明,随着网络深度增加,传统的神经网络变得难以优化。
二、残差网络的提出与结构原理
2.1 残差网络的提出
2015 年,微软研究院的何恺明等人在论文《Deep Residual Learning for Image Recognition》中提出了残差网络,该模型在当年的 ImageNet 大规模视觉识别挑战赛(ILSVRC)中以显著优势夺得冠军,证明了其强大的性能。残差网络的核心思想是通过引入残差块(Residual Block),让网络学习输入与输出之间的残差,从而解决网络退化问题,使得训练更深的神经网络成为可能。
2.2 残差块结构
在一个标准的残差块中,输入 \(x\) 首先经过两个卷积层进行特征提取,然后与原始输入 \(x\) 进行相加操作,最后通过激活函数(通常为 ReLU)得到输出。用公式表示为:
\(y = F(x, \{W_i\}) + x\)
其中,\(F(x, \{W_i\})\) 表示残差函数,是关于输入 \(x\) 和一组权重参数 \(\{W_i\}\) 的函数,它由卷积层、激活函数等操作组成;\(x\) 是输入;\(y\) 是残差块的输出。通过这种残差连接方式,网络可以直接学习输入与输出之间的差异,而不是学习一个全新的映射,降低了学习难度。
2.3 恒等映射与残差学习
当残差函数 \(F(x, \{W_i\}) = 0\) 时,残差块的输出 \(y = x\),此时残差块实现了恒等映射。在网络训练过程中,如果某一层的参数已经学习到了最优状态,那么后续添加的残差块可以通过恒等映射跳过这一层,避免对已学习到的最优参数造成破坏。同时,网络可以根据需要调整残差函数 \(F(x, \{W_i\})\),使得网络在保持已有特征的基础上,学习到更复杂的特征,从而有效地解决了网络退化问题。
2.4 不同类型的残差块
除了上述标准的残差块,根据应用场景和网络结构的不同,还有多种变体。例如,在更深的网络中,为了减少计算量,会使用瓶颈结构(Bottleneck)的残差块。它先通过一个 \(1\times1\) 卷积层对输入通道数进行压缩,再经过一个 \(3\times3\) 卷积层进行特征提取,最后通过一个 \(1\times1\) 卷积层将通道数恢复到合适的维度。这种结构在不损失太多精度的情况下,大幅减少了计算量和参数量。
三、残差网络的代码实现(以 PyTorch 为例)
下面我们使用 PyTorch 框架来实现一个简单的残差网络:
import torch
import torch.nn as nn
# 定义残差块
class ResidualBlock(nn.Module):def __init__(self, in_channels, out_channels, stride=1, downsample=None):super(ResidualBlock, self).__init__()self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)self.bn1 = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)self.bn2 = nn.BatchNorm2d(out_channels)self.downsample = downsample
def forward(self, x):residual = 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:residual = self.downsample(x)
out += residualout = self.relu(out)
return out
# 定义残差网络
class ResNet(nn.Module):def __init__(self, block, layers, num_classes=10):super(ResNet, self).__init__()self.in_channels = 64self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)self.bn1 = nn.BatchNorm2d(64)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)self.layer3 = self._make_layer(block, 256, layers[2], stride=2)self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
self.avgpool = nn.AvgPool2d(7)self.fc = nn.Linear(512, num_classes)
def _make_layer(self, block, out_channels, blocks, stride=1):downsample = Noneif stride != 1 or self.in_channels != out_channels:downsample = nn.Sequential(nn.Conv2d(self.in_channels, out_channels, kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(out_channels))
layers = []layers.append(block(self.in_channels, out_channels, stride, downsample))self.in_channels = out_channelsfor _ in range(1, blocks):layers.append(block(self.in_channels, out_channels))
return nn.Sequential(*layers)
def forward(self, x):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 = x.view(x.size(0), -1)x = self.fc(x)
return x
# 实例化ResNet18
def resnet18():return ResNet(ResidualBlock, [2, 2, 2, 2])
上述代码中,首先定义了 ResidualBlock 类来实现残差块,然后通过 ResNet 类构建完整的残差网络,最后提供了一个 resnet18 函数方便实例化一个 18 层的残差网络。
四、残差网络的应用与影响
4.1 图像识别领域
残差网络在图像识别领域取得了巨大成功,广泛应用于图像分类、目标检测、语义分割等任务。在图像分类中,ResNet 凭借其强大的特征提取能力,能够准确地识别各种图像类别;在目标检测任务中,基于 ResNet 的检测器可以有效地定位和识别图像中的多个目标;在语义分割方面,ResNet 为分割网络提供了良好的特征基础,能够实现对图像像素级别的语义标注。
4.2 其他领域的应用
除了图像识别,残差网络的思想还被应用到了其他深度学习领域,如自然语言处理、语音识别等。在自然语言处理中,通过将残差连接应用到循环神经网络(RNN)或 Transformer 结构中,可以缓解长序列建模时的梯度消失问题,提升模型对长文本的处理能力;在语音识别中,残差网络可以用于提取语音信号的特征,提高语音识别的准确率。
4.3 对深度学习研究的影响
残差网络的提出,不仅解决了网络退化问题,还为深度学习模型的设计提供了新的思路。它证明了通过合理的网络结构设计,可以训练出更深、更复杂的神经网络,从而推动了深度学习领域的发展。此后,基于残差网络的各种改进和创新模型不断涌现,进一步提升了深度学习模型的性能和应用范围。
五、总结与展望
残差网络作为深度学习领域的经典模型,通过引入残差连接,巧妙地解决了网络退化问题,使得训练更深层次的神经网络成为可能。其简单而有效的结构设计,不仅在图像识别等领域取得了优异的成绩,还对整个深度学习研究产生了深远的影响。
随着深度学习研究的不断深入,残差网络也在不断发展和改进。未来,残差网络可能会与其他新兴技术(如自注意力机制、生成对抗网络等)相结合,创造出更强大的模型,在更多领域发挥重要作用。同时,如何进一步优化残差网络的结构,提高其计算效率和泛化能力,也是值得深入研究的方向。
希望本文能够帮助大家更好地理解残差网络的原理与应用。如果你对深度学习感兴趣,不妨尝试使用残差网络进行一些实际项目,亲身体验它的强大之处。如果你在学习过程中有任何疑问或想法,欢迎在评论区留言交流!
相关文章:
从原理到实践:一文详解残差网络
在深度学习的发展历程中,神经网络的深度一直是提升模型性能的关键因素之一。随着网络层数的增加,模型理论上可以学习到更复杂、更抽象的特征表示。然而,在实际训练过程中,研究人员发现,当网络深度达到一定程度后&#…...
把银河装进镜头里!动态星轨素材使用实录
仰望夜空时,神秘的银河与闪烁繁星总令人向往。如今,无需复杂拍摄,借助素材平台就能将绝美星轨融入创作,今天重点安利 制片帮素材! 动态星轨:宇宙的浪漫印记 星轨是地球自转时,星星运动留下的轨…...
C++23中std::span和std::basic_string_view可平凡复制提案解析
文章目录 一、引言二、相关概念解释2.1 平凡复制(Trivially Copyable)2.2 std::span2.3 std::basic_string_view 三、std::span和std::basic_string_view的应用场景3.1 std::span的应用场景3.2 std::basic_string_view的应用场景 四、P2251R1提案对std::…...
【KWDB 2025 创作者计划】_KWDB时序数据库特性及跨模查询
一、概述 数据库的类型多种多样,关系型数据库、时序型数据库、非关系型数据库、内存数据库、分布式数据库、图数据库等等,每种类型都有其特定的使用场景和优势,KaiwuDB 是一款面向 AIoT 场景的分布式、多模融合、支持原生 AI 的数据库…...
树 Part 9
二叉树的建立 了解了二叉树的遍历方法,我们如何在内存中生成一棵二叉链表的二叉树呢?树都没有,哪来遍历。所以我们还得来谈谈关于二叉树建立的问题。 如果要在内存中建立一个如左图这样的树,为了能让每个结点确认是否有左右孩子…...
leetcode每日一题 -- 3362. 零数组变换 III
思路 题意是要找出[最少的区间]使nums数组变为零数组,并且使用的区间可以不连续 我的第一想法是先给区间按照左边界排序(就像区间合并题的准备工作那样)这样的可以使用最大堆,每次将右区间值最大(也就是区间范围最大)的区间应用到差分数组中但是,后续如何处理还是不太会,遂看…...
PARSCALE:大语言模型的第三种扩展范式
----->更多内容,请移步“鲁班秘笈”!!<----- 随着人工智能技术的飞速发展,大语言模型(LLM)已成为推动机器智能向通用人工智能(AGI)迈进的核心驱动力。然而,传统的…...
【 开源:跨平台网络数据传输的万能工具libcurl】
在当今这个互联互通的世界中,数据在各种设备和平台之间自由流动,而 libcurl,就像一把跨平台的万能工具,为开发者提供了处理各种网络数据传输任务所需的强大功能。它不仅是一个库,更是一种通用的解决方案,可…...
2025版 JavaScript性能优化实战指南从入门到精通
JavaScript作为现代Web应用的核心技术,其性能直接影响用户体验。本文将深入探讨JavaScript性能优化的各个方面,提供可落地的实战策略。 一、代码层面的优化 1. 减少DOM操作 DOM操作是JavaScript中最昂贵的操作之一: // 不好的做法&#x…...
RAGFlow知识检索原理解析:混合检索架构与工程实践
一、核心架构设计 RAGFlow构建了四阶段处理流水线,其检索系统采用双路召回+重排序的混合架构: S c o r e f i n a l = α ⋅ B M...
leetcode 148. Sort List
148. Sort List 题目描述 代码: /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNod…...
C#学习11——集合
一、集合 是一组对象的容器,提供了高效的存储、检索和操作数据的方式。 C# 集合分为泛型集合(推荐使用)和非泛型集合,主要位于System.Collections和System.Collections.Generic命名空间中。 二、集合有哪些? 1&…...
paddlehub搭建ocr服务
搭建环境: Ubuntu20.041080Ti显卡 由于GPU硬件比较老,是Pascal架构,只能支持到paddle2.4.2版本,更高版本无法支持;同时,因为paddle老版本的依赖发生了变化,有些地方存在冲突,花费了…...
CSS3过渡
一、什么是CSS3过渡 CSS3 过渡(transitions)是一种效果,它允许你平滑地改变CSS属性的值,从一个状态过渡到另一个状态。是一种动画转换的过程,如渐现、渐弱、动画快慢等。过渡效果可以在用户与页面进行交互时触发&#…...
比斯特自动化|移动电源全自动点焊机:高效点焊助力移动电源制造
在移动电源市场蓬勃发展的当下,电池组合的点焊工艺要求愈发严格。移动电源全自动点焊机应运而生,成为提升生产效率与产品质量的关键设备。 工作原理与结构组成 移动电源全自动点焊机通过瞬间放电产生高温,使电池极耳与镍带等材料在极短时间…...
游戏引擎学习第305天:在平台层中使用内存 Arena 的方法与思路
回顾前一天内容,并为今天的开发工作设定方向 我们正在直播制作完整游戏,当前正在实现一个精灵图(sprite graph)的排序系统。排序的代码已经写完,过程并不复杂,虽然还没做太多优化,但总体思路比…...
[Java][Leetcode middle] 6. Z 字形变换
法一,自己想的 使用一个复合结构的 List<ArrayList<String>> 来存储每一行的字母,最后按序输出。 使用flag来判断到底放到哪一行上去。flag按照:0–1–2–1–0–1–2这样变化,实现躺着的Z字形。 public String conve…...
零基础设计模式——第二部分:创建型模式 - 原型模式
第二部分:创建型模式 - 5. 原型模式 (Prototype Pattern) 我们已经探讨了单例、工厂方法、抽象工厂和生成器模式。现在,我们来看创建型模式的最后一个主要成员——原型模式。这种模式关注的是通过复制现有对象来创建新对象,而不是通过传统的…...
完整改进RIME算法,基于修正多项式微分学习算子Rime-ice增长优化器,完整MATLAB代码获取
1 简介 为了有效地利用雾状冰生长的物理现象,最近开发了一种优化算法——雾状优化算法(RIME)。它模拟硬雾状和软雾状过程,构建硬雾状穿刺和软雾状搜索机制。在本研究中,引入了一种增强版本,称为修改的RIME…...
【1——Android端添加隐私协议(unity)1/3】
前言:这篇仅对于unity 发布Android端上架国内应用商店添加隐私协议,隐私协议是很重要的东西,没有这个东西,是不上了应用商店的。 对于仅仅添加隐私协议,我知道有三种方式,第一种和第二种基本一样 1.直接在unity里面新…...
笔记本6GB本地可跑的图生视频项目(FramePack)
文章目录 (一)简介(二)本地执行(2.1)下载(2.2)更新(2.3)运行(2.4)生成 (三)注意(3.1)效…...
Android View的事件分发机制
ViewGroup的事件分发逻辑 从Activity传递给Window,再传递给ViewGroup,ViewGroup的dispatchTouchEvent()会被调用,如果onInterceptTouchEvent()返回true 转交自身onTouchEvent()处理,如果返回false继续向子View传递,子View的dispatchTouchEve…...
Python字符串格式化(二): f-string的进化
文章目录 一、Python 3.6:重新发明字符串格式化(2016)1. 语法糖的诞生:表达式直嵌技术2. 性能与可读性的双重提升3. 奠定现代格式化的基础架构 二、Python 3.7:解锁异步编程新场景(2018)1. 异步…...
力扣HOT100之二叉树:124. 二叉树中的最大路径和
这道题是困难题,靠自己想还是挺难想的,还是去看的灵神的题解,感觉还是要多复习一下这道题。这道题的思路和之前做的543. 二叉树的直径很像,可以参考之前的这篇博客。这里我们还是用递归来做,定义一个lambda函数来实现递…...
【C++】位图+布隆过滤器
1.位图 概念 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的或是否被标记。 1.二进制位表示 : 位图中的每一位(bit)代表一个元素的状态。通常&…...
Google Agent Development Kit与MCP初试
Google Agent Development Kit与MCP初试 一、背景知识二、搭建智能大脑 - Ollama服务器2.1 为什么要先搭建Ollama?2.2 搭建ollama服务器2.2.1 安装2.2.2 试着用curl命令"问"AI一个问题: 三、构建智能体工坊 - ADK环境3.1 创建容器3.2 安装核心…...
云原生+大数据
虚拟化: 虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提…...
基于cornerstone3D的dicom影像浏览器 第二十一章 显示DICOM TAGS
系列文章目录 第一章 下载源码 运行cornerstone3D example 第二章 修改示例crosshairs的图像源 第三章 vitevue3cornerstonejs项目创建 第四章 加载本地文件夹中的dicom文件并归档 第五章 dicom文件生成png,显示检查栏,序列栏 第六章 stack viewport 显…...
【记录】PPT|PPT打开开发工具并支持Quicker VBA运行
文章目录 打开开发者工具支持Quicker VBA运行 打开开发者工具 参考文章,微软文档:显示“开发工具”选项卡,以下直接复制,如侵私删。 适用对象:Microsoft 365 专属 Excel Microsoft 365 专属 Outlook Microsoft 365 专属…...
西门子 S1500 博途软件舞台威亚 3D 控制方案
西门子 S1500 PLC 是工业自动化领域的主流控制器,适合高精度、高可靠性的舞台威亚控制。下面为你提供基于博途 (TIA Portal) 软件的 3D 控制方案设计。 系统架构设计 舞台威亚 3D 控制系统通常包含以下组件: 硬件层: S1500 PLC 主机伺服驱动…...
第三十二天打卡
import pandas as pd from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier # 加载鸢尾花数据集 iris load_iris() df pd.DataFrame(iris.data, columnsiris.feature_names) …...
同步/异步电路;同步/异步复位
同步/异步电路;同步/异步复位 在 FPGA 设计中,同步电路、异步电路、同步复位和异步复位是基础且关键的概念,它们的特性直接影响电路的可靠性、时序性能和设计复杂度。 一、同步电路(Synchronous Circuit) 定义 同步电…...
spring boot 实现resp视频推流
1、搭建resp服务(docker方式) docker pull aler9/rtsp-simple-serverdocker run -d --restartalways \--name rtsp-server \-p 8554:8554 \aler9/rtsp-simple-server2、maven依赖 <dependency><groupId>org.bytedeco</groupId><a…...
python、R、shell兼容1
一,兼容方式 1,shell中用R、python: (1)python3、R/r(radian)进入 (2)脚本封装:命令行或者封装到sh脚本中 python xxx.py 自定义参数 Rscript xxx.r 自…...
Oracle 11G RAC重启系统异常
vmware安装centos7环境部署Oracle RAC (11.2.0.4) 部署时所有资源情况都是正常的,关机重启虚拟机后集群资源状态异常,请教CSDN大佬 – 部署规划 域名地址备注rac16192.168.31.16rac17192.168.31.17rac16vip192.168.31.26viprac17vip192.168.31.27vip…...
便捷的电脑自动关机辅助工具
软件介绍 本文介绍的软件是一款电脑上实用的倒计时和关机助手。 软件特性 这款关机助手十分贴心,它是一款无需安装的小软件,体积仅60KB,不用担心占用电脑空间,打开即可直接使用。 操作方法 你只需设置好对应的关机时间&#x…...
巧用 FFmpeg 命令行合并多个视频为一个视频文件教程
你是否曾经遇到过需要将多个视频片段合并成一个连续视频的情况?比如,你拍摄了一段旅行的精彩瞬间,想把它们合成一部短片;或者你在制作教学视频时,希望将不同的部分整合在一起。这时候,FFmpeg 就是你的得力助…...
平时使用电脑,如何去维护
在这个数字化的时代,电脑已经成为我们生活和工作中不可或缺的一部分。然而,你是否知道如何正确地维护它,让它始终保持良好的运行状态呢?今天,就让我来为大家揭晓这个谜底。定期清理电脑内部和外部的灰尘是至关重要的。…...
(视觉)分类、检测与分割在不同网络中的设计体现
分类、检测与分割在不同网络中的设计体现 概述 在计算机视觉领域,不同的网络结构在功能和结构上差异显著,同时也共享一些基础设计元素。 卷积神经网络是基石: 卷积层通过特定的卷积核与图像进行卷积运算提取图像中的局部特征,比…...
技术分享 | MySQL大事务导致数据库卡顿
本文为墨天轮数据库管理服务团队第66期技术分享,内容原创,作者为技术顾问孙文龙,如需转载请联系小墨(VX:modb666)并注明来源。 一、现 象 业务侧反馈连接数据库异常,报错 connection is not av…...
C#在 .NET 9.0 中启用二进制序列化:配置、风险与替代方案
在 .NET 9.0 中启用二进制序列化:配置、风险与替代方案 引言一、启用二进制序列化的步骤二、实现序列化与反序列化三、安全风险与缓解措施四、推荐替代方案五、总结 引言 在 .NET 生态中,二进制序列化(Binary Serialization)曾是…...
每日Prompt:像素风格插画
提示词 像素风格插画,日式漫画脸,画面主体为一位站在路边的男孩,人物穿着黑色冲锋衣,手里拿着手机,男孩靠坐在机车旁边,脚边依偎着一只带着小摩托车头盔的小小猫,背景是雨中,身旁停…...
Rust 学习笔记:生命周期
Rust 学习笔记:生命周期 Rust 学习笔记:生命周期使用生命周期防止悬空引用借用检查器函数中的泛型生命周期生命周期注释语法函数签名中的生命周期注解从生命周期的角度思考结构定义中的生命周期注解省略生命周期方法定义中的生命周期注释静态生命周期泛型…...
科学标注法:数据治理的未来之路
在数据治理领域,科学标注法是一种系统化、标准化的数据标注方法论,其核心是通过规范化的流程、技术工具和质量控制机制,将原始数据转化为具有语义和结构特征的可用数据资源。以下从定义、技术特征、应用场景、与传统标注方法的区别以及遵循的标准框架等方面展开详细解析: 一…...
小白刷题 之 如何高效计算二进制数组中最大连续 1 的个数
前言 学习如何快速找出二进制数组中最长的连续 1 序列。 这个问题在数据处理、网络传输和算法面试中经常出现,掌握它不仅能提升编程能力,还能加深对数组操作和循环控制的理解。 🌟 问题背景 想象你是一位网络工程师,正在分析服…...
中科方德鸳鸯火锅平台使用教程:轻松运行Windows应用!
原文链接:中科方德鸳鸯火锅平台使用教程:轻松运行Windows应用! Hello,大家好啊,今天给大家带来一篇中科方德鸳鸯火锅平台使用的文章,欢迎大家分享点赞,点个在看和关注吧!在信创环境…...
完全禁用 Actuator 功能
问题描述: springboot 关闭Actuator无效,原本设置 management:endpoints:enabled-by-default: false # 禁用所有端点屏蔽了/actuator/info和/actuator/health,但/actuator还可以访问。 拉满配置如下,成功屏蔽 # application.y…...
Netty学习专栏(二):Netty快速入门及重要组件详解(EventLoop、Channel、ChannelPipeline)
文章目录 前言一、快速入门:5分钟搭建Echo服务器二、核心组件深度解析2.1 EventLoop:颠覆性的线程模型EventLoop 设计原理核心 API 详解代码实践:完整使用示例 2.2 Channel:统一的网络抽象层Channel 核心架构核心 API 详解代码实践…...
27-FreeRTOS的任务管理
一、FreeRTOS的任务概念 在FreeRTOS中,任务(Task)是操作系统调度的基本单位。每个任务都是一个无限循环的函数,它执行特定的功能。任务可以被看作是一个轻量级的线程,具有自己的堆栈和优先级。下面是如何定义一个任务函…...
upload-labs靶场通关详解:第14关
一、分析源代码 这一关的任务说明已经相当于给出了答案,就是让我们上传一个图片木马,可以理解为图片中包含了一段木马代码。 function getReailFileType($filename){$file fopen($filename, "rb");$bin fread($file, 2); //只读2字节fclose…...