最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

MegEngine Python 層模塊串講(中)

2023-07-28 11:30 作者:曠視天元MegEngine  | 我要投稿

前面的文章中,我們簡單介紹了在?MegEngine imperative?中的各模塊以及它們的作用。對于新用戶而言可能不太了解各個(gè)模塊的使用方法,對于模塊的結(jié)構(gòu)和原理也是一頭霧水。Python?作為現(xiàn)在深度學(xué)習(xí)領(lǐng)域的主流編程語言,其相關(guān)的模塊自然也是深度學(xué)習(xí)框架的重中之重。

模塊串講將對?MegEngine?的?python?層相關(guān)模塊分別進(jìn)行更加深入的介紹,會(huì)涉及到一些原理的解釋和代碼解讀。Python?層模塊串講共分為上、中、下三個(gè)部分,本文將介紹 Python?層的?functional、module?和?optimizer?模塊。理解并掌握這幾個(gè)模塊對于高效搭建神經(jīng)網(wǎng)絡(luò)非常重要。


Python 層計(jì)算接口 —— functional 模塊

我們在定義網(wǎng)絡(luò)結(jié)構(gòu)時(shí)經(jīng)常需要包含一些計(jì)算操作,這些計(jì)算操作就定義在?functional?中。

functional?中實(shí)現(xiàn)了各類計(jì)算函數(shù),包含對很多?op?的封裝,供實(shí)現(xiàn)模型時(shí)調(diào)用。

functional?中有些?op?完全是由?Python?代碼實(shí)現(xiàn),有些則需要調(diào)用?C++?接口完成計(jì)算(沒錯(cuò),這里的計(jì)算就需要?MegDNN kernel)。對于后者,需要有機(jī)制確保我們的實(shí)現(xiàn)能夠轉(zhuǎn)發(fā)到底層正確執(zhí)行,所以你在?functional?的許多?op?實(shí)現(xiàn)中會(huì)看到?builtin?和?apply

  • builtin

    builtin?封裝了所有的?op,我們在?functional?中通過?builtin.SomeOp(param)?的方式獲得一個(gè)算子?SomeOp,param?表示獲取?SomeOp?需要的參數(shù)。

  • apply

    通過?builtin?獲取到?op?后,需要調(diào)用?apply?接口來調(diào)用?op?的底層實(shí)現(xiàn)進(jìn)行計(jì)算。apply?是在?Python?層調(diào)用底層?op?的接口,apply?的第一個(gè)參數(shù)是?op(通過?builtin?獲得),后面的參數(shù)是執(zhí)行這個(gè)?op?需要的參數(shù),都為?Tensor。在?imperative?中?op?計(jì)算通過?apply(op, inputs)?的方式向下傳遞并最終調(diào)用到?MegDNN?中的?kernel。

Functional?中的許多?op?都需要通過?builtin?和?apply?調(diào)用底層?MegDNN?的?op?來進(jìn)行計(jì)算操作。然而在實(shí)際的計(jì)算發(fā)生前,很多時(shí)候需要在?Python?層做一些預(yù)處理。

來看下面這個(gè)例子

這里?concat?方法先對輸入?tensor?數(shù)量、device?在?python?層做了一些預(yù)處理,然后才調(diào)用?builtin?和?apply?向下轉(zhuǎn)發(fā)。

