03-01-模型創(chuàng)建步驟與nn.Module.mp4


torch nn 是pytorch的神經(jīng)網(wǎng)絡(luò)模塊
子模塊:

nn.Module最重要的兩個屬性:

基于LeNet觀察nn.module的創(chuàng)建(RMB2)


class LeNet(nn.Module):
#LeNet繼承于nn.Module
??def __init__(self, classes):
#初始化屬性
????super(LeNet, self).__init__()
#super實現(xiàn)父類函數(shù)調(diào)用功能
步入nn.Module的__init__()初始化,可以看到LeNet調(diào)用了nn.Module一系列有序字典的初始化,其中
self.training = True 表示模型的訓(xùn)練模式


以上就構(gòu)建好了一個Module的基本屬性
可以看到已經(jīng)初始化完畢

接下來,構(gòu)建子模塊

第一個網(wǎng)絡(luò)層是Conv2d的卷積層,步入
class Conv2d(_ConvNd):
Conv2d繼承于ConvNd類
進(jìn)入到了ConvNd類的初始化

可以看到調(diào)用super進(jìn)入到了ConvNd的父類
class _ConvNd(Module):
可知Conv2d其實是一個Module

先實現(xiàn)ConvNd的初始化
接著調(diào)用super進(jìn)入到ConvNd的父類Module

又到了module的init初始化屬性(畢竟conv2d也和LeNet一樣,也是一個Module)

構(gòu)建好之后,跳出之后查看,LeNet中會記錄一個'conv1'網(wǎng)絡(luò)層,因為'conv1'也是一個Module,所以會記錄到modules字典中

既然conv2d也是一個module,故也有初始化的有序字典

接下圖

modules沒有內(nèi)容是因為已經(jīng)沒有子module了,而參數(shù)parameters存儲了權(quán)重和偏置這兩個可學(xué)習(xí)參數(shù),parameter類是繼承于tensor,所以paramter是一個特殊的張量tensor,所以會包含張量的基本屬性
以上就實現(xiàn)了一個子網(wǎng)絡(luò)層的構(gòu)建,同時把conv2d存儲到了modules當(dāng)中進(jìn)行有效的管理
觀察LeNet這個module是如何把子module(conv2d)存儲到LeNet的有序字典modules當(dāng)中

如圖,當(dāng)執(zhí)行一系列操作之后回到lenet.py
只是實現(xiàn)了conv2d的實例化,構(gòu)建了conv2d網(wǎng)絡(luò)層,還沒賦值給LeNet的類屬性conv2當(dāng)中,可以看到有序字典modules還沒有conv2

下一步才是賦值給類屬性
在module當(dāng)中,setattr函數(shù)會攔截所有類屬性賦值操作,下一步進(jìn)入setattr函數(shù)

其中,name、value的值如下圖

用isinstance函數(shù)判斷是否是parameter類型
若是,賦值給name,并且儲存到parameter的有序字典中

value是一個con2d類型,也就是一個module
往下會判斷是否是module

判斷為True進(jìn)行賦值

走完所有子網(wǎng)絡(luò)層,LeNet構(gòu)建完畢


總結(jié)

例如,LeNet是一個大的module,它可以包含很多個子module,如卷積層、池化層、全連接層,都可以包含在LeNet這個大的module當(dāng)中
一個module接受一個復(fù)雜的tensor,進(jìn)行一系列運算,輸出分類概率或者其他的數(shù)據(jù),所以要對module進(jìn)行forward前向傳播操作。