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

深度學(xué)習(xí)如何自動(dòng)微分

人工智能 深度學(xué)習(xí)
在深度學(xué)習(xí)中,求導(dǎo)幾乎是所有優(yōu)化算法的關(guān)鍵步驟,但是對(duì)于單個(gè)值的求導(dǎo)比較簡(jiǎn)單,但是如果對(duì)于模型訓(xùn)練過程中每次都需要手動(dòng)求導(dǎo)就很麻煩,因此深度學(xué)習(xí)框架都提供了自動(dòng)導(dǎo)數(shù)(自動(dòng)微分)。

在深度學(xué)習(xí)中,求導(dǎo)幾乎是所有優(yōu)化算法的關(guān)鍵步驟,但是對(duì)于單個(gè)值的求導(dǎo)比較簡(jiǎn)單,但是如果對(duì)于模型訓(xùn)練過程中每次都需要手動(dòng)求導(dǎo)就很麻煩,因此深度學(xué)習(xí)框架都提供了自動(dòng)導(dǎo)數(shù)(自動(dòng)微分)。

1、PyTorch自動(dòng)微分

對(duì)函數(shù) y = 2X^X 求導(dǎo)(其中X為列向量,這里表示兩段列向量做矩陣乘法),其中PyTorch自動(dòng)微分的代碼如下:

import torch
x = torch.arange(4.0)
print("x: ", x)
x.requires_grad_(True)  # 等價(jià)于x=torch.arange(4.0,requires_grad=True)
print("x.grad: ", x.grad)
y = 2 * torch.dot(x, x)
print("y: ", y)
y.backward()
print("x.grad: ", x.grad)

1、先給x賦值 tensor([0., 1., 2., 3.]) ;2、將x設(shè)置為自動(dòng)微分 ;3、賦值y表達(dá)式,計(jì)算y的值,結(jié)果:tensor(28., grad_fn=<MulBackward0>);4、y.backward() 調(diào)用反向傳播函數(shù)來自動(dòng)計(jì)算y關(guān)于x每個(gè)分量的梯度,并打印這些梯度;

輸出結(jié)果:tensor([ 0., 4., 8., 12.]) 和 y = 4X 的導(dǎo)數(shù)是一樣的。

2、如何自動(dòng)微分

自動(dòng)微分開源實(shí)現(xiàn)很多,其中類似 PyTorch 的 API 包括 karpathy 開源的 https://github.com/karpathy/micrograd 和 https://github.com/tinygrad/tinygrad,這里為了簡(jiǎn)單借鑒 micrograd,重寫部分代碼實(shí)現(xiàn)自動(dòng)微分。

2.1 前向傳播

微分需要支持多個(gè)基礎(chǔ)運(yùn)算,如+,-,*,/,power等,代碼如下:

class Value:
    def __init__(self, data, _children=(), _op=''):
        self.data = data
        self.grad = 0
        self._prev = set(_children)
        self._op = _op

    def __add__(self, other):
        other = other if isinstance(other, Value) else Value(other)
        out = Value(self.data + other.data, (self, other), '+')
        return out

    def __mul__(self, other):
        other = other if isinstance(other, Value) else Value(other)
        out = Value(self.data * other.data, (self, other), '*')
        return out

    def __pow__(self, other):
        assert isinstance(other, (int, float)), "only supporting int/float powers for now"
        out = Value(self.data**other, (self,), f'**{other}')
        return out

    def relu(self):
        out = Value(0 if self.data < 0 else self.data, (self,), 'ReLU')
        return out

    def __neg__(self): # -self
        return self * -1

    def __radd__(self, other): # other + self
        return self + other

    def __sub__(self, other): # self - other
        return self + (-other)

    def __rsub__(self, other): # other - self
        return other + (-self)

    def __rmul__(self, other): # other * self
        return self * other

    def __truediv__(self, other): # self / other
        return self * other**-1

    def __rtruediv__(self, other): # other / self
        return other * self**-1

    def __repr__(self):
        return f"Value(data={self.data}, grad={self.grad})"

那么表達(dá)式 a * b + c + d**2,按照賦值變量的運(yùn)行:

a = Value(2.0)
b = Value(-3.0)
c = Value(10.0)
d = Value(2.0)
d = a * b + c
z = d + f**2
print("z: ", z)

結(jié)果:Value(data=8.0, grad=0),同時(shí)按照前向傳播路徑畫圖如下:

前向傳播前向傳播

2.2 反向傳播

在反向傳播的過程,本質(zhì)是求網(wǎng)絡(luò)的每個(gè)參數(shù)關(guān)于最終損失函數(shù)的梯度,而該梯度可以成是回傳的全局梯度和局部梯度之乘。
其中梯度代表了當(dāng)前層參數(shù)的變化,對(duì)最終預(yù)測(cè)損失的影響(變化率),而該變化率實(shí)際取決于當(dāng)前層參數(shù)對(duì)下一層輸入的影響,以及下一層輸入對(duì)最終預(yù)測(cè)損失的影響,兩個(gè)變化一乘,就是當(dāng)前層參數(shù)對(duì)最終預(yù)測(cè)損失的影響。

