天天看点

深度学习基础:3.反向传播和梯度下降

动态计算图

计算图可以用来表示两个变量之间的关系。例如,构建,则可用一张简单计算图进行表示。

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.)      

梯度下降

梯度下降的代数表示

令多元线性回归方程为

出于加快迭代收敛速度的目标,我们在定义梯度下降的损失函数L时,在原SSE基础上进行比例修正,新的损失函数,其中,m为样本个数。

损失函数有:

并且,根据此前描述过程,在开始梯度下降求解参数之前,我们首先需要设置一组参数的初始取值,以及学习率,然后即可执行迭代运算,其中每一轮迭代过程需要执行以下三步

Step 1.计算梯度表达式

对于任意一个参数,其梯度计算表达式如下:

Step 2.用学习率乘以损失函数梯度,得到迭代移动距离

Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w

更新完所有参数,即完成了一轮的迭代,接下来就能以新的一组参与下一轮迭代。

举例说明

有数据集表示如下:

x y
1 2
2 4
3 6

假设,我们使用进行拟合,则SSE为:

此时,SSE就是一个关于w的一元函数。当使用最小二乘法进行求解时,SSE就是损失函数,并且SSE对于w求导为0的点就是最小值点,因此有:

但我们使用梯度下降求解时:

由于梯度表示方向,在某些情况下我们可以对其绝对数值进行一定程度上的“缩放”,此时我们规定有效梯度是原梯度的1/28,则有

设步长$\alpha=w_0=0$,则迭代过程如下:

第一轮迭代:

第二轮迭代:

第三轮迭代:

第四轮迭代:

依次类推:

梯度下降的矩阵表示

令多元线性回归方程为

因此,方程可表示为

另外,我们将所有自变量的值放在一个矩阵中,有

此时,SSE可表示为:

梯度下降损失函数为:

同样,我们需要设置初始化参数,以及学习率,然后即可开始执行迭代过程,同样,每一轮迭代需要有三步计算:

Step 1.计算梯度表达式

对于参数向量,其梯度计算表达式如下:

Step 2.用学习率乘以损失函数梯度,得到迭代移动距离

Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数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      
X = torch.tensor([[1.,1],[3, 1]], requires_grad = True)      
tensor([[1., 1.],
        [3., 1.]], requires_grad=True)      
y = torch.tensor([2.,4], requires_grad = True).reshape(2,1)      
tensor([[2.],
        [4.]], grad_fn=<ViewBackward>)      
gradDescent(X, y)      
tensor([[1.0372],
        [0.9102]], grad_fn=<SubBackward0>)      
weights = gradDescent(X, y, numIt = 10000)      
tensor([[1.0000],
        [1.0000]], grad_fn=<SubBackward0>)      
torch.mm((torch.mm(X,weights)-y).t(), torch.mm(X,weights)-y)      
tensor([[2.8518e-10]], grad_fn=<MmBackward>)      

继续阅读