【Pytorch神经网络理论篇】 15 过拟合问题的优化技巧(二):Dropout()方法
生活随笔
收集整理的這篇文章主要介紹了
【Pytorch神经网络理论篇】 15 过拟合问题的优化技巧(二):Dropout()方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 Dropout方法
2.1 Dropout原理
在訓練過程中,每次隨機選擇一部分節點不去進行學習。
2.1.1 從Dropout原理來看過擬合的原因
任何一個模型不能完全把數據分開,在某一類中一定會有一些異常數據,過擬合的問題恰恰是把這些異常數據當成規律來學習了。
2.1.2 異常數據的特點
異常數據的特點:與主流樣本中的規律不同,在一個樣本中出現的概率要比主流數據出現的概率低很多。在每次訓練中,忽略模型中一些節點,將小概率的異常數據獲得學習的機會變得更低。這樣,異常數據對模型的影響就會更小。
2.1.3 Dropout的缺陷
Dropout會使一部分節點不去學習,所以在增加模型的泛化能力的同時,會使學習速度隆低。這注意樣會使模型不太容易學成,于是在使用的過程中需要令理地進行調節,也就是確定到底丟棄多少節點。注意,并不是丟棄的節點越多越好。
2.2 Dropout的實現
2.2.1 Dropout的實現
- Dropout:對一維的線性數據進行Dropout處理,輸入形狀是[N,D](N代表次數D代表數據數)。
- Dropout2D:對二維的平面數據進行Dropout處理,輸入形狀是[N,C,H,W]和(N代表批次數,C代表通道數,H代表高度,W代表寬度),系統將對整個通道隨機設為0。
- Dropout3D:對三維的立體數據進行Dropout處理,輸入形狀是[N,C,D,H,W](N代表批次數,C代表通道數,D代表深度,H代表高度,W代表寬度),系統將對整個通道隨機設為0。
2.2.2 Dropout函數定義(基于函數形式)
torch.nn.functional.dropout(input,p=0.5,training=False,inplace=False)- input:代表輸入的模型節點。
- p:表示丟棄率。如果參數值為1,那么表示全部丟棄(置0)。該參數默認值是0.5,表示丟棄50%的節點。
- training:表示該函數當前的使用狀態。如果參數值是False,那么表明不在訓練狀態使用,這時將不丟棄任何節點。
- inplace:表示是否改變輸入值,默認是False。
2.2.3 Dropout函數使用的注意事項
- Dropout改變了神經網絡的網絡結構,它僅僅是屬于訓練時的方法。
- 進行測試時,一般要將函效Dropout的trainimg參數變為False,表示不需要進行丟棄。否則會影響模型的型常輸出。
- 在使用類的方式調用Dropout時,沒有training參數,因為Dropout實例化對象會根據模型本身的調用方式來自動調節training參數。
2.3 通過Dropout改善模型的過擬合狀況
2.3.1 修改上篇文章中的# 2 搭建網絡模型部分?
# 2 搭建網絡模型 # 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:使用類的方法實現步驟1#self.dropout = nn.Dropout(p=0.07)def forward(self,x):x = self.Linear1(x)x = torch.tanh(x)# 方法1 使用函數的方式實現x = nn.functional.dropout(x,p=0.01,training=self.training)# 方法2:使用類的方法實現步驟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 構建數據集 np.random.seed(0) # 設置隨機數種子 X , Y =sklearn.datasets.make_moons(40,noise=0.2) # 生成兩組半圓形數據 arg = np.squeeze(np.argwhere(Y==0),axis=1) # 獲取第1組數據索引 arg2 = np.squeeze(np.argwhere(Y==1),axis=1) # 獲取第2組數據索引 # 顯示數據 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 搭建網絡模型 # 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:使用類的方法實現步驟1#self.dropout = nn.Dropout(p=0.07)def forward(self,x):x = self.Linear1(x)x = torch.tanh(x)# 方法1 使用函數的方式實現x = nn.functional.dropout(x,p=0.01,training=self.training)# 方法2:使用類的方法實現步驟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) # 定義優化器:反向傳播過程中使用。# 3 訓練模型+訓練過程loss可視化 xt = torch.from_numpy(X).type(torch.FloatTensor) # 將numpy數據轉化為張量 yt = torch.from_numpy(Y).type(torch.LongTensor) # 將numpy數據轉化為張量 epochs = 1000 # 定義迭代次數 losses = [] # 損失值列表 for i in range(epochs):loss = model.getloss(xt,yt)losses.append(loss.item()) # 保存損失值中間狀態optimizer.zero_grad() # 清空梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數 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 模型結果可視化,觀察過擬合現象 plot_decision_boundary(lambda x: predict(model,x),X,Y) from sklearn.metrics import accuracy_score print("訓練時的準確率",accuracy_score(model.predict(xt),yt)) # 重新生成兩組半圓數據 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數據轉化為張量 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網絡模型庫 import torch import numpy as np import matplotlib.pyplot as plt# 1.2 定義網絡模型 class LogicNet(nn.Module): #繼承nn.Module類,構建網絡模型def __init__(self,inputdim,hiddendim,outputdim): #初始化網絡結構 ===》即初始化接口部分super(LogicNet,self).__init__()self.Linear1 = nn.Linear(inputdim,hiddendim) #定義全連接層self.Linear2 = nn.Linear(hiddendim,outputdim) #定義全連接層self.criterion = nn.CrossEntropyLoss() #定義交叉熵函數def forward(self,x):# 搭建用兩個全連接層組成的網絡模型 ===》 即正向接口部分:將網絡層模型結構按照正向傳播的順序搭建x = self.Linear1(x)# 將輸入傳入第一個全連接層x = torch.tanh(x)# 將第一個全連接層的結果進行非線性變化x = self.Linear2(x)# 將網絡數據傳入第二個全連接層return xdef predict(self,x):# 實現LogicNet類的預測窗口 ===》 即預測接口部分:利用搭建好的正向接口,得到模型預測結果#調用自身網絡模型,并對結果進行softmax()處理,分別的出預測數據屬于每一個類的概率pred = torch.softmax(self.forward(x),dim=1)# 將正向結果進行softmax(),分別的出預測結果屬于每一個類的概率return torch.argmax(pred,dim=1)# 返回每組預測概率中最大的索引def getloss(self,x,y):# 實現LogicNet類的損失值接口 ===》 即損失值計算接口部分:計算模型的預測結果與真實值之間的誤差,在反向傳播時使用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 數據可視化模型 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): #在直角模型中實現預測結果的可視化#計算范圍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))#根據數據輸入進行預測Z = pred_func(np.c_[xx.ravel(),yy.ravel()])Z = Z.reshape(xx.shape)#將數據的預測結果進行可視化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 全連接網絡與泛化能力
- 全連接網絡是一個通用的近似框架。只要有足夠多的神經元、即使只有一個隱藏層的整網絡,利用常用的Sigmoid、ReLU等激活函數,就可以無限逼近任何連續函數。
- 淺層的網絡具有更好的擬合能力,但是泛化能力相對較弱。
- 深層的網絡具有更好的泛化能力,但是擬合能力相對較弱。
2.4.1?wide_deep模型
wide_deep模型就是利用了深層網絡與淺層網絡的特征實現的組合模型,該模型由以下兩個模型的輸出結果疊加而成。
? ? wide模型是一個單層線性模型(淺層全連接網絡模型)。
? ? deep模型是一個深度的全連接模型(深層全連接網絡模型)。
總結
以上是生活随笔為你收集整理的【Pytorch神经网络理论篇】 15 过拟合问题的优化技巧(二):Dropout()方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python多线程下实现单例模式,以及l
- 下一篇: 计算机网络课制作双绞线实验,《计算机网络