成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深度學(xué)習(xí)中Batch Size對(duì)訓(xùn)練過(guò)程如何影響?

人工智能 深度學(xué)習(xí)
深度學(xué)習(xí)中batch size的大小對(duì)訓(xùn)練過(guò)程的影響是什么樣的?訓(xùn)練過(guò)程中超大batch有什么優(yōu)缺點(diǎn),如何盡可能地避免超大batch帶來(lái)的負(fù)面影響?本文對(duì)這兩個(gè)問(wèn)題進(jìn)行了詳細(xì)的分析和解釋。

之前面試過(guò)程中被問(wèn)到過(guò)兩個(gè)問(wèn)題:

(1)深度學(xué)習(xí)中batch size的大小對(duì)訓(xùn)練過(guò)程的影響是什么樣的?

(2)有些時(shí)候不可避免地要用超大batch,比如人臉識(shí)別,可能每個(gè)batch要有幾萬(wàn)甚至幾十萬(wàn)張人臉圖像,訓(xùn)練過(guò)程中超大batch有什么優(yōu)缺點(diǎn),如何盡可能地避免超大batch帶來(lái)的負(fù)面影響?

面試版回答

在不考慮Batch Normalization的情況下(這種情況我們之后會(huì)在bn的文章里專門探討),先給個(gè)自己當(dāng)時(shí)回答的答案吧(相對(duì)來(lái)說(shuō)學(xué)究一點(diǎn)):

(1) 不考慮bn的情況下,batch size的大小決定了深度學(xué)習(xí)訓(xùn)練過(guò)程中的完成每個(gè)epoch所需的時(shí)間和每次迭代(iteration)之間梯度的平滑程度。(感謝評(píng)論區(qū)的韓飛同學(xué)提醒,batchsize只能說(shuō)影響完成每個(gè)epoch所需要的時(shí)間,決定也算不上吧。根本原因還是CPU,GPU算力吧。瓶頸如果在CPU,例如隨機(jī)數(shù)據(jù)增強(qiáng),batch size越大有時(shí)候計(jì)算的越慢。)

對(duì)于一個(gè)大小為N的訓(xùn)練集,如果每個(gè)epoch中mini-batch的采樣方法采用最常規(guī)的N個(gè)樣本每個(gè)都采樣一次,設(shè)mini-batch大小為b,那么每個(gè)epoch所需的迭代次數(shù)(正向+反向)圖片, 因此完成每個(gè)epoch所需的時(shí)間大致也隨著迭代次數(shù)的增加而增加。

由于目前主流深度學(xué)習(xí)框架處理mini-batch的反向傳播時(shí),默認(rèn)都是先將每個(gè)mini-batch中每個(gè)instance得到的loss平均化之后再反求梯度,也就是說(shuō)每次反向傳播的梯度是對(duì)mini-batch中每個(gè)instance的梯度平均之后的結(jié)果,所以b的大小決定了相鄰迭代之間的梯度平滑程度,b太小,相鄰mini-batch間的差異相對(duì)過(guò)大,那么相鄰兩次迭代的梯度震蕩情況會(huì)比較嚴(yán)重,不利于收斂;b越大,相鄰mini-batch間的差異相對(duì)越小,雖然梯度震蕩情況會(huì)比較小,一定程度上利于模型收斂,但如果b極端大,相鄰mini-batch間的差異過(guò)小,相鄰兩個(gè)mini-batch的梯度沒(méi)有區(qū)別了,整個(gè)訓(xùn)練過(guò)程就是沿著一個(gè)方向蹭蹭蹭往下走,很容易陷入到局部最小值出不來(lái)。

總結(jié)下來(lái):batch size過(guò)小,花費(fèi)時(shí)間多,同時(shí)梯度震蕩嚴(yán)重,不利于收斂;batch size過(guò)大,不同batch的梯度方向沒(méi)有任何變化,容易陷入局部極小值。

