在深度学习中,我们“训练”模型,不断更新它们,使它们在看到越来越多的数据时变得越来越好。
通常情况下,变得更好意味着最小化一个损失函数(loss function),即一个衡量“模型有多糟糕”这个问题的分数。
最终,我们真正关心的是生成一个模型,它能够在从未见过的数据上表现良好。但“训练”模型只能将模型与我们实际能看到的数据相拟合。因此,我们可以将拟合模型的任务分解为两个关键问题:
- 优化(optimization):用模型拟合观测数据的过程;
- 泛化(generalization):数学原理和实践者的智慧,能够指导我们生成出有效性超出用于训练的数据集本身的模型。
导数和微分
这是几乎所有深度学习优化算法的关键步骤。
在深度学习中,我们通常选择对于模型参数可微的损失函数。简而言之,对于每个参数,如果我们把这个参数增加或减少一个无穷小的量,可以知道损失会以多快的速度增加或减少,假设我们有一个函数
f
:
R
→
R
f: \mathbb{R} \rightarrow \mathbb{R}
f:R→R,其输入和输出都是标量。
如果
f
f
f的导数存在,这个极限被定义为
f ′ ( x ) = lim h → 0 f ( x + h ) − f ( x ) h . f'(x) = \lim_{h \rightarrow 0} \frac{f(x+h) - f(x)}{h}. f′(x)=h→0limhf(x+h)−f(x).
如果
f
′
(
a
)
f'(a)
f′(a)存在,则称
f
f
f在
a
a
a处是可微(differentiable)的,如果
f
f
f在一个区间内的每个数上都是可微的,则此函数在此区间中是可微的。
我们可以将导数
f
′
(
x
)
f'(x)
f′(x)解释为
f
(
x
)
f(x)
f(x)相对于
x
x
x的瞬时(instantaneous)变化率,所谓的瞬时变化率是基于
x
x
x中的变化
h
h
h,且
h
h
h接近
0
0
0。
为了更好地解释导数,以下将做一个实验—— 定义 u = f ( x ) = 3 x 2 − 4 x u=f(x)=3x^2-4x u=f(x)=3x2−4x 如下:
import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2l
def f(x):
return 3 * x ** 2 - 4 * x
通过令
x
=
1
x=1
x=1并让
h
h
h接近
0
0
0,
f
(
x
+
h
)
−
f
(
x
)
h
\frac{f(x+h)-f(x)}{h}
hf(x+h)−f(x)的数值结果接近
2
2
2。
虽然这个实验不是一个数学证明,但稍后会看到,当
x
=
1
x=1
x=1时,导数
u
′
u'
u′是
2
2
2。
import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2l
def f(x):
return 3 * x ** 2 - 4 * x
def numerical_lim(f, x, h):
return (f(x + h) - f(x)) / h
h = 0.1
for i in range(5):
print(f'h={h:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}')
h *= 0.1
#h=0.10000, numerical limit=2.30000
#h=0.01000, numerical limit=2.03000
#h=0.00100, numerical limit=2.00300
#h=0.00010, numerical limit=2.00030
#h=0.00001, numerical limit=2.00003
让我们熟悉一下导数的几个等价符号——给定
y
=
f
(
x
)
y=f(x)
y=f(x),其中
x
x
x和
y
y
y分别是函数
f
f
f的自变量和因变量。以下表达式是等价的:
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} = \frac{d}{dx} f(x) = Df(x) = D_x f(x),
f′(x)=y′=dxdy=dxdf=dxdf(x)=Df(x)=Dxf(x),
其中符号 d d x \frac{d}{dx} dxd和 D D D是微分运算符,表示微分操作。
我们可以使用以下规则来对常见函数求微分:
- D C = 0 DC = 0 DC=0( C C C是一个常数)
- D x n = n x n − 1 Dx^n = nx^{n-1} Dxn=nxn−1(幂律(power rule), n n n是任意实数)
- 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
为了微分一个由一些常见函数组成的函数,下面的一些法则方便使用,假设函数 f f f和 g g g都是可微的, C C C是一个常数,则:
常数相乘法则
d
d
x
[
C
f
(
x
)
]
=
C
d
d
x
f
(
x
)
,
\frac{d}{dx} [Cf(x)] = C \frac{d}{dx} f(x),
dxd[Cf(x)]=Cdxdf(x),
加法法则
d d x [ f ( x ) + g ( x ) ] = d d x f ( x ) + d d x g ( x ) , \frac{d}{dx} [f(x) + g(x)] = \frac{d}{dx} f(x) + \frac{d}{dx} g(x), dxd[f(x)+g(x)]=dxdf(x)+dxdg(x),
乘法法则
d d x [ f ( x ) g ( x ) ] = f ( x ) d d x [ g ( x ) ] + g ( x ) d d x [ f ( x ) ] , \frac{d}{dx} [f(x)g(x)] = f(x) \frac{d}{dx} [g(x)] + g(x) \frac{d}{dx} [f(x)], dxd[f(x)g(x)]=f(x)dxd[g(x)]+g(x)dxd[f(x)],
除法法则
d d x [ f ( x ) g ( x ) ] = g ( x ) d d x [ f ( x ) ] − f ( x ) d d x [ g ( x ) ] [ g ( x ) ] 2 . \frac{d}{dx} \left[\frac{f(x)}{g(x)}\right] = \frac{g(x) \frac{d}{dx} [f(x)] - f(x) \frac{d}{dx} [g(x)]}{[g(x)]^2}. dxd[g(x)f(x)]=[g(x)]2g(x)dxd[f(x)]−f(x)dxd[g(x)].
现在我们可以应用上述几个法则来计算
u
′
=
f
′
(
x
)
=
3
d
d
x
x
2
−
4
d
d
x
x
=
6
x
−
4
u'=f'(x)=3\frac{d}{dx}x^2-4\frac{d}{dx}x=6x-4
u′=f′(x)=3dxdx2−4dxdx=6x−4。
令
x
=
1
x=1
x=1,我们有
u
′
=
2
u'=2
u′=2:在这个实验中,数值结果接近
2
2
2,当
x
=
1
x=1
x=1时,此导数也是曲线
u
=
f
(
x
)
u=f(x)
u=f(x)切线的斜率。
为了对导数的这种解释进行可视化,下面 将使用matplotlib
,这个Python中流行的绘图库。
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return 3 * x ** 2 - 4 * x
# def numerical_lim(f, x, h):
# return (f(x + h) - f(x)) / h
# h = 0.1
# for i in range(5):
# print(f'h={h:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}')
# h *= 0.1
# #h=0.10000, numerical limit=2.30000
# #h=0.01000, numerical limit=2.03000
# #h=0.00100, numerical limit=2.00300
# #h=0.00010, numerical limit=2.00030
# #h=0.00001, numerical limit=2.00003
def set_figsize(figsize=(3.5, 2.5)):
"""设置matplotlib的图表大小"""
plt.rcParams['figure.figsize'] = figsize
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
axes.set_title("BeYoung")
"""设置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()
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):
"""绘制数据点"""
if legend is None:
legend = []
set_figsize(figsize)
axes = axes if axes else plt.gca()
# 如果X有一个轴,输出True
def 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), X
elif 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)
plt.show()
x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
偏导数
在深度学习中,函数通常依赖于许多变量。
因此,我们需要将微分的思想推广到多元函数(multivariate function)上。
设 y = f ( x 1 , x 2 , … , x n ) y = f(x_1, x_2, \ldots, x_n) y=f(x1,x2,…,xn)是一个具有 n n n个变量的函数, y y y关于第 i i i个参数 x i x_i xi的偏导数(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 . \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}. ∂xi∂y=h→0limhf(x1,…,xi−1,xi+h,xi+1,…,xn)−f(x1,…,xi,…,xn).
为了计算 ∂ y ∂ x i \frac{\partial y}{\partial x_i} ∂xi∂y,我们可以简单地将 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看作常数,并计算 y y y关于 x i x_i xi的导数,对于偏导数的表示,以下是等价的:
∂ y ∂ x i = ∂ f ∂ x i = f x i = f i = D i f = D x i f . \frac{\partial y}{\partial x_i} = \frac{\partial f}{\partial x_i} = f_{x_i} = f_i = D_i f = D_{x_i} f. ∂xi∂y=∂xi∂f=fxi=fi=Dif=Dxif.
梯度
- 我们可以连结一个多元函数对其所有变量的偏导数,以得到该函数的梯度(gradient)向量。具体而言,设函数 f : R n → R f:\mathbb{R}^n\rightarrow\mathbb{R} f:Rn→R的输入是一个 n n n维向量 x = [ x 1 , x 2 , … , x n ] ⊤ \mathbf{x}=[x_1,x_2,\ldots,x_n]^\top x=[x1,x2,…,xn]⊤,并且输出是一个标量。
- 函数 f ( x ) f(\mathbf{x}) f(x)相对于 x \mathbf{x} x的梯度是一个包含 n n n个偏导数的向量:
- 梯度指向函数值变化最大的方向。
∇ x f ( x ) = [ ∂ f ( x ) ∂ x 1 , ∂ f ( x ) ∂ x 2 , … , ∂ f ( x ) ∂ x n ] ⊤ , \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, ∇xf(x)=[∂x1∂f(x),∂x2∂f(x),…,∂xn∂f(x)]⊤,
其中 ∇ x f ( x ) \nabla_{\mathbf{x}} f(\mathbf{x}) ∇xf(x)通常在没有歧义时被 ∇ f ( x ) \nabla f(\mathbf{x}) ∇f(x)取代。
-
假设 x \mathbf{x} x为 n n n维向量,在微分多元函数时经常使用以下规则:
- 对于所有 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 ∇xAx=A⊤
- 对于所有 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} ∇xx⊤A=A
- 对于所有 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} ∇xx⊤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=∇xx⊤x=2x
同样,对于任何矩阵 X \mathbf{X} X,都有 ∇ X ∥ X ∥ F 2 = 2 X \nabla_{\mathbf{X}} \|\mathbf{X} \|_F^2 = 2\mathbf{X} ∇X∥X∥F2=2X,梯度对于设计深度学习中的优化算法有很大用处。
链式法则
上面方法可能很难找到梯度,这是因为在深度学习中,多元函数通常是复合(composite)的,所以难以应用上述任何规则来微分这些函数。
幸运的是,链式法则可以被用来微分复合函数。
先考虑单变量函数。假设函数 y = f ( u ) y=f(u) y=f(u)和 u = g ( x ) u=g(x) u=g(x)都是可微的,根据链式法则:
d y d x = d y d u d u d x . \frac{dy}{dx} = \frac{dy}{du} \frac{du}{dx}. dxdy=dudydxdu.
现在考虑一个更一般的场景,即函数具有任意数量的变量的情况。
假设可微分函数
y
y
y有变量
u
1
,
u
2
,
…
,
u
m
u_1, u_2, \ldots, u_m
u1,u2,…,um,其中每个可微分函数
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的函数,对于任意
i
=
1
,
2
,
…
,
n
i = 1, 2, \ldots, n
i=1,2,…,n,链式法则给出:
∂ y ∂ x i = ∂ y ∂ u 1 ∂ u 1 ∂ x i + ∂ y ∂ u 2 ∂ u 2 ∂ x i + ⋯ + ∂ y ∂ u m ∂ u m ∂ x i \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} ∂xi∂y=∂u1∂y∂xi∂u1+∂u2∂y∂xi∂u2+⋯+∂um∂y∂xi∂um
小结
- 微分和积分是微积分的两个分支,前者可以应用于深度学习中的优化问题。
- 导数可以被解释为函数相对于其变量的瞬时变化率,它也是函数曲线的切线的斜率。
- 梯度是一个向量,其分量是多变量函数相对于其所有变量的偏导数。
- 链式法则可以用来微分复合函数
练习
- 绘制函数 y = f ( x ) = x 3 − 1 x y = f(x) = x^3 - \frac{1}{x} y=f(x)=x3−x1和其在 x = 1 x = 1 x=1处切线的图像。
- 求函数 f ( x ) = 3 x 1 2 + 5 e x 2 f(\mathbf{x}) = 3x_1^2 + 5e^{x_2} f(x)=3x12+5ex2的梯度。
- 函数 f ( x ) = ∥ x ∥ 2 f(\mathbf{x}) = \|\mathbf{x}\|_2 f(x)=∥x∥2的梯度是什么?
- 尝试写出函数 u = f ( x , y , z ) u = f(x, y, z) u=f(x,y,z),其中 x = x ( a , b ) x = x(a, b) x=x(a,b), y = y ( a , b ) y = y(a, b) y=y(a,b), z = z ( a , b ) z = z(a, b) z=z(a,b)的链式法则。
练习答案
- 绘制函数 y = f ( x ) = x 3 − 1 x y = f(x) = x^3 - \frac{1}{x} y=f(x)=x3−x1和其在 x = 1 x = 1 x=1处切线的图像。
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return x ** 3 - x ** -1
def set_figsize(figsize=(3.5, 2.5)):
"""设置matplotlib的图表大小"""
plt.rcParams['figure.figsize'] = figsize
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
axes.set_title("BeYoung")
"""设置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()
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):
"""绘制数据点"""
if legend is None:
legend = []
set_figsize(figsize)
axes = axes if axes else plt.gca()
# 如果X有一个轴,输出True
def 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), X
elif 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)
x = np.arange(0, 3, 0.1)
plot(x, [f(x), 4 * x - 4], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
plt.show()
- 求函数 f ( x ) = 3 x 1 2 + 5 e x 2 f(\mathbf{x}) = 3x_1^2 + 5e^{x_2} f(x)=3x12+5ex2的梯度。
{\kern 10pt} { f ′ x 1 = 6 x 1 f ′ x 2 = 5 e x 2 \begin{cases} f'\mathbf{x_1} = 6 \mathbf x_1\\f'\mathbf{x_2} = 5e^{x_2} \end{cases} {f′x1=6x1f′x2=5ex2 {\kern 50pt} ∇ f ( x ) \nabla f(\mathbf{x}) ∇f(x) = [ 6 x 1 6 \mathbf x_1 6x1, 5 e x 2 5e^{x_2} 5ex2]
- 函数
f
(
x
)
=
∥
x
∥
2
f(\mathbf{x}) = \|\mathbf{x}\|_2
f(x)=∥x∥2的梯度是什么?
设 x = ( x 1 , x 2 , x 3 , . . . , x n ) x =(x_1,x_2,x_3,...,x_n) x=(x1,x2,x3,...,xn)
{\kern 15pt} ⟹ \Longrightarrow ⟹ f ( x ) = ∥ x ∥ 2 = x 1 2 + x 2 2 + . . . + x n 2 f(x) =\|\mathbf{x}\|_2=\sqrt{x_1^2 + x_2^2 + ... +x_n^2} f(x)=∥x∥2=x12+x22+...+xn2
{\kern 15pt}
⟹
\Longrightarrow
⟹
∂
f
∂
x
=
(
∑
i
=
1
∞
x
i
2
∂
x
1
,
∑
i
=
1
∞
x
i
2
∂
x
2
,
.
.
.
,
∑
i
=
1
∞
x
i
2
∂
x
n
)
\frac{\partial f}{\partial x}= (\frac{\sqrt {\sum_{i=1}^\infty x_i^2}}{\partial x_1}, \frac{\sqrt {\sum_{i=1}^\infty x_i^2}}{\partial x_2},... ,\frac{\sqrt {\sum_{i=1}^\infty x_i^2}}{\partial x_n})
∂x∂f=(∂x1∑i=1∞xi2,∂x2∑i=1∞xi2,...,∂xn∑i=1∞xi2)
{\kern 15pt}
⟹
\Longrightarrow
⟹
∂
f
∂
x
=
(
1
2
∗
2
x
1
∗
(
∑
i
=
1
∞
x
i
2
)
−
1
2
,
1
2
∗
2
x
2
∗
(
∑
i
=
1
∞
x
i
2
)
−
1
2
,
.
.
.
,
1
2
∗
2
x
n
∗
(
∑
i
=
1
∞
x
i
2
)
−
1
2
)
\frac{\partial f}{\partial x}= (\frac{1}{2}*2x_1*(\sum_{i=1}^\infty x_i^2)^{-\frac{1}{2}},\frac{1}{2}*2x_2*(\sum_{i=1}^\infty x_i^2)^{-\frac{1}{2}},...,\frac{1}{2}*2x_n*(\sum_{i=1}^\infty x_i^2)^{-\frac{1}{2}})
∂x∂f=(21∗2x1∗(i=1∑∞xi2)−21,21∗2x2∗(i=1∑∞xi2)−21,...,21∗2xn∗(i=1∑∞xi2)−21)
{\kern 15pt}
⟹
\Longrightarrow
⟹
∂
f
∂
x
=
(
x
1
∑
i
=
1
n
x
i
2
,
x
2
∑
i
=
1
n
x
i
2
,
.
.
.
,
x
n
∑
i
=
1
n
x
i
2
)
\frac{\partial f}{\partial x}= (\frac{x_1}{\sum_{i=1}^{n}x_i^2},\frac{x_2}{\sum_{i=1}^{n}x_i^2},...,\frac{x_n}{\sum_{i=1}^{n}x_i^2})
∂x∂f=(∑i=1nxi2x1,∑i=1nxi2x2,...,∑i=1nxi2xn)
{\kern 15pt}
⟹
\Longrightarrow
⟹
∂
f
∂
x
=
(
x
1
∥
x
∥
2
,
x
2
∥
x
∥
2
,
.
.
.
,
x
n
∥
x
∥
2
)
=
x
∥
x
∥
2
\frac{\partial f}{\partial x}= (\frac{x_1}{\|\mathbf{x}\|_2},\frac{x_2}{\|\mathbf{x}\|_2},...,\frac{x_n}{\|\mathbf{x}\|_2})=\frac{x}{\|\mathbf{x}\|_2}
∂x∂f=(∥x∥2x1,∥x∥2x2,...,∥x∥2xn)=∥x∥2x
- 尝试写出函数
u
=
f
(
x
,
y
,
z
)
u = f(x, y, z)
u=f(x,y,z),其中
x
=
x
(
a
,
b
)
x = x(a, b)
x=x(a,b),
y
=
y
(
a
,
b
)
y = y(a, b)
y=y(a,b),
z
=
z
(
a
,
b
)
z = z(a, b)
z=z(a,b)的链式法则。
∂ u ∂ a = ∂ u ∂ x ∂ x ∂ a + ∂ u ∂ y ∂ y ∂ a + ∂ u ∂ z ∂ z ∂ a \frac{ \partial u}{\partial a}=\frac{ \partial u}{\partial x}\frac{ \partial x}{\partial a}+\frac{ \partial u}{\partial y}\frac{ \partial y}{\partial a}+\frac{ \partial u}{\partial z}\frac{ \partial z}{\partial a} ∂a∂u=∂x∂u∂a∂x+∂y∂u∂a∂y+∂z∂u∂a∂z
∂ u ∂ b = ∂ u ∂ x ∂ x ∂ b + ∂ u ∂ y ∂ y ∂ b + ∂ u ∂ z ∂ z ∂ b \frac{ \partial u}{\partial b}=\frac{ \partial u}{\partial x}\frac{ \partial x}{\partial b}+\frac{ \partial u}{\partial y}\frac{ \partial y}{\partial b}+\frac{ \partial u}{\partial z}\frac{ \partial z}{\partial b} ∂b∂u=∂x∂u∂b∂x+∂y∂u∂b∂y+∂z∂u∂b∂z