numpy手搓卷积

## numpy实现卷积 ### 1 卷积本质 - 设计这样的一个 滤波器(filter,也称为kernel),用这个filter,往我们的图片上“盖”,覆盖一块跟filter一样大的区域之后,对应元素相乘,然后求和。计算一个区域之后,就向其他区域挪动,接着计算,直到把原图片的每一个角落都覆盖到了为止。这个过程就是 “卷积”。 - 可以通过设计特定的filter,让它去跟图片做卷积,就可以识别出图片中的某些特征。 - CNN(convolutional neural network),主要就是通过一个个的filter,不断地提取特征,从局部的特征到总体的特征,从而进行图像识别等等功能 - filter中的参数是通过大量的数据,让机器自己去“学习”这些参数。 ### 2 Padding方式 - 每次卷积,图像都缩小,采用padding的方法。每次卷积前,先给图片周围都补一圈空白,让卷积之后图片跟原来一样大,同时,原来的边缘也被计算了更多次。 - “让卷积之后的大小不变”的padding方式,称为 “Same”方式, 把不经过任何填白的,称为 “Valid”方式。 #### 2.1 “Valid”方式 ![](https://ai-studio-static-online.cdn.bcebos.com/8131725726ac4e729751f6208a64e1b326d0c3b5e04f4600a7737b72ec6a6780) #### 2.1 “Same”方式 ![](https://ai-studio-static-online.cdn.bcebos.com/bd68f585f81d443292a5c8af76aae336718a4126cbb744c68629ca8eabd4a1ba) #### 2.3 Padding计算公式 ![](https://upload-images.jianshu.io/upload_images/24901004-bdc12e5ed0e5587d.png) ### 3 多卷积核多通道 - 在单核单通道的基础上执行多遍,然后把结果累加。 - (1)一个循环是输入通道数对循环:把卷积核在每个通道数据上卷积,然后结果累加 - (2)一个循环是核个数对循环:每个卷积核执行步骤(1),然后把结果累加,如下图 ![](https://ai-studio-static-online.cdn.bcebos.com/fe3bc0d615eb49398a94b05b6f4608bf8508b93a4a36401fb4f636a2604dd2b1) ![](https://ai-studio-static-online.cdn.bcebos.com/fdbd8960755043f7badbbbaddbf3fac3027434f1fc4f421884524daced9d8d28) ### 4 代码实现(循环计算实现和矩阵计算实现) #### 4.1 一维卷积 在 NumPy 中实现卷积操作可以通过使用 `numpy.convolve` 函数或手动编写卷积操作的代码来完成。以下是两种方法的示例: **方法一:使用 `numpy.convolve` 函数** `numpy.convolve` 函数用于执行一维卷积操作。首先,您需要定义一个卷积核(滤波器),然后将它应用于输入信号。下面是一个示例: ```python 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'` 表示执行有效卷积,即仅计算信号和卷积核完全重叠的部分。输出将是卷积的结果。 **方法二:手动实现卷积操作** 您也可以手动编写卷积操作的代码,通过遍历输入信号并应用卷积核来计算卷积的结果。以下是一个示例: ```python 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 手动实现的简单示例: ```python 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 卷积操作: ```python 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` 函数添加多通道卷积支持,您需要考虑输入数据和卷积核的通道维度,并执行多通道卷积操作。以下是一个经过修改的示例,支持多通道卷积: ```python 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](https://mdnice.com/?platform=6)多平台发布
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容