(2)(存疑,只是突發(fā)奇想)如果硬件資源允許,想要追求訓(xùn)練速度使用超大batch,可以采用一次正向+多次反向的方法,避免模型陷入局部最小值。即使用超大epoch做正向傳播,在反向傳播的時(shí)候,分批次做多次反向轉(zhuǎn)播,比如將一個(gè)batch size為64的batch,一次正向傳播得到結(jié)果,instance級(jí)別求loss(先不平均),得到64個(gè)loss結(jié)果;反向傳播的過(guò)程中,分四次進(jìn)行反向傳播,每次取16個(gè)instance的loss求平均,然后進(jìn)行反向傳播,這樣可以做到在節(jié)約一定的訓(xùn)練時(shí)間,利用起硬件資源的優(yōu)勢(shì)的情況下,避免模型訓(xùn)練陷入局部最小值。

通俗版回答

那么我們可以把第一個(gè)問(wèn)題簡(jiǎn)化為一個(gè)小時(shí)候經(jīng)常玩的游戲:

深度學(xué)習(xí)訓(xùn)練過(guò)程:貼鼻子

訓(xùn)練樣本:負(fù)責(zé)指揮的小朋友們(觀察角度各不一樣)

模型:負(fù)責(zé)貼的小朋友

模型衡量指標(biāo):最終貼的位置和真實(shí)位置之間的距離大小

圖片圖片

由于每個(gè)小朋友站的位置各不一樣,所以他們對(duì)鼻子位置的觀察也各不一樣。(訓(xùn)練樣本的差異性),這時(shí)候假設(shè)小明是負(fù)責(zé)貼鼻子的小朋友,小朋友A、B、C、D、E是負(fù)責(zé)指揮的同學(xué)(A, B站在圖的右邊,C,D, E站在左邊),這時(shí)候小明如果采用:

  1. 每次隨機(jī)詢問(wèn)一個(gè)同學(xué),那么很容易出現(xiàn),先詢問(wèn)到了A,A說(shuō)向左2cm,再問(wèn)C,C說(shuō)向右5cm,然后B,B說(shuō)向左4cm,D說(shuō)向右3cm,這樣每次指揮的差異都比較大,結(jié)果調(diào)過(guò)來(lái)調(diào)過(guò)去,沒(méi)什么進(jìn)步。
  2. 每次隨機(jī)詢問(wèn)兩個(gè)同學(xué),每次取詢問(wèn)的意見(jiàn)的平均,比如先問(wèn)到了(A, C),A說(shuō)向左2cm,C說(shuō)向右5cm,那就取個(gè)均值,向右1.5cm。然后再問(wèn)(B, D),這樣的話減少了極端情況(前后兩次迭代差異巨大)這種情況的發(fā)生,能更好更快的完成游戲。
  3. 每次全問(wèn)一遍,然后取均值,這樣每次移動(dòng)的方向都是所有人決定的均值,這樣的話,最后就是哪邊的小朋友多最終結(jié)果就被很快的拉向哪邊了。(梯度方向不變,限于極小值)

科學(xué)版回答

就用MINST做一下實(shí)驗(yàn)吧(代碼主要轉(zhuǎn)自cnblogs.com/jiangnanyan):

  • cnblogs.com/jiangnanyan
  • 鏈接:https://www.cnblogs.com/jiangnanyanyuchen/p/9782223.html

實(shí)驗(yàn)環(huán)境:

1080ti * 1

Pytorch 0.4.1

超參數(shù):SGD(lr = 0.02, momentum=0.5) 偷懶沒(méi)有根據(jù)batch size細(xì)調(diào)

我們先創(chuàng)建一個(gè)簡(jiǎn)單的模型:

fromtorch.nnimport*
importtorch.nn.functionalasF
classSimpleModel(Module):
def__init__(self):
super(SimpleModel, self).__init__()
self.conv1 = Conv2d(in_channels=1, out_channels=10, kernel_size=5)
self.conv2 = Conv2d(10, 20, 5)
self.conv3 = Conv2d(20, 40, 3)
self.mp = MaxPool2d(2)
self.fc = Linear(40, 10)

defforward(self, x):
        in_size = x.size(0)
        x = F.relu(self.mp(self.conv1(x)))
        x = F.relu(self.mp(self.conv2(x)))
        x = F.relu(self.mp(self.conv3(x)))

        x = x.view(in_size, -1)
        x =self.fc(x)
print(x.size())
return F.log_softmax(x, dim=1)

然后把MINST加載出來(lái)訓(xùn)練一下:

