日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lesson 9.5 从0实现多层神经网络的正向传播

發(fā)布時間:2025/4/5 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lesson 9.5 从0实现多层神经网络的正向传播 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

五、從0實現(xiàn)深度神經(jīng)網(wǎng)絡(luò)的正向傳播


學(xué)到這里,我們已經(jīng)學(xué)完了一個普通深度神經(jīng)網(wǎng)絡(luò)全部的基本元素——用來構(gòu)筑神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)的層與激活函數(shù),輸入神經(jīng)網(wǎng)絡(luò)的數(shù)據(jù)(特征、權(quán)重、截距),并且我們了解從左向右的過程是神經(jīng)網(wǎng)絡(luò)的正向傳播(也叫做前向傳播,或者向前傳播)。還記得我們的架構(gòu)圖嗎?在過去的課程中我們所學(xué)習(xí)的內(nèi)容都是在torch.nn這個模塊下,現(xiàn)在我們就使用封裝好的torch.nn模塊來實現(xiàn)一個完整、多層的神經(jīng)網(wǎng)絡(luò)的正向傳播。

假設(shè)我們有500條數(shù)據(jù),20個特征,標(biāo)簽為3分類。我們現(xiàn)在要實現(xiàn)一個三層神經(jīng)網(wǎng)絡(luò),這個神經(jīng)網(wǎng)絡(luò)的架構(gòu)如下:第一層有13個神經(jīng)元,第二層有8個神經(jīng)元,第三層是輸出層。其中,第一層的激活函數(shù)是relu,第二層是sigmoid。我們要如何實現(xiàn)它呢?來看代碼:

#繼承nn.Module類完成正向傳播 import torch import torch.nn as nn from torch.nn import functional as F #確定數(shù)據(jù)torch.manual_seed(420) X = torch.rand((500,20),dtype=torch.float32) y = torch.randint(low=0,high=3,size=(500,1),dtype=torch.float32) #繼承nn.Modules類來定義神經(jīng)網(wǎng)路的架構(gòu)class Model(nn.Module):#init:定義類本身,__init__函數(shù)是在類被實例化的瞬間就會執(zhí)行的函數(shù)def __init__(self,in_features=10,out_features=2): #in_features: 輸入該神經(jīng)網(wǎng)絡(luò)的特征數(shù)目#out_features: 神經(jīng)網(wǎng)絡(luò)的輸?shù)某鰯?shù)目(分類的數(shù)目)super(Model,self).__init__() #super(請查找這個類的父類,請使用找到的父類替換現(xiàn)在的類)self.linear1 = nn.Linear(in_features,13,bias=True) #輸入層不用寫,這里是隱藏層的第一層self.linear2 = nn.Linear(13,8,bias=True)self.output = nn.Linear(8,out_features,bias=True)#__init__之外的函數(shù),是在__init__被執(zhí)行完畢后,就可以被調(diào)用的函數(shù)def forward(self, x):z1 = self.linear1(x)sigma1 = torch.relu(z1)z2 = self.linear2(sigma1)sigma2 = torch.sigmoid(z2)z3 = self.output(sigma2)sigma3 = F.softmax(z3,dim=1)return sigma3input_ = X.shape[1] #特征的數(shù)目 output_ = len(y.unique()) #分類的數(shù)目#實例化神經(jīng)網(wǎng)絡(luò)類 torch.manual_seed(420) net = Model(in_features=input_, out_features=output_) #在這一瞬間,所有的層就已經(jīng)被實例化了,所有隨機(jī)的w和b也都被建立好了net.forward(X) #查看輸出的標(biāo)簽 #net(X)的結(jié)果也一樣,因為除了init外只有forward函數(shù) #tensor([[0.4140, 0.3496, 0.2365], # [0.4210, 0.3454, 0.2336], # [0.4011, 0.3635, 0.2355], # ..., # [0.4196, 0.3452, 0.2352], # [0.4153, 0.3455, 0.2392], # [0.4153, 0.3442, 0.2405]], grad_fn=<SoftmaxBackward0>) net.forward(X).shape #torch.Size([500, 3]) net.forward(X).argmax(axis = 1) #tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # . # . # . # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) sigma = net.forward(X) sigma.max(axis=1) #torch.return_types.max(values=tensor([0.4140, 0.4210, 0.4011, 0.4253, 0.4321, 0.4133, 0.4034, 0.4247, 0.4265, # 0.4131, 0.4177, 0.4101, 0.4164, 0.4234, 0.4195, 0.4163, 0.4154, 0.4090, # 0.4183, 0.4149, 0.4096, 0.4119, 0.4098, 0.4181, 0.4208, 0.4206, 0.4203, # . # . # . # 0.4150, 0.4169, 0.4135, 0.4201, 0.4259, 0.4095, 0.4218, 0.4181, 0.4158, # 0.4081, 0.4123, 0.4196, 0.4153, 0.4153], grad_fn=<MaxBackward0>), #indices=tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # . # . # . # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) net.linear1.weight #Parameter containing: #tensor([[ 1.3656e-01, -1.3459e-01, 2.1281e-01, -1.7763e-01, -6.8218e-02, # -1.5410e-01, 1.7245e-01, 8.3885e-02, -1.1153e-01, -1.7294e-01, # -1.2947e-01, -4.3138e-02, -1.1413e-01, 1.6295e-01, -9.4082e-02, # -1.4629e-01, -6.8982e-02, -2.1836e-01, -1.0859e-01, -1.2199e-01], # . # . # . # [-1.2258e-01, -6.8325e-02, -2.1929e-01, -1.4939e-01, 1.9226e-01, # -6.2922e-02, -7.6377e-02, 2.1955e-01, -4.5838e-02, 9.8011e-03, # -2.9400e-03, -9.5241e-02, -7.9775e-02, -1.8708e-01, 1.7828e-01, # -1.7552e-01, -1.0328e-01, -1.9697e-02, -1.7449e-01, 2.0408e-02]], # requires_grad=True) net.linear1.bias #Parameter containing: #tensor([ 1.3508e-01, 1.5439e-01, -1.9350e-01, -6.8777e-02, 1.3787e-01, # -1.8474e-01, 1.2763e-01, 1.8031e-01, 9.5152e-02, -1.2660e-01, # 1.4317e-01, -1.4945e-01, 3.4258e-05], requires_grad=True) net.linear1.weight.shape #torch.Size([13, 20]) # w*X X(500,20)——>自動轉(zhuǎn)化成——>(20,500) (13, 20)*(20,500) = (13,500) net.linear2.weight.shape #后 #前 #torch.Size([8, 13]) net.output.weight.shape #torch.Size([3, 8]) 最后從(3,500)——>自動轉(zhuǎn)化成——>(500,3)

