最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

07 自動(dòng)求導(dǎo)【動(dòng)手學(xué)深度學(xué)習(xí)v2】

2021-11-15 11:16 作者:如果我是泡橘子  | 我要投稿

向量鏈?zhǔn)椒▌t




例1:


  • 線性回歸的例子:利用鏈?zhǔn)椒▌t對(duì)線性回歸求導(dǎo)
  • <x,w>:x 和 w 做內(nèi)積
  • 上圖中求 z 對(duì) w 的導(dǎo)數(shù)時(shí),第二項(xiàng) b 對(duì) a 的導(dǎo)數(shù)在代入時(shí)應(yīng)該應(yīng)該寫作 d (a - y) ,圖中少了一對(duì)括號(hào)



例2:


  • 上圖中求 z 對(duì) w 的導(dǎo)數(shù)時(shí),第二項(xiàng) b 對(duì) a 的導(dǎo)數(shù)在代入時(shí)應(yīng)該應(yīng)該寫作 d (a - y) ,圖中少了一對(duì)括號(hào)
  • 圖中 ||b|| 表示求 b 的范數(shù)



自動(dòng)求導(dǎo)


計(jì)算一個(gè)函數(shù)在指定值上的導(dǎo)數(shù)



自動(dòng)求導(dǎo)與符號(hào)求導(dǎo)、數(shù)值求導(dǎo)的區(qū)別

  • 符號(hào)求導(dǎo):指定一個(gè)函數(shù),然后求函數(shù)的導(dǎo)數(shù)(這里可以理解為對(duì)某一個(gè)函數(shù)進(jìn)行求導(dǎo),求出其導(dǎo)函數(shù),而不是一個(gè)具體的值),它是一個(gè)顯式的計(jì)算
  • 數(shù)值求導(dǎo):給定一個(gè)未知函數(shù)(不知道其具體表達(dá)式),然后利用數(shù)值去擬合它的導(dǎo)數(shù)(這里有點(diǎn)像利用極限去求導(dǎo)的過(guò)程)



計(jì)算圖


雖然使用pytorch不用去理解計(jì)算圖,但是有必要知道其內(nèi)部的工作原理,便于使用其它框架(如tensorflow等)時(shí)去理解計(jì)算圖

  • 加入中間變量 a 、 b ,將他們做成一個(gè)基本的計(jì)算子
  • 每個(gè)圓圈表示一個(gè)操作,也可以表示成為一個(gè)輸入


顯式構(gòu)造

(Tensorflow / Theano / MXNet)


from mxnet import sym

a = sym.var()

b = sym.var()

c = 2 * a + b

# bind data into a and b later

  • 此處會(huì)報(bào)錯(cuò)“No module named 'mxnet'”,直接在conda環(huán)境下使用 pip install mxnet 或者沐神之前用的在程序第一行使用 !pip install mxnet 這行代碼進(jìn)行安裝也可

輸出:

TypeError: var() missing 1 required positional argument: 'name'

  • 這里會(huì)提示缺少一個(gè)位置參數(shù)
  • 這里應(yīng)該不是一段完整的可運(yùn)行的代碼,只是為了介紹顯式構(gòu)造


隱式構(gòu)造

(PyTorch / MXNet)


from mxnet import autograd , nd

with autograd.record():

? ? a = nd.ones((2,1))

? ? b = nd.ones((2,1))

? ? c = 2 * a + b

輸出:

  • 沒(méi)有輸出,但也不會(huì)報(bào)錯(cuò)





自動(dòng)求導(dǎo)的兩種模式



反向積累




反向累積總結(jié)



復(fù)雜度


  • 內(nèi)存復(fù)雜度:深度神經(jīng)網(wǎng)絡(luò)耗費(fèi)GPU資源的根源,做梯度的時(shí)候需要存儲(chǔ)前面的運(yùn)行結(jié)果
  • 正向累積:不管神經(jīng)網(wǎng)絡(luò)的深度有多深都不需要存儲(chǔ)任何的結(jié)果,但是因?yàn)樾枰獙?duì)每一層計(jì)算梯度,所以每計(jì)算一個(gè)梯度都需要重新掃描一遍,計(jì)算復(fù)雜度太高