importtime
importtorch
importtorch.nnasnn
importtorch.nn.functionalasF
importtorch.optimasoptim
importos
fromtorchvisionimport datasets, transforms
fromsimple_modelimport SimpleModel

os.environ['CUDA_VISIBLE_DEVICES'] ="0"
use_cuda = torch.cuda.is_available()
batch_size =6
lr =1e-2
# MNIST Dataset

train_dataset = datasets.MNIST(root='./data/',
                               train=True,
                               transform=transforms.ToTensor(),
                               download=True)

test_dataset = datasets.MNIST(root='./data/',
                              train=False,
                              transform=transforms.ToTensor())

# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                          batch_size=batch_size,
                                          shuffle=False)

model = SimpleModel()
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.5)

if use_cuda:
    model = nn.DataParallel(model).cuda()
iter_losses = []
deftrain(epoch):
    model.train()

    total_loss =0
    compution_time =0
    e_sp = time.time()
for batch_idx, (data, target) inenumerate(train_loader):

if use_cuda:
            data = data.cuda()
            target = target.cuda()

        b_sp = time.time()
        output = model(data)
        loss = F.nll_loss(output, target)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        compution_time += time.time() - b_sp

# optimizer.step()
    epoch_time = time.time() - e_sp
print('Train Epoch: {} \t Loss: {:.6f}\t epoch time: {:.6f} s\t epoch compution time: {:.6f} s'.format(
        epoch, total_loss /len(train_loader), epoch_time, compution_time))
return total_loss /len(train_loader)
deftest():
    model.eval()
with torch.no_grad():
        test_loss =0
        correct =0
for data, target in test_loader:
if use_cuda:
                data = data.cuda()
                target = target.cuda()
            output = model(data)
# sum up batch loss
            test_loss += F.nll_loss(output, target).item()
# get the index of the max log-probability
            pred = output.data.max(1, keepdim=True)[1]
            correct += pred.eq(target.data.view_as(pred)).cpu().sum()

        test_loss /=len(test_loader)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
            test_loss, correct, len(test_loader.dataset),
100.* correct /len(test_loader.dataset)))
return test_loss, 100.* correct.item() /len(test_loader.dataset)

if __name__ =="__main__":
for epoch inrange(1, 10000):
        train_l = train(epoch)
        val_l, val_a = test()

我們從以下指標(biāo)來(lái)看一下不同batch size之間的區(qū)別:

迭代速度

圖片圖片

感覺(jué)之前做的實(shí)驗(yàn)有點(diǎn)不太科學(xué),重新捋了一下思路,把時(shí)間計(jì)算的代碼也放到了前面的代碼之中,有興趣的同學(xué)也可以自己做一下看看。

(表中 Epoch Time是在此batch size下完成一個(gè)epoch所需的所有時(shí)間,包括加載數(shù)據(jù)和計(jì)算的時(shí)間,Epoch Computation Time拋去了加載數(shù)據(jù)所需的時(shí)間。)

(時(shí)間確實(shí)是有偏量,上面的數(shù)據(jù)可以大體做個(gè)參考,要做科學(xué)考究的話,還是要多做幾次實(shí)驗(yàn)求均值減少偏差。)

其實(shí)純粹cuda計(jì)算的角度來(lái)看,完成每個(gè)iter的時(shí)間大batch和小batch區(qū)別并不大,這可能是因?yàn)楸敬螌?shí)驗(yàn)中,反向傳播的時(shí)間消耗要比正向傳播大得多,所以batch size的大小對(duì)每個(gè)iter所需的時(shí)間影響不明顯,未來(lái)將在大一點(diǎn)的數(shù)據(jù)庫(kù)和更復(fù)雜的模型上做一下實(shí)驗(yàn)。(因?yàn)榉聪虻倪^(guò)程取決于模型的復(fù)雜度,與batchsize的大小關(guān)系不大,而正向則同時(shí)取決于模型的復(fù)雜度和batch size的大小。而本次實(shí)驗(yàn)中反向的過(guò)程要比正向的過(guò)程時(shí)間消耗大得多,所以batch size的大小對(duì)完成每個(gè)iter所需的耗時(shí)影響不大。)

