日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

PyTorch框架学习四——计算图与动态图机制

發(fā)布時(shí)間:2024/7/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PyTorch框架学习四——计算图与动态图机制 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

PyTorch框架學(xué)習(xí)四——計(jì)算圖與動(dòng)態(tài)圖機(jī)制

  • 一、計(jì)算圖
  • 二、動(dòng)態(tài)圖與靜態(tài)圖
  • 三、torch.autograd
    • 1.torch.autograd.backward()
    • 2.torch.autograd.grad()
    • 3.autograd小貼士
    • 4.代碼演示理解
      • (1)構(gòu)建計(jì)算圖并反向求導(dǎo):
      • (2)grad_tensors的理解:
      • (3)autograd.gard與create_graph的結(jié)合:
      • (4)小貼士1
      • (5)小貼士2
      • (6)小貼士3

一、計(jì)算圖

計(jì)算圖是用來(lái)描述運(yùn)算的有向無(wú)環(huán)圖,它包含了兩個(gè)主要元素:結(jié)點(diǎn)(Node)與邊(Edge)。其中結(jié)點(diǎn)表示數(shù)據(jù),如向量、矩陣、張量等,而邊表示運(yùn)算,如加減乘除卷積等。

下面用計(jì)算圖來(lái)表示:y=(x+w)×(w+1)這樣的一個(gè)運(yùn)算。

令 a = x + w,b = w + 1,則y = a×b。

計(jì)算圖如下圖所示:

構(gòu)建這樣的計(jì)算圖是很方便求解梯度的,以對(duì)w求偏導(dǎo)為例,假設(shè)x和w的初始值為2和1:

