利用矩阵相乘手动实现卷积操作

卷积(Convolution) 是信号处理和图像处理中的一种重要操作,广泛应用于深度学习(尤其是卷积神经网络,CNN)中。它的核心思想是通过一个卷积核(Kernel) 或 滤波器(Filter) 对输入信号或图像进行扫描,提取局部特征。在信号处理领域,卷积可以看作是两个函数或信号在某种程度上的“重叠”运算。在图像处理中,卷积是图像滤波的核心操作。图像滤波器,例如边缘检测、模糊和锐化都是通过卷积来实现的。

1. 卷积的数学定义

一维离散卷积

给定两个离散信号 f 和 g,它们的卷积 (f∗g) 定义为:

(f * g)[n] = \sum_{m=-\infty}^{\infty} f[m] \cdot g[n - m]

二维离散卷积

对于二维信号(如图像),卷积的定义为:

(f * g)[m, n] = \sum_{k_1=-\infty}^{\infty} \sum_{k_2=-\infty}^{\infty} f[k_1, k_2] \cdot g[m - k_1, n - k_2]

2. 卷积的直观理解

卷积操作可以理解为:

  1. 滑动窗口:卷积核在输入信号或图像上滑动。

  2. 点积操作:在每个位置,卷积核与输入信号的局部区域进行点积。

  3. 特征提取:通过卷积核提取输入信号的局部特征。

3. 卷积的参数

在深度学习中,卷积操作通常包含以下参数:

  • 输入(Input):输入信号或图像,形状为 (batch_size, channels, height, width)

  • 卷积核(Kernel):滤波器,形状为 (out_channels, in_channels, kernel_height, kernel_width)

  • 步长(Stride):卷积核滑动的步长,控制输出的大小。

  • 填充(Padding):在输入信号或图像的边缘填充值(如 0),控制输出的大小。

  • 输出(Output):卷积操作的结果,形状为 (batch_size, out_channels, output_height, output_width)

4. 卷积的输出大小

卷积操作的输出大小可以通过以下公式计算:

\text{output\_height} = \left\lfloor \frac{\text{input\_height} - \text{kernel\_height}+2*\text{padding}}{\text{stride}} \right\rfloor + 1

其中:

  • input_size:输入信号或图像的大小。

  • kernel_size:卷积核的大小。

  • padding:填充大小。

  • stride:步长。

5.卷积的计算

1.单输入通道,单个卷积核

输入图片的像素值如下:

\begin{bmatrix} 1 & 1 & 1 & 0 & 0 \\ 0 & 1 & 1 & 1 & 0 \\ 0 & 0 & 1 & 1 & 1 \\ 0 & 0 & 1 & 1 & 0 \\ 0 & 1 & 1 & 0 & 0 \end{bmatrix}

卷积核为:

\begin{bmatrix} 1 & 0 &1 \\ 0 & 1 & 0 \\ 1 & 0 & 1 \\ \end{bmatrix}

计算第一个子区域和卷积核的对应元素乘积之和,如下图所示:

 Cov_feature[0,0]=1x1+1x0+1x1+0x0+1x1+1x0+0x1+0x0+1x1 =4

接着计算第二个子区域和卷积核的对应元素乘积之和,如下图所示:

Cov_feature[0,1] =1x1+1x0+0x1+1x0+1x1+1x0+0x1+1x0+1x1=3

……

2.多输入通道,单个卷积核

若输入含有多个通道,则对于某个卷积核,分别对每个通道求feature map后将对应位置相加得到最终的feature map,如下图所示:

3.多个卷积核

6. 卷积的代码实现

1.简单卷积的实现(不包含batch_size,channels):

import  torch