完成每個(gè)epoch運(yùn)算的所需的全部時(shí)間主要卡在:1. load數(shù)據(jù)的時(shí)間,2. 每個(gè)epoch的iter數(shù)量。因此對(duì)于每個(gè)epoch,不管是純計(jì)算時(shí)間還是全部時(shí)間,大體上還是大batch能夠更節(jié)約時(shí)間一點(diǎn),但隨著batch增大,iter次數(shù)減小,完成每個(gè)epoch的時(shí)間更取決于加載數(shù)據(jù)所需的時(shí)間,此時(shí)也不見(jiàn)得大batch能帶來(lái)多少的速度增益了。

梯度平滑程度

我們?cè)賮?lái)看一下不同batch size下的梯度的平滑程度,我們選取了每個(gè)batch size下前1000個(gè)iter的loss,來(lái)看一下loss的震蕩情況,結(jié)果如下圖所示:

圖片圖片

如果感覺(jué)這張圖不太好看,可以看一下這張圖:

圖片圖片

由于現(xiàn)在絕大多數(shù)的框架在進(jìn)行mini-batch的反向傳播的時(shí)候,默認(rèn)都是將batch中每個(gè)instance的loss平均化之后在進(jìn)行反向傳播,所以相對(duì)大一點(diǎn)的batch size能夠防止loss震蕩的情況發(fā)生。從這兩張圖中可以看出batch size越小,相鄰iter之間的loss震蕩就越厲害,相應(yīng)的,反傳回去的梯度的變化也就越大,也就越不利于收斂。同時(shí)很有意思的一個(gè)現(xiàn)象,batch size為1的時(shí)候,loss到后期會(huì)發(fā)生爆炸,這主要是lr=0.02設(shè)置太大,所以某個(gè)異常值的出現(xiàn)會(huì)嚴(yán)重?cái)_動(dòng)到訓(xùn)練過(guò)程。這也是為什么對(duì)于較小的batchsize,要設(shè)置小lr的原因之一,避免異常值對(duì)結(jié)果造成的擾巨大擾動(dòng)。而對(duì)于較大的batchsize,要設(shè)置大一點(diǎn)的lr的原因則是大batch每次迭代的梯度方向相對(duì)固定,大lr可以加速其收斂過(guò)程。

收斂速度

在衡量不同batch size的優(yōu)劣這一點(diǎn)上,我選用衡量不同batch size在同樣參數(shù)下的收斂速度快慢的方法。

下表中可以看出,在minst數(shù)據(jù)集上,從整體時(shí)間消耗上來(lái)看(考慮了加載數(shù)據(jù)所需的時(shí)間),同樣的參數(shù)策略下 (lr = 0.02, momentum=0.5 ),要模型收斂到accuracy在98左右,batchsize在 6 - 60 這個(gè)量級(jí)能夠花費(fèi)最少的時(shí)間,而batchsize為1的時(shí)候,收斂不到98;batchsize過(guò)大的時(shí)候,因?yàn)槟P褪諗靠炻Q于梯度方向和更新次數(shù),所以大batch盡管梯度方向更為穩(wěn)定,但要達(dá)到98的accuracy所需的更新次數(shù)并沒(méi)有量級(jí)上的減少,所以也就需要花費(fèi)更多的時(shí)間,當(dāng)然這種情況下可以配合一些調(diào)參策略比如warmup LR,衰減LR等等之類的在一定程度上進(jìn)行解決(這個(gè)先暫且按下不表),但也不會(huì)有本質(zhì)上的改善。

不過(guò)單純從計(jì)算時(shí)間上來(lái)看,大batch還是可以很明顯地節(jié)約所需的計(jì)算時(shí)間的,原因前面講過(guò)了,主要因?yàn)楸敬螌?shí)驗(yàn)中純計(jì)算時(shí)間中,反向占的時(shí)間比重遠(yuǎn)大于正向。

圖片圖片

(我一直覺(jué)得直接比較不同batch size下的絕對(duì)收斂精度來(lái)衡量batch size的好壞是沒(méi)有太大意義的,因?yàn)椴煌腷atch size要配合不同的調(diào)參策略用才能達(dá)到其最佳效果,而要想在每個(gè)batch size下都找到合適的調(diào)參策略那可太難了,所以用這種方法來(lái)決定batch size未免有點(diǎn)武斷。)

