46交叉驗(yàn)證2
只能用val set反饋去調(diào)整參數(shù),看到test acc 不該做任何事情,如果反饋去調(diào)整參數(shù)泛化能力會(huì)變?nèi)?br /> k-fold cross-validation
如果按照原來(lái)的劃分是50k -train 10k-val 10k-test,因?yàn)閠est肯定不能反饋回去,所以我們要利用10k的val,可以先和50ktrain+10kval train一次,然后60k的數(shù)據(jù)再劃分中間某10k為val(如圖黃色部分),這樣確保60k的數(shù)據(jù)都可以是train,每次切換train,既防止死記硬背又防止數(shù)據(jù)沒(méi)有充分利用,但是其實(shí)用的也不是特別多,因?yàn)楸举|(zhì)數(shù)據(jù)量沒(méi)有增加
#
-*- 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# 超參數(shù)
from torchvision import datasets
, transforms
from visdom import Visdombatch_size
= 200
learning_rate
= 0.01
epochs
= 10# 獲取訓(xùn)練數(shù)據(jù)
train_db
= datasets
.MNIST('../data', train
=True
, download
=True
, # train
=True則得到的是訓(xùn)練集transform
=transforms
.Compose([ # transform進(jìn)行數(shù)據(jù)預(yù)處理transforms
.ToTensor(), # 轉(zhuǎn)成Tensor類型的數(shù)據(jù)transforms
.Normalize((0.1307,), (0.3081,)) # 進(jìn)行數(shù)據(jù)標(biāo)準(zhǔn)化
(減去均值除以方差
)]))# DataLoader把訓(xùn)練數(shù)據(jù)分成多個(gè)小組,此函數(shù)每次拋出一組數(shù)據(jù)。直至把所有的數(shù)據(jù)都拋出。就是做一個(gè)數(shù)據(jù)的初始化
train_loader
= torch
.utils
.data
.DataLoader(train_db
, batch_size
=batch_size
, shuffle
=True
)# 獲取測(cè)試數(shù)據(jù)
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串聯(lián)起來(lái)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
)#網(wǎng)絡(luò)結(jié)構(gòu) 就是foward函數(shù)
optimizer
=optim
.SGD(net
.parameters(),lr
=learning_rate
)#使用nn
.Module可以直接代替之前
[w1
,b1
,w2
,b2
.。。
]
criteon
=nn
.CrossEntropyLoss().to(device
)#在訓(xùn)練
-測(cè)試的迭代過(guò)程之前,定義兩條曲線,這里相當(dāng)于是占位,
#在訓(xùn)練
-測(cè)試的過(guò)程中再不斷填充點(diǎn)以實(shí)現(xiàn)曲線隨著訓(xùn)練動(dòng)態(tài)增長(zhǎng):
'''
這里第一步可以提供參數(shù)env
='xxx'來(lái)設(shè)置環(huán)境窗口的名稱,這里什么都沒(méi)傳,所以是在默認(rèn)的main窗口下。第二第三步的viz
.line的前兩個(gè)參數(shù)是曲線的Y和X的坐標(biāo)(前面是縱軸后面才是橫軸),
這里為了占位所以都設(shè)置了
0(實(shí)際上為L(zhǎng)oss初始Y值設(shè)置為
0的話,
在圖中剛開始的地方會(huì)有個(gè)大跳躍有點(diǎn)難看,因?yàn)長(zhǎng)oss肯定是從大往小了走的)。
為它們?cè)O(shè)置了不同的win參數(shù),它們就會(huì)在不同的窗口中展示,
因?yàn)榈谌蕉x的是測(cè)試集的loss和acc兩條曲線,所以在X等于
0時(shí)Y給了兩個(gè)初始值。
'''
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()#在每個(gè)batch訓(xùn)練完后,為訓(xùn)練曲線添加點(diǎn),來(lái)讓曲線實(shí)時(shí)增長(zhǎng):#注意這里用win參數(shù)來(lái)選擇是哪條曲線,# 用update
='append'的方式添加曲線的增長(zhǎng)點(diǎn),前面是Y坐標(biāo),后面是X坐標(biāo)。
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()))#每一個(gè)epcho test一次可以發(fā)現(xiàn)acc再增加
,在val_set里面進(jìn)行參數(shù)調(diào)整test_loss
=0correct
=0for data
,target in val_loader
:data
=data
.view(-1,28*28)#第一個(gè)維度保持不變寫
-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測(cè)試,之后不能再反饋回去調(diào)整參數(shù)
test_loss
=0
correct
=0for data
,target in test_loader
:data
=data
.view(-1,28*28)#第一個(gè)維度保持不變寫
-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
如果不是必要的話盡量選擇小的參數(shù)量
減小overfitting
更多數(shù)據(jù)
減少層數(shù)、正則化
dropout會(huì)增加魯棒性
數(shù)據(jù)增強(qiáng)
使用val set提前終結(jié)
regularization使得θ范數(shù)的值接近0,減少模型復(fù)雜度,因?yàn)槭沟酶呔暰W(wǎng)絡(luò)bx^3 ,b x4前面的參數(shù)非常非常小,比如表達(dá)能力為七次方的一個(gè)網(wǎng)絡(luò)結(jié)構(gòu)x7經(jīng)過(guò)regularization會(huì)退化成一個(gè)更小次方的一個(gè)網(wǎng)絡(luò)結(jié)構(gòu),同時(shí)保持網(wǎng)絡(luò)結(jié)構(gòu)又能降低網(wǎng)絡(luò)結(jié)構(gòu)的復(fù)雜度,防止了overfitting
左圖曲線不光滑說(shuō)明網(wǎng)絡(luò)表達(dá)能力強(qiáng)可以學(xué)到復(fù)雜的模式,但是因?yàn)閿?shù)據(jù)集不復(fù)雜可能是噪聲造成的因此泛化能力不強(qiáng),右圖是我們想要的
只有在overfitting的時(shí)候才能設(shè)置weight_decay,否則會(huì)降低原來(lái)模型的復(fù)雜程度,因?yàn)闆](méi)有overfitting的時(shí)候模型的表達(dá)能力是匹配的,加了反而會(huì)使test acc下降,weight_decay就是λ=0.01使得w趨近于0,降低模型復(fù)雜度(迫使weight慢慢趨近于0)
對(duì)網(wǎng)絡(luò)全局的范數(shù)有約束
48動(dòng)量與學(xué)習(xí)率衰減
momentum(慣性):
learning rate decay:迫使學(xué)習(xí)率慢慢變?yōu)?
動(dòng)量其實(shí)就是當(dāng)前更新方向加歷史慣性的結(jié)合,取決于b參數(shù)怎么選會(huì)產(chǎn)生不同的效應(yīng)
如圖沒(méi)有動(dòng)量,w的更新只考慮當(dāng)前的更新方向不考慮歷史的方向,所以更新的方向很尖銳(都是尖尖角),在局部最優(yōu)就不動(dòng)了
如圖,考慮0.78的歷史方向和0.22的當(dāng)前方向,使得更新的幅度和程度緩和下來(lái),陷入局部最優(yōu)解的小坑,加了動(dòng)量(考慮慣性)就會(huì)沖出小坑
adam內(nèi)置了momentum不需要自己設(shè)置
SGD需要
learning rate decay
lr大了不收斂,小了更新慢
可能lr=0.1剛開始設(shè)置大一點(diǎn)(步數(shù)大一點(diǎn))的隨著訓(xùn)練過(guò)程慢慢減小到0.001這樣還是能找到最優(yōu)解,learning rate decay動(dòng)態(tài)尋找lr的過(guò)程
lr的微調(diào)可以在原來(lái)已經(jīng)效果好的基礎(chǔ)上會(huì)提升性能
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)
在發(fā)現(xiàn)loss不再降低或者acc不再提高之后,降低學(xué)習(xí)率。各參數(shù)意義如下:
scheduler
=ReduceLROnPlateau(optimizer
, mode
='min')
scheduler
.step(loss_val
)
#在發(fā)現(xiàn)loss不再降低或者acc不再提高之后,降低學(xué)習(xí)率,假設(shè)patience
=10就是連續(xù)調(diào)用scheduler
.step(loss_val這個(gè)函數(shù)連續(xù)
10次)
#去監(jiān)聽loss發(fā)現(xiàn)loss連續(xù)
10次沒(méi)有減少(達(dá)到平原狀態(tài)),代表需要把lr減少一定程度,如果loss不飽和就什么都不做,只是記錄作用
49early stop dropuot
可以依照經(jīng)驗(yàn),在某個(gè)不在上升的點(diǎn)進(jìn)行early stop
dropout
防止overfitting,使訓(xùn)練過(guò)程中有效的w的數(shù)量越小越好,和learning rate decay中使得w越來(lái)越小不一樣,就是網(wǎng)絡(luò)連接過(guò)程中每部分連接的地方有一定的概率會(huì)丟失不參與連接,這樣用到有效的參數(shù)量會(huì)減少
可以看到藍(lán)色曲線比較平滑不容易o(hù)verfitting
在連接的層之間加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所有連接都會(huì)使用不會(huì)參考斷開的行為,防止在test中斷開,所以人為的切換到eval中,net_dropped.eval()
stochastic 并不是真的隨機(jī),符合某一分布
deterministic
數(shù)據(jù)很大的時(shí)候不可能整個(gè)數(shù)據(jù)集load到顯存中,為了節(jié)省顯存
stochastic gradient descent
不再是求整個(gè)樣本的loss對(duì)w的梯度,而是求一個(gè)batch梯度
50什么是卷積1
黑白圖片每張圖的每個(gè)點(diǎn)表示了灰度值從0-255可以變換到0-1
彩色圖片三個(gè)通道
一層一般值的是權(quán)值w和輸出是一層,三個(gè)隱藏層,一共是4層(一般input layer不算)
多少參數(shù)就是有多少條線
局部相關(guān)性 感受野,感受不是全局的是一次一次小塊
卷積神經(jīng)網(wǎng)絡(luò),卷積指的是局部相關(guān)性
卷積:滑動(dòng)小窗口從2828變成33參數(shù)大大降低
本來(lái)有784條全連接的權(quán)值現(xiàn)在變成9個(gè)與之位置相關(guān)的位置權(quán)值,位置太遠(yuǎn)不考慮
卷積層的權(quán)值數(shù)量會(huì)成倍減少,但是可以考慮到全局信息只是移動(dòng)的時(shí)候是用的同樣的參數(shù),同時(shí)考慮了全局的屬性但是又考慮了位置相近的信息,
小窗口和大窗口做的是相乘再累加再的一個(gè)操作變成點(diǎn),這叫卷積操作
52卷積層1
kernel的類型決定了你以什么方式觀察這個(gè)map,卷積運(yùn)算后得到新的map,新map和之前map大小類似或者一致,但是數(shù)據(jù)不同
多個(gè)kernel代表觀察角度的信息不同,如圖可能有觀察blur face dog edge的多個(gè)信息
七個(gè)kernel 維度(7,1,3,3),新的map是7features map
卷積運(yùn)算的過(guò)程
上下左右都打了一個(gè)padding 所以得到的feature map也是5*5
input channel:黑白照片1 彩色照片3,中間可能是16或者64等等等
kernel channel:指的是你有多少個(gè)核
kernel size:3*3
stride:步長(zhǎng) 每次kernel移動(dòng)的大小 一次移動(dòng)幾格
padding:打的空白的行和列 如果行列打兩行的話padding是1
輸出圖片公式的大小如圖
53卷積層2
input的通道數(shù)是多少,kernel的通道數(shù)也要是多少
x[1,3,28,28]#一張圖片 三個(gè)通道rgb 2828的大小
one k:[3,3,3]:第一個(gè)3是對(duì)應(yīng)x的三個(gè)通道,后面是kernel的size33,如果input的channel是16 則kernel的channel也必須是16,必須和inut的channel是一一對(duì)應(yīng)的
multi-k:[16,3,3,3]16表示一共有16個(gè)kernel,可能是不同類型的kernel比如edge、blur等等,第一個(gè)3表示是輸入圖片的通道RGB
bias[16]:每個(gè)kernel會(huì)帶一個(gè)偏置,所以16個(gè)kernel生成維度16的bias
out:[1,16,26,26]#1表示幾張圖片就是batch,16和kernel的個(gè)數(shù)是對(duì)應(yīng)的,2626輸出圖片的大小,這取決于padding的大小也有可能是2828
kernel也成為filter weight
LeNet-5
如圖所示分析兩個(gè)convolutions的信息
x[1,32,32]
c1:[6,28,28]
所以中間的kernel是[6,1,55]因?yàn)榕coutput是6代表有六種kernel,32變28,所以kernelsize是55 (32-28+1=5)
s2:[6,14,14]6是因?yàn)閏1作為input是6,
C3[16,10,10]16是因?yàn)樯弦徊?br /> 所以kernel是[16,6,5,5]16是因?yàn)?6是16種kernel,6是6因?yàn)閕nput channel是6,所以bias是[16]
總結(jié)kernel[num of category,input_channel,kernel_height,kernel_weight]
不停疊加(stack)
conv1是低級(jí)特征線條等等
conv2是小型概念弧形圓形等等
conv3高緯的概念有沒(méi)有輪子窗戶等等
由具像到抽象
為什么叫特征學(xué)習(xí):因?yàn)榫褪翘卣鞑粩嗵崛〉倪^(guò)程
54卷積層3
實(shí)現(xiàn)二維的卷積神經(jīng)網(wǎng)絡(luò)
layer
=nn
.Conv2d(1,3,kernel_size
=3,stride
=1,padding
=0)
#batch是1,3是ker個(gè)數(shù)因?yàn)閕nput_channel是3
#如果sride
=2,就是隔一個(gè)看一個(gè)outputsize可能會(huì)折半,是一種降維的功能
。不推薦直接使用layer.forward函數(shù),建議直接實(shí)例化layer使用layer(x)因?yàn)槔锩嬗?call函數(shù)不僅會(huì)實(shí)現(xiàn)forward函數(shù)還有pytorch自帶封裝好的一些hooks
w和b是需要梯度信息的在kernel卷積的過(guò)程中會(huì)自動(dòng)更新
w=[16,3,5,5]16表示16種類kernel ,3是input_channel,5*5kernel_size,當(dāng)輸入的x的channel和3不匹配的時(shí)候會(huì)報(bào)錯(cuò)
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進(jìn)行relu操作
觀察這個(gè)窗口是取這個(gè)窗口的最大值還是平均值
subsampling隔行采樣
pooling是取當(dāng)前窗口的一個(gè)最小值或者平均值
以上都是降維操作
upsample:針對(duì)tensor放大兩倍,簡(jiǎn)單復(fù)制最近一個(gè)數(shù)值的過(guò)程
實(shí)現(xiàn)上采樣F.interpolate
out=F.interpolate(x,scale_factor=2,mode=‘nearest’),放大2倍,nearest就是采用臨近復(fù)制的模式,channel通道不會(huì)改變
relu激活函數(shù)
一個(gè)簡(jiǎn)單的unit神經(jīng)元單元一般是conv2d-batch_normalization-pooling-relu
relu函數(shù)加在feature_map上的效應(yīng):把feature_map中負(fù)的單元給去掉,把相應(yīng)低的點(diǎn)去掉,如圖圈起來(lái)的相應(yīng)太低,把該部分像素點(diǎn)變成0
layer=nn.ReLu(inplace=True)#表示x->x’的過(guò)程,x’使用的是x的內(nèi)存空間節(jié)省內(nèi)存
之后會(huì)發(fā)現(xiàn)out最小值都變成0,因?yàn)樨?fù)數(shù)都被過(guò)濾了
總結(jié)
以上是生活随笔為你收集整理的pytorch教程龙曲良46-55的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。