從數學上講,卷積與加減乘除同樣是一種運算,其運算的根本操做是將兩個函數的其中一個先平移,而後再與另外一個函數相稱後的累加和。這個運算過程當中,由於涉及到積分、級數的操做,因此看起來很複雜。在卷積(轉自wiki百科)中已經講過了卷積的定義以下所示:html
對於定義在連續域的函數,卷積定義爲ios
對於定義在離散域的函數,卷積定義爲網絡
這裏令U(x,y) = f(x)g(y) ,考慮到函數 f 和 g 應該地位平等,即變量 x 和 y 應該地位平等,一種可取的辦法就是沿直線 x+y = t將U(x,y)捲起來。下面爲t取實際值的時候的座標圖,能夠看到不一樣取值的t能夠遍歷整個平面。函數
將x+y=t中t取一次定值(這個定值多是咱們想要知道的某時刻的結果或着某種特徵,由咱們賦值),代入到U(x,y)中,就至關於U(x,y)所在平面沿着x+y=t直線作一次旋轉以下列動圖所示:post
這裏即是完成了整個卷積的降維過程,完成降維過程後,U(x,y)也就從一個二元函數 U(x,y) = f(x)g(y) 被捲成一元函數 V(x)=f(x)g(t-x),最後再對x求積分(即遍歷降維後的軸上的特徵點之和)。學習
編寫卷積的程序,須要根據其離散方程組來進行了解。前面已經知道了卷積的離散函數的定義公式爲:url
在用C語言等其餘語言進行實現是能夠採用定義,利用兩個for循環完成代碼。 spa
根據離散公式,能夠編寫以下C++代碼:.net
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; float min(float a, float b) { return a < b ? a : b; } void convolution(float *input1, float *input2, float *output, int mm, int nn) { float *xx = new float[mm + nn - 1]; float *tempinput2 = new float[mm + nn - 1]; for (int i = 0; i < nn; i++) { tempinput2[i] = input2[i]; } for (int i = nn; i < mm + nn - 1; i++) { tempinput2[i] = 0.0; } // do convolution for (int i = 0; i < mm + nn - 1; i++) { xx[i] = 0.0; int tem = (min(i, mm)) == mm ? mm - 1 : min(i, mm); for (int j = 0; j <= tem; j++) { xx[i] += (input1[j] * tempinput2[i - j]); } } // set value to the output array for (int i = 0; i < mm + nn - 1; i++) output[i] = xx[i]; delete[] xx; } int main() { float a[3] = {2,6,4 }; float b[5] = {1,2,5,4,8}; float *c = new float[9]; convolution(a, b, c, 3, 5); for (int i = 0; i < 7; i++) { cout << c[i] << " "; } getchar(); return 0; }
運行結果如上圖所示,打開matlab進行驗證有:3d
卷積的列表法計算 :
如圖所示:斜線上數據相加,即是卷積結果;該方法適合用於並行計算求卷積。
圖中的輸入的數據維度爲14×1414×14,過濾器大小爲5×55×5,兩者作卷積,輸出的數據維度爲10×1010×10(14−5+1=1014−5+1=10)。若是你對卷積維度的計算不清楚,能夠參考我以前的博客吳恩達深度學習筆記(deeplearning.ai)之卷積神經網絡(CNN)(上)。
上述內容沒有引入channel的概念,也能夠說channel的數量爲1。若是將二維卷積中輸入的channel的數量變爲3,即輸入的數據維度變爲(14×14×314×14×3)。因爲卷積操做中過濾器的channel數量必須與輸入數據的channel數量相同,過濾器大小也變爲5×5×35×5×3。在卷積的過程當中,過濾器與數據在channel方向分別卷積,以後將卷積後的數值相加,即執行10×1010×10次3個數值相加的操做,最終輸出的數據維度爲10×1010×10。
以上都是在過濾器數量爲1的狀況下所進行的討論。若是將過濾器的數量增長至16,即16個大小爲10×10×310×10×3的過濾器,最終輸出的數據維度就變爲10×10×1610×10×16。能夠理解爲分別執行每一個過濾器的卷積操做,最後將每一個卷積的輸出在第三個維度(channel 維度)上進行拼接。
二維卷積經常使用於計算機視覺、圖像處理領域。
圖中的輸入的數據維度爲8,過濾器的維度爲5。與二維卷積相似,卷積後輸出的數據維度爲8−5+1=48−5+1=4。
若是過濾器數量仍爲1,輸入數據的channel數量變爲16,即輸入數據維度爲8×168×16。這裏channel的概念至關於天然語言處理中的embedding,而該輸入數據表明8個單詞,其中每一個單詞的詞向量維度大小爲16。在這種狀況下,過濾器的維度由55變爲5×165×16,最終輸出的數據維度仍爲44。
若是過濾器數量爲nn,那麼輸出的數據維度就變爲4×n4×n。
一維卷積經常使用於序列模型,天然語言處理領域。
這裏採用代數的方式對三維卷積進行介紹,具體思想與一維卷積、二維卷積相同。
假設輸入數據的大小爲a1×a2×a3a1×a2×a3,channel數爲cc,過濾器大小爲ff,即過濾器維度爲f×f×f×cf×f×f×c(通常不寫channel的維度),過濾器數量爲nn。
基於上述狀況,三維卷積最終的輸出爲(a1−f+1)×(a2−f+1)×(a3−f+1)×n(a1−f+1)×(a2−f+1)×(a3−f+1)×n。該公式對於一維卷積、二維卷積仍然有效,只有去掉不相干的輸入數據維度就行。
三維卷積經常使用於醫學領域(CT影響),視頻處理領域(檢測動做及人物行爲)。
打個比方,往平靜的水面裏面扔石頭。咱們把水面的反應看做是一種衝擊響應。水面在t=0時刻石頭丟進去的時候會激起高度爲h(0)的波紋,但水面不會立馬歸於平靜,隨着時間的流逝,波紋幅度會愈來愈小,在t=1時刻,幅度衰減爲h(1), 在t=2時刻,幅度衰減爲h(2)……直到一段時間後,水面重複歸於平靜。
從時間軸上來看,咱們只在t=0時刻丟了一塊石頭,其它時刻並無作任何事,但在t=1,2….時刻,水面是不平靜的,這是由於過去(t=0時刻)的做用一直持續到了如今。
那麼,問題來了:
若是咱們在t=1時刻也丟入一塊石子呢?此時t=0時刻的影響尚未消失(水面尚未恢復平靜)新的石子又丟進來了,那麼如今激起的波浪有多高呢?答案是當前激起的波浪與t=0時刻殘餘的影響的疊加。那麼t=0時刻對t=1時刻的殘餘影響有多大呢?
爲了便於說明,接下來咱們做一下兩個假設:
1. 水面對於「單位石塊」的響應是固定的
2. 丟一個兩倍於的「單位石塊」的石塊激起的波紋高度是丟一個石塊的兩倍(即系統知足線性疊加原理)
如今咱們來計算每一時刻的波浪有多高:
y(0)=x(0)*h(0);
當前石塊引發的影響x(1)*h(0);
t=0時刻石塊x(0)引發的殘餘影響x(0)*h(1);
y(1)=x(1)*h(0)+ x(0)*h(1);
當前石塊引發的影響x(2)*h(0);
t=0時刻石塊x(0)引發的殘餘影響x(0)*h(2);
t=1時刻石塊x(1)引發的殘餘影響x(1)*h(1);
y(2)=x(2)*h(0)+ x(1)*h(1)+x(0)*h(2);
……
當前石塊引發的影響x(N)*h(0);
t=0時刻石塊x(0)引發的殘餘影響x(0)*h(N);
t=1時刻石塊x(1)引發的殘餘影響x(1)*h(N-1);
y(N)=x(N)*h(0)+ x(N-1)*h(1)+x(N-2)*h(2)+…+x(0)*h(N);
這就是離散卷積的公式了
理解了上面的問題,下面咱們來看看「翻轉」是怎麼回事:
當咱們每次要丟石子時,站在當前的時間點,系統的對咱們的迴應都是h(0),時間軸以後的(h(1),h(2).....)都是對將來的影響。而總體的迴應要加上過去對於如今的殘餘影響。
如今咱們來觀察t=4這個時刻。
站在t=0時刻看他對於將來(t=4)時刻(從如今日後4秒)的影響,可見是x(0)*h(4)
站在t=1時刻看他對於將來(t=4)時刻的影響(從如今日後3秒),可見是x(1)*h(3)
站在t=2時刻看他對於將來(t=4)時刻的影響(從如今日後2秒),可見是x(2)*h(2)
站在t=3時刻看他對於將來(t=4)時刻的影響(從如今日後1秒),可見是x(3)*h(1)
因此所謂的翻轉只是由於你站立的如今是過去的將來,而由於h(t)始終不變,故h(1)實際上是前一秒的h(1),而前一秒的h(1)就是如今,因此從當前x(4)的角度往左看,你看到的是過去的做用。h(t)未翻轉前,當從h(0)往右看,你看到的是如今對於將來的影響,當翻轉h(t)以後,從h(0)往左看,你依次看到的愈來愈遠的過去對如今的影響,而這個影響,與從x=4向左看的做用影響相對應(都是愈來愈遠的過去),做用與做用的響應就對應起來了,這一切的本質,是由於你站立的時間觀察點和方向在變。
一幅圖像在生成的過程當中,會隨機產生一些噪點,以下圖所示:
噪點在圖片中,就至關於在平地上聳起的山峯,是一個與其餘數據不符的一個較大值。
咱們能夠經過卷積操做將噪點經過濾波給濾掉,首先,將圖片用矩陣表示出來。
而後經過下面的核來進行濾波(這個在後面的文章中將會詳細講到,原理與卷積在信號處理中的應用同樣)
通過以下的卷積運算
就能夠完成在圖片上的平均濾波的效果了,經過卷積濾波後的效果以下所示: