PyTorch框架:(2)使用PyTorch框架构建神经网络模型---气温预测
目錄
第一步:數(shù)據(jù)導(dǎo)入
第二步:將時(shí)間轉(zhuǎn)換成標(biāo)準(zhǔn)格式(比如datatime格式)
第三步: 展示數(shù)據(jù):(畫了4個(gè)子圖)
?第四步:做獨(dú)熱編碼
?第五步:指定輸入與輸出
?第六步:對(duì)數(shù)據(jù)做一個(gè)標(biāo)準(zhǔn)化
?第七步:用torch來構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò)模型
第八步:預(yù)測結(jié)果
?第九步:畫圖
第一步:數(shù)據(jù)導(dǎo)入
第二步:將時(shí)間轉(zhuǎn)換成標(biāo)準(zhǔn)格式(比如datatime格式)
?
第三步: 展示數(shù)據(jù):(畫了4個(gè)子圖)
?
?
?第四步:做獨(dú)熱編碼
Q1:為什么做獨(dú)熱編碼?
A1:因?yàn)閿?shù)據(jù)中其中有一列比較特殊,其他列都是數(shù)值,但是week列是一些字符串,我們首先將字符串轉(zhuǎn)換成一種數(shù)值的形式,比較簡單的方法就是做一個(gè)獨(dú)熱編碼,在pandas當(dāng)中可以使用pd.get_dummies()不用把這個(gè)特征傳進(jìn)來,我直接features,因?yàn)閒eatures是我們傳進(jìn)來的一個(gè)數(shù)據(jù)他會(huì)自動(dòng)的幫我們做判斷,判斷這個(gè)數(shù)據(jù)中哪一列是字符串,我自動(dòng)對(duì)他做獨(dú)熱(one-hot)編碼。
?如上做完one-hot編碼之后,week這一列就沒有了,數(shù)據(jù)里邊做了一個(gè)one-hot encoding,對(duì)我們當(dāng)前需要的列做了一個(gè)額外的編碼,并且還再次把他們拼接到我們的數(shù)據(jù)當(dāng)中。
PS:這就是數(shù)據(jù)處理的第一步,先把數(shù)據(jù)都轉(zhuǎn)換成數(shù)值的形式。
?第五步:指定輸入與輸出
因?yàn)閤和y都混在一起了,一會(huì)建模的時(shí)候我得知道我的輸入是什么,我的輸出是什么,所以需要指定好。
?
?PS:上述代碼中從features中剔除掉(.drop)標(biāo)簽actual,剩下的就是x了。
?第六步:對(duì)數(shù)據(jù)做一個(gè)標(biāo)準(zhǔn)化
因?yàn)閿?shù)據(jù)中有些數(shù)值比較大,有些數(shù)值比較小(做完標(biāo)準(zhǔn)化之后結(jié)果收斂的速度會(huì)更快一些,收斂的損失值相對(duì)于來說會(huì)更小一點(diǎn))。所以做一個(gè)標(biāo)準(zhǔn)化預(yù)處理再用torch進(jìn)行建模。
這里使用的是sklearn中的預(yù)處理模塊,在預(yù)處理模塊中有一個(gè)標(biāo)準(zhǔn)化的操作:
此時(shí)數(shù)據(jù)是ndarray格式。
?第七步:用torch來構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò)模型
構(gòu)建網(wǎng)絡(luò)模型有兩種方法:第一種是比較麻煩的,一步步的去寫;第二種簡單一些。
第一種:基于Pytorch來構(gòu)建神經(jīng)網(wǎng)絡(luò)模型。
?
?(1)首先將上述的ndarray格式的數(shù)據(jù)轉(zhuǎn)換成tensor格式。
(2)權(quán)重參數(shù)初始化:一般使用隨機(jī)的標(biāo)準(zhǔn)的正態(tài)分布比較合適。
- ? ? ? 準(zhǔn)備w1和b1:
? ? ? ? ? ? ? ?初始化w1:輸入是[348,14],要把現(xiàn)在的14個(gè)輸入特征,轉(zhuǎn)換成128個(gè)隱層特征。w就是[14,128]。
? ? ? ? ? ? ? ?初始化偏置參數(shù)b1:對(duì)于w1來說來說我得到了128個(gè)神經(jīng)元特征,那b1就是微調(diào),不是對(duì)整體做一個(gè)微調(diào),而是對(duì)每一個(gè)特征都做一個(gè)微調(diào)。PS:偏置參數(shù)的個(gè)數(shù)永遠(yuǎn)是跟得到的特征結(jié)果個(gè)數(shù)是一致的。
第一個(gè)隱層得到了128個(gè)特征,我輸出結(jié)果是一個(gè)回歸任務(wù),要得到一個(gè)實(shí)際的值,所以128肯定不行,我得再來個(gè)w2;
- ? ? ? 準(zhǔn)備w2和b2:
? ? ?? ? ? ? ?初始化w2[128,1]前邊連的是你中間的特征128個(gè),我要把這128個(gè)特征轉(zhuǎn)化成一個(gè)值,回歸任務(wù)是一個(gè)值,所以說w2的矩陣維度就是128x1;
? ? ? ? ? ? ? 初始化偏置參數(shù)b2=1,因?yàn)樽罱K結(jié)果得到的是一個(gè)值,所以b2為1,是對(duì)最終的結(jié)果進(jìn)行一個(gè)微調(diào)。
PS:注意權(quán)重參數(shù)在接下來迭代過程當(dāng)中要計(jì)算他的梯度,所以在初始化過程中,都帶了參數(shù)requires_grad=True,都是需要計(jì)算梯度的。
(3)初始化學(xué)習(xí)率。
(4)把上述初始化的參數(shù)由前到后給它串起來。
- ? ? ? ? ? ? ?計(jì)算第一個(gè)隱層結(jié)果:.mm就是矩陣乘法。
- ? ? ? ? ? ? ?將結(jié)果經(jīng)過激活函數(shù):.relu激活函數(shù)。
- ? ? ? ? ? ? ?計(jì)算最后一層的結(jié)果。
- ? ? ? ? ? ? ?------------------至此前向傳播計(jì)算出來了--------------------------
- ? ? ? ? ? ? ?計(jì)算損失。
- ? ? ? ? ? ? ?基于損失執(zhí)行反向傳播(計(jì)算梯度)、并更新w1、b1和w2、b2;(負(fù)的學(xué)習(xí)率表示我沿著梯度的反方向,把學(xué)習(xí)率乘過來,把梯度乘過來就完事了)PS:更新完一次梯度時(shí),記得清空,要不然下次會(huì)累加在一起的。
?第二種:更簡單的構(gòu)建網(wǎng)絡(luò)模型
?
retain_graph=True表示接下來要不要重復(fù)的執(zhí)行這個(gè)cell的代碼,指定為True,重復(fù)執(zhí)行的話他不會(huì)報(bào)錯(cuò)。
??指定輸入的樣本數(shù)量;
隱層神經(jīng)元的個(gè)數(shù);
輸出的結(jié)果;
加上batch_size;(加上batch_size之后,之前訓(xùn)練的時(shí)候是把數(shù)據(jù)全部讀入進(jìn)去,相當(dāng)于批量梯度下降,這里我們不做批量梯度下降,使用mini_batch,指定一個(gè)batch)
構(gòu)建網(wǎng)絡(luò)模型;(之前構(gòu)建模型是一步步寫的wx+b,這樣比較麻煩)
? ? ? ? ? 第一步:先把序列寫好?;按照torch.nn模塊下序列去寫。
? ? ? ? ? ? ? ? ? ? ? ?第一層指定好它的輸入與輸出(hidden_size得到多少個(gè)隱層的神經(jīng)元),中間加上激活函數(shù);
? ? ? ? ? ? ? ? ? ? ? ?第二層再連一個(gè)全連接層nn.Linear(hidden_size,output_size)。第一個(gè)參數(shù)表示寫好前邊連什么,第二個(gè)參數(shù)表示得到什么結(jié)果。
?所以這樣直接使用touch.nn模塊下的序列結(jié)構(gòu),可以把這個(gè)網(wǎng)絡(luò)直接的定義出來(這里按照兩層全連接的模塊去寫,后續(xù)可以加卷積加池化等都可以torch.nn模塊下你能想到的層別人都給你寫好了,直接調(diào)用就行)。
? ? ? ? ? 第二步:損失函數(shù)直接調(diào)用現(xiàn)成的包。
? ? ? ? ? 第三步:把優(yōu)化器拿進(jìn)來。(之前是做一個(gè)梯度下降,每一次自己計(jì)算梯度,自己更新,自己再置0,這樣比較麻煩;簡單方法使用torch當(dāng)中的優(yōu)化器,優(yōu)化器里邊有挺多的,這里使用SGD梯度下降也行用Adm也行,Adm用的更多一些,他可以動(dòng)態(tài)的去調(diào)整學(xué)習(xí)率,學(xué)習(xí)率一開始可能會(huì)比較大,他會(huì)加入一個(gè)衰減函數(shù),讓學(xué)習(xí)率隨著迭代進(jìn)行慢慢變小,所以這個(gè)應(yīng)該是更合理一些的)
? ? ? ? ?第四步:指定玩優(yōu)化器之后開始訓(xùn)練網(wǎng)絡(luò)。(訓(xùn)練網(wǎng)絡(luò)的方法其實(shí)和之前是一樣的,寫一個(gè)循環(huán),這里多做了一步,這里不是取全部的數(shù)據(jù)了,而是取其中部分的數(shù)據(jù),在這里torch.tensor當(dāng)中在構(gòu)造它的輸入數(shù)據(jù)的時(shí)候,這里傳進(jìn)來兩個(gè)索引,一個(gè)是start索引,一個(gè)是end索引,表示我從原始數(shù)據(jù)當(dāng)中一步步的每一次取16個(gè)數(shù)據(jù),因?yàn)樵O(shè)置了batch=16,所以每次會(huì)取16個(gè)這樣的x和y;接下來預(yù)測一個(gè)結(jié)果prediction,就是走一個(gè)前向傳播,my_nn(xx)里邊的xx就是我輸入的一個(gè)batch的數(shù)據(jù),然后剛才在定義序列的時(shí)候給他起的名字叫做my_nn,然后要得到一個(gè)結(jié)果你只需要在這個(gè)my_nn當(dāng)中把實(shí)際的x給傳進(jìn)去,相當(dāng)于這一塊x來了之后,先走my_nn中的第一個(gè)torch.nn.Linear(),再走第二個(gè)torch.nn.Sigmoid(),再走第三個(gè)torch.nn.Linear()按照這個(gè)順序得到一個(gè)輸出結(jié)果,這就完事了;所以預(yù)測值比較簡單,不需要一步步去寫他是怎么計(jì)算的,只需要把它傳入到我們剛才定義好的序列模塊當(dāng)中就可以了;然后計(jì)算損失值使用定義的cost方法MSELoss;然后做優(yōu)化,優(yōu)化過程中每次迭代一次要對(duì)梯度進(jìn)行清0的操作optimizer.zero_grad()(這一步放到后邊也行),然后進(jìn)行一次反向傳播,接下來optimizer.step()就是說我們要不要去做一個(gè)更新,.step相當(dāng)于把前邊的所有的更新操作放入到這一個(gè)函數(shù)當(dāng)中了,直接調(diào)用就可以了;接下來為了一會(huì)把這個(gè)損失打印出來我把這個(gè)損失batch_loss給他讀進(jìn)來就完事了。之后就是打印損失)這一步對(duì)應(yīng)上圖中的第二個(gè)圖。
第八步:預(yù)測結(jié)果
?拿一個(gè)x,轉(zhuǎn)化為tensor的格式,傳到網(wǎng)絡(luò)當(dāng)中,其實(shí)傳入到網(wǎng)絡(luò)就是相當(dāng)于走了一次前向傳播,會(huì)得到實(shí)際的預(yù)測值,把實(shí)際結(jié)果的預(yù)測值拿到手就可以了,.data.numpy()相當(dāng)于轉(zhuǎn)化成array數(shù)組的形式(因?yàn)橄逻呉褂胢yplot畫圖,不轉(zhuǎn)化成numpy的格式的話tensor的格式畫不了)。
?第九步:畫圖
?
X軸定義為日期,所以先把日期都拿到手轉(zhuǎn)化成標(biāo)準(zhǔn)的格式dates;
拿預(yù)測的結(jié)果值predictions_data(其中predict要reshape一下因?yàn)槲覀円氖且涣械母袷?#xff0c;不能是一個(gè)矩陣的格式。并要構(gòu)建一個(gè)DataFrame,因?yàn)榛贒ataFrame畫圖比較簡單,直接傳進(jìn)去就得了。)
總結(jié)
以上是生活随笔為你收集整理的PyTorch框架:(2)使用PyTorch框架构建神经网络模型---气温预测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PyTorch框架:(1)基本处理操作
- 下一篇: PyTorch框架:(3)使用PyTor