1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        使用PyTorch時,最常見的4個錯誤

        共 5655字,需瀏覽 12分鐘

         ·

        2020-11-21 15:47

        ↑ 點擊藍(lán)字?關(guān)注極市平臺

        作者丨Yuval Greenfield
        來源丨AI公園
        編輯丨極市平臺

        極市導(dǎo)讀

        ?

        本文總結(jié)了使用PyTorch時常見的4個錯誤,并給出了每一種錯誤出現(xiàn)的原因并給出了詳細(xì)的修復(fù)方法及代碼步驟:1.沒有首先嘗試過擬合單個batch。2.忘了為網(wǎng)絡(luò)設(shè)置train/eval模式。3.在.backward()之前忘記了.zero_grad()。4.將softmaxed輸出傳遞給了期望原始logits的損失。>>加入極市CV技術(shù)交流群,走在計算機視覺的最前沿

        最常見的神經(jīng)網(wǎng)絡(luò)錯誤:

        1)你沒有首先嘗試過擬合單個batch。

        2)你忘了為網(wǎng)絡(luò)設(shè)置train/eval模式。

        3)在.backward()之前忘記了.zero_grad()(在pytorch中)。

        4)將softmaxed輸出傳遞給了期望原始logits的損失,還有其他嗎?

        這篇文章將逐點分析這些錯誤是如何在PyTorch代碼示例中體現(xiàn)出來的。

        代碼:https://github.com/missinglinkai/common-nn-mistakes

        常見錯誤 #1 你沒有首先嘗試過擬合單個batch

        Andrej說我們應(yīng)該過擬合單個batch。為什么?好吧,當(dāng)你過擬合了單個batch —— 你實際上是在確保模型在工作。我不想在一個巨大的數(shù)據(jù)集上浪費了幾個小時的訓(xùn)練時間,只是為了發(fā)現(xiàn)因為一個小錯誤,它只有50%的準(zhǔn)確性。當(dāng)你的模型完全記住輸入時,你會得到的結(jié)果是對其最佳表現(xiàn)的很好的預(yù)測。

        可能最佳表現(xiàn)為零,因為在執(zhí)行過程中拋出了一個異常。但這沒關(guān)系,因為我們很快就能發(fā)現(xiàn)問題并解決它??偨Y(jié)一下,為什么你應(yīng)該從數(shù)據(jù)集的一個小子集開始過擬合:

        • 發(fā)現(xiàn)bug

        • 估計最佳的可能損失和準(zhǔn)確率

        • 快速迭代

        在PyTorch數(shù)據(jù)集中,你通常在dataloader上迭代。你的第一個嘗試可能是索引train_loader。

        #?TypeError:?'DataLoader'?object?does?not?support?indexing
        first_batch?=?train_loader[0]

        你會立即看到一個錯誤,因為DataLoaders希望支持網(wǎng)絡(luò)流和其他不需要索引的場景。所以沒有__getitem__方法,這導(dǎo)致了[0]操作失敗,然后你會嘗試將其轉(zhuǎn)換為list,這樣就可以支持索引。

        #?slow,?wasteful
        first_batch?=?list(train_loader)[0]

        但這意味著你要評估整個數(shù)據(jù)集這會消耗你的時間和內(nèi)存。那么我們還能嘗試什么呢?

        在Python for循環(huán)中,當(dāng)你輸入如下:

        for?item?in?iterable:
        ????do_stuff(item)

        你有效地得到了這個:

        iterator?=?iter(iterable)
        try:
        ????while?True:
        ????????item?=?next(iterator)
        ????????do_stuff(item)
        except?StopIteration:
        ????pass

        調(diào)用“iter”函數(shù)來創(chuàng)建迭代器,然后在循環(huán)中多次調(diào)用該函數(shù)的“next”來獲取下一個條目。直到我們完成時,StopIteration被觸發(fā)。在這個循環(huán)中,我們只需要調(diào)用next, next, next… 。為了模擬這種行為但只獲取第一項,我們可以使用這個:

        first?=?next(iter(iterable))

        我們調(diào)用“iter”來獲得迭代器,但我們只調(diào)用“next”函數(shù)一次。注意,為了清楚起見,我將下一個結(jié)果分配到一個名為“first”的變量中。我把這叫做“next-iter” trick。在下面的代碼中,你可以看到完整的train data loader的例子:

        for?batch_idx,?(data,?target)?in?enumerate(train_loader):
        ????#?training?code?here

        下面是如何修改這個循環(huán)來使用 first-iter trick :

        first_batch?=?next(iter(train_loader))
        for?batch_idx,?(data,?target)?in?enumerate([first_batch]?*?50):
        ????#?training?code?here

        你可以看到我將“first_batch”乘以了50次,以確保我會過擬合。

        常見錯誤 #2: 忘記為網(wǎng)絡(luò)設(shè)置 train/eval 模式

        為什么PyTorch關(guān)注我們是訓(xùn)練還是評估模型?最大的原因是dropout。這項技術(shù)在訓(xùn)練中隨機去除神經(jīng)元。

        想象一下,如果右邊的紅色神經(jīng)元是唯一促成正確結(jié)果的神經(jīng)元。一旦我們移除紅色神經(jīng)元,它就迫使其他神經(jīng)元訓(xùn)練和學(xué)習(xí)如何在沒有紅色的情況下保持準(zhǔn)確。這種drop-out提高了最終測試的性能 —— 但它對訓(xùn)練期間的性能產(chǎn)生了負(fù)面影響,因為網(wǎng)絡(luò)是不全的。在運行腳本并查看MissingLink dashobard的準(zhǔn)確性時,請記住這一點。

        在這個特定的例子中,似乎每50次迭代就會降低準(zhǔn)確度。

        如果我們檢查一下代碼 —— 我們看到確實在train函數(shù)中設(shè)置了訓(xùn)練模式。

        def?train(model,?optimizer,?epoch,?train_loader,?validation_loader):
        ????model.train()?#?????????????
        ????for?batch_idx,?(data,?target)?in?experiment.batch_loop(iterable=train_loader):
        ????????data,?target?=?Variable(data),?Variable(target)
        ????????#?Inference
        ????????output?=?model(data)
        ????????loss_t?=?F.nll_loss(output,?target)
        ????????#?The?iconic?grad-back-step?trio
        ????????optimizer.zero_grad()
        ????????loss_t.backward()
        ????????optimizer.step()
        ????????if?batch_idx?%?args.log_interval?==?0:
        ????????????train_loss?=?loss_t.item()
        ????????????train_accuracy?=?get_correct_count(output,?target)?*?100.0?/?len(target)
        ????????????experiment.add_metric(LOSS_METRIC,?train_loss)
        ????????????experiment.add_metric(ACC_METRIC,?train_accuracy)
        ????????????print('Train?Epoch:?{}?[{}/{}?({:.0f}%)]\tLoss:?{:.6f}'.format(
        ????????????????epoch,?batch_idx,?len(train_loader),
        ????????????????100.?*?batch_idx?/?len(train_loader),?train_loss))
        ????????????with?experiment.validation():
        ????????????????val_loss,?val_accuracy?=?test(model,?validation_loader)?#?????????????
        ????????????????experiment.add_metric(LOSS_METRIC,?val_loss)
        ????????????????experiment.add_metric(ACC_METRIC,?val_accuracy)

        這個問題不太容易注意到,在循環(huán)中我們調(diào)用了test函數(shù)。

        def?test(model,?test_loader):
        ????model.eval()
        ????#?...

        在test函數(shù)內(nèi)部,我們將模式設(shè)置為eval!這意味著,如果我們在訓(xùn)練過程中調(diào)用了test函數(shù),我們就會進(jìn)eval模式,直到下一次train函數(shù)被調(diào)用。這就導(dǎo)致了每一個epoch中只有一個batch使用了drop-out ,這就導(dǎo)致了我們看到的性能下降。

        修復(fù)很簡單 —— 我們將model.train()?向下移動一行,讓如訓(xùn)練循環(huán)中。理想的模式設(shè)置是盡可能接近推理步驟,以避免忘記設(shè)置它。修正后,我們的訓(xùn)練過程看起來更合理,沒有中間的峰值出現(xiàn)。請注意,由于使用了drop-out ,訓(xùn)練準(zhǔn)確性會低于驗證準(zhǔn)確性。

        常用的錯誤 #3: 忘記在.backward()之前進(jìn)行.zero_grad()

        當(dāng)在 “l(fā)oss”張量上調(diào)用 “backward” 時,你是在告訴PyTorch從loss往回走,并計算每個權(quán)重對損失的影響有多少,也就是這是計算圖中每個節(jié)點的梯度。使用這個梯度,我們可以最優(yōu)地更新權(quán)值。

        這是它在PyTorch代碼中的樣子。最后的“step”方法將根據(jù)“backward”步驟的結(jié)果更新權(quán)重。從這段代碼中可能不明顯的是,如果我們一直在很多個batch上這么做,梯度會爆炸,我們使用的step將不斷變大。

        output?=?model(input)?#?forward-pass
        loss_fn.backward()????#?backward-pass
        optimizer.step()??????#?update?weights?by?an?ever?growing?gradient?????????????

        為了避免step變得太大,我們使用?zero_grad?方法。

        output?=?model(input)?#?forward-pass
        optimizer.zero_grad()?#?reset?gradient?????
        loss_fn.backward()????#?backward-pass
        optimizer.step()??????#?update?weights?using?a?reasonably?sized?gradient?????

        這可能感覺有點過于明顯,但它確實賦予了對梯度的精確控制。有一種方法可以確保你沒有搞混,那就是把這三個函數(shù)放在一起:

        • zero_grad

        • backward

        • step

        在我們的代碼例子中,在完全不使用zero_grad的情況下。神經(jīng)網(wǎng)絡(luò)開始變得更好,因為它在改進(jìn),但梯度最終會爆炸,所有的更新變得越來越垃圾,直到網(wǎng)絡(luò)最終變得無用。

        調(diào)用backward之后再做zero_grad。什么也沒有發(fā)生,因為我們擦掉了梯度,所以權(quán)重沒有更新。剩下的唯一有變化的是dropout。

        我認(rèn)為在每次step方法被調(diào)用時自動重置梯度是有意義的。

        backward的時候不使用zero_grad的一個原因是,如果你每次調(diào)用step()?時都要多次調(diào)用backward,例如,如果你每個batch只能將一個樣本放入內(nèi)存中,那么一個梯度會噪聲太大,你想要在每個step中聚合幾個batch的梯度。另一個原因可能是在計算圖的不同部分調(diào)用backward?—— 但在這種情況下,你也可以把損失加起來,然后在總和上調(diào)用backward

        常見錯誤 #4: 你把做完softmax的結(jié)果送到了需要原始logits的損失函數(shù)中

        logits是最后一個全連接層的激活值。softmax也是同樣的激活值,但是經(jīng)過了標(biāo)準(zhǔn)化。logits值,你可以看到有些是正的,一些是負(fù)的。而log_softmax之后的值,全是負(fù)值。如果看柱狀圖的話,可以看到分布式一樣的,唯一的差別就是尺度,但就是這個細(xì)微的差別,導(dǎo)致最后的數(shù)學(xué)計算完全不一樣了。但是為什么這是一個常見的錯誤呢?在PyTorch的官方MNIST例子中,查看forward?方法,在最后你可以看到最后一個全連接層self.fc2,然后就是log_softmax。

        但是當(dāng)你查看官方的PyTorch resnet或者AlexNet模型的時候,你會發(fā)現(xiàn)這些模型在最后并沒有softmax層,最后得到就是全連接的輸出,就是logits。

        這兩個的差別在文檔中沒有說的很清楚。如果你查看nll_loss函數(shù),并沒有提得輸入是logits還是softmax,你的唯一希望是在示例代碼中發(fā)現(xiàn)nll_loss使用了log_softmax作為輸入。


        推薦閱讀




          添加極市小助手微信(ID : cvmart2),備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標(biāo)檢測-深圳),即可申請加入極市目標(biāo)檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學(xué)影像/3D/SLAM/自動駕駛/超分辨率/姿態(tài)估計/ReID/GAN/圖像增強/OCR/視頻理解等技術(shù)交流群:每月大咖直播分享、真實項目需求對接、求職內(nèi)推、算法競賽、干貨資訊匯總、與?10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動交流~

          △長按添加極市小助手

          △長按關(guān)注極市平臺,獲取最新CV干貨

          覺得有用麻煩給個在看啦~??
          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          1. <strong id="7actg"></strong>
          2. <table id="7actg"></table>

          3. <address id="7actg"></address>
            <address id="7actg"></address>
            1. <object id="7actg"><tt id="7actg"></tt></object>
              帮老师揉腿慢慢滑进内裤在线 | 精品尤物在线观看 | 无人乱码一区二区三区的观看模式 | 久久精品国产亚洲aⅴ瑜伽 | 男人捅女人30分钟视频 | 少妇荡乳情欲办公室毛片一区二区 | 97超碰在线人人 | japan21xxxxhd美女 | 娱乐圈名器高h喷水荡肉爽文 | 亚洲精品一区二区口爆 |