自動(dòng)求導(dǎo)的實(shí)現(xiàn)



import torch

x = torch.arange(4.0)

x

輸出:

tensor([0., 1., 2., 3.])


在計(jì)算 y 關(guān)于 向量x 的梯度之前,需要一個(gè)地方來(lái)存儲(chǔ)梯度


x.requires_grad_(True)

# 等價(jià)于 x = torch.arange(4.0,requires_grad=True)

x.grad # 默認(rèn)值是None


然后計(jì)算y


y = 2 * torch.dot(x,x)

y

  • y 等于 x 與 x 的內(nèi)積的兩倍

輸出:

tensor(28., grad_fn=<DotBackward0>)

  • grad_fn:這里是隱式構(gòu)造圖,所以有一個(gè)求梯度的函數(shù),告知 y 是從 x 計(jì)算過(guò)來(lái)的


通過(guò)調(diào)用反向傳播函數(shù)來(lái)自動(dòng)計(jì)算 y 關(guān)于 x 每個(gè)分量的梯度


y.backward()

x.grad

  • y.backward():求導(dǎo)
  • 利用 x.grad 來(lái)訪問(wèn)導(dǎo)數(shù)

輸出:

tensor([ 0., 4., 8., 12.])


x.grad == 4 * x

  • 驗(yàn)證一下結(jié)果

輸出:

tensor([True, True, True, True])


計(jì)算 x 的另一個(gè)函數(shù)


# 在默認(rèn)情況下,PyTorch會(huì)累積梯度,因此在進(jìn)行另外一個(gè)函數(shù)之前需要清除之前的值

x.grad.zero_()

y = x.sum()

y.backward()

x.grad

  • PyTorch中下劃線表示重寫內(nèi)容,zero_表示把所有的梯度清零

輸出:

tensor([1., 1., 1., 1.])


深度學(xué)習(xí)中,目的不是計(jì)算微分矩陣,而是批量中每個(gè)樣本單獨(dú)計(jì)算的偏導(dǎo)數(shù)之和

  • 深度學(xué)習(xí)中很少對(duì)一個(gè)向量進(jìn)行求導(dǎo),而只是對(duì)一個(gè)標(biāo)量進(jìn)行求導(dǎo)
  • 絕大部分情況下會(huì)先進(jìn)行求和,再進(jìn)行求導(dǎo),這樣子就是一個(gè)標(biāo)量


# 對(duì)非標(biāo)量調(diào)用 backward 需要傳入一個(gè) gradient 參數(shù)

x.grad.zero_()

y = x * x

# 等價(jià)于 y.backward(torch.ones(len(x)))

y.sum().backward()

x.grad

  • y.detach():把 y 當(dāng)作一個(gè)常數(shù)而不是一個(gè)關(guān)于 x 的函數(shù)

輸出;

tensor([0., 2., 4., 6.])

  • 以后將會(huì)用于在一些場(chǎng)景下將網(wǎng)絡(luò)中的參數(shù)固定


即使構(gòu)建函數(shù)的計(jì)算圖需要通過(guò)Python控制流(例如:條件、循環(huán)或任意函數(shù)調(diào)用),仍然可以計(jì)算得到變量的梯度


def f(a):

? ? b = a * 2

? ? while b.norm() < 1000:

? ? ? ? b = b * 2

? ? if b.sum() > 0:

? ? ? ? c = b

? ? else:

? ? ? ? c = 100 * b

? ? return c


a = torch.randn(size = (),requires_grad=True)

d = f(a)

d.backward()

  • size=():表示是一個(gè)標(biāo)量
  • require_grad=True:表示需要梯度
  • 在計(jì)算的時(shí)候,torch會(huì)把整個(gè)計(jì)算圖存下來(lái),然后倒著做一遍
  • 隱式計(jì)算的好處在于對(duì)于控制流做的更好一些,但是速度比較慢





Q&A


1、ppt上隱式構(gòu)造和顯式構(gòu)造看起來(lái)為什么差不多?


  • 看上去是差不多,但是顯式構(gòu)造是先把整個(gè)計(jì)算寫出來(lái),然后再給值
  • 用python來(lái)實(shí)現(xiàn)一個(gè)函數(shù)和用數(shù)學(xué)來(lái)實(shí)現(xiàn)一個(gè)函數(shù)是不一樣的
  • 很多情況下,在使用的時(shí)候顯式構(gòu)造非常不方便