如果你是初次接觸“類”,那這段代碼中新內(nèi)容可能會有點多。但如果你對python基礎(chǔ)比較熟悉,你就會發(fā)現(xiàn)這個類其實非常簡單。在神經(jīng)網(wǎng)絡(luò)的類中,我們以線性的順序從左向右描繪神經(jīng)網(wǎng)絡(luò)的計算過程,并且無需考慮在這之間www的結(jié)構(gòu)是如何,矩陣之間如何進(jìn)行相互運算。所以只要你對自己要建立的神經(jīng)網(wǎng)絡(luò)的架構(gòu)是熟悉的,pytorch代碼就非常容易。在這里,特別需要強(qiáng)調(diào)一下的可能是super函數(shù)的用法。

super函數(shù)用于調(diào)用父類的一個函數(shù),在這里我們使用super函數(shù)來幫助子類(我們建立的神經(jīng)網(wǎng)絡(luò)模型)繼承一些通過類名調(diào)用無法被繼承的屬性和方法。謹(jǐn)防小伙伴們不熟悉super的用法,在這里我們來說明一下:

#建立一個父類 class FooParent(object):def __init__(self):self.parent = 'PARENT!!'print ('Running __init__, I am parent')def bar(self,message):self.bar = "This is bar"print ("%s from Parent" % message) FooParent() #父類實例化的瞬間,運行自己的__init__ #Running __init__, I am parent #<__main__.FooParent at 0x7f93b8c122e0> FooParent().parent #父類運行自己的__init__中定義的屬性 #Running __init__, I am parent #'PARENT!!'#建立一個子類,并通過類名調(diào)用讓子類繼承父類的方法與屬性 class FooChild(FooParent):def __init__(self):print ('Running __init__, I am child') #查看子類是否繼承了方法 FooChild() #Running __init__, I am child #<__main__.FooChild at 0x7f9388024eb0> FooChild().bar("HAHAHA") #Running __init__, I am child #HAHAHA from Parent FooChild().parent '''子類沒有繼承到父類的__init__中定義的屬性 為了讓子類能夠繼承到父類的__init__函數(shù)中的內(nèi)容,我們使用super函數(shù) 新建一個子類,并使用super函數(shù)''' #Running __init__, I am child #-------------------------------------------------------------#-------------- #AttributeError Traceback (most #recent call last) #<ipython-input-39-8b9902cbe6fd> in <module> #----> 1 FooChild().parent #子類沒有繼承到父類的__init__中定義的屬性 # 2 #為了讓子類能夠繼承到父類的__init__函數(shù)中的內(nèi)容,我們使用super函數(shù) # 3 #新建一個子類,并使用super函數(shù) # #AttributeError: 'FooChild' object has no attribute 'parent' '''以上內(nèi)容表示,通過class a(b)方法不能繼承父類的__init__中定義的屬性和方法'''class FooChild(FooParent):def __init__(self):super(FooChild,self).__init__()print ('Child')print ("I am running the __init__") #再次調(diào)用parent屬性 FooChild() #執(zhí)行自己的init功能的同時,也執(zhí)行了父類的init函數(shù)定義的功能 #Running __init__, I am parent #父類那里繼承來的 #Child #I am running the __init__ #<__main__.FooChild at 0x7f93a256b6a0> FooChild().parent #Running __init__, I am parent #Child #I am running the __init__ #'PARENT!!'

