PyTorch 自定義層(區別於自定義模型)

2021-10-04 14:50:14 字數 4879 閱讀 5488

博主在學習三值神經網路時,使用了lenet-5模型,程式設計**,需要對lenet-5模型中的卷積層全連線層進行自定義,搜尋他人方法後,博主產生了乙個疑問,絕大多數提供的自定義層方法都是繼承nn.module模型,而這方法據說是官方提供(官網**:pytorch),自定義線性層**如下:

class

linear

(nn.module)

:def

__init__

(self, input_features, output_features, bias=

true):

super

(linear, self)

.__init__(

) self.input_features = input_features

self.output_features = output_features

self.weight = nn.parameter(torch.tensor(output_features, input_features)

)if bias:

self.bias = nn.parameter(torch.tensor(output_features)

)else

: self.register_parameter(

'bias'

,none

) self.weight.data.uniform_(

-0.1

,0.1

)if bias is

notnone

: self.bias.data.uniform_(

-0.1

,0.1

)def

forward

(self,

input):

return linearfunction.

(input

, self.weight, self.bias)

博主因涉獵pytorch時長過短,對此了解不多,初始僅是覺得奇怪,為何自定義層需要繼承nn.module模型,乍一看像是自定義模型而非自定義層

因博主過於小白,當時就想,這麼誤人子弟的自定義方法不應該籠統地用nn.module一齊實現,pytorch是乙個成熟的軟體,應該知道還有博主這種小小白沒辦法立刻上手以nn.module為依賴的自定義層方法(說實話,博主看了幾天才看懂上面的**是啥意思……哭泣……)

所以博主又搜尋了github中與已發表**相關的pytorch深度學習**,終於發現了pytorch自定義層的簡單方法,可以細節到區分具體層的種類,而不會產生混淆

以下為博主使用的lenet-5模型,為直觀體現自定義層的方法,博主僅留下了自定義的卷積層與全連線層,即**中ternaryconv2d(1, 32, kernel_size=5)ternarylinear(512, 10)部分

# lenet-5模型

class

lenet_5

(nn.module)

:def

__init__

(self)

:super

(lenet_5, self)

.__init__(

) self.conv1 = ternaryconv2d(1,

32, kernel_size=5)

# 卷積

self.fc1 = ternarylinear(

512,10)

# 全連線

defforward

(self, x)

: x = self.conv1(x)

x = self.fc1(x)

return x

以下為博主自定義的卷積層(ternaryconv2d)與全連線層(ternarylinear)

class

ternaryconv2d

(nn.conv2d)

:# def __init__(self, *args, **kwargs):

# 該方法接受任意個數的引數,其中不指定key的引數會以list形式儲存到args變數中,指定key的引數會以dict的形式儲存到kwargs變數中

def__init__

(self,

*args,

**kwargs)

:super

(ternaryconv2d, self)

.__init__(

*args,

**kwargs)

defforward

(self,

input):

out = f.conv2d(

input

, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups)

return out

class

ternarylinear

(nn.linear)

:def

__init__

(self,

*args,

**kwargs)

:super

(ternarylinear, self)

.__init__(

*args,

**kwargs)

defforward

(self,

input):

out = f.linear(

input

, self.weight, self.bias)

return out

以卷積層為例,類名可自行定義,但必須繼承nn.conv2d,在該層初始化使用時,若無引數設定,將會預設卷積層的引數,預設引數可查閱官方文件(在 python api 中)獲知,這裡博主將其貼上了過來:

class torch

.nn.conv2d(in_channels, out_channels, kernel_size, stride=

1, padding=

0, dilation=

1, groups=

1, bias=

true

, padding_mode=

'zeros'

)

而後,在definit() 函式中可初始化引數,在def forward()函式中可對卷積層自行設計

若想自定義其他型別的層,只需修改繼承的nn.conv2d即可,操作非常簡單且不會產生歧義

博主將模型與層的**整合如下,便於複製使用:

class

ternaryconv2d

(nn.conv2d)

:# def __init__(self, *args, **kwargs):

# 該方法接受任意個數的引數,其中不指定key的引數會以list形式儲存到args變數中,指定key的引數會以dict的形式儲存到kwargs變數中

def__init__

(self,

*args,

**kwargs)

:super

(ternaryconv2d, self)

.__init__(

*args,

**kwargs)

defforward

(self,

input):

out = f.conv2d(

input

, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups)

return out

class

ternarylinear

(nn.linear)

:def

__init__

(self,

*args,

**kwargs)

:super

(ternarylinear, self)

.__init__(

*args,

**kwargs)

defforward

(self,

input):

out = f.linear(

input

, self.weight, self.bias)

return out

# lenet-5模型

class

lenet_5

(nn.module)

:def

__init__

(self)

:super

(lenet_5, self)

.__init__(

) self.conv1 = ternaryconv2d(1,

32, kernel_size=5)

# 卷積

self.fc1 = ternarylinear(

512,10)

# 全連線

defforward

(self, x)

: x = self.conv1(x)

x = self.fc1(x)

return x

因官方模型類api過多,博主無法一一檢視,博主猜測nn.module模型中應該與自定義層所使用的nn.conv2d有著某種繼承關係,所以可以如此使用

PyTorch 自定義層

與使用module類構造模型類似。下面的centeredlayer類通過繼承module類自定義了乙個將輸入減掉均值後輸出的層,並將層的計算定義在了forward函式裡。這個層裡不含模型引數。class mydense nn.module def init self super mydense,se...

從頭學pytorch 十一 自定義層

一文裡說了怎麼寫自定義的模型.本篇說怎麼自定義層.分兩種 核心都一樣,自定義乙個繼承自nn.module的類,在類的forward函式裡實現該layer的計算,不同的是,帶引數的layer需要用到nn.parameter 直接繼承nn.module import torch from torch i...

Pytorch 實現自定義引數層的例子

注意,一般官方介面都帶有可導功能,如果你實現的層不具有可導功能,就需要自己實現梯度的反向傳遞。官方linear層 class linear module def init self,in features,www.cppcns.com out features,bias true super lin...