动态计算图 计算图可以用来表示两个变量之间的关系。例如,构建y=x^2,则可用一张简单计算图进行表示。
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输出:
梯度下降 梯度下降的代数表示 令多元线性回归方程为
f(x) = w_1x_1+w_2x_2+...+w_dx_d+b
令
\hat w = (w_1,w_2,...,w_d,b) \hat x = (x_1,x_2,...,x_d,1) 出于加快迭代收敛速度的目标,我们在定义梯度下降的损失函数L时,在原SSE基础上进行比例修正,新的损失函数
L(w_1,w_2,...,w_d,b) = \frac{1}{2m}SSE ,其中,m为样本个数。
损失函数有:
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 并且,根据此前描述过程,在开始梯度下降求解参数之前,我们首先需要设置一组参数的初始取值
(w_1, w_2..., w_d, b) ,以及学习率\alpha ,然后即可执行迭代运算,其中每一轮迭代过程需要执行以下三步
Step 1.计算梯度表达式
对于任意一个参数w_i ,其梯度计算表达式如下:
\frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) Step 2.用学习率乘以损失函数梯度,得到迭代移动距离
\alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w
w_i = w_i - \alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) 更新完所有参数,即完成了一轮的迭代,接下来就能以新的一组w_i 参与下一轮迭代。
举例说明 有数据集表示如下:
假设,我们使用
y = wx 进行拟合,则SSE为:
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就是一个关于w的一元函数。当使用最小二乘法进行求解时,SSE就是损失函数,并且SSE对于w求导为0的点就是最小值点,因此有:
\frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) = 0 w=2 但我们使用梯度下降求解时:
grad^* = \frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) 由于梯度表示方向,在某些情况下我们可以对其绝对数值进行一定程度上的“缩放”,此时我们规定有效梯度是原梯度的1/28,则有
grad = w-2 设步长$\alpha=
0.5,初始值点取为 w_0=0$,则迭代过程如下:
第一轮迭代:
grad(w_0)=grad(0)=-2,w_0=0,w_1=w_0-\alpha*grad(w_0)=0-\frac{1}{2}(-2)=1 第二轮迭代:
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(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(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} 依次类推:
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}; ... w_n=\frac{2^n-1}{2^{n-1}} = 2-\frac{1}{2^{n-1}} \lim_{n→\infty} (w_n) = \lim_{n→\infty} (2-\frac{1}{2^{n-1}}) = 2 梯度下降的矩阵表示 令多元线性回归方程为
f(x) = w_1x_1+w_2x_2+...+w_dx_d+b
令
\hat w = (w_1,w_2,...,w_d,b) \hat x = (x_1,x_2,...,x_d,1)
因此,方程可表示为
f(x) = \hat w * \hat x^T 另外,我们将所有自变量的值放在一个矩阵中,有
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] y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right] 此时,SSE可表示为:
SSE = ||y - X\hat w^T||_2^2 = (y - X\hat w^T)^T(y - X\hat w^T) = E(\hat w) 梯度下降损失函数为:
L(\hat w) = \frac{1}{2m} SSE =\frac{1}{2m} (y - X\hat w^T)^T(y - X\hat w^T) 同样,我们需要设置初始化参数
(w_1, w_2..., w_d, b) ,以及学习率\alpha ,然后即可开始执行迭代过程,同样,每一轮迭代需要有三步计算:
Step 1.计算梯度表达式
对于参数向量\hat w ,其梯度计算表达式如下:
\frac{\partial}{\partial \hat w}L(\hat w) = \frac{1}{m}X^T(X\hat w ^T - Y) Step 2.用学习率乘以损失函数梯度,得到迭代移动距离
\alpha \frac{\partial}{\partial \hat w}L(\hat w) Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w
\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) 更新完所有参数,即完成了一轮的迭代,接下来就能以新的\hat 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 weightsX = torch.tensor([[1.,1],[3, 1]], requires_grad = True)
Xtensor([[1., 1.],
[3., 1.]], requires_grad=True)y = torch.tensor([2.,4], requires_grad = True).reshape(2,1)
ytensor([[2.],
[4.]], grad_fn=<ViewBackward>)tensor([[1.0372],
[0.9102]], grad_fn=<SubBackward0>)weights = gradDescent(X, y, numIt = 10000)
weightstensor([[1.0000],
[1.0000]], grad_fn=<SubBackward0>)SSE =(y - X\hat w^T)^T(y - X\hat w^T) torch.mm((torch.mm(X,weights)-y).t(), torch.mm(X,weights)-y)tensor([[2.8518e-10]], grad_fn=<MmBackward>)