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

别再死记公式了!用Python手写一个卷积层,彻底搞懂CNN里的‘卷’是怎么算的

用Python手写卷积层从零理解CNN的卷运算当你第一次看到卷积神经网络(CNN)的数学公式时那些复杂的符号和下标是否让你望而却步作为计算机视觉领域的基石CNN的核心在于理解卷积运算的本质。本文将带你用NumPy从零实现一个完整的卷积层通过可视化每个计算步骤让你真正掌握这个看似神秘的操作。1. 卷积运算的本质滑动窗口的局部计算卷积运算的核心思想非常简单一个小窗口在输入数据上滑动每次计算窗口内数据的加权和。这个小窗口就是我们常说的卷积核或滤波器。让我们用一个具体的例子来说明假设我们有一个5×5的灰度图像单通道输入和一个3×3的卷积核。计算过程如下将卷积核对准输入图像的左上角3×3区域对应位置元素相乘后求和得到输出特征图的一个像素值滑动窗口步长通常为1重复上述过程直到覆盖整个输入用Python代码表示这个基本操作import numpy as np def conv2d_single_channel(input, kernel): # 获取输入和卷积核的尺寸 in_h, in_w input.shape k_h, k_w kernel.shape # 计算输出特征图的尺寸 out_h in_h - k_h 1 out_w in_w - k_w 1 # 初始化输出特征图 output np.zeros((out_h, out_w)) # 滑动窗口计算 for i in range(out_h): for j in range(out_w): # 获取当前窗口 window input[i:ik_h, j:jk_w] # 对应位置相乘后求和 output[i,j] np.sum(window * kernel) return output这个简单的实现已经包含了卷积运算的所有关键要素。让我们用一个具体的例子测试# 示例输入和卷积核 input_img np.array([[1,2,3,4,5], [6,7,8,9,10], [11,12,13,14,15], [16,17,18,19,20], [21,22,23,24,25]]) kernel np.array([[1,0,-1], [1,0,-1], [1,0,-1]]) # 执行卷积运算 feature_map conv2d_single_channel(input_img, kernel) print(feature_map)提示这个卷积核实际上是一个垂直边缘检测器它会突出显示图像中垂直方向的亮度变化。2. 多通道卷积从灰度到彩色图像现实中的图像通常是RGB三通道的我们的卷积层需要能够处理多通道输入并产生多通道输出。这引入了几个关键概念输入通道数(C_in)输入数据的通道数如RGB图像的3输出通道数(C_out)我们希望提取的不同特征数量卷积核维度对于每个输出通道我们需要一个形状为(C_in, K_h, K_w)的卷积核让我们扩展之前的实现来处理多通道情况def conv2d_multi_channel(input, kernels, bias): input: (C_in, H, W) kernels: (C_out, C_in, K_h, K_w) bias: (C_out,) C_out, C_in, k_h, k_w kernels.shape _, in_h, in_w input.shape # 计算输出尺寸 out_h in_h - k_h 1 out_w in_w - k_w 1 # 初始化输出特征图 output np.zeros((C_out, out_h, out_w)) # 对每个输出通道计算 for c_out in range(C_out): # 对每个输入通道计算 for c_in in range(C_in): # 获取当前输入通道和对应的卷积核 input_channel input[c_in] kernel kernels[c_out, c_in] # 滑动窗口计算 for i in range(out_h): for j in range(out_w): window input_channel[i:ik_h, j:jk_w] output[c_out, i, j] np.sum(window * kernel) # 添加偏置项 output[c_out] bias[c_out] return output这个实现展示了CNN中一个关键特性每个输出通道都是所有输入通道的加权组合。这允许网络学习输入数据不同通道间的复杂关系。3. 卷积层的完整实现步长、填充与批量处理在实际的CNN中我们还需要考虑几个重要参数步长(Stride)控制卷积核滑动的步幅填充(Padding)在输入周围添加零值以控制输出尺寸批量维度同时处理多个输入样本让我们实现一个更完整的卷积层class Conv2D: def __init__(self, in_channels, out_channels, kernel_size, stride1, padding0): self.in_channels in_channels self.out_channels out_channels self.kernel_size kernel_size if isinstance(kernel_size, tuple) else (kernel_size, kernel_size) self.stride stride self.padding padding # 初始化权重和偏置 scale np.sqrt(1 / (in_channels * self.kernel_size[0] * self.kernel_size[1])) self.weights np.random.randn(out_channels, in_channels, self.kernel_size[0], self.kernel_size[1]) * scale self.bias np.zeros(out_channels) def forward(self, x): # 处理批量维度 if x.ndim 3: x x[np.newaxis, ...] batch_size, C_in, in_h, in_w x.shape C_out self.out_channels k_h, k_w self.kernel_size # 计算输出尺寸 out_h (in_h 2*self.padding - k_h) // self.stride 1 out_w (in_w 2*self.padding - k_w) // self.stride 1 # 应用填充 if self.padding 0: padded_x np.zeros((batch_size, C_in, in_h 2*self.padding, in_w 2*self.padding)) padded_x[:, :, self.padding:-self.padding, self.padding:-self.padding] x x padded_x # 初始化输出 output np.zeros((batch_size, C_out, out_h, out_w)) # 执行卷积运算 for b in range(batch_size): for c_out in range(C_out): for i in range(0, out_h): for j in range(0, out_w): h_start i * self.stride w_start j * self.stride h_end h_start k_h w_end w_start k_w window x[b, :, h_start:h_end, w_start:w_end] output[b, c_out, i, j] np.sum(window * self.weights[c_out]) self.bias[c_out] return output.squeeze() if batch_size 1 else output这个实现包含了现代CNN卷积层的所有关键特性。让我们测试一下# 创建一个3通道输入4通道输出的卷积层 conv_layer Conv2D(in_channels3, out_channels4, kernel_size3, stride1, padding1) # 随机生成一个批量数据 (2个样本每个3通道高宽为5x5) batch_input np.random.randn(2, 3, 5, 5) # 前向传播 output conv_layer.forward(batch_input) print(output.shape) # 应该输出 (2, 4, 5, 5)注意paddingsame意味着输出尺寸将与输入尺寸相同需要适当的填充和步长组合4. 可视化卷积过程理解特征提取为了真正理解卷积层在做什么可视化计算过程非常有帮助。让我们用matplotlib来可视化一个边缘检测的例子import matplotlib.pyplot as plt # 创建一个简单的测试图像 test_img np.zeros((9,9)) test_img[3:6, :] 1 # 添加一个水平白色条带 # 定义水平和垂直边缘检测器 horizontal_kernel np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]]) vertical_kernel np.array([[1, 0, -1], [1, 0, -1], [1, 0, -1]]) # 应用卷积 horizontal_edges conv2d_single_channel(test_img, horizontal_kernel) vertical_edges conv2d_single_channel(test_img, vertical_kernel) # 可视化 plt.figure(figsize(12,4)) plt.subplot(131) plt.title(Original Image) plt.imshow(test_img, cmapgray) plt.subplot(132) plt.title(Horizontal Edges) plt.imshow(horizontal_edges, cmapgray) plt.subplot(133) plt.title(Vertical Edges) plt.imshow(vertical_edges, cmapgray) plt.show()这个可视化清晰地展示了不同卷积核如何提取不同类型的特征。在CNN中这些卷积核不是手工设计的而是通过训练数据学习得到的。5. 性能优化向量化实现我们之前的实现使用了多重循环这在Python中效率不高。让我们用NumPy的向量化操作来优化def conv2d_vectorized(input, weights, bias, stride1, padding0): # 处理批量维度 if input.ndim 3: input input[np.newaxis, ...] batch_size, C_in, in_h, in_w input.shape C_out, _, k_h, k_w weights.shape # 计算输出尺寸 out_h (in_h 2*padding - k_h) // stride 1 out_w (in_w 2*padding - k_w) // stride 1 # 应用填充 if padding 0: padded_input np.zeros((batch_size, C_in, in_h 2*padding, in_w 2*padding)) padded_input[:, :, padding:-padding, padding:-padding] input input padded_input # 使用im2col技巧将输入转换为矩阵 cols np.zeros((batch_size, C_in, k_h, k_w, out_h, out_w)) for i in range(k_h): for j in range(k_w): cols[:, :, i, j, :, :] input[:, :, i:iout_h*stride:stride, j:jout_w*stride:stride] cols cols.transpose(0, 4, 5, 1, 2, 3).reshape(batch_size*out_h*out_w, -1) weights_flat weights.reshape(C_out, -1) # 矩阵乘法计算卷积 output (cols weights_flat.T).reshape(batch_size, out_h, out_w, C_out).transpose(0, 3, 1, 2) output bias.reshape(1, -1, 1, 1) return output.squeeze() if batch_size 1 else output这个向量化实现比之前的循环版本快得多特别是对于大输入尺寸。它使用了im2col技巧这是许多深度学习框架中优化卷积运算的常用方法。6. 从卷积层到完整CNN理解了卷积层的实现后我们可以将其扩展到完整的CNN架构。一个典型的CNN由以下层组成卷积层提取局部特征激活函数引入非线性如ReLU池化层降采样减少计算量全连接层最终分类让我们实现一个简单的CNN前向传播class SimpleCNN: def __init__(self): self.conv1 Conv2D(3, 16, 3, padding1) # 输入3通道输出16通道 self.conv2 Conv2D(16, 32, 3, padding1) # 输入16通道输出32通道 def forward(self, x): # 第一卷积层 ReLU激活 x self.conv1.forward(x) x np.maximum(0, x) # ReLU # 第二卷积层 ReLU激活 x self.conv2.forward(x) x np.maximum(0, x) # 全局平均池化 x np.mean(x, axis(2,3)) return x # 测试网络 cnn SimpleCNN() test_input np.random.randn(1, 3, 32, 32) # 1个样本3通道32x32 output cnn.forward(test_input) print(output.shape) # 应该输出 (1, 32)这个简单的CNN已经能够从输入图像中提取有意义的特征。在实际应用中我们还会添加更多层和正则化技术来提高性能。