一次正向,多次反向

這部分在pytorch上進(jìn)行了實(shí)驗(yàn),但發(fā)現(xiàn)pytorch在backward中加入retain_graph進(jìn)行多次反向傳播的時(shí)候,時(shí)間消耗特別大,所以盡管采用一次正向,多次反向的方法,減少了超大batch size收斂到98的accuracy所需的iteration,但由于每個(gè)iteration時(shí)間消耗增加,所以并沒(méi)有帶來(lái)時(shí)間節(jié)省,我后續(xù)還要探究一下原因,再重新做一下實(shí)驗(yàn),然后再貼結(jié)果,給結(jié)論。

做了幾次實(shí)驗(yàn),基本失敗,一個(gè)大batch分成10份反向傳播,基本等同于lr放大10倍。大batch還是要配合著更復(fù)雜的lr策略來(lái)做,比如warmup,循環(huán)lr,lr衰減等等。

實(shí)驗(yàn)的漏洞

為了保證獨(dú)立變量,我在實(shí)驗(yàn)中不同batch設(shè)置了同樣的lr,然后比較收斂速度,這樣是不公平的,畢竟大batch還是要配合更大的初始lr,所以后續(xù)還要做一下實(shí)驗(yàn),固定每個(gè)batch size, 看lr的變化對(duì)不同batch size收斂素的的影響。

責(zé)任編輯:武曉燕 來(lái)源: 海邊的拾遺者
相關(guān)推薦

2025-02-12 13:42:25

2017-10-25 16:30:47

深度學(xué)習(xí)分布式訓(xùn)練

2022-12-19 08:40:42

2017-09-26 10:09:55

EpochBatch Size神經(jīng)網(wǎng)絡(luò)

2017-04-25 18:03:11

Caffe深度學(xué)習(xí)框架

2024-11-12 09:20:03

神經(jīng)網(wǎng)絡(luò)語(yǔ)言模型

2023-01-06 08:42:02

學(xué)習(xí)訓(xùn)練

2024-10-28 15:30:36

2024-09-29 16:11:53

2022-04-08 14:40:59

框架訓(xùn)練模型

2020-12-07 10:09:43

機(jī)器學(xué)習(xí)金融行業(yè)深度學(xué)習(xí)

2025-03-03 10:42:50

深度學(xué)習(xí)PyTorch大型語(yǔ)言模型

2017-05-03 22:05:48

深度學(xué)習(xí)候選采樣深度學(xué)習(xí)庫(kù)

2024-01-11 09:00:00

2010-02-02 13:45:05

Python程序?qū)W習(xí)

2023-01-09 08:00:00

遷移學(xué)習(xí)機(jī)器學(xué)習(xí)數(shù)據(jù)集

2023-11-08 10:25:00

模型技術(shù)

2022-12-12 15:09:50

2014-02-19 11:41:49

產(chǎn)品產(chǎn)品研發(fā)

2025-04-24 09:25:00

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品精品视频一区二区三区 | 国产91亚洲精品一区二区三区 | 91精品国产色综合久久不卡98口 | 精品久久久久久久人人人人传媒 | 亚洲一区国产精品 | 国产精彩视频在线观看 | 国产1区2区 | 国产精品一区一区 | 国产日韩欧美 | 91色站| 青青草华人在线视频 | 亚洲欧美视频 | 91资源在线 | 在线免费中文字幕 | 日韩在线国产精品 | 欧美一级欧美三级在线观看 | 午夜在线精品偷拍 | 美女久久久久久久 | 91免费看片神器 | 国产在线精品一区二区 | 国产一区二区影院 | 91久久精品国产91久久性色tv | 在线一级片 | 久久网一区二区三区 | 久久午夜视频 | 成人精品福利 | 伊人热久久| 狠狠躁天天躁夜夜躁婷婷老牛影视 | 521av网站 | 国产成人久久久 | 久久一日本道色综合久久 | 亚洲视频网 | 国产一级久久久久 | 久草a√ | 亚洲天堂久久 | 国产美女福利在线观看 | 亚洲色图网址 | 亚洲区视频 | 亚洲一区二区三 | 91视频一区| 美女视频黄的 |