def  matrix_muti_for_cov(x,kernel,stride=1):
    # kernel.shape ->(h,w)
    
    output_h= int((x.shape[0]-kernel.shape[0])/stride) +1   # 计算输入的高
    output_w= int((x.shape[1]-kernel.shape[1])/stride) +1   # 计算输入的宽
    output =torch.zeros(output_h,output_w) #  初始化为(output_h,output_w)的矩阵
    
    for i in range (0,x.shape[0]-kernel.shape[0]+1,stride): # 遍历高的维度
        
        for j in range (0,x.shape[1]-kernel.shape[1]+1,stride): # 遍历宽的维度
            
            area = x[i:i+kernel.shape[0],j:j+kernel.shape[1]] # 获取卷积核滑过区域
            output[i,j] =torch.sum(area*kernel)  实现卷积操作
    return  output

 调用函数,求卷积结果


input =torch.randn(5,5)
kernel =torch.randn(3,3)  
output =matrix_muti_for_cov(input,kernel)
print(output)

 输出为

tensor([[-2.0837, -1.1043,  3.2571],
        [-1.1638,  0.7576,  3.2776],
        [ 0.3669,  0.4015,  0.9808]])

使用torch.nn.functional.conv2d(input,jernel) 来测试:

在conv2d函数中,要求

input.shape(batch_size,in_channels,hight,weight)

kernel.shape(out_channels,in_channels,kernel_hight,kernel_weight)

input =input.reshape((1,1,input.shape[0],input.shape[1]))
kernel =kernel.reshape((1,1,kernel.shape[0],kernel.shape[1]))
cov_out =F.conv2d(input,kernel)
print(cov_out.squeeze(0).squeeze(0))

 输出为

tensor([[-2.0837, -1.1043,  3.2571],
        [-1.1638,  0.7576,  3.2776],
        [ 0.3669,  0.4015,  0.9808]])

cov_out.squeeze(0).squeeze(0)是为了将batch_size维度和channels维度的数据剔出,和上面的output的数据维度相对应。

对上述代码进行简单的升级操作

def  matrix_muti_for_cov(x,kernel,stride=1,padding=0):
    # kernel.shape ->(h,w)
    output_h= int((x.shape[0]-kernel.shape[0])/stride) +1
    output_w= int((x.shape[1]-kernel.shape[1])/stride) +1
    output =torch.zeros(output_h,output_w)
    area_matrix = torch.zeros(output.numel(),kernel.numel())
    kernel_matrix =kernel.reshape(kernel.numel(),-1)
    for i in range (0,x.shape[0]-kernel.shape[0]+1,stride):
        for j in range (0,x.shape[1]-kernel.shape[1]+1,stride):
            
            area = x[i:i+kernel.shape[0],j:j+kernel.shape[1]]
            area_matrix[i+j] = torch.flatten(area)
    output_matrix =area_matrix@ kernel_matrix
    output = output_matrix.reshape(output_h, output_w)
    return  output

2.简易完整卷积的实现(包含batch_size,channels,stride,padding):

def  matrix_muti_for_cov2(input,kernel,stride=1,padding=1):
    
    # input.size ---> [batch_size,channels,hight,weight]
    batch,channel,x_h,x_w =input.shape

    # input.size ---> [out_channels,in_channels,kernel_hight,kernel_weight]
    channel_out,channels_in,kernel_h,kernel_w =kernel.shape

    # math.floor() 函数的作用是向下取整,也称为取底。 它返回小于或等于给定数值的最大整数
    output_h= (math.floor((x_h+2*padding-kernel_h)/stride) +1)
    output_w= (math.floor((x_w+2*padding-kernel_w)/stride) +1)

    output =torch.zeros(batch,channel_out,output_h,output_w)  # 初始化矩阵
    input_padded = torch.zeros(batch, channel, x_h+2*padding, x_w+2*padding) #  实现padding操作
    input_padded[:,:,padding:x_h+padding,padding:x_w+padding] =input  # 将input的值赋值给input_padded对应的区域
    for  b in range(batch):   # 遍历batch维度
        
        for c_out  in  range(channel_out):  # 遍历out_channel维度
            
            for i in range (0,output_h,stride): # 遍历hight维度
                
                for j in range (0,output_w,stride):  # 遍历 weight维度

     
                    area = input_padded[b,:,i:i+kernel_h,j:j+kernel_w]
                    output[b,c_out,i,j] =torch.sum(area*kernel[c_out])                   
                        
    return output