相关文章:

别再死记公式了!用Python手写一个卷积层,彻底搞懂CNN里的‘卷’是怎么算的

用Python手写卷积层:从零理解CNN的"卷"运算 当你第一次看到卷积神经网络(CNN)的数学公式时,那些复杂的符号和下标是否让你望而却步?作为计算机视觉领域的基石,CNN的核心在于理解卷积运算的本质。本文将带你用NumPy从零实…...

【审计专栏】【财务领域】 第四十九篇 人在企业中的核心资产和核心利益01

编号 类型 企业 (行业/企业产品/企业利益链/生态位与层级) 业务领域 企业性质 企业中人的角色/岗位/利益矩阵 人在企业中的核心资产/附属资产 资产的业务-财务数学模型及数字/数值 关联知识 1 核心经营性资产(如IP、数据、品牌) 行业:人工智能 产品:工业视觉检…...

危急时刻的六条基本安全提示

人机协作,AI模型:Deepseek 仅供参考 危急时刻的六条基本安全提示 以下内容仅为通用性安全建议,供在紧急情况下保持冷静、保护自身安全时参考。所有建议均基于常理和公共安全常识,不包含任何具体操作细节或可能被不当使用的信息…...

简单学习 --> SSE

我们使用AI时,AI对我们说的话不会一次性把全部内容弹出来,而是会像流水一样,一点点吐出来,那么这种丝滑的交互体验,背后的核心就是 SSE (Server-Sent Events)。 什么是 SSE? SSE(Server-Sent …...

什么情况下会核销贷款

贷款核销的核心前提是:贷款被认定为 “损失类” 且经 “穷尽追偿” 仍无法收回,银行按监管与会计规则从账面冲销,但债权不消灭、仍可追偿。一、核心认定条件(满足其一即可)破产 / 注销 / 吊销:借款人和担保…...

基于SMD与贝壳的微型音频装置:从电路设计到嵌入式开发的完整实践

1. 项目概述:一个藏在贝壳里的声音世界你小时候有没有捡起一个海螺壳,把它贴在耳边,然后听到里面传来“呜呜”的海风声?那个瞬间,仿佛整个海洋都被装进了小小的贝壳里。今天这个项目,就是把那个童年的魔法&…...

DIY四路自动音频源切换器:从信号检测到继电器隔离的完整设计

1. 项目概述与核心需求解析作为一个喜欢在工作室里捣鼓各种音频设备的玩家,我经常遇到一个挺烦人的问题:我的功放只有一组输入,但我想接的设备却有好几个——台式电脑、平板、蓝牙接收模块,还有一台树莓派。每次想切换音源&#x…...

基于GSM与Arduino的远程控制系统:DIY电话控制与短信报警方案

1. 项目概述与核心价值如果你曾经想过,在离家几十公里外,仅凭一部普通的手机,就能远程打开家里的车库门、查看门窗是否关好,甚至在异常情况发生时让系统自动打电话给你报警,那么这个基于GSM的远程控制系统项目&#xf…...

对比自行维护多个 API 源,使用 Taotoken 聚合服务在运维复杂度上的降低

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比自行维护多个 API 源,使用 Taotoken 聚合服务在运维复杂度上的降低 在构建依赖多个大语言模型的应用时&#xff0c…...

我们公司全员把 Cursor 换成了自研的 全开源AtomCode

【引子】这是一篇实录——一位 CTO 用 28 天,用 Claude GLM 双模型调度,造出了一个让全公司放弃 Cursor 的工具。然后我意识到我们正在经历的事情,比"换工具"大得多。【读者承诺】接下来 15 分钟,你会拿到三件东西:一个真实案例(28 天 1,146 commits 是怎么做出来的…...

OmenSuperHub:基于WMI BIOS控制的高性能笔记本硬件管理方案

OmenSuperHub:基于WMI BIOS控制的高性能笔记本硬件管理方案 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 在惠…...

氘可来昔替尼常见副作用为鼻咽炎头痛及腹泻,如何应对?

任何口服药物的临床价值,都必须在疗效与安全性的天平上找到精准的平衡点。氘可来昔替尼以PASI 75应答率的全面胜出证明了自己在银屑病治疗中的卓越地位,而其不良反应谱同样经过了严苛的临床验证。鼻咽炎、头痛和腹泻构成了这款药物最需关注的三大安全信号…...

氘可来昔替尼常见副作用为鼻咽炎头痛及腹泻,如何应对

任何口服药物的临床价值,都必须在疗效与安全性的天平上找到精准的平衡点。氘可来昔替尼以PASI 75应答率的全面胜出证明了自己在银屑病治疗中的卓越地位,而其不良反应谱同样经过了严苛的临床验证。鼻咽炎、头痛和腹泻构成了这款药物最需关注的三大安全信号…...

Adobe-GenP 3.0:轻松激活Adobe全家桶的完整指南

Adobe-GenP 3.0:轻松激活Adobe全家桶的完整指南 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP Adobe-GenP 3.0是一款专为Adobe Creative Cloud系列软件…...

InVideo插件深度解析:如何在Unreal Engine中实现高效视频流播放与录制

InVideo插件深度解析:如何在Unreal Engine中实现高效视频流播放与录制 【免费下载链接】InVideo 基于UE4实现的rtsp的视频播放插件 项目地址: https://gitcode.com/gh_mirrors/in/InVideo InVideo是一个基于Unreal Engine 5开发的RTSP视频播放插件&#xff0…...

如何用WaveTools终极优化《鸣潮》游戏性能:从卡顿到丝滑的完整指南

如何用WaveTools终极优化《鸣潮》游戏性能:从卡顿到丝滑的完整指南 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 如果你正在玩《鸣潮》却频繁遭遇帧率波动、画面卡顿或操作延迟,那…...

基于IRS2092的200W D类功放设计:从PWM原理到保护电路实战

1. 项目概述与核心思路折腾音响功放,从经典的AB类玩到D类,感觉就像是从燃油车换到了电动车,动力响应和效率完全是两个维度。这次要聊的这块“200W Class-D Audio Power Amplifier [150115]”单板功放,就是一个非常典型的D类功放设…...

别再手动测模型了!用Simulink Test Manager实现自动化测试(附Excel表格配置详解)

从手动测试到智能验证:Simulink Test Manager全流程自动化实战指南 在模型开发的迭代过程中,工程师们常常陷入"修改-测试-记录"的循环泥潭。每次参数调整后,手动运行模型、记录数据、比对结果不仅消耗大量时间,更可能因…...

Unity项目DrawCall降不下来?试试用Mesh Baker合并贴图集,保姆级图文教程

Unity性能优化实战:用Mesh Baker合并贴图集降低DrawCall全流程解析当你的Unity项目帧率开始卡顿,Profiler里DrawCall数字居高不下时,合并贴图集往往是解决问题的关键一步。本文将以一个实际项目为例,带你从零开始使用Mesh Baker的…...

量子纠错码VarQEC:原理、实现与硬件优化

1. 量子纠错码基础与实验背景量子纠错码(Quantum Error Correction Codes, QEC)是量子计算中保护量子信息免受噪声影响的核心技术。与经典纠错码不同,量子纠错需要应对量子态特有的退相干和纠缠特性。传统QEC如[[5,1,3]]完美码虽然理论完备&a…...

Unity/Unreal开发者必看:用手机和陀螺仪实验,5分钟搞懂万向节死锁(附避坑指南)

Unity/Unreal开发者实战指南:用手机陀螺仪5分钟破解万向节死锁当你调试第一人称视角时,角色突然卡在墙面无法转动;当无人机模型在俯冲90度时失控乱转——这些很可能都是万向节死锁(Gimbal Lock)在作祟。作为实时3D开发中最恼人的数学陷阱之一…...

别再只用递归了!用C语言栈实现非递归快速排序,内存效率提升实战

从递归到迭代:C语言栈实现非递归快速排序的工程实践 在嵌入式开发和大规模数据处理场景中,递归实现的快速排序常常面临栈溢出风险。当排序10万个元素的数组时,递归深度可能达到log₂100000≈17层,在仅有2KB栈空间的STM32F103上极易…...

终极歌词同步神器LRCGET:5分钟为你的音乐库添加完美歌词

终极歌词同步神器LRCGET:5分钟为你的音乐库添加完美歌词 【免费下载链接】lrcget Utility for mass-downloading LRC synced lyrics for your offline music library. 项目地址: https://gitcode.com/gh_mirrors/lr/lrcget 你是否厌倦了在听歌时手动搜索歌词…...

如何用HsMod解锁炉石传说60+项隐藏功能:终极优化指南

如何用HsMod解锁炉石传说60项隐藏功能:终极优化指南 【免费下载链接】HsMod Hearthstone Modification Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod HsMod是一款基于BepInEx开发的炉石传说功能增强插件,为玩家提供…...

保姆级教程:在Ubuntu上配置Frida环境,搞定Android App的IO重定向与签名绕过

在Ubuntu上构建Android逆向工程环境:Frida实战与IO重定向技术解析 对于习惯Linux环境的安全研究人员而言,Windows-centric的逆向工具链往往带来诸多不便。本文将系统性地介绍如何在Ubuntu上搭建完整的Android逆向环境,并深入探讨如何利用Frid…...

【Lindy营销自动化工作流终极指南】:20年实战验证的7大反脆弱性设计原则,92%企业漏掉的关键衰减阈值

更多请点击: https://intelliparadigm.com 第一章:Lindy营销自动化工作流的基本范式与历史验证 Lindy效应指出,一个事物的预期剩余寿命与其当前年龄成正比——在营销自动化领域,Lindy范式体现为:经时间检验仍被广泛采…...

Unity3D深度纹理实战:手把手教你实现可交互的激光雷达扫描特效(附完整C#/Shader代码)

Unity3D深度纹理实战:手把手教你实现可交互的激光雷达扫描特效(附完整C#/Shader代码)在科幻题材的游戏开发中,激光雷达扫描特效是营造科技感的经典元素。从《赛博朋克2077》的战术目镜到《看门狗》的环境扫描,这种动态…...

3分钟掌握JetBrains IDE试用期重置:终极完整指南

3分钟掌握JetBrains IDE试用期重置:终极完整指南 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter JetBrains IDE试用期重置工具(ide-eval-resetter)是一个开源项目,专…...

HoRain云--CLAUDE.md 使用指南

🎬 HoRain云小助手:个人主页 🔥 个人专栏: 《Linux 系列教程》《c语言教程》 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!…...

企业云盘签章技术方案:从数字签名原理到工程落地

背景 电子签章在企业云盘中的落地,不只是一个"上传盖章图片"的功能实现。本质上,它是一套涉及数字签名、PKI基础设施、文档完整性校验的综合性技术方案。本文从技术选型角度,说清楚企业云盘内置签章需要解决哪些问题、主流实现方案…...