那么反向傳播的代碼實(shí)現(xiàn)就是要將每個(gè)變量與表達(dá)式的結(jié)果關(guān)聯(lián),根據(jù)微積分的鏈?zhǔn)椒▌t(https://zh.wikipedia.org/wiki/%E9%93%BE%E5%BC%8F%E6%B3%95%E5%88%99),如果變量 z 依賴于變量 y,而變量 y 又依賴于變量 x(即 y 和 z 是因變量),那么 z 也通過中間變量 y 來依賴于 x,其中 c = 2 * a; d = c + b; 推倒如下:

c = 2 * a 
d = c + b

求導(dǎo)數(shù) dd/da 可以根據(jù)微分傳遞性轉(zhuǎn)換 dd/dc * dc/da
那么 dd/dc = 1(加法的導(dǎo)數(shù)是常數(shù)),dc/da = 2(乘法的導(dǎo)數(shù)對(duì)應(yīng)是2),所以 dd/da = 2

根據(jù)前向傳播的代碼添加反向傳播:

class Value:
    def __init__(self, data, _children=(), _op=''):
        self.data = data
        self.grad = 0
        self._backward = lambda: None
        self._prev = set(_children)
        self._op = _op

    def __add__(self, other):
        other = other if isinstance(other, Value) else Value(other)
        out = Value(self.data + other.data, (self, other), '+')

        def _backward():
            self.grad += out.grad
            other.grad += out.grad
        out._backward = _backward

        return out

    def __mul__(self, other):
        other = other if isinstance(other, Value) else Value(other)
        out = Value(self.data * other.data, (self, other), '*')

        def _backward():
            self.grad += other.data * out.grad
            other.grad += self.data * out.grad
        out._backward = _backward

        return out

    def __pow__(self, other):
        assert isinstance(other, (int, float)), "only supporting int/float powers for now"
        out = Value(self.data**other, (self,), f'**{other}')

        def _backward():
            self.grad += (other * self.data**(other-1)) * out.grad
        out._backward = _backward

        return out

    def relu(self):
        out = Value(0 if self.data < 0 else self.data, (self,), 'ReLU')

        def _backward():
            self.grad += (out.data > 0) * out.grad
        out._backward = _backward

        return out
    
    def backward(self):
        topo = []
        visited = set()
        
        def build_topo(v):
            if v not in visited:
                visited.add(v)
                for child in v._prev:
                    build_topo(child)
                topo.append(v)
        build_topo(self)

        self.grad = 1
        for v in reversed(topo):
            v._backward()

其中 backward 遍歷所有孩子節(jié)點(diǎn),然后 reversed 計(jì)算每個(gè)_backward,那么表達(dá)式 a * b + c + d**2,按照賦值變量的運(yùn)行:

a = Value(2.0)
b = Value(-3.0)
c = Value(10.0)
f = Value(2.0)
d = a * b + c
z = d + f**2
z.backward()
print("a: ", a.grad)

結(jié)果:a:-3.0,同時(shí)按照反向傳播路徑畫圖如下:

反向傳播反向傳播

3、總結(jié)

以上就是構(gòu)造自動(dòng)微分的代碼,功能比較簡(jiǎn)單,主要是理解梯度的計(jì)算方法,并計(jì)算各個(gè)計(jì)算變量在圖節(jié)點(diǎn)上的關(guān)系。

責(zé)任編輯:華軒 來源: 周末程序猿
相關(guān)推薦

2020-11-06 10:36:39

自動(dòng)駕駛

2017-08-03 16:20:42

深度學(xué)習(xí)文本摘要遞歸神經(jīng)網(wǎng)絡(luò)

2018-03-23 09:29:56

深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)前端設(shè)計(jì)模型

2017-05-17 15:09:06

深度學(xué)習(xí)人工智能

2010-04-27 18:18:55

AIX微分區(qū)

2016-12-27 14:06:36

Python代碼基礎(chǔ)

2020-11-04 07:10:42

深度學(xué)習(xí)DJL 語言

2023-08-17 14:22:17

深度學(xué)習(xí)機(jī)器學(xué)習(xí)

2017-08-03 11:00:20

2018-01-08 07:58:51

深度學(xué)習(xí)編程人工智能

2018-05-06 15:51:22

2023-03-26 20:43:45

2021-01-18 10:42:36

深度學(xué)習(xí)知識(shí)圖譜

2020-11-13 15:38:12

深度學(xué)習(xí)編程人工智能

2021-07-01 08:00:00

深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)架構(gòu)

2021-03-08 11:28:59

人工智能深度學(xué)習(xí)Python

2017-07-30 15:16:31

深度強(qiáng)化學(xué)習(xí)遷移交叉路口

2017-09-24 12:13:52

深度學(xué)習(xí)自動(dòng)編碼器機(jī)器學(xué)習(xí)

2017-03-18 16:28:40

人工智能機(jī)器學(xué)習(xí)深度學(xué)習(xí)

2023-09-12 16:20:04

邊緣AI深度學(xué)習(xí)
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 午夜大片| 成人性视频免费网站 | 四虎海外| 一区二区三区四区在线播放 | 久久综合香蕉 | 欧美一区2区三区4区公司 | 国产精品1区| 视频一区在线观看 | 亚洲男人天堂av | 国产精品视频在线播放 | 久久久国产精品 | 久久久久久久一区二区 | 日韩中文字幕高清 | 国产精品久久久久久妇女 | 一区二区在线看 | 91久操视频 | 久久久久亚洲精品 | www.亚洲免费 | 成人夜晚看av | 欧美一区二区三区在线观看 | 在线日韩精品视频 | 日本午夜在线视频 | 成人三级av | 久久99这里只有精品 | 影音av | 欧美精品第一区 | 91精品国产一区二区三区动漫 | 午夜无码国产理论在线 | 99re国产精品 | 欧美精品一区二区三区在线 | 91观看 | 91社区在线观看高清 | 欧美在线观看一区 | 国产一级片一区二区三区 | 欧美精品在欧美一区二区 | 久久久久久久久久久蜜桃 | 国产精品永久免费视频 | 欧美综合一区二区 | 亚洲一区国产精品 | 日韩精品色网 | 成人免费视频网站在线看 |