【Pytorch神经网络理论篇】 15 过拟合问题的优化技巧(二):Dropout()方法
1 Dropout方法
2.1 Dropout原理
在訓練過程中,每次隨機選擇一部分節(jié)點不去進行學習。
2.1.1 從Dropout原理來看過擬合的原因
任何一個模型不能完全把數(shù)據(jù)分開,在某一類中一定會有一些異常數(shù)據(jù),過擬合的問題恰恰是把這些異常數(shù)據(jù)當成規(guī)律來學習了。
2.1.2 異常數(shù)據(jù)的特點
異常數(shù)據(jù)的特點:與主流樣本中的規(guī)律不同,在一個樣本中出現(xiàn)的概率要比主流數(shù)據(jù)出現(xiàn)的概率低很多。在每次訓練中,忽略模型中一些節(jié)點,將小概率的異常數(shù)據(jù)獲得學習的機會變得更低。這樣,異常數(shù)據(jù)對模型的影響就會更小。
2.1.3 Dropout的缺陷
Dropout會使一部分節(jié)點不去學習,所以在增加模型的泛化能力的同時,會使學習速度隆低。這注意樣會使模型不太容易學成,于是在使用的過程中需要令理地進行調(diào)節(jié),也就是確定到底丟棄多少節(jié)點。注意,并不是丟棄的節(jié)點越多越好。
2.2 Dropout的實現(xiàn)
2.2.1 Dropout的實現(xiàn)
- Dropout:對一維的線性數(shù)據(jù)進行Dropout處理,輸入形狀是[N,D](N代表次數(shù)D代表數(shù)據(jù)數(shù))。
- Dropout2D:對二維的平面數(shù)據(jù)進行Dropout處理,輸入形狀是[N,C,H,W]和(N代表批次數(shù),C代表通道數(shù),H代表高度,W代表寬度),系統(tǒng)將對整個通道隨機設(shè)為0。
- Dropout3D:對三維的立體數(shù)據(jù)進行Dropout處理,輸入形狀是[N,C,D,H,W](N代表批次數(shù),C代表通道數(shù),D代表深度,H代表高度,W代表寬度),系統(tǒng)將對整個通道隨機設(shè)為0。
2.2.2 Dropout函數(shù)定義(基于函數(shù)形式)
torch.nn.functional.dropout(input,p=0.5,training=False,inplace=False)- input:代表輸入的模型節(jié)點。
- p:表示丟棄率。如果參數(shù)值為1,那么表示全部丟棄(置0)。該參數(shù)默認值是0.5,表示丟棄50%的節(jié)點。
- training:表示該函數(shù)當前的使用狀態(tài)。如果參數(shù)值是False,那么表明不在訓練狀態(tài)使用,這時將不丟棄任何節(jié)點。
- inplace:表示是否改變輸入值,默認是False。
2.2.3 Dropout函數(shù)使用的注意事項
- Dropout改變了神經(jīng)網(wǎng)絡(luò)的網(wǎng)絡(luò)結(jié)構(gòu),它僅僅是屬于訓練時的方法。
- 進行測試時,一般要將函效Dropout的trainimg參數(shù)變?yōu)镕alse,表示不需要進行丟棄。否則會影響模型的型常輸出。
- 在使用類的方式調(diào)用Dropout時,沒有training參數(shù),因為Dropout實例化對象會根據(jù)模型本身的調(diào)用方式來自動調(diào)節(jié)training參數(shù)。
2.3 通過Dropout改善模型的過擬合狀況
2.3.1 修改上篇文章中的# 2 搭建網(wǎng)絡(luò)模型部分?
# 2 搭建網(wǎng)絡(luò)模型 # model = LogicNet(inputdim=2,hiddendim=500,outputdim=2) # 實例化模型,增加擬合能力將hiddendim賦值為500 # 替換為 class Logic_Dropout_Net(LogicNet):def __init__(self,inputdim,hiddendim,outputdim):super(Logic_Dropout_Net, self).__init__(inputdim,hiddendim,outputdim)# 方法2:使用類的方法實現(xiàn)步驟1#self.dropout = nn.Dropout(p=0.07)def forward(self,x):x = self.Linear1(x)x = torch.tanh(x)# 方法1 使用函數(shù)的方式實現(xiàn)x = nn.functional.dropout(x,p=0.01,training=self.training)# 方法2:使用類的方法實現(xiàn)步驟2# x = self.dropout(x)x = self.Linear2(x)return xmodel = Logic_Dropout_Net(inputdim=2,hiddendim=500,outputdim=2) # 初始化模型2.3.2 Dropout方法---代碼總覽
Dropout01.py import sklearn.datasets import torch import numpy as np import matplotlib.pyplot as plt from torch import nnfrom LogicNet_fun import LogicNet,moving_average,predict,plot_decision_boundary# 1 構(gòu)建數(shù)據(jù)集 np.random.seed(0) # 設(shè)置隨機數(shù)種子 X , Y =sklearn.datasets.make_moons(40,noise=0.2) # 生成兩組半圓形數(shù)據(jù) arg = np.squeeze(np.argwhere(Y==0),axis=1) # 獲取第1組數(shù)據(jù)索引 arg2 = np.squeeze(np.argwhere(Y==1),axis=1) # 獲取第2組數(shù)據(jù)索引 # 顯示數(shù)據(jù) plt.title("train moons data") plt.scatter(X[arg,0],X[arg,1],s=100,c='b',marker='+',label = 'data1') plt.scatter(X[arg2,0],X[arg2,1],s=40,c='r',marker='o',label = 'data2') plt.legend() plt.show()# 2 搭建網(wǎng)絡(luò)模型 # model = LogicNet(inputdim=2,hiddendim=500,outputdim=2) # 實例化模型,增加擬合能力將hiddendim賦值為500 # 替換為 class Logic_Dropout_Net(LogicNet):def __init__(self,inputdim,hiddendim,outputdim):super(Logic_Dropout_Net, self).__init__(inputdim,hiddendim,outputdim)# 方法2:使用類的方法實現(xiàn)步驟1#self.dropout = nn.Dropout(p=0.07)def forward(self,x):x = self.Linear1(x)x = torch.tanh(x)# 方法1 使用函數(shù)的方式實現(xiàn)x = nn.functional.dropout(x,p=0.01,training=self.training)# 方法2:使用類的方法實現(xiàn)步驟2# x = self.dropout(x)x = self.Linear2(x)return xmodel = Logic_Dropout_Net(inputdim=2,hiddendim=500,outputdim=2) # 初始化模型optimizer = torch.optim.Adam(model.parameters(),lr=0.01) # 定義優(yōu)化器:反向傳播過程中使用。# 3 訓練模型+訓練過程loss可視化 xt = torch.from_numpy(X).type(torch.FloatTensor) # 將numpy數(shù)據(jù)轉(zhuǎn)化為張量 yt = torch.from_numpy(Y).type(torch.LongTensor) # 將numpy數(shù)據(jù)轉(zhuǎn)化為張量 epochs = 1000 # 定義迭代次數(shù) losses = [] # 損失值列表 for i in range(epochs):loss = model.getloss(xt,yt)losses.append(loss.item()) # 保存損失值中間狀態(tài)optimizer.zero_grad() # 清空梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數(shù) avgloss = moving_average(losses) # 獲得損失值的移動平均值 plt.figure(1) plt.subplot(211) plt.xlabel('step number') plt.ylabel('Training loss') plt.title('step number vs Training loss') plt.show()# 4 模型結(jié)果可視化,觀察過擬合現(xiàn)象 plot_decision_boundary(lambda x: predict(model,x),X,Y) from sklearn.metrics import accuracy_score print("訓練時的準確率",accuracy_score(model.predict(xt),yt)) # 重新生成兩組半圓數(shù)據(jù) Xtest,Ytest = sklearn.datasets.make_moons(80,noise=0.2) plot_decision_boundary(lambda x: predict(model,x),Xtest,Ytest) Xtest_t = torch.from_numpy(Xtest).type(torch.FloatTensor) # 將numpy數(shù)據(jù)轉(zhuǎn)化為張量 Ytest_t = torch.from_numpy(Ytest).type(torch.LongTensor) print("測試時準確率",accuracy_score(model.predict(Xtest_t),Ytest_t)) LogicNet_fun.py import torch.nn as nn #引入torch網(wǎng)絡(luò)模型庫 import torch import numpy as np import matplotlib.pyplot as plt# 1.2 定義網(wǎng)絡(luò)模型 class LogicNet(nn.Module): #繼承nn.Module類,構(gòu)建網(wǎng)絡(luò)模型def __init__(self,inputdim,hiddendim,outputdim): #初始化網(wǎng)絡(luò)結(jié)構(gòu) ===》即初始化接口部分super(LogicNet,self).__init__()self.Linear1 = nn.Linear(inputdim,hiddendim) #定義全連接層self.Linear2 = nn.Linear(hiddendim,outputdim) #定義全連接層self.criterion = nn.CrossEntropyLoss() #定義交叉熵函數(shù)def forward(self,x):# 搭建用兩個全連接層組成的網(wǎng)絡(luò)模型 ===》 即正向接口部分:將網(wǎng)絡(luò)層模型結(jié)構(gòu)按照正向傳播的順序搭建x = self.Linear1(x)# 將輸入傳入第一個全連接層x = torch.tanh(x)# 將第一個全連接層的結(jié)果進行非線性變化x = self.Linear2(x)# 將網(wǎng)絡(luò)數(shù)據(jù)傳入第二個全連接層return xdef predict(self,x):# 實現(xiàn)LogicNet類的預測窗口 ===》 即預測接口部分:利用搭建好的正向接口,得到模型預測結(jié)果#調(diào)用自身網(wǎng)絡(luò)模型,并對結(jié)果進行softmax()處理,分別的出預測數(shù)據(jù)屬于每一個類的概率pred = torch.softmax(self.forward(x),dim=1)# 將正向結(jié)果進行softmax(),分別的出預測結(jié)果屬于每一個類的概率return torch.argmax(pred,dim=1)# 返回每組預測概率中最大的索引def getloss(self,x,y):# 實現(xiàn)LogicNet類的損失值接口 ===》 即損失值計算接口部分:計算模型的預測結(jié)果與真實值之間的誤差,在反向傳播時使用y_pred = self.forward(x)loss = self.criterion(y_pred,y)# 計算損失值的交叉熵return loss# 1.5 訓練可視化 def moving_average(a,w=10): #計算移動平均損失值if len(a) < w:return a[:]return [val if idx < w else sum(a[(idx - w):idx]) / w for idx, val in enumerate(a)]def moving_average_to_simp(a,w=10): #if len(a) < w:return a[:]val_list = []for idx, val in enumerate(a):if idx < w:# 如果列表 a 的下標小于 w, 直接將元素添加進 xxx 列表val_list.append(val)else:# 向前取 10 個元素計算平均值, 添加到 xxx 列表val_list.append(sum(a[(idx - w):idx]) / w)def plot_losses(losses):avgloss = moving_average(losses)#獲得損失值的移動平均值plt.figure(1)plt.subplot(211)plt.plot(range(len(avgloss)),avgloss,'b--')plt.xlabel('step number')plt.ylabel('Training loss')plt.title('step number vs Training loss')plt.show()# 1.7 數(shù)據(jù)可視化模型 def predict(model,x): #封裝支持Numpy的預測接口x = torch.from_numpy(x).type(torch.FloatTensor)model = LogicNet(inputdim=2, hiddendim=3, outputdim=2)ans = model.predict(x)return ans.numpy()def plot_decision_boundary(pred_func,X,Y): #在直角模型中實現(xiàn)預測結(jié)果的可視化#計算范圍x_min ,x_max = X[:,0].min()-0.5 , X[:,0].max()+0.5y_min ,y_max = X[:,1].min()-0.5 , X[:,1].max()+0.5h=0.01xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))#根據(jù)數(shù)據(jù)輸入進行預測Z = pred_func(np.c_[xx.ravel(),yy.ravel()])Z = Z.reshape(xx.shape)#將數(shù)據(jù)的預測結(jié)果進行可視化plt.contourf(xx,yy,Z,cmap=plt.cm.Spectral)plt.title("Linear predict")arg = np.squeeze(np.argwhere(Y==0),axis=1)arg2 = np.squeeze(np.argwhere(Y==1),axis=1)plt.scatter(X[arg,0],X[arg,1],s=100,c='b',marker='+')plt.scatter(X[arg2,0],X[arg2,1],s=40,c='r',marker='o')plt.show()2.4 全連接網(wǎng)絡(luò)與泛化能力
- 全連接網(wǎng)絡(luò)是一個通用的近似框架。只要有足夠多的神經(jīng)元、即使只有一個隱藏層的整網(wǎng)絡(luò),利用常用的Sigmoid、ReLU等激活函數(shù),就可以無限逼近任何連續(xù)函數(shù)。
- 淺層的網(wǎng)絡(luò)具有更好的擬合能力,但是泛化能力相對較弱。
- 深層的網(wǎng)絡(luò)具有更好的泛化能力,但是擬合能力相對較弱。
2.4.1?wide_deep模型
wide_deep模型就是利用了深層網(wǎng)絡(luò)與淺層網(wǎng)絡(luò)的特征實現(xiàn)的組合模型,該模型由以下兩個模型的輸出結(jié)果疊加而成。
? ? wide模型是一個單層線性模型(淺層全連接網(wǎng)絡(luò)模型)。
? ? deep模型是一個深度的全連接模型(深層全連接網(wǎng)絡(luò)模型)。
總結(jié)
以上是生活随笔為你收集整理的【Pytorch神经网络理论篇】 15 过拟合问题的优化技巧(二):Dropout()方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python多线程下实现单例模式,以及l
- 下一篇: 计算机网络课制作双绞线实验,《计算机网络