2、需要正向和反向都要算一遍嗎?


  • 在神經(jīng)網(wǎng)絡(luò)中求梯度的時(shí)候,需要正著算一遍,然后再反著算一遍
  • 自動(dòng)求導(dǎo)的時(shí)候只需要反著算一遍,不需要正著再算一遍





3、為什么Pytorch會(huì)默認(rèn)累積梯度?


  • 反向傳播的時(shí)候需要把內(nèi)存結(jié)果存起來(lái),因此耗費(fèi)內(nèi)存比較多
  • PyTorch對(duì)內(nèi)存的管理不太好,如果對(duì)于一個(gè)很大的批量,如果無(wú)法一次計(jì)算全計(jì)算出來(lái),則可以將其劃分成多次計(jì)算,然后進(jìn)行累加,從而得到正確的結(jié)果
  • 當(dāng)weight在不同的模型之間進(jìn)行共享時(shí)也是有好處的餓





4、為什么是0246?是這么理解嗎:x^2對(duì)x求導(dǎo)


2 * x 等于0246





5、為什么深度學(xué)習(xí)中一般對(duì)標(biāo)量求導(dǎo)而不是對(duì)矩陣或者向量,如果我的loss是包含向量或者矩陣,那求導(dǎo)之前是不是要把它們變成標(biāo)量?


  • 因?yàn)閘oss通常是一個(gè)標(biāo)量
  • 如果loss是一個(gè)向量的話,隨著神經(jīng)網(wǎng)絡(luò)深度的增加,它會(huì)變成一個(gè)很大的張量,無(wú)法進(jìn)行計(jì)算





6、mxnet不用gluo的時(shí)候,除了用sym構(gòu)建一個(gè)網(wǎng)絡(luò)層,有什么自動(dòng)求導(dǎo)的好的方法嗎?比如我構(gòu)建了一個(gè)loss公式后


跳過(guò)了。。。





7、今天講的求導(dǎo),會(huì)在pytorch里如何實(shí)現(xiàn)代碼呢?


  • 講了實(shí)現(xiàn),但是沒(méi)有講具體公式的實(shí)現(xiàn),有興趣可以自己試一下

?
自動(dòng)求導(dǎo) QA P3 - 03:39
?





8、多個(gè)loss分別反向的時(shí)候是不是需要累積梯度?


  • 是的,神經(jīng)網(wǎng)絡(luò)中有多個(gè)loss的話,是需要進(jìn)行累積的,這也是為什么pytorch默認(rèn)是累加梯度的





9、為什么獲取.grad前需要backward?


  • 不去backward的話就不會(huì)去計(jì)算梯度,這件事情占用很多的內(nèi)存,所以需要手動(dòng)backward計(jì)算梯度





10、求導(dǎo)過(guò)程是不是都是有向圖,也就是可以用樹狀結(jié)構(gòu)來(lái)表示,有沒(méi)有其它環(huán)狀的圖結(jié)構(gòu)?


  • 有,例如循環(huán)神經(jīng)網(wǎng)絡(luò)就能夠變成一個(gè)環(huán)狀的圖結(jié)構(gòu)





11、pytorch或mxnet框架審計(jì)上可以實(shí)現(xiàn)矢量的求導(dǎo)嗎?


?
自動(dòng)求導(dǎo) QA P3 - 05:44
?





----end----

07 自動(dòng)求導(dǎo)【動(dòng)手學(xué)深度學(xué)習(xí)v2】的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
曲水县| 榆林市| 永新县| 米脂县| 伊宁市| 玛纳斯县| 阳曲县| 苏州市| 宁晋县| 蒲城县| 通榆县| 昌江| 宜宾市| 永善县| 淮阳县| 永安市| 南靖县| 阿尔山市| 从江县| 进贤县| 苗栗县| 驻马店市| 五原县| 娄底市| 无极县| 株洲市| 泊头市| 永顺县| 石屏县| 平定县| 梁山县| 昌都县| 枣强县| 龙海市| 莲花县| 慈利县| 肥东县| 白银市| 仙桃市| 贡觉县| 湖南省|