而對于?diag(https://github.com/MegEngine/MegEngine/blob/master/imperative/python/megengine/functional/tensor.py#L229)?這個(gè)?op,無需預(yù)處理直接向下傳遞即可:

對于實(shí)現(xiàn)了對應(yīng)?kernel?的?op,其在?imperative?層的實(shí)現(xiàn)通常非常的短。

上面?concat?和?diag?的?apply?調(diào)用會(huì)進(jìn)入?py_apply?(https://github.com/MegEngine/MegEngine/blob/master/imperative/python/src/tensor.cpp#L79)函數(shù),并通過解析?Python?中的參數(shù),將它們轉(zhuǎn)換成?C++?中的對應(yīng)類型,然后調(diào)用?imperative::apply,進(jìn)入?dispatch(https://github.com/MegEngine/MegEngine/blob/master/imperative/python/megengine/functional/tensor.py#L995)?層。

部分?functional?的?op?不直接調(diào)用?py_apply?而是有對應(yīng)的?cpp?實(shí)現(xiàn),比如?squeeze

這樣的實(shí)現(xiàn)往往是需要在調(diào)用?py_apply?之前做一些預(yù)處理,但使用?python?實(shí)現(xiàn)性能較差,所以我們將相關(guān)預(yù)處理以及?py_apply?的邏輯在?C++?層面實(shí)現(xiàn)。

本文主要介紹?Python?層的方法,關(guān)于?C++?部分的實(shí)現(xiàn)會(huì)在之后的文章進(jìn)行更深入的介紹。

在這里我們只需要知道,functional?中包裝了所有關(guān)于?Tensor?計(jì)算相關(guān)的接口,是所有計(jì)算的入口,實(shí)際的計(jì)算操作通常會(huì)被轉(zhuǎn)發(fā)到更底層的?C++?實(shí)現(xiàn)。

用戶可以參考官方文檔(https://www.megengine.org.cn/doc/stable/zh/reference/functional.html?highlight=functional)獲取所有?functional?中的方法介紹。

模塊結(jié)構(gòu)的小型封裝版本 —— module 模塊

神經(jīng)網(wǎng)絡(luò)模型是由對輸入數(shù)據(jù)執(zhí)行操作的各種層(Layer),或者說模塊(Module)組成。

Module?用來定義網(wǎng)絡(luò)模型結(jié)構(gòu),用戶實(shí)現(xiàn)算法時(shí)要用組合模塊?Module (megengine/module)?的方式搭建模型,定義神經(jīng)網(wǎng)絡(luò)時(shí)有些結(jié)構(gòu)經(jīng)常在模型中反復(fù)使用,將這樣的結(jié)構(gòu)封裝為一個(gè)?Module,既可以減少重復(fù)代碼也降低了復(fù)雜模型編碼的難度。

一個(gè)?module?類主要有兩類函數(shù):

  • __init__:構(gòu)造函數(shù),定義了模型各個(gè)層的大小。用戶自定義的?Module?都源自基類?class Module,所以在構(gòu)造函數(shù)中一定要先調(diào)用?super().__init__(),設(shè)置?Module?的一些基本屬性。模型要使用的所有層 / 模塊都需要在構(gòu)造函數(shù)中聲明。

  • forward:定義模型結(jié)構(gòu),實(shí)現(xiàn)前向傳播,也就是將數(shù)據(jù)輸入模型到輸出的過程。這里會(huì)調(diào)用?Functional (megengine/functional)?中的函數(shù)進(jìn)行前向計(jì)算,forward?表示的是模型實(shí)現(xiàn)的邏輯。

來看一個(gè)例子:

__init__?表明模型中有一個(gè)參數(shù)?a,它的初值是固定的,forward?中實(shí)現(xiàn)了具體的計(jì)算邏輯,也就是對傳入的參數(shù)與?a?進(jìn)行乘法運(yùn)算。

對于一些更復(fù)雜的計(jì)算操作(如卷積、池化等)就需要借助?functional?中提供的方法來完成。

除了?__init__?和?forward,基類?class Module?提供了很多屬性和方法,常用的有:

  • def buffers(self, recursive: bool = True, **kwargs) -> Iterable[Tensor]:返回一個(gè)可迭代對象,遍歷當(dāng)前模塊的所有?buffers

  • def parameters(self, recursive: bool = True, **kwargs) -> Iterable[Parameter]:返回一個(gè)可迭代對象,遍歷當(dāng)前模塊所有的?parameters;

  • def tensors(self, recursive: bool = True, **kwargs) -> Iterable[Parameter]:返回一個(gè)此?module?的?Tensor?的可迭代對象;

  • def children(self, **kwargs) -> "Iterable[Module]":返回一個(gè)可迭代對象,該對象包括屬于當(dāng)前模塊的直接屬性的子模塊;

  • def named_buffers(self, prefix: Optional[str] = None, recursive: bool = True, **kwargs) -> Iterable[Tuple[str, Tensor]]:返回當(dāng)前模塊中?key?與?buffer?的鍵值對的可迭代對象,這里?key?是從該模塊至?buffer?的點(diǎn)路徑(dotted path);

  • def named_parameters(self, prefix: Optional[str] = None, recursive: bool = True, **kwargs) -> Iterable[Tuple[str, Parameter]]:返回當(dāng)前模塊中?key?與?parameter?的鍵值對的可迭代對象,這里?key?是從該模塊至?buffer?的點(diǎn)路徑(dotted path);

  • def named_tensors(self, prefix: Optional[str] = None, recursive: bool = True, **kwargs) -> Iterable[Tuple[str, Tensor]]:返回當(dāng)前模塊中?key?與?Tensorbuffer + parameter) 的鍵值對的可迭代對象,這里?key?是從該模塊至?Tensor?的點(diǎn)路徑(dotted path);

  • def named_modules(self, prefix: Optional[str] = None, **kwargs) -> "Iterable[Tuple[str, Module]]":返回一個(gè)可迭代對象,該對象包括當(dāng)前模塊自身在內(nèi)的其內(nèi)部所有模塊組成的?key-module?鍵-模塊對,這里?key?是從該模塊至各子模塊的點(diǎn)路徑(dotted path);

  • def named_children(self, **kwargs) -> "Iterable[Tuple[str, Module]]":返回一個(gè)可迭代對象,該對象包括當(dāng)前模塊的所有子模塊(submodule)與鍵(key)組成的?key-submodule?對,這里?key?是子模塊對應(yīng)的屬性名;

  • def state_dict(self, rst=None, prefix="", keep_var=False):返回模塊的狀態(tài)字典,狀態(tài)字典是一個(gè)保存當(dāng)前模塊所有可學(xué)習(xí)的?Tensor?(buffer + parameter)的字典。出于兼容性考慮,字典中的?value?的數(shù)據(jù)結(jié)構(gòu)類型為?numpy.ndarray?(而不是?Tensor),并且不可修改,是只讀的;

  • def load_state_dict(self, state_dict: Union[dict, Callable[[str, Tensor], Optional[np.ndarray]]], strict=True, ):加載一個(gè)模塊的狀態(tài)字典,這個(gè)方法常用于模型訓(xùn)練過程的保存與加載。

值得一提的是,Parameters?和?Buffer?都是與?Module?相關(guān)的?Tensor,它們的區(qū)別可以理解為:

  • Parameter?是模型的參數(shù),在訓(xùn)練過程中會(huì)通過反向傳播進(jìn)行更新,因此值是可能改變的,常見的有?weight、bias?等;

  • Buffer?是模型用到的統(tǒng)計(jì)量,不會(huì)在反向傳播過程中更新,常見的有?mean、var?等。

在?MegEngine?的?module(https://github.com/MegEngine/MegEngine/tree/master/imperative/python/megengine/module)目錄?下可以看到已經(jīng)有很多常見的?module?實(shí)現(xiàn),用戶實(shí)現(xiàn)自己的模型可以根據(jù)需要復(fù)用其中的模塊。

使用 optimizer 模塊優(yōu)化模型參數(shù)

MegEngine?中的?optimizer(https://github.com/MegEngine/MegEngine/tree/master/imperative/python/megengine/optimizer)?模塊實(shí)現(xiàn)了基于各種常見優(yōu)化策略的優(yōu)化器,為用戶提供了包括?SGD、ADAM?在內(nèi)的常見優(yōu)化器實(shí)現(xiàn)。這些優(yōu)化器能夠基于參數(shù)的梯度信息,按照算法所定義的策略執(zhí)行更新。

大部分情況下用戶不會(huì)自己實(shí)現(xiàn)優(yōu)化器,這里以?SGD?優(yōu)化器為例,優(yōu)化神經(jīng)網(wǎng)絡(luò)模型參數(shù)的基本流程如下:

  • 這里我們構(gòu)造了一個(gè)優(yōu)化器?optimizer,傳入?yún)?shù)是?model?需要被優(yōu)化的?Parameter,和?learning rate

  • 優(yōu)化器通過執(zhí)行?step()?方法進(jìn)行一次優(yōu)化;

  • 優(yōu)化器通過執(zhí)行?clear_grad()?方法清空參數(shù)梯度。

    • 為何要手動(dòng)清空梯度?

      梯度管理器執(zhí)行?backward()?方法時(shí), 會(huì)將當(dāng)前計(jì)算所得到的梯度以累加的形式積累到原有梯度上,而不是直接做替換。 因此對于新一輪的梯度計(jì)算,通常需要將上一輪計(jì)算得到的梯度信息清空。 何時(shí)進(jìn)行梯度清空是由人為控制的,這樣可允許靈活進(jìn)行梯度的累積。

用戶也可以繼承?class Optimizer(https://github.com/MegEngine/MegEngine/blob/master/imperative/python/megengine/optimizer/optimizer.py#L32),實(shí)現(xiàn)自己的優(yōu)化器。


以上就是關(guān)于?functional,Module,optimizer?的模塊的基本介紹,這幾個(gè)模塊是我們搭建模型訓(xùn)練的最核心的部分,熟悉這部分后,我們就可以高效搭建神經(jīng)網(wǎng)絡(luò)了。

更多 MegEngine 信息獲取,您可以:查看文檔:https://www.megengine.org.cn/doc/stable/zh/

GitHub 項(xiàng)目: https://github.com/MegEngine

加入 MegEngine 用戶交流 QQ 群:1029741705

歡迎參與 MegEngine 社區(qū)貢獻(xiàn),成為?Awesome MegEngineerhttps://www.megengine.org.cn/community-AMGE,榮譽(yù)證書、定制禮品享不停。





MegEngine Python 層模塊串講(中)的評(píng)論 (共 條)

分享到微博請遵守國家法律
杭锦旗| 平度市| 沅江市| 湄潭县| 古田县| 光山县| 重庆市| 彩票| 波密县| 苍梧县| 晋江市| 城步| 靖边县| 合川市| 石门县| 黄平县| 海门市| 敦煌市| 桃园县| 都安| 泰来县| 东乡| 中卫市| 万安县| 苏州市| 台北县| 乌海市| 平度市| 商南县| 闽侯县| 合作市| 大姚县| 邯郸市| 西昌市| 安龙县| 宾阳县| 广元市| 平武县| 景泰县| 潮州市| 平邑县|