调用函数, 测试结果

cov_out =matrix_muti_for_cov2(input,kernel)
# print(cov_out)
cov_out2 =F.conv2d(input,kernel,padding=1)
# print(cov_out2)
if torch.allclose(cov_out, cov_out2, rtol=1e-05, atol=1e-08):
    print("两个卷积结果近似相等。") 
else:
    print("两个卷积结果不相等。")  
    print("最大绝对误差:", torch.max(torch.abs(cov_out - cov_out2))) 

 输出为“ 两个卷积结果近似相等。”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/981234.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32-HAL库初始化时钟

使能和失能外设GPIOA 时钟信号初始化函数 HAL_RCC_OscConfig函数: HAL_StatusTypeDef是该函数的返回值类型,最顶上的那句话只是这个函数的原型 HAL_RCC_ClockConfig函数: 因为FLASH实际上只能支持24MHz的时钟信号所以如果用高于24MHz的信号输入则要用到等…

windows环境执行composer install出错

现在的项目环境都是要求比较新的版本,就比如今天部署测试一个新框架遇到了下面这些问题,报错原因有以下几点: PHP版本低了,现在的新项目都是要求PHP8以上版本;指令废弃,配置文件禁用即可;切换P…

Three.js 入门(光线投射实现3d场景交互事件)