強(qiáng)調(diào)兩個(gè)概念:

  • 葉子結(jié)點(diǎn):用戶創(chuàng)建的結(jié)點(diǎn),如x與w,tensor中的is_leaf屬性就是指示張量是否為葉子結(jié)點(diǎn)。非葉子結(jié)點(diǎn)運(yùn)算后會(huì)被釋放,葉子結(jié)點(diǎn)的梯度會(huì)被保留,若想保留非葉子結(jié)點(diǎn)的梯度,可以用retain_grad()。
  • grad_fn:記錄創(chuàng)建張量時(shí)所用的方法(函數(shù)),在梯度的反向傳播時(shí)會(huì)用到,以上述的計(jì)算為例:y.grad_fn = <MulBackward 0>,a.grad_fn = <AddBackward 0>。
  • 二、動(dòng)態(tài)圖與靜態(tài)圖

    動(dòng)態(tài)圖靜態(tài)圖
    實(shí)現(xiàn)方式運(yùn)算與搭建同時(shí)進(jìn)行先搭建計(jì)算圖,后計(jì)算
    特點(diǎn)靈活易調(diào)節(jié)高效但不靈活
    框架PyTorchTensorFlow

    三、torch.autograd

    這是一個(gè)自動(dòng)求導(dǎo)系統(tǒng),提供了類和函數(shù)用來(lái)對(duì)任意標(biāo)量函數(shù)進(jìn)行求導(dǎo)。
    下面介紹autograd中兩個(gè)自動(dòng)求導(dǎo)的函數(shù):

    1.torch.autograd.backward()

    沒(méi)有返回值,但是已經(jīng)對(duì)數(shù)據(jù)進(jìn)行了自動(dòng)求導(dǎo)。

    torch.autograd.backward(tensors: Union[torch.Tensor, Sequence[torch.Tensor]], grad_tensors: Union[torch.Tensor, Sequence[torch.Tensor], None] = None, retain_graph: Optional[bool] = None, create_graph: bool = False, grad_variables: Union[torch.Tensor, Sequence[torch.Tensor], None] = None)

  • tensors:用于求導(dǎo)的張量們。
  • grad_tensors:多梯度權(quán)重,下面用例子理解。
  • retain_graph:(布爾,可選)若為False,計(jì)算圖計(jì)算完之后就會(huì)被釋放,若為True,則會(huì)保留。
  • create_graph:(布爾,可選)若為True,會(huì)創(chuàng)建導(dǎo)數(shù)的計(jì)算圖,用于更高階的求導(dǎo),默認(rèn)為False。
  • 2.torch.autograd.grad()

    torch.autograd.grad(outputs: Union[torch.Tensor, Sequence[torch.Tensor]], inputs: Union[torch.Tensor, Sequence[torch.Tensor]], grad_outputs: Union[torch.Tensor, Sequence[torch.Tensor], None] = None, retain_graph: Optional[bool] = None, create_graph: bool = False, only_inputs: bool = True, allow_unused: bool = False)

    3.autograd小貼士

  • 梯度不會(huì)自動(dòng)清零,若不清零,則會(huì)疊加上原來(lái)的數(shù)據(jù),需要手動(dòng)清零:grad.zero_()。
  • 依賴于葉子結(jié)點(diǎn)的結(jié)點(diǎn),requires_grad默認(rèn)為True。
  • 葉子結(jié)點(diǎn)不可執(zhí)行in-place操作,in-place操作為在原始內(nèi)存中改變數(shù)據(jù)的操作,如a += torch.ones((1, )) (加等操作a的內(nèi)存地址不變,所以對(duì)張量不能做這項(xiàng)操作)。這是因?yàn)?#xff0c;在前向傳播時(shí),會(huì)記錄葉子結(jié)點(diǎn)的地址,反向求導(dǎo)時(shí)是會(huì)依據(jù)記錄的地址去取值進(jìn)行運(yùn)算的,若在中途用in-place操作改變了值,則梯度求解會(huì)出錯(cuò)。
  • 4.代碼演示理解

    (1)構(gòu)建計(jì)算圖并反向求導(dǎo):

    # 設(shè)置 x 和 w 的初始值 w = torch.tensor([1.], requires_grad=True) x = torch.tensor([2.], requires_grad=True) # 構(gòu)建計(jì)算圖 a = torch.add(w, x) b = torch.add(w, 1) y = torch.mul(a, b) # 反向求導(dǎo) y.backward() print(w.grad, x.grad)

    結(jié)果如下,與手動(dòng)計(jì)算結(jié)果一致:

    tensor([5.]) tensor([2.])

    (2)grad_tensors的理解:

    w = torch.tensor([1.], requires_grad=True) x = torch.tensor([2.], requires_grad=True)a = torch.add(w, x) # retain_grad() b = torch.add(w, 1)y0 = torch.mul(a, b) # y0 = (x+w) * (w+1) y1 = torch.add(a, b) # y1 = (x+w) + (w+1) dy1/dw = 2loss = torch.cat([y0, y1], dim=0) # [y0, y1] grad_tensors = torch.tensor([1., 2.])loss.backward(gradient=grad_tensors) # gradient 傳入 torch.autograd.backward()中的grad_tensorsprint(w.grad)

    grad_tensors的作用就類似于一個(gè)權(quán)重,當(dāng)要求導(dǎo)的對(duì)象有多個(gè)梯度時(shí),它就是各個(gè)梯度加和的權(quán)重,比如這里 dy0 / dw = 5,dy1/dw = 2,那么w的總梯度值為 5×1 + 2×2 = 9。
    結(jié)果如下:

    tensor([9.])

    (3)autograd.gard與create_graph的結(jié)合:

    x = torch.tensor([3.], requires_grad=True) y = torch.pow(x, 2) # y = x**2grad_1 = torch.autograd.grad(y, x, create_graph=True) # grad_1 = dy/dx = 2x = 2 * 3 = 6 print(grad_1)grad_2 = torch.autograd.grad(grad_1[0], x) # grad_2 = d(dy/dx)/dx = d(2x)/dx = 2 print(grad_2)

    其中y就是用于求導(dǎo)的張量,x就是需要梯度的張量,grad_1就是第一次求導(dǎo)后x的梯度,因?yàn)閏reate_graph為True,所以已經(jīng)構(gòu)建了導(dǎo)數(shù)的計(jì)算圖,可以對(duì)grad_1再次求導(dǎo),得到第二次求導(dǎo)后x的梯度grad_2:

    (tensor([6.], grad_fn=<MulBackward0>),) (tensor([2.]),)

    (4)小貼士1

    這里我們構(gòu)建了四次計(jì)算圖,四次一模一樣的計(jì)算:

    w = torch.tensor([1.], requires_grad=True) x = torch.tensor([2.], requires_grad=True)for i in range(4):a = torch.add(w, x)b = torch.add(w, 1)y = torch.mul(a, b)y.backward()print(w.grad)

    若我們不對(duì)梯度手動(dòng)清零,結(jié)果就如下所示:

    tensor([5.]) tensor([10.]) tensor([15.]) tensor([20.])

    因?yàn)槊看蔚奶荻榷家粯佣紴?,所以若不手動(dòng)清零,則梯度會(huì)疊加起來(lái)。
    我們?cè)谠瓉?lái)的基礎(chǔ)上添加上手動(dòng)清零:

    w = torch.tensor([1.], requires_grad=True) x = torch.tensor([2.], requires_grad=True)for i in range(4):a = torch.add(w, x)b = torch.add(w, 1)y = torch.mul(a, b)y.backward()print(w.grad)w.grad.zero_()

    結(jié)果為:

    tensor([5.]) tensor([5.]) tensor([5.]) tensor([5.])

    這樣才是正確的。

    (5)小貼士2

    w = torch.tensor([1.], requires_grad=True) x = torch.tensor([2.], requires_grad=True)a = torch.add(w, x) b = torch.add(w, 1) y = torch.mul(a, b)print(a.requires_grad, b.requires_grad, y.requires_grad)

    結(jié)果為:

    True True True

    (6)小貼士3

    a = torch.ones((1, )) print(id(a), a)a += torch.ones((1, )) print(id(a), a)

    結(jié)果為:

    2379593847576 tensor([1.]) 2379593847576 tensor([2.])

    可見加等操作是in-place操作,是在原始內(nèi)存中改變數(shù)據(jù)的操作。
    而加法操作就不是,如下所示:

    a = torch.ones((1, )) print(id(a), a)a = a + torch.ones((1, )) print(id(a), a)

    內(nèi)存不一樣:

    3019154559688 tensor([1.]) 3019156480632 tensor([2.])

    如果我們對(duì)葉子結(jié)點(diǎn)進(jìn)行in-place操作:

    w = torch.tensor([1.], requires_grad=True) x = torch.tensor([2.], requires_grad=True)a = torch.add(w, x) b = torch.add(w, 1) y = torch.mul(a, b)w += torch.ones((1,)) # w.add_(1)y.backward()print(w.grad)

    會(huì)報(bào)如下錯(cuò)誤提示:

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的PyTorch框架学习四——计算图与动态图机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。