动态计算图
计算图可以用来表示两个变量之间的关系。例如,构建
y
=
x
2
y=x^2
y=x2,则可用一张简单计算图进行表示。
pytorch支持动态计算图,动态意义在于,当创建其它由计算图中变量而来的新变量时,新变量会自动添加到计算图内。
而Tensorflow v1仅支持静态计算图,需要提前定义各个变量的关系,灵活性不如动态计算图。
反向传播
通过反向传播,可以计算各变量的导数。
x = torch.tensor(1.,requires_grad = True) #requires_grad=True表示x可导
y = x ** 2
y.backward()
# 在y=x**2函数关系基础上,x取值为1时的导数值
x.grad
输出:
tensor(2.)
梯度下降
梯度下降的代数表示
令多元线性回归方程为
f
(
x
)
=
w
1
x
1
+
w
2
x
2
+
.
.
.
+
w
d
x
d
+
b
f(x) = w_1x_1+w_2x_2+...+w_dx_d+b
f(x)=w1x1+w2x2+...+wdxd+b
令
w
^
=
(
w
1
,
w
2
,
.
.
.
,
w
d
,
b
)
\hat w = (w_1,w_2,...,w_d,b)
w^=(w1,w2,...,wd,b)
x
^
=
(
x
1
,
x
2
,
.
.
.
,
x
d
,
1
)
\hat x = (x_1,x_2,...,x_d,1)
x^=(x1,x2,...,xd,1)
出于加快迭代收敛速度的目标,我们在定义梯度下降的损失函数L时,在原SSE基础上进行比例修正,新的损失函数 L ( w 1 , w 2 , . . . , w d , b ) = 1 2 m S S E L(w_1,w_2,...,w_d,b) = \frac{1}{2m}SSE L(w1,w2,...,wd,b)=2m1SSE,其中,m为样本个数。
损失函数有:
L ( w 1 , w 2 , . . . , w d , b ) = 1 2 m ∑ j = 0 m ( f ( x 1 ( j ) , x 2 ( j ) , . . . 1 ) − y j ) 2 L(w_1,w_2,...,w_d,b) = \frac{1}{2m}\sum_{j=0}^{m}(f(x_1^{(j)}, x_2^{(j)}, ...1) - y_j)^2 L(w1,w2,...,wd,b)=2m1j=0∑m(f(x1(j),x2(j),...1)−yj)2
并且,根据此前描述过程,在开始梯度下降求解参数之前,我们首先需要设置一组参数的初始取值 ( w 1 , w 2 . . . , w d , b ) (w_1, w_2..., w_d, b) (w1,w2...,wd,b),以及学习率 α \alpha α,然后即可执行迭代运算,其中每一轮迭代过程需要执行以下三步
Step 1.计算梯度表达式
对于任意一个参数 w i w_i wi,其梯度计算表达式如下:
∂ ∂ w i L ( w 1 , w 2 . . . , w d , b ) \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) ∂wi∂L(w1,w2...,wd,b)
Step 2.用学习率乘以损失函数梯度,得到迭代移动距离
α ∂ ∂ w i L ( w 1 , w 2 . . . , w d , b ) \alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) α∂wi∂L(w1,w2...,wd,b)
Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w
w i = w i − α ∂ ∂ w i L ( w 1 , w 2 . . . , w d , b ) w_i = w_i - \alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) wi=wi−α∂wi∂L(w1,w2...,wd,b)
更新完所有参数,即完成了一轮的迭代,接下来就能以新的一组 w i w_i wi参与下一轮迭代。
举例说明
有数据集表示如下:
x | y |
---|---|
1 | 2 |
2 | 4 |
3 | 6 |
假设,我们使用 y = w x y = wx y=wx进行拟合,则SSE为:
S S E = ( 2 − 1 ∗ w ) 2 + ( 4 − 2 ∗ w ) 2 + ( 6 − 3 ∗ w ) 2 = w 2 − 4 w + 4 + 4 w 2 − 16 w + 16 + 9 w 2 − 36 w + 36 = 14 w 2 − 56 w + 56 = 14 ( w 2 − 4 w + 4 ) SSE = (2-1*w)^2 + (4-2*w)^2 + (6-3*w)^2 \\ = w^2-4w+4+4w^2-16w+16+9w^2-36w+36 \\ = 14w^2-56w+56 \\ = 14(w^2-4w+4) SSE=(2−1∗w)2+(4−2∗w)2+(6−3∗w)2=w2−4w+4+4w2−16w+16+9w2−36w+36=14w2−56w+56=14(w2−4w+4)
此时,SSE就是一个关于w的一元函数。当使用最小二乘法进行求解时,SSE就是损失函数,并且SSE对于w求导为0的点就是最小值点,因此有:
∂ S S E ( a ) ∂ ( a ) = 14 ( 2 w − 4 ) = 28 ( w − 2 ) = 0 \frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) = 0 ∂(a)∂SSE(a)=14(2w−4)=28(w−2)=0
w = 2 w=2 w=2
但我们使用梯度下降求解时:
g r a d ∗ = ∂ S S E ( a ) ∂ ( a ) = 14 ( 2 w − 4 ) = 28 ( w − 2 ) grad^* = \frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) grad∗=∂(a)∂SSE(a)=14(2w−4)=28(w−2)
由于梯度表示方向,在某些情况下我们可以对其绝对数值进行一定程度上的“缩放”,此时我们规定有效梯度是原梯度的1/28,则有
g r a d = w − 2 grad = w-2 grad=w−2
设步长$\alpha= 0.5 , 初 始 值 点 取 为 0.5,初始值点取为 0.5,初始值点取为w_0=0$,则迭代过程如下:
第一轮迭代:
g r a d ( w 0 ) = g r a d ( 0 ) = − 2 , w 0 = 0 , w 1 = w 0 − α ∗ g r a d ( w 0 ) = 0 − 1 2 ( − 2 ) = 1 grad(w_0)=grad(0)=-2,w_0=0,w_1=w_0-\alpha*grad(w_0)=0-\frac{1}{2}(-2)=1 grad(w0)=grad(0)=−2,w0=0,w1=w0−α∗grad(w0)=0−21(−2)=1
第二轮迭代:
g r a d ( w 1 ) = g r a d ( 1 ) = − 1 , w 1 = 1 , w 2 = w 1 − α ∗ g r a d ( w 1 ) = 1 − 1 2 ( − 1 ) = 3 2 grad(w_1)=grad(1)=-1,w_1=1,w_2=w_1-\alpha*grad(w_1)=1-\frac{1}{2}(-1)=\frac{3}{2} grad(w1)=grad(1)=−1,w1=1,w2=w1−α∗grad(w1)=1−21(−1)=23
第三轮迭代:
g r a d ( w 2 ) = g r a d ( 3 2 ) = − 1 2 , w 2 = 3 2 , w 3 = w 2 − α ∗ g r a d ( w 2 ) = 3 2 − 1 2 ( − 1 2 ) = 7 4 grad(w_2)=grad(\frac{3}{2})=-\frac{1}{2},w_2=\frac{3}{2},w_3=w_2-\alpha*grad(w_2)=\frac{3}{2}-\frac{1}{2}(-\frac{1}{2})=\frac{7}{4} grad(w2)=grad(23)=−21,w2=23,w3=w2−α∗grad(w2)=23−21(−21)=47
第四轮迭代:
g r a d ( w 3 ) = g r a d ( 7 4 ) = − 1 4 , w 3 = 7 4 , w 4 = w 3 − α ∗ g r a d ( w 3 ) = 7 4 − 1 2 ( − 1 4 ) = 15 8 grad(w_3)=grad(\frac{7}{4})=-\frac{1}{4},w_3=\frac{7}{4},w_4=w_3-\alpha*grad(w_3)=\frac{7}{4}-\frac{1}{2}(-\frac{1}{4})=\frac{15}{8} grad(w3)=grad(47)=−41,w3=47,w4=w3−α∗grad(w3)=47−21(−41)=815
依次类推:
w 5 = 15 8 + 1 16 = 31 16 ; w 6 = 31 16 + 1 32 = 63 32 ; w 7 = 63 32 + 1 64 = 127 64 ; . . . w_5 = \frac{15}{8}+\frac{1}{16} = \frac{31}{16}; w_6 = \frac{31}{16}+\frac{1}{32} = \frac{63}{32}; w_7 = \frac{63}{32}+\frac{1}{64} = \frac{127}{64}; ... w5=815+161=1631;w6=1631+321=3263;w7=3263+641=64127;...
w n = 2 n − 1 2 n − 1 = 2 − 1 2 n − 1 w_n=\frac{2^n-1}{2^{n-1}} = 2-\frac{1}{2^{n-1}} wn=2n−12n−1=2−2n−11
lim n → ∞ ( w n ) = lim n → ∞ ( 2 − 1 2 n − 1 ) = 2 \lim_{n→\infty} (w_n) = \lim_{n→\infty} (2-\frac{1}{2^{n-1}}) = 2 n→∞lim(wn)=n→∞lim(2−2n−11)=2
梯度下降的矩阵表示
令多元线性回归方程为
f
(
x
)
=
w
1
x
1
+
w
2
x
2
+
.
.
.
+
w
d
x
d
+
b
f(x) = w_1x_1+w_2x_2+...+w_dx_d+b
f(x)=w1x1+w2x2+...+wdxd+b
令
w
^
=
(
w
1
,
w
2
,
.
.
.
,
w
d
,
b
)
\hat w = (w_1,w_2,...,w_d,b)
w^=(w1,w2,...,wd,b)
x
^
=
(
x
1
,
x
2
,
.
.
.
,
x
d
,
1
)
\hat x = (x_1,x_2,...,x_d,1)
x^=(x1,x2,...,xd,1)
因此,方程可表示为
f ( x ) = w ^ ∗ x ^ T f(x) = \hat w * \hat x^T f(x)=w^∗x^T
另外,我们将所有自变量的值放在一个矩阵中,有
X
=
[
x
11
x
12
.
.
.
x
1
d
1
x
21
x
22
.
.
.
x
2
d
1
.
.
.
.
.
.
.
.
.
.
.
.
1
x
m
1
x
12
.
.
.
x
m
d
1
]
X = \left [\begin{array}{cccc} x_{11} &x_{12} &... &x_{1d} &1 \\ x_{21} &x_{22} &... &x_{2d} &1 \\ ... &... &... &... &1 \\ x_{m1} &x_{12} &... &x_{md} &1 \\ \end{array}\right]
X=⎣⎢⎢⎡x11x21...xm1x12x22...x12............x1dx2d...xmd1111⎦⎥⎥⎤
y = [ y 1 y 2 . . . y m ] y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right] y=⎣⎢⎢⎢⎢⎢⎢⎡y1y2...ym⎦⎥⎥⎥⎥⎥⎥⎤
此时,SSE可表示为:
S S E = ∣ ∣ y − X w ^ T ∣ ∣ 2 2 = ( y − X w ^ T ) T ( y − X w ^ T ) = E ( w ^ ) SSE = ||y - X\hat w^T||_2^2 = (y - X\hat w^T)^T(y - X\hat w^T) = E(\hat w) SSE=∣∣y−Xw^T∣∣22=(y−Xw^T)T(y−Xw^T)=E(w^)
梯度下降损失函数为:
L ( w ^ ) = 1 2 m S S E = 1 2 m ( y − X w ^ T ) T ( y − X w ^ T ) L(\hat w) = \frac{1}{2m} SSE =\frac{1}{2m} (y - X\hat w^T)^T(y - X\hat w^T) L(w^)=2m1SSE=2m1(y−Xw^T)T(y−Xw^T)
同样,我们需要设置初始化参数 ( w 1 , w 2 . . . , w d , b ) (w_1, w_2..., w_d, b) (w1,w2...,wd,b),以及学习率 α \alpha α,然后即可开始执行迭代过程,同样,每一轮迭代需要有三步计算:
Step 1.计算梯度表达式
对于参数向量 w ^ \hat w w^,其梯度计算表达式如下:
∂ ∂ w ^ L ( w ^ ) = 1 m X T ( X w ^ T − Y ) \frac{\partial}{\partial \hat w}L(\hat w) = \frac{1}{m}X^T(X\hat w ^T - Y) ∂w^∂L(w^)=m1XT(Xw^T−Y)
Step 2.用学习率乘以损失函数梯度,得到迭代移动距离
α ∂ ∂ w ^ L ( w ^ ) \alpha \frac{\partial}{\partial \hat w}L(\hat w) α∂w^∂L(w^)
Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w
w ^ = w ^ − α ∂ ∂ w ^ L ( w ^ ) = w ^ − α m X T ( X w ^ T − Y ) \hat w = \hat w - \alpha \frac{\partial}{\partial \hat w}L(\hat w) = \hat w - \frac{\alpha}{m}X^T(X\hat w ^T - Y) w^=w^−α∂w^∂L(w^)=w^−mαXT(Xw^T−Y)
更新完所有参数,即完成了一轮的迭代,接下来就能以新的 w ^ \hat w w^参与下一轮迭代。
编程实现
编写一个函数求梯度,默认学习率为0.01,迭代次数为1000次。
def gradDescent(X, y, eps = torch.tensor(0.01, requires_grad = True), numIt = 1000):
m, n = X.shape
weights = torch.zeros(n, 1, requires_grad = True)
for k in range(numIt):
grad = torch.mm(X.t(), (torch.mm(X, weights) - y))/2
weights = weights - eps * grad
return weights
X = torch.tensor([[1.,1],[3, 1]], requires_grad = True)
X
tensor([[1., 1.],
[3., 1.]], requires_grad=True)
y = torch.tensor([2.,4], requires_grad = True).reshape(2,1)
y
tensor([[2.],
[4.]], grad_fn=<ViewBackward>)
gradDescent(X, y)
tensor([[1.0372],
[0.9102]], grad_fn=<SubBackward0>)
weights = gradDescent(X, y, numIt = 10000)
weights
tensor([[1.0000],
[1.0000]], grad_fn=<SubBackward0>)
S S E = ( y − X w ^ T ) T ( y − X w ^ T ) SSE =(y - X\hat w^T)^T(y - X\hat w^T) SSE=(y−Xw^T)T(y−Xw^T)
torch.mm((torch.mm(X,weights)-y).t(), torch.mm(X,weights)-y)
tensor([[2.8518e-10]], grad_fn=<MmBackward>)