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{nablatext{loss}}{nabla{theta}}=2sum{[y-f_theta(x)]}*frac{nabla{f_theta{(x)}}}{nabla{theta}}$
接下来用代码进行详解
代码语言:javascript复制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功能
代码语言:javascript复制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]))
此时输出会报错
代码语言:javascript复制element 0 of tensors does not require grad and does not have a grad_fn
这是由于w参数在初始化时并没有赋予其导数信息,pytorch不知道w需要求导信息,因此在进行求导时会报错。因此在进行此类计算时必须要对需要求到的参数进行更新。更新代码为:.requires_grad_()
,最后面的_
是进行了repalce(替换)操作
在进行更新操作后,还需要进行动态图更新,即重新设置求导信息
代码语言:javascript复制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{nablatext{loss}}{nabla{w1}},frac{nablatext{loss}}{nabla{w2}},...$loss.backward()
,想查看某个变量的导数信息,直接调用.grad
即可。例如print(w1.grad)