MENU

Typical Loss and its gradient

December 29, 2019 • Read: 3463 • Deep Learning阅读设置

MSE(Mean Squared Error)

  • $loss = \sum(y-\hat{y})^2$
  • $L2-norm = ||y-(xw+b)||_2$
  • $loss = norm(y-(xw+b))^2$

介绍一下各种 norm

常用的 norm 有 L1-norm,L2-norm 即 L1,L2 范数。那么问题来了,什么是范数?

在线性代数以及一些数学领域种,norm 的定义是

a function that assigns a strictly positive length or size to each vector in a vector space, except for the zero vector. ——Wikipedia

对于一个 p-norm,严格定义是

$$ ||X||_p := (\sum_{i=1}^n |x_i|^p)^\frac{1}{p} $$

其中当 p 取 1 时,被称为 L1-norm,p 取 2 时,被称为 L2-norm

根据上述公式,L1-norm 的定义也就得到了,$||X||_1 := \sum_{i=1}^n |x_i|$

同理,L2-norm,$||X||_2 := (\sum_{i=1}^n |x_i|^2)^\frac {1}{2}$,L2 展开就是熟悉的欧几里得范数,$||X||_2 := \sqrt {x_1^2 +・・・+ x_n^2}$

Derivative

  • $loss = \sum[y-f_\theta(x)]^2$
  • $\frac{\nabla\text{loss}}{\nabla{\theta}}=2\sum{[y-f_\theta(x)]}*\frac{\nabla{f_\theta{(x)}}}{\nabla{\theta}}$

接下来用代码进行详解

  • import torch
  • # 假设构建的是 pred = wx + b 的线性模型
  • # 令x初始化为1,w为dim = 1,值为2的tensor,b假设为0
  • x = torch.ones(1)
  • print(x)
  • w = torch.full([1],2)
  • print(w)

分别输出 x 和 w 的值分别为 tensor([1.])tensor([2.])

引入 pytorch 中的功能包,使用 mse_loss 功能

  • import torch.nn.functional as F
  • mse = F.mse_loss(input=x*w, target=torch.ones(1))
  • # x*w为label值,target为pred值
  • print(mse)

输出 tensor(1.)

上面的结果进行了运算 $\sqrt {(1-2)^2}$

在实际使用求导功能中,我们一般使用 autograd.grad 功能(自动求导)进行运算

API 为: torch.autograd.grad(pred, [w]),括号内依次为预测值和要求导的参数

  • print(torch.autograd.grad(mse, [w]))

此时输出会报错

  • element 0 of tensors does not require grad and does not have a grad_fn

这是由于 w 参数在初始化时并没有赋予其导数信息,pytorch 不知道 w 需要求导信息,因此在进行求导时会报错。因此在进行此类计算时必须要对需要求到的参数进行更新。更新代码为:.requires_grad_(),最后面的_是进行了 repalce(替换)操作

在进行更新操作后,还需要进行动态图更新,即重新设置求导信息

  • w.requires_grad_()
  • mse = F.mse_loss(x*w, torch.ones(1))
  • print(torch.autograd.grad(mse, [w]))

输出为 (tensor([2.]),)

上面的结果进行了运算 $2*(1-2)*(-1) = 2$

以后在设置需要求导的参数时,直接在创建 tensor 时,即加入 requires_grad=True 即可

  • x = torch.ones(1)
  • w = torch.full([1], 2, requires_grad=True)
  • import torch.nn.functional as F
  • mse = F.mse_loss(x*w, torch.ones(1))
  • print(torch.autograd.grad(mse, [w]))

对比上文,更简便的办法是使用.backward() 函数进行求导

  • # 首先构建tensor
  • x = torch.ones(1)
  • w = torch.full([1], 2, requires_grad=True)
  • # 构建动态图,完成MSE的构建
  • mse = F.mse_loss(torch.ones(1), x*w)
  • # 对其求导时直接对设定的loss使用.backward()函数
  • mse.backward()
  • # 对设定的loss信息进行从后向前传递
  • # 使用参数.grad函数即可输出相应的求导信息
  • print(w.grad)

输出 tensor([2.],)

在此总结两种求导方法

  • torch.autograd.grad(loss, [w1,w2,...]),该函数返回的是 $\frac {\nabla\text {loss}}{\nabla {w1}},\frac {\nabla\text {loss}}{\nabla {w2}},...$
  • loss.backward(),想查看某个变量的导数信息,直接调用.grad 即可。例如 print(w1.grad)
Archives Tip
QR Code for this page
Tipping QR Code
Leave a Comment