动态计算图
计算图可以用来表示两个变量之间的关系。例如,构建y=x^2,则可用一张简单计算图进行表示。 pytorch支持动态计算图,动态意义在于,当创建其它由计算图中变量而来的新变量时,新变量会自动添加到计算图内。 而Tensorflow v1仅支持静态计算图,需要提前定义各个变量的关系,灵活性不如动态计算图。
反向传播
通过反向传播,可以计算各变量的导数。
代码语言:javascript复制x = torch.tensor(1.,requires_grad = True) #requires_grad=True表示x可导
y = x ** 2
y.backward()
# 在y=x**2函数关系基础上,x取值为1时的导数值
x.grad
输出:
代码语言:javascript复制tensor(2.)
梯度下降
梯度下降的代数表示
令多元线性回归方程为
令
出于加快迭代收敛速度的目标,我们在定义梯度下降的损失函数L时,在原SSE基础上进行比例修正,新的损失函数
,其中,m为样本个数。
损失函数有:
并且,根据此前描述过程,在开始梯度下降求解参数之前,我们首先需要设置一组参数的初始取值
,以及学习率alpha ,然后即可执行迭代运算,其中每一轮迭代过程需要执行以下三步
Step 1.计算梯度表达式
对于任意一个参数w_i ,其梯度计算表达式如下:
Step 2.用学习率乘以损失函数梯度,得到迭代移动距离
Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w
更新完所有参数,即完成了一轮的迭代,接下来就能以新的一组w_i 参与下一轮迭代。
举例说明
有数据集表示如下:
x | y |
---|---|
1 | 2 |
2 | 4 |
3 | 6 |
假设,我们使用
进行拟合,则SSE为:
此时,SSE就是一个关于w的一元函数。当使用最小二乘法进行求解时,SSE就是损失函数,并且SSE对于w求导为0的点就是最小值点,因此有:
但我们使用梯度下降求解时:
由于梯度表示方向,在某些情况下我们可以对其绝对数值进行一定程度上的“缩放”,此时我们规定有效梯度是原梯度的1/28,则有
设步长$alpha=
w_0=0$,则迭代过程如下:
第一轮迭代:
第二轮迭代:
第三轮迭代:
第四轮迭代:
依次类推:
梯度下降的矩阵表示
令多元线性回归方程为
令
因此,方程可表示为
另外,我们将所有自变量的值放在一个矩阵中,有
此时,SSE可表示为:
梯度下降损失函数为:
同样,我们需要设置初始化参数
,以及学习率alpha ,然后即可开始执行迭代过程,同样,每一轮迭代需要有三步计算:
Step 1.计算梯度表达式
对于参数向量hat w ,其梯度计算表达式如下:
Step 2.用学习率乘以损失函数梯度,得到迭代移动距离
Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w
更新完所有参数,即完成了一轮的迭代,接下来就能以新的hat w 参与下一轮迭代。
编程实现
编写一个函数求梯度,默认学习率为0.01,迭代次数为1000次。
代码语言:javascript复制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
代码语言:javascript复制X = torch.tensor([[1.,1],[3, 1]], requires_grad = True)
X
代码语言:javascript复制tensor([[1., 1.],
[3., 1.]], requires_grad=True)
代码语言:javascript复制y = torch.tensor([2.,4], requires_grad = True).reshape(2,1)
y
代码语言:javascript复制tensor([[2.],
[4.]], grad_fn=<ViewBackward>)
代码语言:javascript复制gradDescent(X, y)
代码语言:javascript复制tensor([[1.0372],
[0.9102]], grad_fn=<SubBackward0>)
代码语言:javascript复制weights = gradDescent(X, y, numIt = 10000)
weights
代码语言:javascript复制tensor([[1.0000],
[1.0000]], grad_fn=<SubBackward0>)
代码语言:javascript复制torch.mm((torch.mm(X,weights)-y).t(), torch.mm(X,weights)-y)
代码语言:javascript复制tensor([[2.8518e-10]], grad_fn=<MmBackward>)