利用矩陣相乘手動實現卷積操作

卷積(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  torchdef  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) +1output_w= int((x.shape[1]-kernel.shape[1])/stride) +1output =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_matrixoutput = 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))) 

?輸出為“ 兩個卷積結果近似相等。”

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71288.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71288.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71288.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端面試場景題葵花寶典之四

87.場景面試之大數運算:超過js中number最大值的數怎么處理 在 JavaScript 中,Number.MAX_SAFE_INTEGER(即 2^53 - 1,即 9007199254740991)是能被安全表示的最大整數。超過此值時,普通的 Number 類型會出現…

Linux中死鎖問題的探討

在 Linux 中,死鎖(Deadlock) 是指多個進程或線程因為競爭資源而相互等待,導致所有相關進程或線程都無法繼續執行的狀態。死鎖是一種嚴重的系統問題,會導致系統資源浪費,甚至系統崩潰。 死鎖的定義 死鎖是指…

【基于Mesh組網的UWB技術討論】

基于Mesh組網的UWB技術討論 Mesh 組網無線Mesh與無線中繼的區別 基于Mesh拓撲的UWB技術可行性星型拓撲 / Mesh拓撲的UWB技術比較 Mesh 組網 Mesh(網格)是一種無中心、自組織的高度業務協同的網絡。通常分為無線Mesh和有線Mesh,但在實際應用場景,有線Mes…

Python Cookbook-3.1 計算昨天和明天的日期