本篇主要学习内容 : 光线投射器交互事件 点赞 关注 收藏 学会了 1.光线投射器 Raycaster 此类旨在协助光线投射。光线投射用于鼠标拾取(确定鼠标在 3D 空间中的哪些对象上)等。 Raycaster( origin : Vector3, direction : Vector3, near : Float,…

蓝桥杯web第三天

展开扇子题目, #box:hover #item1 { transform:rotate(-60deg); } 当悬浮在父盒子,子元素旋转 webkit display: -webkit-box:将元素设置为弹性伸缩盒子模型。-webkit-box-orient: vertical:设置伸缩盒子的子元素排列方…

Unity 使用NGUI制作无限滑动列表

原理: 复用几个子物体,通过子物体的循环移动实现,如下图 在第一个子物体滑动到超出一定数值时,使其放到最下方 --------------------------------------------------------------》 然后不停的循环往复,向下滑动也是这…

网络安全蜜罐产品研究现状

🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 一、知识点总结 1、蜜罐(Honeypot):诱捕攻击者的一个陷阱。 2、蜜网(Honeynet):采用了技术…

SpringBoot3—场景整合:环境准备

一、云服务器 阿里云服务器开通安装以下组件 dockerrediskafkaprometheusgrafana 下载windterm:https://github.com/kingToolbox/WindTerm/releases/download/2.5.0/WindTerm_2.5.0_Windows_Portable_x86_64.zip 重要:开通云服务器以后,请一…

Ollama进行DeepSeek本地部署存在安全风险解决方案,nginx反向代理配置

文章目录 概要整体架构流程技术细节**## 1.下载nginx [https://nginx.org/en/download.html](https://nginx.org/en/download.html),推荐Stable version稳定版**2.下载完成解压文件,打开conf文件夹下的nginx.conf,贴上反向代理配置3.然后点击解压文件夹下的nginx.exe,启动成…

【音视频】ffmpeg音视频处理基本流程

一、ffmpeg音视频处理基本流程 首先先看两条命令 ffmpeg -i 1.mp4 -acodec copy -vcodec libx264 -s 1280x720 2.flv ffmpeg -i 1.mp4 -acodec copy -vcodec libx265 -s 1280x720 3.mkv-i :表示输入源,这里是1.mp4,是当前路径下的视频文件-acodec copy…

计算机网络基础:认识网络拓扑结构

计算机网络基础:认识网络拓扑结构 一、前言二、网络拓扑结构的基本概念2.1 定义2.2 作用 三、常见的物理拓扑结构3.1 总线型拓扑结构3.1.1 定义和结构3.1.2 工作原理3.1.3 优点3.1.4 缺点3.1.5 适用场景3.1.6 示例图 3.2 星型拓扑结构3.2.1 定义和结构3.2.2 工作原理…

基于Android平台的SOME/IP测试模块 EPT-ETS

在汽车产业智能化、网联化的时代浪潮中,汽车电子系统正经历着前所未有的变革。SOME/IP(Scalable service-Oriented MiddlewarE over IP)协议作为汽车电子通信领域的关键技术,其稳定性、可靠性与高效性对于整车性能的提升起着至关重…

【实战 ES】实战 Elasticsearch:快速上手与深度实践-2.2.3案例:电商订单日志每秒10万条写入优化

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 Elasticsearch批量写入性能调优实战:2.2.3 案例:电商订单日志每秒10万条写入优化1. 原始架构与瓶颈分析1.1 初始集群配置1.2 性能瓶颈定位 2. 全链路…

解决redis lettuce连接池经常出现连接拒绝(Connection refused)问题

一.软件环境 windows10、11系统、springboot2.x、redis 6 7 linux(centos)系统没有出现这问题,如果你是linux系统碰到的,本文也有一定大参考价值。 根本思路就是:tcp/ip连接的保活(keepalive)。 二.问题描述 在spr…

【开源项目-AI研发】ai-engineer-toolkit

项目地址(Fork: 40, Star: 301) GitHub - break-into-data/ai-engineer-toolkit: Projects & Resources to help you become a better AI Developer. 项目介绍 官方介绍:帮助你成为更好的 AI 开发者的工具和资源 项目本身是个表格&am…

白帽子讲Web安全资源下载

资源简介 本仓库提供《白帽子讲Web安全》一书的资源下载。这本书由阿里巴巴安全专家刺总编写,是网络安全领域的经典之作,对于从事网络安全工作的专业人士来说是必备的参考资料。 资源描述 书名: 白帽子讲Web安全作者: 阿里巴巴刺总适用人群: 网络安全…

深度学习架构Seq2Seq-添加并理解注意力机制(一)

第一章:人工智能之不同数据类型及其特点梳理 第二章:自然语言处理(NLP):文本向量化从文字到数字的原理 第三章:循环神经网络RNN:理解 RNN的工作机制与应用场景(附代码) 第四章:循环神经网络RNN、LSTM以及GR…

基于springboot的丢失儿童的基因比对系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 本丢失儿童的基因比对系统采用B/S架构,数据库是MySQL,网站的搭建与开发采用了先进的Java进行编写,使用了Spring Boot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。用户主要功能包括:用户注册、登…

Mysql面试篇笔记:

优化: 1.如何定位慢查询: 首先压测接口,查看那个接口比较慢,可以通过多种工具,比如Skywaking 可以查看各个接口响应时间,查看接口最慢,然后去跟踪接口,查看详细信息&#…

嵌入式产品级-超小尺寸游戏机(从0到1 硬件-软件-外壳)

Ultra-small size gaming console。 超小尺寸游戏机-Pico This embedded product is mainly based on miniaturization, followed by his game functions are also very complete, for all kinds of games can be played, and there will be relevant illustrations in the fo…

计算机网络-实验四子网划分

三、实验内容及步骤 1.要求 【题目】某单位申请了⼀个 C 类⽹络,单位内部有3个部门,各部门约50台主机,需要划分为3个⼦⽹,各部门接⼊到汇聚交换机,在汇聚层进⾏路由连通。假定申请到的C类网络为200.200.200.0。 2.实…