工信部網(wǎng)站用戶(hù)名專(zhuān)業(yè)的seo外包公司
【作者主頁(yè)】Francek Chen
【專(zhuān)欄介紹】 ? ? ?PyTorch深度學(xué)習(xí) ? ? ? 深度學(xué)習(xí) (DL, Deep Learning) 特指基于深層神經(jīng)網(wǎng)絡(luò)模型和方法的機(jī)器學(xué)習(xí)。它是在統(tǒng)計(jì)機(jī)器學(xué)習(xí)、人工神經(jīng)網(wǎng)絡(luò)等算法模型基礎(chǔ)上,結(jié)合當(dāng)代大數(shù)據(jù)和大算力的發(fā)展而發(fā)展出來(lái)的。深度學(xué)習(xí)最重要的技術(shù)特征是具有自動(dòng)提取特征的能力。神經(jīng)網(wǎng)絡(luò)算法、算力和數(shù)據(jù)是開(kāi)展深度學(xué)習(xí)的三要素。深度學(xué)習(xí)在計(jì)算機(jī)視覺(jué)、自然語(yǔ)言處理、多模態(tài)數(shù)據(jù)分析、科學(xué)探索等領(lǐng)域都取得了很多成果。本專(zhuān)欄介紹基于PyTorch的深度學(xué)習(xí)算法實(shí)現(xiàn)。
【GitCode】專(zhuān)欄資源保存在我的GitCode倉(cāng)庫(kù):https://gitcode.com/Morse_Chen/PyTorch_deep_learning。
文章目錄
- 一、導(dǎo)數(shù)和微分
- 二、偏導(dǎo)數(shù)
- 三、梯度
- 四、鏈?zhǔn)椒▌t
- 小結(jié)
??在2500年前,古希臘人把一個(gè)多邊形分成三角形,并把它們的面積相加,才找到計(jì)算多邊形面積的方法。為了求出曲線形狀(比如圓)的面積,古希臘人在這樣的形狀上刻內(nèi)接多邊形。如圖1所示,內(nèi)接多邊形的等長(zhǎng)邊越多,就越接近圓。這個(gè)過(guò)程也被稱(chēng)為逼近法(method of exhaustion)。
??事實(shí)上,逼近法就是積分(integral calculus)的起源。2000多年后,微積分的另一支,微分(differential calculus)被發(fā)明出來(lái)。在微分學(xué)最重要的應(yīng)用是優(yōu)化問(wèn)題,即考慮如何把事情做到最好。正如在【深度學(xué)習(xí)基礎(chǔ)】深度學(xué)習(xí)導(dǎo)論 中討論的那樣,這種問(wèn)題在深度學(xué)習(xí)中是無(wú)處不在的。
??在深度學(xué)習(xí)中,我們“訓(xùn)練”模型,不斷更新它們,使它們?cè)诳吹皆絹?lái)越多的數(shù)據(jù)時(shí)變得越來(lái)越好。通常情況下,變得更好意味著最小化一個(gè)損失函數(shù)(loss function),即一個(gè)衡量“模型有多糟糕”這個(gè)問(wèn)題的分?jǐn)?shù)。最終,我們真正關(guān)心的是生成一個(gè)模型,它能夠在從未見(jiàn)過(guò)的數(shù)據(jù)上表現(xiàn)良好。但“訓(xùn)練”模型只能將模型與我們實(shí)際能看到的數(shù)據(jù)相擬合。因此,我們可以將擬合模型的任務(wù)分解為兩個(gè)關(guān)鍵問(wèn)題:
- 優(yōu)化(optimization):用模型擬合觀測(cè)數(shù)據(jù)的過(guò)程;
- 泛化(generalization):數(shù)學(xué)原理和實(shí)踐者的智慧,能夠指導(dǎo)我們生成出有效性超出用于訓(xùn)練的數(shù)據(jù)集本身的模型。
??為了幫助讀者在后面的章節(jié)中更好地理解優(yōu)化問(wèn)題和方法,本節(jié)提供了一個(gè)非常簡(jiǎn)短的入門(mén)教程,幫助讀者快速掌握深度學(xué)習(xí)中常用的微分知識(shí)。
一、導(dǎo)數(shù)和微分
??我們首先討論導(dǎo)數(shù)的計(jì)算,這是幾乎所有深度學(xué)習(xí)優(yōu)化算法的關(guān)鍵步驟。在深度學(xué)習(xí)中,我們通常選擇對(duì)于模型參數(shù)可微的損失函數(shù)。簡(jiǎn)而言之,對(duì)于每個(gè)參數(shù),如果我們把這個(gè)參數(shù)增加或減少一個(gè)無(wú)窮小的量,可以知道損失會(huì)以多快的速度增加或減少。
??假設(shè)我們有一個(gè)函數(shù) f : R → R f: \mathbb{R} \rightarrow \mathbb{R} f:R→R,其輸入和輸出都是標(biāo)量。如果 f f f的導(dǎo)數(shù)存在,這個(gè)極限被定義為
f ′ ( x ) = lim ? h → 0 f ( x + h ) ? f ( x ) h (1) f'(x) = \lim_{h \rightarrow 0} \frac{f(x+h) - f(x)}{h}\tag{1} f′(x)=h→0lim?hf(x+h)?f(x)?(1)
??如果 f ′ ( a ) f'(a) f′(a)存在,則稱(chēng) f f f在 a a a處是可微(differentiable)的。如果 f f f在一個(gè)區(qū)間內(nèi)的每個(gè)數(shù)上都是可微的,則此函數(shù)在此區(qū)間中是可微的。我們可以將式(1)中的導(dǎo)數(shù) f ′ ( x ) f'(x) f′(x)解釋為 f ( x ) f(x) f(x)相對(duì)于 x x x的瞬時(shí)(instantaneous)變化率。所謂的瞬時(shí)變化率是基于 x x x中的變化 h h h,且 h h h接近 0 0 0。
??為了更好地解釋導(dǎo)數(shù),讓我們做一個(gè)實(shí)驗(yàn)。定義 u = f ( x ) = 3 x 2 ? 4 x u=f(x)=3x^2-4x u=f(x)=3x2?4x 如下:
%matplotlib inline
import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2ldef f(x):return 3 * x ** 2 - 4 * x
??通過(guò)令 x = 1 x=1 x=1并讓 h h h接近 0 0 0,式(1)中 f ( x + h ) ? f ( x ) h \frac{f(x+h)-f(x)}{h} hf(x+h)?f(x)?的數(shù)值結(jié)果接近 2 2 2。雖然這個(gè)實(shí)驗(yàn)不是一個(gè)數(shù)學(xué)證明,但稍后會(huì)看到,當(dāng) x = 1 x=1 x=1時(shí),導(dǎo)數(shù) u ′ u' u′是 2 2 2。
def numerical_lim(f, x, h):return (f(x + h) - f(x)) / hh = 0.1
for i in range(5):print(f'h={h:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}')h *= 0.1
??讓我們熟悉一下導(dǎo)數(shù)的幾個(gè)等價(jià)符號(hào)。給定 y = f ( x ) y=f(x) y=f(x),其中 x x x和 y y y分別是函數(shù) f f f的自變量和因變量。以下表達(dá)式是等價(jià)的:
f ′ ( x ) = y ′ = d y d x = d f d x = d d x f ( x ) = D f ( x ) = D x f ( x ) f'(x) = y' = \frac{dy}{dx} = \frac{df}{dx} = \fracvxwlu0yf4{dx} f(x) = Df(x) = D_x f(x) f′(x)=y′=dxdy?=dxdf?=dxd?f(x)=Df(x)=Dx?f(x) 其中符號(hào) d d x \fracvxwlu0yf4{dx} dxd?和 D D D是微分運(yùn)算符,表示微分操作。我們可以使用以下規(guī)則來(lái)對(duì)常見(jiàn)函數(shù)求微分:
- D C = 0 DC = 0 DC=0( C C C是一個(gè)常數(shù))
- D x n = n x n ? 1 Dx^n = nx^{n-1} Dxn=nxn?1(冪律(power rule), n n n是任意實(shí)數(shù))
- D e x = e x De^x = e^x Dex=ex
- D ln ? ( x ) = 1 / x D\ln(x) = 1/x Dln(x)=1/x
??為了微分一個(gè)由一些常見(jiàn)函數(shù)組成的函數(shù),下面的一些法則方便使用。假設(shè)函數(shù) f f f和 g g g都是可微的, C C C是一個(gè)常數(shù),則:
常數(shù)相乘法則
d d x [ C f ( x ) ] = C d d x f ( x ) , (2) \fracvxwlu0yf4{dx} [Cf(x)] = C \fracvxwlu0yf4{dx} f(x),\tag{2} dxd?[Cf(x)]=Cdxd?f(x),(2)
加法法則
d d x [ f ( x ) + g ( x ) ] = d d x f ( x ) + d d x g ( x ) , (3) \fracvxwlu0yf4{dx} [f(x) + g(x)] = \fracvxwlu0yf4{dx} f(x) + \fracvxwlu0yf4{dx} g(x),\tag{3} dxd?[f(x)+g(x)]=dxd?f(x)+dxd?g(x),(3)
乘法法則
d d x [ f ( x ) g ( x ) ] = f ( x ) d d x [ g ( x ) ] + g ( x ) d d x [ f ( x ) ] , (4) \fracvxwlu0yf4{dx} [f(x)g(x)] = f(x) \fracvxwlu0yf4{dx} [g(x)] + g(x) \fracvxwlu0yf4{dx} [f(x)],\tag{4} dxd?[f(x)g(x)]=f(x)dxd?[g(x)]+g(x)dxd?[f(x)],(4)
除法法則
d d x [ f ( x ) g ( x ) ] = g ( x ) d d x [ f ( x ) ] ? f ( x ) d d x [ g ( x ) ] [ g ( x ) ] 2 . (5) \fracvxwlu0yf4{dx} \left[\frac{f(x)}{g(x)}\right] = \frac{g(x) \fracvxwlu0yf4{dx} [f(x)] - f(x) \fracvxwlu0yf4{dx} [g(x)]}{[g(x)]^2}.\tag{5} dxd?[g(x)f(x)?]=[g(x)]2g(x)dxd?[f(x)]?f(x)dxd?[g(x)]?.(5)
??現(xiàn)在我們可以應(yīng)用上述幾個(gè)法則來(lái)計(jì)算 u ′ = f ′ ( x ) = 3 d d x x 2 ? 4 d d x x = 6 x ? 4 u'=f'(x)=3\fracvxwlu0yf4{dx}x^2-4\fracvxwlu0yf4{dx}x=6x-4 u′=f′(x)=3dxd?x2?4dxd?x=6x?4。令 x = 1 x=1 x=1,我們有 u ′ = 2 u'=2 u′=2:在這個(gè)實(shí)驗(yàn)中,數(shù)值結(jié)果接近 2 2 2,這一點(diǎn)得到了在本節(jié)前面的實(shí)驗(yàn)的支持。當(dāng) x = 1 x=1 x=1時(shí),此導(dǎo)數(shù)也是曲線 u = f ( x ) u=f(x) u=f(x)切線的斜率。
??為了對(duì)導(dǎo)數(shù)的這種解釋進(jìn)行可視化,我們將使用matplotlib
,這是一個(gè)Python中流行的繪圖庫(kù)。要配置matplotlib
生成圖形的屬性,我們需要定義幾個(gè)函數(shù)。在下面,use_svg_display
函數(shù)指定matplotlib
軟件包輸出svg圖表以獲得更清晰的圖像。
??注意,注釋#@save
是一個(gè)特殊的標(biāo)記,會(huì)將對(duì)應(yīng)的函數(shù)、類(lèi)或語(yǔ)句保存在d2l
包中。因此,以后無(wú)須重新定義就可以直接調(diào)用它們(例如,d2l.use_svg_display()
)。
def use_svg_display(): #@save"""使用svg格式在Jupyter中顯示繪圖"""backend_inline.set_matplotlib_formats('svg')
??我們定義set_figsize
函數(shù)來(lái)設(shè)置圖表大小。注意,這里可以直接使用d2l.plt
,因?yàn)閷?dǎo)入語(yǔ)句from matplotlib import pyplot as plt
已標(biāo)記為保存到d2l
包中。
def set_figsize(figsize=(3.5, 2.5)): #@save"""設(shè)置matplotlib的圖表大小"""use_svg_display()d2l.plt.rcParams['figure.figsize'] = figsize
??下面的set_axes
函數(shù)用于設(shè)置由matplotlib
生成圖表的軸的屬性。
#@save
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):"""設(shè)置matplotlib的軸"""axes.set_xlabel(xlabel)axes.set_ylabel(ylabel)axes.set_xscale(xscale)axes.set_yscale(yscale)axes.set_xlim(xlim)axes.set_ylim(ylim)if legend:axes.legend(legend)axes.grid()
??通過(guò)這三個(gè)用于圖形配置的函數(shù),定義一個(gè)plot
函數(shù)來(lái)簡(jiǎn)潔地繪制多條曲線,因?yàn)槲覀冃枰谡麄€(gè)書(shū)中可視化許多曲線。
#@save
def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):"""繪制數(shù)據(jù)點(diǎn)"""if legend is None:legend = []set_figsize(figsize)axes = axes if axes else d2l.plt.gca()# 如果X有一個(gè)軸,輸出Truedef has_one_axis(X):return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)and not hasattr(X[0], "__len__"))if has_one_axis(X):X = [X]if Y is None:X, Y = [[]] * len(X), Xelif has_one_axis(Y):Y = [Y]if len(X) != len(Y):X = X * len(Y)axes.cla()for x, y, fmt in zip(X, Y, fmts):if len(x):axes.plot(x, y, fmt)else:axes.plot(y, fmt)set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
??現(xiàn)在我們可以繪制函數(shù) u = f ( x ) u=f(x) u=f(x)及其在 x = 1 x=1 x=1處的切線 y = 2 x ? 3 y=2x-3 y=2x?3,其中系數(shù) 2 2 2是切線的斜率。
x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
二、偏導(dǎo)數(shù)
??到目前為止,我們只討論了僅含一個(gè)變量的函數(shù)的微分。在深度學(xué)習(xí)中,函數(shù)通常依賴(lài)于許多變量。因此,我們需要將微分的思想推廣到多元函數(shù)(multivariate function)上。
??設(shè) y = f ( x 1 , x 2 , … , x n ) y = f(x_1, x_2, \ldots, x_n) y=f(x1?,x2?,…,xn?)是一個(gè)具有 n n n個(gè)變量的函數(shù)。 y y y關(guān)于第 i i i個(gè)參數(shù) x i x_i xi?的偏導(dǎo)數(shù)(partial derivative)為:
? y ? x i = lim ? h → 0 f ( x 1 , … , x i ? 1 , x i + h , x i + 1 , … , x n ) ? f ( x 1 , … , x i , … , x n ) h (6) \frac{\partial y}{\partial x_i} = \lim_{h \rightarrow 0} \frac{f(x_1, \ldots, x_{i-1}, x_i+h, x_{i+1}, \ldots, x_n) - f(x_1, \ldots, x_i, \ldots, x_n)}{h}\tag{6} ?xi??y?=h→0lim?hf(x1?,…,xi?1?,xi?+h,xi+1?,…,xn?)?f(x1?,…,xi?,…,xn?)?(6)
??為了計(jì)算 ? y ? x i \frac{\partial y}{\partial x_i} ?xi??y?,我們可以簡(jiǎn)單地將 x 1 , … , x i ? 1 , x i + 1 , … , x n x_1, \ldots, x_{i-1}, x_{i+1}, \ldots, x_n x1?,…,xi?1?,xi+1?,…,xn?看作常數(shù),并計(jì)算 y y y關(guān)于 x i x_i xi?的導(dǎo)數(shù)。對(duì)于偏導(dǎo)數(shù)的表示,以下是等價(jià)的:
? y ? x i = ? f ? x i = f x i = f i = D i f = D x i f (7) \frac{\partial y}{\partial x_i} = \frac{\partial f}{\partial x_i} = f_{x_i} = f_i = D_i f = D_{x_i} f\tag{7} ?xi??y?=?xi??f?=fxi??=fi?=Di?f=Dxi??f(7)
三、梯度
??我們可以連結(jié)一個(gè)多元函數(shù)對(duì)其所有變量的偏導(dǎo)數(shù),以得到該函數(shù)的梯度(gradient)向量。具體而言,設(shè)函數(shù) f : R n → R f:\mathbb{R}^n\rightarrow\mathbb{R} f:Rn→R的輸入是一個(gè) n n n維向量 x = [ x 1 , x 2 , … , x n ] ? \mathbf{x}=[x_1,x_2,\ldots,x_n]^\top x=[x1?,x2?,…,xn?]?,并且輸出是一個(gè)標(biāo)量。函數(shù) f ( x ) f(\mathbf{x}) f(x)相對(duì)于 x \mathbf{x} x的梯度是一個(gè)包含 n n n個(gè)偏導(dǎo)數(shù)的向量:
? x f ( x ) = [ ? f ( x ) ? x 1 , ? f ( x ) ? x 2 , … , ? f ( x ) ? x n ] ? (8) \nabla_{\mathbf{x}} f(\mathbf{x}) = \bigg[\frac{\partial f(\mathbf{x})}{\partial x_1}, \frac{\partial f(\mathbf{x})}{\partial x_2}, \ldots, \frac{\partial f(\mathbf{x})}{\partial x_n}\bigg]^\top\tag{8} ?x?f(x)=[?x1??f(x)?,?x2??f(x)?,…,?xn??f(x)?]?(8) 其中 ? x f ( x ) \nabla_{\mathbf{x}} f(\mathbf{x}) ?x?f(x)通常在沒(méi)有歧義時(shí)被 ? f ( x ) \nabla f(\mathbf{x}) ?f(x)取代。
假設(shè) x \mathbf{x} x為 n n n維向量,在微分多元函數(shù)時(shí)經(jīng)常使用以下規(guī)則:
- 對(duì)于所有 A ∈ R m × n \mathbf{A} \in \mathbb{R}^{m \times n} A∈Rm×n,都有 ? x A x = A ? \nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top ?x?Ax=A?
- 對(duì)于所有 A ∈ R n × m \mathbf{A} \in \mathbb{R}^{n \times m} A∈Rn×m,都有 ? x x ? A = A \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A} ?x?x?A=A
- 對(duì)于所有 A ∈ R n × n \mathbf{A} \in \mathbb{R}^{n \times n} A∈Rn×n,都有 ? x x ? A x = ( A + A ? ) x \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x} ?x?x?Ax=(A+A?)x
- ? x ∥ x ∥ 2 = ? x x ? x = 2 x \nabla_{\mathbf{x}} \|\mathbf{x} \|^2 = \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{x} = 2\mathbf{x} ?x?∥x∥2=?x?x?x=2x
??同樣,對(duì)于任何矩陣 X \mathbf{X} X,都有 ? X ∥ X ∥ F 2 = 2 X \nabla_{\mathbf{X}} \|\mathbf{X} \|_F^2 = 2\mathbf{X} ?X?∥X∥F2?=2X。正如我們之后將看到的,梯度對(duì)于設(shè)計(jì)深度學(xué)習(xí)中的優(yōu)化算法有很大用處。
四、鏈?zhǔn)椒▌t
??然而,上面方法可能很難找到梯度。這是因?yàn)樵谏疃葘W(xué)習(xí)中,多元函數(shù)通常是復(fù)合(composite)的,所以難以應(yīng)用上述任何規(guī)則來(lái)微分這些函數(shù)。幸運(yùn)的是,鏈?zhǔn)椒▌t可以被用來(lái)微分復(fù)合函數(shù)。
??讓我們先考慮單變量函數(shù)。假設(shè)函數(shù) y = f ( u ) y=f(u) y=f(u)和 u = g ( x ) u=g(x) u=g(x)都是可微的,根據(jù)鏈?zhǔn)椒▌t:
d y d x = d y d u d u d x (9) \frac{dy}{dx} = \frac{dy}{du} \frac{du}{dx}\tag{9} dxdy?=dudy?dxdu?(9) 現(xiàn)在考慮一個(gè)更一般的場(chǎng)景,即函數(shù)具有任意數(shù)量的變量的情況。假設(shè)可微分函數(shù) y y y有變量 u 1 , u 2 , … , u m u_1, u_2, \ldots, u_m u1?,u2?,…,um?,其中每個(gè)可微分函數(shù) u i u_i ui?都有變量 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1?,x2?,…,xn?。注意, y y y是 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1?,x2?,…,xn?的函數(shù)。對(duì)于任意 i = 1 , 2 , … , n i = 1, 2, \ldots, n i=1,2,…,n,鏈?zhǔn)椒▌t給出:
? y ? x i = ? y ? u 1 ? u 1 ? x i + ? y ? u 2 ? u 2 ? x i + ? + ? y ? u m ? u m ? x i (10) \frac{\partial y}{\partial x_i} = \frac{\partial y}{\partial u_1} \frac{\partial u_1}{\partial x_i} + \frac{\partial y}{\partial u_2} \frac{\partial u_2}{\partial x_i} + \cdots + \frac{\partial y}{\partial u_m} \frac{\partial u_m}{\partial x_i}\tag{10} ?xi??y?=?u1??y??xi??u1??+?u2??y??xi??u2??+?+?um??y??xi??um??(10)
小結(jié)
- 微分和積分是微積分的兩個(gè)分支,前者可以應(yīng)用于深度學(xué)習(xí)中的優(yōu)化問(wèn)題。
- 導(dǎo)數(shù)可以被解釋為函數(shù)相對(duì)于其變量的瞬時(shí)變化率,它也是函數(shù)曲線的切線的斜率。
- 梯度是一個(gè)向量,其分量是多變量函數(shù)相對(duì)于其所有變量的偏導(dǎo)數(shù)。
- 鏈?zhǔn)椒▌t可以用來(lái)微分復(fù)合函數(shù)。