46交叉驗證2
只能用val set反饋去調整參數,看到test acc 不該做任何事情,如果反饋去調整參數泛化能力會變弱
k-fold cross-validation
如果按照原來的劃分是50k -train 10k-val 10k-test,因為test肯定不能反饋回去,所以我們要利用10k的val,可以先和50ktrain+10kval train一次,然后60k的數據再劃分中間某10k為val(如圖黃色部分),這樣確保60k的數據都可以是train,每次切換train,既防止死記硬背又防止數據沒有充分利用,但是其實用的也不是特別多,因為本質數據量沒有增加
#
-*- codeing
= utf
-8 -*-
# @Time
:2021/5/14 21:06
# @Author
:sueong
# @File
:ll
.py
# @Software
:PyCharm
import torch
import torch
.nn as nn
from torch import optim
from visdom import Visdom# 超參數
from torchvision import datasets
, transforms
from visdom import Visdombatch_size
= 200
learning_rate
= 0.01
epochs
= 10# 獲取訓練數據
train_db
= datasets
.MNIST('../data', train
=True
, download
=True
, # train
=True則得到的是訓練集transform
=transforms
.Compose([ # transform進行數據預處理transforms
.ToTensor(), # 轉成Tensor類型的數據transforms
.Normalize((0.1307,), (0.3081,)) # 進行數據標準化
(減去均值除以方差
)]))# DataLoader把訓練數據分成多個小組,此函數每次拋出一組數據。直至把所有的數據都拋出。就是做一個數據的初始化
train_loader
= torch
.utils
.data
.DataLoader(train_db
, batch_size
=batch_size
, shuffle
=True
)# 獲取測試數據
test_db
= datasets
.MNIST('../data', train
=False
,transform
=transforms
.Compose([transforms
.ToTensor(),transforms
.Normalize((0.1307,), (0.3081,))]))test_loader
= torch
.utils
.data
.DataLoader(test_db
, batch_size
=batch_size
, shuffle
=True
)print('train:',len(train_db
),'test:',len(test_db
))
train_db
,val_db
=torch
.utils
.data
.random_split(train_db
,[50000,10000])
print('db1:',len(train_db
),'db2:',len(test_db
))
train_loader
=torch
.utils
.data
.DataLoader(train_db
,batch_size
=batch_size
,shuffle
=True
)
val_loader
=torch
.utils
.data
.DataLoader(val_db
,batch_size
=batch_size
,shuffle
=True
)class MLP(nn
.Module
):def
__init__(self
):super(MLP
,self
).__init__()self
.model
=nn
.Sequential(#sequential串聯起來nn
.Linear(784,200),nn
.LeakyReLU(inplace
=True
),nn
.Linear(200, 200),nn
.LeakyReLU(inplace
=True
),nn
.Linear(200,10),nn
.LeakyReLU(inplace
=True
),)def
forward(self
,x
):x
= self
.model(x
)return x
#Train
device
=torch
.device('cuda:0')
net
=MLP().to(device
)#網絡結構 就是foward函數
optimizer
=optim
.SGD(net
.parameters(),lr
=learning_rate
)#使用nn
.Module可以直接代替之前
[w1
,b1
,w2
,b2
.。。
]
criteon
=nn
.CrossEntropyLoss().to(device
)#在訓練
-測試的迭代過程之前,定義兩條曲線,這里相當于是占位,
#在訓練
-測試的過程中再不斷填充點以實現曲線隨著訓練動態增長:
'''
這里第一步可以提供參數env
='xxx'來設置環境窗口的名稱,這里什么都沒傳,所以是在默認的main窗口下。第二第三步的viz
.line的前兩個參數是曲線的Y和X的坐標(前面是縱軸后面才是橫軸),
這里為了占位所以都設置了
0(實際上為Loss初始Y值設置為
0的話,
在圖中剛開始的地方會有個大跳躍有點難看,因為Loss肯定是從大往小了走的)。
為它們設置了不同的win參數,它們就會在不同的窗口中展示,
因為第三步定義的是測試集的loss和acc兩條曲線,所以在X等于
0時Y給了兩個初始值。
'''
for epoch in
range(epochs
):for batch_ind
,(data
,target
) in
enumerate(train_loader
):data
=data
.view(-1,28*28)data
,target
=data
.to(device
),target
.to(device
) #target
.cuda()logits
=net(data
)#這不要再加softmax logits就是predloss
=criteon(logits
,target
)#求lossoptimizer
.zero_grad()loss
.backward()# print(w1.grad.norm(), w2.grad.norm())optimizer
.step()#在每個batch訓練完后,為訓練曲線添加點,來讓曲線實時增長:#注意這里用win參數來選擇是哪條曲線,# 用update
='append'的方式添加曲線的增長點,前面是Y坐標,后面是X坐標。
if batch_ind
%100==0:print('Train Epoch:{} [{}/{} ({:.0f}%)]\t Loss:{:.6f}'.format(epoch
,batch_ind
*len(data
),len(train_loader
.dataset
),100.* batch_ind
/len(train_loader
),loss
.item()))#每一個epcho test一次可以發現acc再增加
,在val_set里面進行參數調整test_loss
=0correct
=0for data
,target in val_loader
:data
=data
.view(-1,28*28)#第一個維度保持不變寫
-1data
, target
= data
.to(device
), target
.to(device
)logits
=net(data
)test_loss
+=criteon(logits
,target
).item()pred
=logits
.data
.max(1)[1]# 在dim
=1上找最大值correct
+= pred
.eq(target
).float().sum().item()test_loss
/=len(val_loader
.dataset
)print('\n val set:average loss:{:.4f},Accuracy:{}/{} ({:.0f}%)\n'.format(test_loss
,correct
,len(val_loader
.dataset
),100.*correct
/len(val_loader
.dataset
)))#最終在test set測試,之后不能再反饋回去調整參數
test_loss
=0
correct
=0for data
,target in test_loader
:data
=data
.view(-1,28*28)#第一個維度保持不變寫
-1data
, target
= data
.to(device
), target
.to(device
)logits
=net(data
)test_loss
+=criteon(logits
,target
).item()pred
=logits
.data
.max(1)[1]# 在dim
=1上找最大值correct
+= pred
.eq(target
).float().sum().item()test_loss
/=len(test_loader
.dataset
)
print('\n test set:average loss:{:.4f},Accuracy:{}/{} ({:.0f}%)\n'.format(test_loss
,correct
,len(test_loader
.dataset
),100.*correct
/len(test_loader
.dataset
)))'''F
:\anaconda\envs\pytorch\python
.exe F
:/pythonProject1
/pythonProject3
/ll
.py
train
: 60000 test
: 10000
db1
: 50000 db2
: 10000
Train Epoch:
0 [0/50000 (0%)] Loss
:2.295601
Train Epoch:
0 [20000/50000 (40%)] Loss
:2.054641
Train Epoch:
0 [40000/50000 (80%)] Loss
:1.664214val set
:average loss:
0.0074,Accuracy
:5805.0/10000 (58%)Train Epoch:
1 [0/50000 (0%)] Loss
:1.464827
Train Epoch:
1 [20000/50000 (40%)] Loss
:1.394560
Train Epoch:
1 [40000/50000 (80%)] Loss
:1.171521val set
:average loss:
0.0058,Accuracy
:6342.0/10000 (63%)Train Epoch:
2 [0/50000 (0%)] Loss
:1.220029
Train Epoch:
2 [20000/50000 (40%)] Loss
:1.126450
Train Epoch:
2 [40000/50000 (80%)] Loss
:0.636756val set
:average loss:
0.0027,Accuracy
:8721.0/10000 (87%)Train Epoch:
3 [0/50000 (0%)] Loss
:0.635576
Train Epoch:
3 [20000/50000 (40%)] Loss
:0.389597
Train Epoch:
3 [40000/50000 (80%)] Loss
:0.323504val set
:average loss:
0.0018,Accuracy
:8981.0/10000 (90%)Train Epoch:
4 [0/50000 (0%)] Loss
:0.346836
Train Epoch:
4 [20000/50000 (40%)] Loss
:0.372384
Train Epoch:
4 [40000/50000 (80%)] Loss
:0.282964val set
:average loss:
0.0016,Accuracy
:9077.0/10000 (91%)Train Epoch:
5 [0/50000 (0%)] Loss
:0.308849
Train Epoch:
5 [20000/50000 (40%)] Loss
:0.365416
Train Epoch:
5 [40000/50000 (80%)] Loss
:0.271487val set
:average loss:
0.0015,Accuracy
:9148.0/10000 (91%)Train Epoch:
6 [0/50000 (0%)] Loss
:0.340268
Train Epoch:
6 [20000/50000 (40%)] Loss
:0.293617
Train Epoch:
6 [40000/50000 (80%)] Loss
:0.302988val set
:average loss:
0.0014,Accuracy
:9175.0/10000 (92%)Train Epoch:
7 [0/50000 (0%)] Loss
:0.214405
Train Epoch:
7 [20000/50000 (40%)] Loss
:0.256376
Train Epoch:
7 [40000/50000 (80%)] Loss
:0.324643val set
:average loss:
0.0013,Accuracy
:9220.0/10000 (92%)Train Epoch:
8 [0/50000 (0%)] Loss
:0.403245
Train Epoch:
8 [20000/50000 (40%)] Loss
:0.217200
Train Epoch:
8 [40000/50000 (80%)] Loss
:0.224958val set
:average loss:
0.0012,Accuracy
:9251.0/10000 (93%)Train Epoch:
9 [0/50000 (0%)] Loss
:0.300052
Train Epoch:
9 [20000/50000 (40%)] Loss
:0.236280
Train Epoch:
9 [40000/50000 (80%)] Loss
:0.220537val set
:average loss:
0.0012,Accuracy
:9273.0/10000 (93%)test set
:average loss:
0.0012,Accuracy
:9320.0/10000 (93%)Process finished with exit code
0'''
47 regulization
如果不是必要的話盡量選擇小的參數量
減小overfitting
更多數據
減少層數、正則化
dropout會增加魯棒性
數據增強
使用val set提前終結
regularization使得θ范數的值接近0,減少模型復雜度,因為使得高緯網絡bx^3 ,b x4前面的參數非常非常小,比如表達能力為七次方的一個網絡結構x7經過regularization會退化成一個更小次方的一個網絡結構,同時保持網絡結構又能降低網絡結構的復雜度,防止了overfitting
左圖曲線不光滑說明網絡表達能力強可以學到復雜的模式,但是因為數據集不復雜可能是噪聲造成的因此泛化能力不強,右圖是我們想要的
只有在overfitting的時候才能設置weight_decay,否則會降低原來模型的復雜程度,因為沒有overfitting的時候模型的表達能力是匹配的,加了反而會使test acc下降,weight_decay就是λ=0.01使得w趨近于0,降低模型復雜度(迫使weight慢慢趨近于0)
對網絡全局的范數有約束
48動量與學習率衰減
momentum(慣性):
learning rate decay:迫使學習率慢慢變為0
動量其實就是當前更新方向加歷史慣性的結合,取決于b參數怎么選會產生不同的效應
如圖沒有動量,w的更新只考慮當前的更新方向不考慮歷史的方向,所以更新的方向很尖銳(都是尖尖角),在局部最優就不動了
如圖,考慮0.78的歷史方向和0.22的當前方向,使得更新的幅度和程度緩和下來,陷入局部最優解的小坑,加了動量(考慮慣性)就會沖出小坑
adam內置了momentum不需要自己設置
SGD需要
learning rate decay
lr大了不收斂,小了更新慢
可能lr=0.1剛開始設置大一點(步數大一點)的隨著訓練過程慢慢減小到0.001這樣還是能找到最優解,learning rate decay動態尋找lr的過程
lr的微調可以在原來已經效果好的基礎上會提升性能
torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
在發現loss不再降低或者acc不再提高之后,降低學習率。各參數意義如下:
scheduler
=ReduceLROnPlateau(optimizer
, mode
='min')
scheduler
.step(loss_val
)
#在發現loss不再降低或者acc不再提高之后,降低學習率,假設patience
=10就是連續調用scheduler
.step(loss_val這個函數連續
10次)
#去監聽loss發現loss連續
10次沒有減少(達到平原狀態),代表需要把lr減少一定程度,如果loss不飽和就什么都不做,只是記錄作用
49early stop dropuot
可以依照經驗,在某個不在上升的點進行early stop
dropout
防止overfitting,使訓練過程中有效的w的數量越小越好,和learning rate decay中使得w越來越小不一樣,就是網絡連接過程中每部分連接的地方有一定的概率會丟失不參與連接,這樣用到有效的參數量會減少
可以看到藍色曲線比較平滑不容易overfitting
在連接的層之間加dropout,在兩層之間斷掉一部分輸入,否則就是直連
pytorch中p=dropout_prob:p=1有可能全部斷掉,p=0.1線斷開的比較少,
在tf中keep_prob :p=1所有連接都保持住,p=0.1保持住的概率是0.1 所以斷開的概率是0.99
dropout在train和test的行為是不一樣的
train中 連接可能斷開
test所有連接都會使用不會參考斷開的行為,防止在test中斷開,所以人為的切換到eval中,net_dropped.eval()
stochastic 并不是真的隨機,符合某一分布
deterministic
數據很大的時候不可能整個數據集load到顯存中,為了節省顯存
stochastic gradient descent
不再是求整個樣本的loss對w的梯度,而是求一個batch梯度
50什么是卷積1
黑白圖片每張圖的每個點表示了灰度值從0-255可以變換到0-1
彩色圖片三個通道
一層一般值的是權值w和輸出是一層,三個隱藏層,一共是4層(一般input layer不算)
多少參數就是有多少條線
局部相關性 感受野,感受不是全局的是一次一次小塊
卷積神經網絡,卷積指的是局部相關性
卷積:滑動小窗口從2828變成33參數大大降低
本來有784條全連接的權值現在變成9個與之位置相關的位置權值,位置太遠不考慮
卷積層的權值數量會成倍減少,但是可以考慮到全局信息只是移動的時候是用的同樣的參數,同時考慮了全局的屬性但是又考慮了位置相近的信息,
小窗口和大窗口做的是相乘再累加再的一個操作變成點,這叫卷積操作
52卷積層1
kernel的類型決定了你以什么方式觀察這個map,卷積運算后得到新的map,新map和之前map大小類似或者一致,但是數據不同
多個kernel代表觀察角度的信息不同,如圖可能有觀察blur face dog edge的多個信息
七個kernel 維度(7,1,3,3),新的map是7features map
卷積運算的過程
上下左右都打了一個padding 所以得到的feature map也是5*5
input channel:黑白照片1 彩色照片3,中間可能是16或者64等等等
kernel channel:指的是你有多少個核
kernel size:3*3
stride:步長 每次kernel移動的大小 一次移動幾格
padding:打的空白的行和列 如果行列打兩行的話padding是1
輸出圖片公式的大小如圖
53卷積層2
input的通道數是多少,kernel的通道數也要是多少
x[1,3,28,28]#一張圖片 三個通道rgb 2828的大小
one k:[3,3,3]:第一個3是對應x的三個通道,后面是kernel的size33,如果input的channel是16 則kernel的channel也必須是16,必須和inut的channel是一一對應的
multi-k:[16,3,3,3]16表示一共有16個kernel,可能是不同類型的kernel比如edge、blur等等,第一個3表示是輸入圖片的通道RGB
bias[16]:每個kernel會帶一個偏置,所以16個kernel生成維度16的bias
out:[1,16,26,26]#1表示幾張圖片就是batch,16和kernel的個數是對應的,2626輸出圖片的大小,這取決于padding的大小也有可能是2828
kernel也成為filter weight
LeNet-5
如圖所示分析兩個convolutions的信息
x[1,32,32]
c1:[6,28,28]
所以中間的kernel是[6,1,55]因為與output是6代表有六種kernel,32變28,所以kernelsize是55 (32-28+1=5)
s2:[6,14,14]6是因為c1作為input是6,
C3[16,10,10]16是因為上一步
所以kernel是[16,6,5,5]16是因為16是16種kernel,6是6因為input channel是6,所以bias是[16]
總結kernel[num of category,input_channel,kernel_height,kernel_weight]
不停疊加(stack)
conv1是低級特征線條等等
conv2是小型概念弧形圓形等等
conv3高緯的概念有沒有輪子窗戶等等
由具像到抽象
為什么叫特征學習:因為就是特征不斷提取的過程
54卷積層3
實現二維的卷積神經網絡
layer
=nn
.Conv2d(1,3,kernel_size
=3,stride
=1,padding
=0)
#batch是1,3是ker個數因為input_channel是3
#如果sride
=2,就是隔一個看一個outputsize可能會折半,是一種降維的功能
。不推薦直接使用layer.forward函數,建議直接實例化layer使用layer(x)因為里面有.call函數不僅會實現forward函數還有pytorch自帶封裝好的一些hooks
w和b是需要梯度信息的在kernel卷積的過程中會自動更新
w=[16,3,5,5]16表示16種類kernel ,3是input_channel,5*5kernel_size,當輸入的x的channel和3不匹配的時候會報錯
x[B,C,W,H]
w[N,C,W,H]#kernel[num of category,input_channel,kernel_height,kernel_weight]`
55池化與采樣
down/up sample
pooling:下采樣 把feature map變小,與圖片縮小不太類似
upsample:上采樣 把圖片放大類似
relu:在feature map進行relu操作
觀察這個窗口是取這個窗口的最大值還是平均值
subsampling隔行采樣
pooling是取當前窗口的一個最小值或者平均值
以上都是降維操作
upsample:針對tensor放大兩倍,簡單復制最近一個數值的過程
實現上采樣F.interpolate
out=F.interpolate(x,scale_factor=2,mode=‘nearest’),放大2倍,nearest就是采用臨近復制的模式,channel通道不會改變
relu激活函數
一個簡單的unit神經元單元一般是conv2d-batch_normalization-pooling-relu
relu函數加在feature_map上的效應:把feature_map中負的單元給去掉,把相應低的點去掉,如圖圈起來的相應太低,把該部分像素點變成0
layer=nn.ReLu(inplace=True)#表示x->x’的過程,x’使用的是x的內存空間節省內存
之后會發現out最小值都變成0,因為負數都被過濾了
總結
以上是生活随笔為你收集整理的pytorch教程龙曲良46-55的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。