no module named numpy_nn.functional和nn.Module
Pytorch的低階API主要包括張量操作,動態(tài)計算圖和自動微分。
如果把模型比作一個房子,那么低階API就是【模型之磚】。
在低階API層次上,可以把Pytorch當做一個增強版的numpy來使用。
Pytorch提供的方法比numpy更全面,運算速度更快,如果需要的話,還可以使用GPU進行加速。
前面幾章我們對低階API已經(jīng)有了一個整體的認識,本章我們將重點詳細介紹張量操作和動態(tài)計算圖。
張量的操作主要包括張量的結(jié)構(gòu)操作和張量的數(shù)學(xué)運算。
張量結(jié)構(gòu)操作諸如:張量創(chuàng)建,索引切片,維度變換,合并分割。
張量數(shù)學(xué)運算主要有:標量運算,向量運算,矩陣運算。另外我們會介紹張量運算的廣播機制。
動態(tài)計算圖我們將主要介紹動態(tài)計算圖的特性,計算圖中的Function,計算圖與反向傳播。
本篇我們介紹動態(tài)計算圖。
import?osimport?datetime
#打印時間
def?printbar():
????nowtime?=?datetime.datetime.now().strftime('%Y-%m-%d?%H:%M:%S')
????print("\n"+"=========="*8?+?"%s"%nowtime)
#mac系統(tǒng)上pytorch和matplotlib在jupyter中同時跑需要更改環(huán)境變量
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"?
一,nn.functional 和 nn.Module
前面我們介紹了Pytorch的張量的結(jié)構(gòu)操作和數(shù)學(xué)運算中的一些常用API。
利用這些張量的API我們可以構(gòu)建出神經(jīng)網(wǎng)絡(luò)相關(guān)的組件(如激活函數(shù),模型層,損失函數(shù))。
Pytorch和神經(jīng)網(wǎng)絡(luò)相關(guān)的功能組件大多都封裝在 torch.nn模塊下。
這些功能組件的絕大部分既有函數(shù)形式實現(xiàn),也有類形式實現(xiàn)。
其中nn.functional(一般引入后改名為F)有各種功能組件的函數(shù)實現(xiàn)。例如:
(激活函數(shù))
- F.relu
- F.sigmoid
- F.tanh
- F.softmax
(模型層)
- F.linear
- F.conv2d
- F.max_pool2d
- F.dropout2d
- F.embedding
(損失函數(shù))
- F.binary_cross_entropy
- F.mse_loss
- F.cross_entropy
為了便于對參數(shù)進行管理,一般通過繼承 nn.Module 轉(zhuǎn)換成為類的實現(xiàn)形式,并直接封裝在 nn 模塊下。例如:
(激活函數(shù))
- nn.ReLU
- nn.Sigmoid
- nn.Tanh
- nn.Softmax
(模型層)
- nn.Linear
- nn.Conv2d
- nn.MaxPool2d
- nn.Dropout2d
- nn.Embedding
(損失函數(shù))
- nn.BCELoss
- nn.MSELoss
- nn.CrossEntropyLoss
實際上nn.Module除了可以管理其引用的各種參數(shù),還可以管理其引用的子模塊,功能十分強大。
二,使用nn.Module來管理參數(shù)
在Pytorch中,模型的參數(shù)是需要被優(yōu)化器訓(xùn)練的,因此,通常要設(shè)置參數(shù)為 requires_grad = True 的張量。
同時,在一個模型中,往往有許多的參數(shù),要手動管理這些參數(shù)并不是一件容易的事情。
Pytorch一般將參數(shù)用nn.Parameter來表示,并且用nn.Module來管理其結(jié)構(gòu)下的所有參數(shù)。
import?torch?from?torch?import?nn?
import?torch.nn.functional??as?F
from?matplotlib?import?pyplot?as?plt
#?nn.Parameter?具有?requires_grad?=?True?屬性
w?=?nn.Parameter(torch.randn(2,2))
print(w)
print(w.requires_grad)
Parameter?containing:
tensor([[?0.3544,?-1.1643],
????????[?1.2302,??1.3952]],?requires_grad=True)
True
#?nn.ParameterList?可以將多個nn.Parameter組成一個列表
params_list?=?nn.ParameterList([nn.Parameter(torch.rand(8,i))?for?i?in?range(1,3)])
print(params_list)
print(params_list[0].requires_grad)
ParameterList(
????(0):?Parameter?containing:?[torch.FloatTensor?of?size?8x1]
????(1):?Parameter?containing:?[torch.FloatTensor?of?size?8x2]
)
True
#?nn.ParameterDict?可以將多個nn.Parameter組成一個字典
params_dict?=?nn.ParameterDict({"a":nn.Parameter(torch.rand(2,2)),
???????????????????????????????"b":nn.Parameter(torch.zeros(2))})
print(params_dict)
print(params_dict["a"].requires_grad)
ParameterDict(
????(a):?Parameter?containing:?[torch.FloatTensor?of?size?2x2]
????(b):?Parameter?containing:?[torch.FloatTensor?of?size?2]
)
True
#?可以用Module將它們管理起來
#?module.parameters()返回一個生成器,包括其結(jié)構(gòu)下的所有parameters
module?=?nn.Module()
module.w?=?w
module.params_list?=?params_list
module.params_dict?=?params_dict
num_param?=?0
for?param?in?module.parameters():
????print(param,"\n")
????num_param?=?num_param?+?1
print("number?of?Parameters?=",num_param)
Parameter?containing:
tensor([[?0.3544,?-1.1643],
????????[?1.2302,??1.3952]],?requires_grad=True)?
Parameter?containing:
tensor([[0.9391],
????????[0.7590],
????????[0.6899],
????????[0.4786],
????????[0.2392],
????????[0.9645],
????????[0.1968],
????????[0.1353]],?requires_grad=True)?
Parameter?containing:
tensor([[0.8012,?0.9587],
????????[0.0276,?0.5995],
????????[0.7338,?0.5559],
????????[0.1704,?0.5814],
????????[0.7626,?0.1179],
????????[0.4945,?0.2408],
????????[0.7179,?0.0575],
????????[0.3418,?0.7291]],?requires_grad=True)?
Parameter?containing:
tensor([[0.7729,?0.2383],
????????[0.7054,?0.9937]],?requires_grad=True)?
Parameter?containing:
tensor([0.,?0.],?requires_grad=True)?
number?of?Parameters?=?5
#實踐當中,一般通過繼承nn.Module來構(gòu)建模塊類,并將所有含有需要學(xué)習(xí)的參數(shù)的部分放在構(gòu)造函數(shù)中。
#以下范例為Pytorch中nn.Linear的源碼的簡化版本
#可以看到它將需要學(xué)習(xí)的參數(shù)放在了__init__構(gòu)造函數(shù)中,并在forward中調(diào)用F.linear函數(shù)來實現(xiàn)計算邏輯。
class?Linear(nn.Module):
????__constants__?=?['in_features',?'out_features']
????def?__init__(self,?in_features,?out_features,?bias=True):
????????super(Linear,?self).__init__()
????????self.in_features?=?in_features
????????self.out_features?=?out_features
????????self.weight?=?nn.Parameter(torch.Tensor(out_features,?in_features))
????????if?bias:
????????????self.bias?=?nn.Parameter(torch.Tensor(out_features))
????????else:
????????????self.register_parameter('bias',?None)
????def?forward(self,?input):
????????return?F.linear(input,?self.weight,?self.bias)
三,使用nn.Module來管理子模塊
一般情況下,我們都很少直接使用 nn.Parameter來定義參數(shù)構(gòu)建模型,而是通過一些拼裝一些常用的模型層來構(gòu)造模型。
這些模型層也是繼承自nn.Module的對象,本身也包括參數(shù),屬于我們要定義的模塊的子模塊。
nn.Module提供了一些方法可以管理這些子模塊。
children() 方法: 返回生成器,包括模塊下的所有子模塊。
named_children()方法:返回一個生成器,包括模塊下的所有子模塊,以及它們的名字。
modules()方法:返回一個生成器,包括模塊下的所有各個層級的模塊,包括模塊本身。
named_modules()方法:返回一個生成器,包括模塊下的所有各個層級的模塊以及它們的名字,包括模塊本身。
其中chidren()方法和named_children()方法較多使用。
modules()方法和named_modules()方法較少使用,其功能可以通過多個named_children()的嵌套使用實現(xiàn)。
class?Net(nn.Module):????
????def?__init__(self):
????????super(Net,?self).__init__()
????????
????????self.embedding?=?nn.Embedding(num_embeddings?=?10000,embedding_dim?=?3,padding_idx?=?1)
????????self.conv?=?nn.Sequential()
????????self.conv.add_module("conv_1",nn.Conv1d(in_channels?=?3,out_channels?=?16,kernel_size?=?5))
????????self.conv.add_module("pool_1",nn.MaxPool1d(kernel_size?=?2))
????????self.conv.add_module("relu_1",nn.ReLU())
????????self.conv.add_module("conv_2",nn.Conv1d(in_channels?=?16,out_channels?=?128,kernel_size?=?2))
????????self.conv.add_module("pool_2",nn.MaxPool1d(kernel_size?=?2))
????????self.conv.add_module("relu_2",nn.ReLU())
????????
????????self.dense?=?nn.Sequential()
????????self.dense.add_module("flatten",nn.Flatten())
????????self.dense.add_module("linear",nn.Linear(6144,1))
????????self.dense.add_module("sigmoid",nn.Sigmoid())
????????
????def?forward(self,x):
????????x?=?self.embedding(x).transpose(1,2)
????????x?=?self.conv(x)
????????y?=?self.dense(x)
????????return?y
????
net?=?Net()
i?=?0
for?child?in?net.children():
????i+=1
????print(child,"\n")
print("child?number",i)
Embedding(10000,?3,?padding_idx=1)?
Sequential(
??(conv_1):?Conv1d(3,?16,?kernel_size=(5,),?stride=(1,))
??(pool_1):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_1):?ReLU()
??(conv_2):?Conv1d(16,?128,?kernel_size=(2,),?stride=(1,))
??(pool_2):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_2):?ReLU()
)?
Sequential(
??(flatten):?Flatten()
??(linear):?Linear(in_features=6144,?out_features=1,?bias=True)
??(sigmoid):?Sigmoid()
)?
child?number?3
i?=?0
for?name,child?in?net.named_children():
????i+=1
????print(name,":",child,"\n")
print("child?number",i)
embedding?:?Embedding(10000,?3,?padding_idx=1)?
conv?:?Sequential(
??(conv_1):?Conv1d(3,?16,?kernel_size=(5,),?stride=(1,))
??(pool_1):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_1):?ReLU()
??(conv_2):?Conv1d(16,?128,?kernel_size=(2,),?stride=(1,))
??(pool_2):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_2):?ReLU()
)?
dense?:?Sequential(
??(flatten):?Flatten()
??(linear):?Linear(in_features=6144,?out_features=1,?bias=True)
??(sigmoid):?Sigmoid()
)?
child?number?3
i?=?0
for?module?in?net.modules():
????i+=1
????print(module)
print("module?number:",i)
Net(
??(embedding):?Embedding(10000,?3,?padding_idx=1)
??(conv):?Sequential(
????(conv_1):?Conv1d(3,?16,?kernel_size=(5,),?stride=(1,))
????(pool_1):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
????(relu_1):?ReLU()
????(conv_2):?Conv1d(16,?128,?kernel_size=(2,),?stride=(1,))
????(pool_2):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
????(relu_2):?ReLU()
??)
??(dense):?Sequential(
????(flatten):?Flatten()
????(linear):?Linear(in_features=6144,?out_features=1,?bias=True)
????(sigmoid):?Sigmoid()
??)
)
Embedding(10000,?3,?padding_idx=1)
Sequential(
??(conv_1):?Conv1d(3,?16,?kernel_size=(5,),?stride=(1,))
??(pool_1):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_1):?ReLU()
??(conv_2):?Conv1d(16,?128,?kernel_size=(2,),?stride=(1,))
??(pool_2):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_2):?ReLU()
)
Conv1d(3,?16,?kernel_size=(5,),?stride=(1,))
MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
ReLU()
Conv1d(16,?128,?kernel_size=(2,),?stride=(1,))
MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
ReLU()
Sequential(
??(flatten):?Flatten()
??(linear):?Linear(in_features=6144,?out_features=1,?bias=True)
??(sigmoid):?Sigmoid()
)
Flatten()
Linear(in_features=6144,?out_features=1,?bias=True)
Sigmoid()
module?number:?13
下面我們通過named_children方法找到embedding層,并將其參數(shù)設(shè)置為不可訓(xùn)練(相當于凍結(jié)embedding層)。
children_dict?=?{name:module?for?name,module?in?net.named_children()}print(children_dict)
embedding?=?children_dict["embedding"]
embedding.requires_grad_(False)?#凍結(jié)其參數(shù)
{'embedding':?Embedding(10000,?3,?padding_idx=1),?'conv':?Sequential(
??(conv_1):?Conv1d(3,?16,?kernel_size=(5,),?stride=(1,))
??(pool_1):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_1):?ReLU()
??(conv_2):?Conv1d(16,?128,?kernel_size=(2,),?stride=(1,))
??(pool_2):?MaxPool1d(kernel_size=2,?stride=2,?padding=0,?dilation=1,?ceil_mode=False)
??(relu_2):?ReLU()
),?'dense':?Sequential(
??(flatten):?Flatten()
??(linear):?Linear(in_features=6144,?out_features=1,?bias=True)
??(sigmoid):?Sigmoid()
)}
#可以看到其第一層的參數(shù)已經(jīng)不可以被訓(xùn)練了。
for?param?in?embedding.parameters():
????print(param.requires_grad)
????print(param.numel())
False
30000
from?torchkeras?import?summary
summary(net,input_shape?=?(200,),input_dtype?=?torch.LongTensor)
#?不可訓(xùn)練參數(shù)數(shù)量增加
----------------------------------------------------------------
????????Layer?(type)???????????????Output?Shape?????????Param?#
================================================================
?????????Embedding-1???????????????[-1,?200,?3]??????????30,000
????????????Conv1d-2??????????????[-1,?16,?196]?????????????256
?????????MaxPool1d-3???????????????[-1,?16,?98]???????????????0
??????????????ReLU-4???????????????[-1,?16,?98]???????????????0
????????????Conv1d-5??????????????[-1,?128,?97]???????????4,224
?????????MaxPool1d-6??????????????[-1,?128,?48]???????????????0
??????????????ReLU-7??????????????[-1,?128,?48]???????????????0
???????????Flatten-8?????????????????[-1,?6144]???????????????0
????????????Linear-9????????????????????[-1,?1]???????????6,145
??????????Sigmoid-10????????????????????[-1,?1]???????????????0
================================================================
Total?params:?40,625
Trainable?params:?10,625
Non-trainable?params:?30,000
----------------------------------------------------------------
Input?size?(MB):?0.000763
Forward/backward?pass?size?(MB):?0.287796
Params?size?(MB):?0.154972
Estimated?Total?Size?(MB):?0.443531
----------------------------------------------------------------
如果本書對你有所幫助,想鼓勵一下作者,記得給本項目加一顆星星star??,并分享給你的朋友們喔?!
如果對本書內(nèi)容理解上有需要進一步和作者交流的地方,可以在公眾號后臺回復(fù)關(guān)鍵字:加群,加入讀者交流群和大家討論。
公眾號后臺回復(fù)關(guān)鍵字:pytorch,獲取項目github地址。
總結(jié)
以上是生活随笔為你收集整理的no module named numpy_nn.functional和nn.Module的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue 项目调试总结
- 下一篇: 我的世界1.6.2 java_我的世界J