通過使用super函數(shù),我們的神經(jīng)網(wǎng)絡(luò)模型從nn.Module那里繼承了哪些有用的屬性和方法呢?首先,如果不加super函數(shù),神經(jīng)網(wǎng)絡(luò)的向前傳播是無法運行的:

class Model(nn.Module):def __init__(self,in_features=10,out_features=2):#super(Model,self).__init__() #super(請查找這個類的父類,請使用找到的父類替換現(xiàn)在的類)self.linear1 = nn.Linear(in_features,13,bias=True) #輸入層不用寫,這里是隱藏層的第一層self.linear2 = nn.Linear(13,8,bias=True)self.output = nn.Linear(8,out_features,bias=True)def forward(self, x):z1 = self.linear1(x)sigma1 = torch.relu(z1)z2 = self.linear2(sigma1)sigma2 = torch.sigmoid(z2)z3 = self.output(sigma2)sigma3 = F.softmax(z3,dim=1)return sigma3 net=Model(in_features=input_, out_features=output_)

輸出結(jié)果:
nn.Module類的定義代碼有一千多行,其__init__函數(shù)中有許多復(fù)雜的內(nèi)容需要被繼承,因此super函數(shù)一定不能漏下。

我們從nn.Module中繼承了這些有用的方法:

#屬性的繼承 net.training #是否用于訓(xùn)練 #True#方法的繼承 net.cuda() #將整個網(wǎng)絡(luò)轉(zhuǎn)移到GPU上運行 net.cpu() #將整個網(wǎng)絡(luò)轉(zhuǎn)移到CPU上運行net.apply() #對__init__中的所有對象(全部層)都執(zhí)行同樣的操作 #對神經(jīng)網(wǎng)絡(luò)中所有的層,init函數(shù)中所有的對象都執(zhí)行同樣的操作 #比如,令所有線性層的初始權(quán)重w都為0 def initial_0(m): #init函數(shù)里面的所有層print(m)if type(m) == nn.Linear:m.weight.data.fill_(0)print(m.weight) net.apply(initial_0)

輸出結(jié)果:

#一個特殊的方法 net.parameters() #一個迭代器,我們可以通過循環(huán)的方式查看里面究竟是什么內(nèi)容 for param in net.parameters():print(param) #[*net.parameters()]

輸出結(jié)果:
當(dāng)然,nn.Module中的方法完全不止這幾個。之后我們用到更多方法時,我們會一一向大家進(jìn)行介紹。相信你現(xiàn)在已經(jīng)對從0建立自己的神經(jīng)網(wǎng)絡(luò)有些感覺了,之后我們會在這個代碼的基礎(chǔ)上,不斷加入新知識,并讓我們的代碼變得越來越豐富。試試看自己編寫一個架構(gòu),進(jìn)行一些探索,并執(zhí)行完整的向前傳播流程吧。

總結(jié)

以上是生活随笔為你收集整理的Lesson 9.5 从0实现多层神经网络的正向传播的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。