任務 獲得今天的日期,并以此計算昨天和明天的日期。 解決方案 方案一: 無論何時遇到有關“時間變化”或者“時間差”的問題,先考慮datetime包: import datetime today datetime.date.today() yesterday today - datetime.timedelta(day…

USB 模塊 全面解析(二)

本文是我整理的一些 USB 的學習心得,希望能對大家有所幫助。 文章目錄 前言🍍USB 協議層數據格式🍇包格式🍓 PID 域🍓 令牌包🍓 數據包🍓 握手包 🍇傳輸類型🍓 批量傳輸&…

從基礎到實踐(十):MOS管的全面解析與實際應用

MOS管(金屬-氧化物半導體場效應晶體管)是現代電子技術的基石,憑借高輸入阻抗、低功耗和易集成特性,成為數字電路、電源管理和信號處理的核心元件。從微處理器到新能源汽車電驅系統,其高效開關與放大功能支撐了計算機、…

AES/CBC/PKCS5Padding加密

1、加密代碼如下 public static String encryptAEs_CBC(String data,String key,byte[] iv) {Cipher cipher = null;try {cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//位數不夠,自動補一個長度int blocksize = cipher.getBlockSize();byte[] dataBytes …

指紋細節提取(Matlab實現)

指紋細節提取概述指紋作為人體生物特征識別領域中應用最為廣泛的特征之一,具有獨特性、穩定性和便利性。指紋細節特征對于指紋識別的準確性和可靠性起著關鍵作用。指紋細節提取,即從指紋圖像中精確地提取出能夠表征指紋唯一性的關鍵特征點,是…

Python 圖像處理之 Pillow 庫:玩轉圖片

哈嘍,大家好,我是木頭左! Pillow 庫作為 Python 圖像處理的重要工具之一,為提供了便捷且功能豐富的接口,讓能夠輕松地對圖像進行各種操作,從簡單的裁剪、旋轉到復雜的濾鏡應用、圖像合成等,幾乎無所不能。接下來,就讓一起深入探索如何使用 Pillow 庫來處理圖片,開啟一…

Android Flow 示例

在Android開發的世界里,處理異步數據流一直是一個挑戰。隨著Kotlin的流行,Flow作為Kotlin協程庫的一部分,為開發者提供了一種全新的方式來處理這些問題。今天,我將深入探討Flow的設計理念,并通過具體的例子展示如何在實…

記錄uniapp小程序對接騰訊IM即時通訊無ui集成(2)

完成以上步驟之后開始進行登錄,登陸就需要賬號。這個賬號我們可以在騰訊云中創建。 有了賬號之后開始去小程序進行登陸操作。騰訊云接口文檔 這里除了帳號還需要一個校驗值userSig正常項目開發這個字段可以在登陸后讓后端返回,現在是測試我們直接去控制…

北京航空航天大學計算機復試上機真題

北京航空航天大學計算機復試上機真題 2023北京航空航天大學計算機復試上機真題 在線評測&#xff1a;https://app2098.acapp.acwing.com.cn/ 階乘和 題目描述 求Sn1!2!3!4!5!…n!之值&#xff0c;其中n是一個數字。 輸入格式 輸入一個n&#xff08;n<20&#xff09; …

阿里萬相,正式開源

大家好&#xff0c;我是小悟。 阿里萬相正式開源啦。這就像是AI界突然開啟了一扇通往寶藏的大門&#xff0c;而且還是免費向所有人敞開的那種。 你想想看&#xff0c;在這個科技飛速發展的時代&#xff0c;AI就像是擁有神奇魔法的魔法師&#xff0c;不斷地給我們帶來各種意想…

算法之數據結構

目錄 數據結構 數據結構與算法面試題 數據結構 《倚天村 ? 圖解數據結構》 | 小傅哥 bugstack 蟲洞棧 ?數據結構基礎知識體系詳解? | Java 全棧知識體系 線性數據結構 | JavaGuide 數據結構與算法面試題 數據結構與算法面試題 | 小林coding

零基礎學習之——深度學習算法介紹01

第一節.基礎骨干網絡 物體分類是計算機視覺&#xff08;computer vision&#xff0c;CV&#xff09;中最經典的、也是目前研究得最為透徹的一 個領域&#xff0c;該領域的開創者也是深度學習領域的“名人”級別的人物&#xff0c;例如 Geoffrey Hinton、Yoshua Bengio 等。物…

弧度與角度之間的轉換公式

Radian 弧度的英語 簡稱 Rad Degree 角度的英語 簡稱 Deg 角度轉弧度 RadDeg*180/π CogMuisc.DegToRad(double degress) DegRad/180*π CogMuisc.RadToDeg(double radians) 總結: 角度大 弧度小 弧度轉角度 肯定要乘以一個大于1的數 那就是…

css之英文換行樣式

在 CSS 中&#xff0c;要實現英文文本自動換行但不從單詞中間斷開的效果&#xff0c;可以使用 word-wrap 或 overflow-wrap 屬性。以下是相關的 CSS 屬性和它們的配置&#xff1a; 使用 overflow-wrap 或 word-wrap /* This property is used to handle word breaking */ .wo…

40歲開始學Java:Java中單例模式(Singleton Pattern),適用場景有哪些?

在Java中&#xff0c;單例模式&#xff08;Singleton Pattern&#xff09;用于確保一個類只有一個實例&#xff0c;并提供全局訪問點。以下是詳細的實現方式、適用場景及注意事項&#xff1a; 一、單例模式的實現方式 1. 餓漢式&#xff08;Eager Initialization&#xff09; …

【前端基礎】3、HTML的常用元素(h、p、img、a、iframe、div、span)、不常用元素(strong、i、code、br)

HTML結構 一個HTML包含以下部分&#xff1a; 文檔類型聲明html元素 head元素body元素 例&#xff08;CSDN&#xff09;&#xff1a; 一、文檔類型聲明 HTML最一方的文檔稱為&#xff1a;文檔類型聲明&#xff0c;用于聲明文檔類型。即&#xff1a;<!DOCTYPE html>…

文本挖掘+情感分析+主題建模+K-Meas聚類+詞頻統計+詞云(景區游客評論情感分析)

本文通過情感分析技術對景區游客評論進行深入挖掘,結合數據預處理、情感分類和文本挖掘,分析游客評價與情感傾向。利用樸素貝葉斯和SVM等模型進行情感預測,探討滿意度與情感的關系。通過KMeans聚類和LDA主題分析,提取游客關心的話題,提供優化建議,為未來研究提供方向。 …