1 前言
MNN 模型模型轉(zhuǎn)換結(jié)束后進行 optimizeNet 的第一項即為 turnInnerProduct2Convolution蔬咬,拋開各種復(fù)雜的優(yōu)化考慮,單是 減少了概念的維護 一點就已經(jīng)很讓人心動了沐寺。
日常開發(fā)中林艘,可能大家都感到過 Inner Procuct、MatMul混坞、BLAS狐援、Concolution 等操作存在那么些相似性,但究竟哪里相似究孕,哪里不同咕村,或許沒有去仔細地分析過。一方面因為多維操作的分析想象的確比較燒腦蚊俺;另一方面沒有需求啊懈涛,推理用就好了,模型用就好了泳猬,跑崩了官方提issue啊批钠,找前向框架開發(fā)解決啊得封!
這不失為一個不錯的思路埋心。然而,拋開某些緊急場景下我們要自己實現(xiàn)一些模型操作轉(zhuǎn)換設(shè)計忙上,又或要實現(xiàn)一些模型操作優(yōu)化…… 作為一個AI時代的新青年拷呆,難道我們不該有一些“AI工程師的好奇心”,培養(yǎng)下 “AI工程師的自我修養(yǎng)” 嘛疫粥!
追根究底 是件很有趣的事情茬斧, 同事 也是 作為積累 在很多緊急的關(guān)鍵時刻能 “救命”的東西。那么馬上開始梗逮,讓我們一起來看看 類似卷積的相關(guān)操作的相互變換 吧项秉。
2 變換
2.1 回憶 - 卷積的關(guān)鍵參數(shù)
我們先來回憶一下卷積的相關(guān)參數(shù)
2.1.1 輸入Input
input_width : 輸入寬,如圖設(shè)為10
input_height : 輸入高慷彤,如圖設(shè)為10
input_channel : 輸入維度娄蔼,如圖設(shè)為3
input_padX : 水平方向加邊 - 本文不討論,設(shè)為0
input_padY : 垂直方向加邊 - 本文不討論底哗,設(shè)為0
input_padMode : 加邊模式 - 本文不討論
input_group_number : 輸入分組 - 暫不討論岁诉,設(shè)為 1
2.1.2 卷積核Kernal
kernal_width : 卷積核寬,如圖設(shè)為3
kernel_height : 卷積核高跋选,如圖設(shè)為3
kernal_dilateX : 水平方向膨脹 - 本文不討論涕癣,設(shè)為1
kernal_dilateY : 垂直方向膨脹 - 本文不討論,設(shè)為1
kernal_number = input_channel * output_channel野建,舉例的計算結(jié)果為 3 x 4 = 12
(output_channel 的說明在 2.1.5 部分)
2.1.3 偏置Bias
bias_number = output_channel属划,舉例的計算結(jié)果為 4
(output_channel 的說明在 2.1.5 部分)
2.1.4 其他配置(步長Stride)
strideX : 水平方向步長 - 本文不討論,設(shè)為1
strideY : 垂直方向步長 - 本文不討論候生,設(shè)為1
2.1.5 輸出Output
output_width : (input_width + input_padX * 2 - ((kernal_width - 1) * kernal_dilateX + 1)) / strideX + 1同眯,按上面的設(shè)置計算,為8
output_height : (input_height + input_padY * 2 - ((kernal_height - 1) * kernal_dilateY + 1)) / strideY + 1唯鸭,按上面的設(shè)置計算须蜗,為8
output_channel : 輸出維度,如圖設(shè)為4
2.1.6 卷積操作示例
按照上面示例的配置目溉,我們得到一份卷積運算明肮,如下圖:
2.2 Convolution的基礎(chǔ)參數(shù)變換
我們首先關(guān)注如下5個配置的修改變化:
input_channel 輸入維度(或輸入特征)數(shù)量
output_channel 輸出維度(或輸出特征)數(shù)量
kernal_width 卷積核寬度
kernel_height 卷積核高度
group 卷積分組數(shù)量
應(yīng)該蠻直觀的吧柿估,相信大家稍微不熟悉的應(yīng)該只有分組卷積 (Group Convolution) 了吧。
金哥和你一起學(xué)模型壓縮——結(jié)構(gòu)篇(1)
這篇文章中對分組卷積略有介紹陷猫,可以適當(dāng)參考秫舌。
(姚神記得給我支付寶打廣告費~!)
2.3 Convolution <--> Inner Product
讓我們漸入佳境绣檬,看看Convolution與Inner Product的轉(zhuǎn)換關(guān)系足陨。
Convolution 使用 1x1 的 kernal墨缘,再將輸入 size 變?yōu)?1x1 就退化成了 Inner Product!
有些神奇對不對零抬,更精彩的還在后面~
2.4 Convolution(Inner Product)<-> MatMul
Inner Product 退化為一個矩陣乘法很簡單镊讼,Inner Product 可以看做是一個特殊的 Convolution,所以 MatMul 也可以看做一個特殊的 Convolution平夜。
但細心的小伙伴會發(fā)現(xiàn)我們舉例的 MatMul 的左矩陣是 1 x 3 的褥芒,如果換證一個 2 x 3 的正常矩陣嚼松?……貌似轉(zhuǎn)換就不太順利了……
別急,我們先來了解下 BLAS锰扶。
2.5 BLAS
BLAS 即 Basic Linear Algebra Subprograms献酗,即 基礎(chǔ)線性代數(shù)子程序。
我們比較常見的 GEMM坷牛,即廣義矩陣乘法就是 BLAS 的一種高級形式罕偎。
會到我們 2.4節(jié) 遺留的問題颜及,有沒有發(fā)現(xiàn) 11號 的 GEMM 變換 MatMul 很容易呢甩苛?
馬上來看看 BLAS & Convolution 的相互變換
2.6 Convolution(InnerProduct) <-> BLAS
我們以退化為 Inner Product 的 Convolution 為例來描述 Convolution & BLAS 之間的關(guān)聯(lián)
GEMM 可以看做一個 每組kernal都完全相同 的分組卷積讯蒲!
所以轉(zhuǎn)模型的時候想將一個 GEMM 轉(zhuǎn)化為 Convolution 的話,是要 犧牲一些存儲空間 咯肄扎。
我們可以理解為分組卷積的變種
2.7 總結(jié)
把我們 2.1 ~ 2.6 描述的變換整合到一張圖
還是有點復(fù)雜的犯祠,不過針對 有不同操作轉(zhuǎn)換硬需求 的小伙伴旭等,相信這張圖能為整理思路節(jié)約不少的時間!
3 后記
然而衡载,Convolution 的變換場景還不止如此搔耕,比如當(dāng) Group Convolution 的 Input Channel、Output Channel痰娱、Group Number 相等時度迂,就變成了一個 DepthWise Convolution !
有機會我們再慢慢研究討論咯~