首页 > 其他分享 >numpy手搓卷积

numpy手搓卷积

时间:2023-10-05 18:55:06浏览次数:30  
标签:kernel 卷积 height width np input numpy

numpy实现卷积

1 卷积本质

  • 设计这样的一个 滤波器(filter,也称为kernel),用这个filter,往我们的图片上“盖”,覆盖一块跟filter一样大的区域之后,对应元素相乘,然后求和。计算一个区域之后,就向其他区域挪动,接着计算,直到把原图片的每一个角落都覆盖到了为止。这个过程就是 “卷积”。
  • 可以通过设计特定的filter,让它去跟图片做卷积,就可以识别出图片中的某些特征。
  • CNN(convolutional neural network),主要就是通过一个个的filter,不断地提取特征,从局部的特征到总体的特征,从而进行图像识别等等功能
  • filter中的参数是通过大量的数据,让机器自己去“学习”这些参数。

2 Padding方式

  • 每次卷积,图像都缩小,采用padding的方法。每次卷积前,先给图片周围都补一圈空白,让卷积之后图片跟原来一样大,同时,原来的边缘也被计算了更多次。
  • “让卷积之后的大小不变”的padding方式,称为 “Same”方式, 把不经过任何填白的,称为 “Valid”方式。

2.1 “Valid”方式

2.1 “Same”方式

2.3 Padding计算公式

3 多卷积核多通道

  • 在单核单通道的基础上执行多遍,然后把结果累加。
  • (1)一个循环是输入通道数对循环:把卷积核在每个通道数据上卷积,然后结果累加
  • (2)一个循环是核个数对循环:每个卷积核执行步骤(1),然后把结果累加,如下图

4 代码实现(循环计算实现和矩阵计算实现)

4.1 一维卷积

在 NumPy 中实现卷积操作可以通过使用 numpy.convolve 函数或手动编写卷积操作的代码来完成。以下是两种方法的示例:

方法一:使用 numpy.convolve 函数

numpy.convolve 函数用于执行一维卷积操作。首先,您需要定义一个卷积核(滤波器),然后将它应用于输入信号。下面是一个示例:

import numpy as np

# 定义输入信号
signal = np.array([1, 2, 3, 4, 5])

# 定义卷积核(滤波器)
kernel = np.array([0.5, 1, 0.5])

# 使用 numpy.convolve 执行卷积操作
convolution_result = np.convolve(signal, kernel, mode='valid')

print("卷积结果:", convolution_result)

在这个示例中,signal 是输入信号,kernel 是卷积核。mode='valid' 表示执行有效卷积,即仅计算信号和卷积核完全重叠的部分。输出将是卷积的结果。

方法二:手动实现卷积操作

您也可以手动编写卷积操作的代码,通过遍历输入信号并应用卷积核来计算卷积的结果。以下是一个示例:

import numpy as np

# 定义输入信号
signal = np.array([1, 2, 3, 4, 5])

# 定义卷积核(滤波器)
kernel = np.array([0.5, 1, 0.5])

# 初始化卷积结果数组
convolution_result = np.zeros(len(signal) - len(kernel) + 1)

# 执行卷积操作
for i in range(len(convolution_result)):
    convolution_result[i] = np.sum(signal[i:i + len(kernel)] * kernel)

print("卷积结果:", convolution_result)

这个示例手动执行了卷积操作,遍历输入信号并计算卷积结果。输出将与使用 numpy.convolve 函数得到的结果相同。

这两种方法都可用于实现简单的卷积操作。然而,对于更复杂的卷积神经网络 (CNN) 等应用,通常会使用深度学习框架(如 TensorFlow 或 PyTorch),它们提供了高度优化的卷积操作,能够更高效地处理大型数据集和复杂的模型。

4.2 二维卷积

手动实现二维图片数据的卷积操作涉及到卷积核(滤波器)在输入图像上滑动并执行点积运算的过程。以下是一个使用 NumPy 手动实现的简单示例:

import numpy as np

# 创建一个示例的二维图片数据(4x4 像素)
image = np.array([[1, 2, 3, 4],
                  [5, 6, 7, 8],
                  [9, 10, 11, 12],
                  [13, 14, 15, 16]], dtype=np.float32)

# 定义一个卷积核(滤波器)
kernel = np.array([[1, 0],
                   [0, -1]], dtype=np.float32)

# 获取输入图像和卷积核的尺寸
image_height, image_width = image.shape
kernel_height, kernel_width = kernel.shape

# 计算卷积后的输出图像的尺寸
output_height = image_height - kernel_height + 1
output_width = image_width - kernel_width + 1

# 初始化输出图像
output_image = np.zeros((output_height, output_width), dtype=np.float32)

# 执行卷积操作
for i in range(output_height):
    for j in range(output_width):
        output_image[i, j] = np.sum(image[i:i+kernel_height, j:j+kernel_width] * kernel)

# 打印卷积结果
print(output_image)

在这个示例中,我们首先创建了一个示例的二维图片数据和一个卷积核。然后,我们计算了卷积后的输出图像的尺寸,并初始化一个用于存储输出的数组。接下来,我们使用两层嵌套的循环遍历输入图像,并在每个位置执行卷积操作,将结果存储在输出图像中。最后,我们打印了卷积的结果。

这个示例是一个简单的手动卷积实现,用于说明卷积的基本原理。在实际应用中,通常会使用深度学习框架来执行卷积操作,因为它们提供了高度优化的卷积操作,并且能够处理更大的图像和复杂的卷积核。手动实现卷积通常用于教育目的或深入理解卷积的工作原理。

4.3 添加padding和stride

要用 NumPy 实现类似 PyTorch 的 Conv2D 函数,需要考虑卷积核的大小、步幅、填充以及多通道的情况。以下是一个简化的示例,用 NumPy 实现一个基本的 2D 卷积操作:

import numpy as np

def conv2d_numpy(input_data, kernel, stride=1, padding=0):
    # 获取输入数据的尺寸
    input_height, input_width = input_data.shape
    # 获取卷积核的尺寸
    kernel_height, kernel_width = kernel.shape
    # 计算输出图像的尺寸
    output_height = (input_height - kernel_height + 2 * padding) // stride + 1
    output_width = (input_width - kernel_width + 2 * padding) // stride + 1
    
    # 初始化输出图像
    output_data = np.zeros((output_height, output_width))
    
    # 填充输入数据(根据填充数量添加额外的行和列)
    if padding > 0:
        input_data = np.pad(input_data, ((padding, padding), (padding, padding)), mode='constant')
    
    # 执行卷积操作
    for i in range(0, input_height - kernel_height + 1, stride):
        for j in range(0, input_width - kernel_width + 1, stride):
            output_data[i // stride, j // stride] = np.sum(input_data[i:i+kernel_height, j:j+kernel_width] * kernel)
    
    return output_data

# 创建一个示例的二维图片数据(4x4 像素)
image = np.array([[1, 2, 3, 4],
                  [5, 6, 7, 8],
                  [9, 10, 11, 12],
                  [13, 14, 15, 16]], dtype=np.float32)

# 定义一个卷积核(滤波器)
kernel = np.array([[1, 0],
                   [0, -1]], dtype=np.float32)

# 执行自定义的卷积操作
result = conv2d_numpy(image, kernel, stride=1, padding=0)

# 打印卷积结果
print(result)

这个示例中,我们首先定义了一个自定义的 conv2d_numpy 函数,用于执行二维卷积操作。然后,我们创建了一个示例的二维图片数据和一个卷积核,并调用自定义函数来执行卷积操作。最后,我们打印了卷积的结果。

请注意,这是一个简化的实现,不包括多通道、批次处理以及更复杂的功能。实际上,深度学习框架(如 PyTorch)提供了高度优化的卷积操作,能够处理多通道、批次和更复杂的模型。手动实现卷积通常用于教育目的或深入理解卷积的工作原理。

4.4 多通道支持

要为 conv2d_numpy 函数添加多通道卷积支持,您需要考虑输入数据和卷积核的通道维度,并执行多通道卷积操作。以下是一个经过修改的示例,支持多通道卷积:

import numpy as np

def conv2d_numpy(input_data, kernel, stride=1, padding=0):
    # 获取输入数据的尺寸和通道数
    input_height, input_width, input_channels = input_data.shape
    # 获取卷积核的尺寸和通道数
    kernel_height, kernel_width, kernel_channels = kernel.shape
    # 计算输出图像的尺寸
    output_height = (input_height - kernel_height + 2 * padding) // stride + 1
    output_width = (input_width - kernel_width + 2 * padding) // stride + 1
    
    # 初始化输出图像
    output_data = np.zeros((output_height, output_width))
    
    # 填充输入数据(根据填充数量添加额外的行和列)
    if padding > 0:
        input_data = np.pad(input_data, ((padding, padding), (padding, padding), (0, 0)), mode='constant')
    
    # 执行多通道卷积操作
    for i in range(0, input_height - kernel_height + 1, stride):
        for j in range(0, input_width - kernel_width + 1, stride):
            for k in range(kernel_channels):
                output_data[i // stride, j // stride] += np.sum(input_data[i:i+kernel_height, j:j+kernel_width, k] * kernel[:, :, k])
    
    return output_data

# 创建一个示例的多通道二维图片数据(4x4 像素,3个通道)
image = np.random.rand(4, 4, 3).astype(np.float32)

# 定义一个多通道的卷积核(滤波器)
kernel = np.random.rand(2, 2, 3).astype(np.float32)

# 执行多通道卷积操作
result = conv2d_numpy(image, kernel, stride=1, padding=0)

# 打印卷积结果
print(result)

这个示例中,我们修改了 conv2d_numpy 函数以支持多通道的输入数据和卷积核。在执行卷积操作时,我们遍历了通道维度并对每个通道进行卷积,然后将结果相加以生成输出。请注意,多通道卷积需要确保输入图像和卷积核的通道数匹配,否则会出现维度错误。

本文由mdnice多平台发布

标签:kernel,卷积,height,width,np,input,numpy
From: https://www.cnblogs.com/haidao09/p/17743755.html

相关文章

  • 附录A NumPy高级应用
    在这篇附录中,我会深入NumPy库的数组计算。这会包括ndarray更内部的细节,和更高级的数组操作和算法。本章包括了一些杂乱的章节,不需要仔细研究。A.1ndarray对象的内部机理NumPy的ndarray提供了一种将同质数据块(可以是连续或跨越)解释为多维数组对象的方式。正如你之前所看到的那......
  • 第04章 NumPy基础:数组和矢量计算
    NumPy(NumericalPython的简称)是Python数值计算最重要的基础包。大多数提供科学计算的包都是用NumPy的数组作为构建基础。NumPy的部分功能如下:ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。用于对整组数据进行快速运算的标准数学函数(无需编写循环)。......
  • 【研究生学习】深度学习中几种常用的卷积形式的原理以及其Pytorch调用
    本篇博客主要记录一下在深度学习中几种常用的卷积形式的基本原理、输入输出维度,以及如何在Pytorch中调用这些卷积形式卷积卷积实际上是对图像的不同区域进行特征提取,一般认为输入图像的维度为H×W×C,如下图所示:图像具有颜色通道,一般是RGB,需要理解的是不同通道数的图像和不同的......
  • python numpy 稀疏矩阵与密集矩阵
    在NumPy中,稀疏矩阵和密集矩阵是两种不同的数据表示方式,用于存储矩阵数据。它们之间的主要区别在于存储元素的方式和内存占用。稀疏矩阵(SparseMatrix):区别:存储方式:稀疏矩阵只存储非零元素的位置和数值,而忽略零元素,从而节省内存。内存占用:由于只存储非零元素,稀疏矩阵在处理大规模......
  • AttributeError: module 'numpy' has no attribute 'int'.
    AttributeError:module'numpy'hasnoattribute'int'.numpy                    1.24.1                  pypi_0   pypiscikit-learn             1.2.2                   pypi_0   p......
  • numpy -- 数据分析三剑客
    博客地址:https://www.cnblogs.com/zylyehuo/NumPy(NumericalPython)是Python语言中做科学计算的基础库。重在于数值计算,也是大部分Python科学计算库的基础,多用于在大型、多维数组上执行的数值运算。开发环境anaconda集成环境:集成好了数据分析和机器学习中所需要的全......
  • ICLR2023 | 用于图像复原的基础二值卷积单元
    前言 本文分享ICLR2023论文BasicBinaryConvolutionUnitForBinarizedImageRestorationNetwork ,介绍用于图像复原的基础二值卷积单元。本文转载自我爱计算机视觉仅用于学术分享,若侵权请联系删除欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结、最新技术跟踪、......
  • 范德蒙德卷积公式
    公式范德蒙德卷积公式:\[\sum\limits_{i=0}^k\dbinom{n}{i}\dbinom{m}{k-i}=\dbinom{n+m}{k}\]证明证明也非常的简单:1.组合证明记现有\(n\)个男生\(m\)个女生,在这之中选\(k\)个人的方案数。则\(\sum\limits_{i=0}^k\dbinom{n}{i}\dbinom{m}{k-i}\)表示为先枚举男生......
  • 卷积导向快速傅里叶变换(FFT/NTT)教程
    1Forewords卷积,但不止卷积-FFT漫谈先有FT,再有DFT,才有FFT时频转换是最初的用途发现单位根优秀性质,JamesCooley,JohnTukey发明现代FFT加速DFT,但此前相似的发现早已有之后来将DFT与卷积定理联系,FFT才被用于计算多项式乘法复数运算精度误差推动了NTT的发......
  • 水果识别系统Python+TensorFlow+卷积神经网络算法【图像识别】
    引言随着科技的发展,我们生活中的各种便利工具日益增加。例如,你有没有想过,当你在超市里看到一个陌生的水果,却不知道它是什么名字时,有一个工具可以帮你识别出来?今天,我要为大家介绍一种基于Python的水果识别系统。这个系统不仅识别准确,还具有友好的用户界面。下面,让我们一起探索这个......