首页 > 其他分享 >Metric评价指标及损失函数

Metric评价指标及损失函数

时间:2022-11-08 15:55:40浏览次数:33  
标签:函数 Metric error MAE import np 评价 self mindspore

Error系列的指标及loss损失函数,该系列有:

  • 均方误差(Mean Square Error,MSE)
  • 平均绝对误差(Mean Absolute Error,MAE)
  • 均方根误差(Root Mean Square Error,RMSE)
  • 均方对数误差(Mean Squared Log Error)
  • 平均相对误差(Mean Relative Error,MAE)

这次讲一下平均绝对误差(Mean Absolute Error,MAE)的原理介绍及MindSpore的实现代码。

一. 平均绝对误差(Mean Absolute Error,MAE)介绍

平均绝对误差指的就是模型预测值 f(x) 与样本真实值 y 之间距离的平均值。其公式如下所示:

 

 

 为了简化讨论,忽略下标 i,m = 1,以 y-f(x) 为横坐标,MAE 为纵坐标,绘制其损失函数的图形:

 

 

 

直观上来看,MAE 的曲线呈 V 字型,连续但在 y-f(x)=0 处不可导,计算机求解导数比较困难。而且 MAE 大部分情况下梯度都是相等的,这意味着即使对于小的损失值,其梯度也是大的。这不利于函数的收敛和模型的学习。

值得一提的是,MAE 相比 MSE 有个优点就是 MAE 对离群点不那么敏感,更有包容性。因为 MAE 计算的是误差 y-f(x) 的绝对值,无论是 y-f(x)>1 还是 y-f(x)<1,没有平方项的作用,惩罚力度都是一样的,所占权重一样。针对 MSE 中的例子,我们来使用 MAE 进行求解,看下拟合直线有什么不同。(我们先用numpy举一下例子。)

X = np.vstack((np.ones_like(x),x))    # 引入常数项 1
m = X.shape[1]
# 参数初始化
W = np.zeros((1,2))

# 迭代训练
num_iter = 20
lr = 0.01
J = []
for i in range(num_iter):
   y_pred = W.dot(X)
   loss = 1/m * np.sum(np.abs(y-y_pred))
   J.append(loss)
   mask = (y-y_pred).copy()
   mask[y-y_pred > 0] = 1
   mask[mask <= 0] = -1
   W = W + lr * 1/m * mask.dot(X.T)

# 作图
y1 = W[0,0] + W[0,1]*1
y2 = W[0,0] + W[0,1]*20
plt.scatter(x, y)
plt.plot([1,20],[y1,y2],'r--')
plt.xlabel('x')
plt.ylabel('y')
plt.title('MAE')
plt.show()

 

注意上述代码中对 MAE 计算梯度的部分。

拟合结果如下图所示:

 

 

 显然,使用 MAE 损失函数,受离群点的影响较小,拟合直线能够较好地表征正常数据的分布情况。这一点,MAE 要优于 MSE。二者的对比图如下:

 

 

 

  • 选择 MSE 还是 MAE 呢?

实际应用中,我们应该选择 MSE 还是 MAE 呢?从计算机求解梯度的复杂度来说,MSE 要优于 MAE,而且梯度也是动态变化的,能较快准确达到收敛。但是从离群点角度来看,如果离群点是实际数据或重要数据,而且是应该被检测到的异常值,那么我们应该使用MSE。另一方面,离群点仅仅代表数据损坏或者错误采样,无须给予过多关注,那么我们应该选择MAE作为损失。

二. Mean Absolute Error的MindSpore代码实现

好了,原理已经讲完,话不多说,我们开始上代码。使用的是MindSpore框架实现的代码。

Mean Absolute Error的Metric代码实现

"""Error."""
import numpy as np
from .metric import Metric


class MAE(Metric):
    
    def __init__(self):
        super(MAE, self).__init__()
        self.clear()

    def clear(self):
        """清除历史数据"""
        self._abs_error_sum = 0
        self._samples_num = 0

    def update(self, *inputs):
        # 检验输入个数
        if len(inputs) != 2:
            raise ValueError('Mean absolute error need 2 inputs (y_pred, y), but got {}'.format(len(inputs)))
        y_pred = self._convert_data(inputs[0])
        y = self._convert_data(inputs[1])
        # 复现公式计算
        abs_error_sum = np.abs(y.reshape(y_pred.shape) - y_pred)
        # 多组数据进行累加
        self._abs_error_sum += abs_error_sum.sum()
        # 统计数据的个数,方便后面求均值
        self._samples_num += y.shape[0]

    def eval(self):
        """
        返回值是一个float的标量。
        """
        if self._samples_num == 0:
            raise RuntimeError('Total samples num must not be 0.')
        return self._abs_error_sum / self._samples_num
import numpy as np
import mindspore
from mindspore import Tensor
from mindspore.nn.metrics import MAE

x = Tensor(np.array([0.1, 0.2, 0.6, 0.9]), mindspore.float32)
y = Tensor(np.array([0.1, 0.25, 0.7, 0.9]), mindspore.float32)
error = MAE()
error.clear()
error.update(x, y)
result = error.eval()
print(result)

0.037499990314245224

 

每个batch(比如两组数据)进行计算的时候如下:

import numpy as np
from mindspore import Tensor
from mindspore.nn.metrics import MAE

error = MAE()
error.clear()
x = Tensor(np.array([0.1, 0.2, 0.6, 0.9]))
y = Tensor(np.array([0.1, 0.25, 0.7, 0.9]))
error.update(x, y)

x1 = Tensor(np.array([0.1, 0.2, 0.6, 0.9]))
y1 = Tensor(np.array([0.1, 0.25, 0.7, 0.9]))
error.update(x1, y1)
result = metric.eval()

print(result)

 

Mean Squared Error的Loss代码实现

 

import mindspore
import mindspore.common.dtype as mstype
from mindspore.common.tensor import Tensor
from mindspore.common.parameter import Parameter
from mindspore.ops import operations as P
from mindspore.ops import functional as F
from mindspore import nn

class MAELoss(_Loss):

    def construct(self, logits, label):
        _check_shape(logits.shape, label.shape)
        x = F.absolute(logits - label)
        return self.get_loss(x)

 

 使用方法如下:

 

import numpy as np
from mindspore import nn
import mindspore
from mindspore import Tensor

loss = nn.MAELoss()
input_data = Tensor(np.array([1, 2, 3]), mindspore.float32)
target_data = Tensor(np.array([1, 2, 2]), mindspore.float32)
output = loss(input_data, target_data)
print(output)

0.33333334

 

 

 

参考:https://zhuanlan.zhihu.com/p/353125247

https://gitee.com/mindspore/mindspore

https://www.mindspore.cn/

 

标签:函数,Metric,error,MAE,import,np,评价,self,mindspore
From: https://www.cnblogs.com/liuwd/p/16869979.html

相关文章

  • python 函数装饰器
    #函数传入的参数可以是函数deffunc1():print('1')deffunc2(func):#func为函数func()print('2')func2(func1)#12 deffunc1(func):......
  • VUE2 实现一个页面 调用 另一个页面的函数
    今天我在Vue 需要实现 一个这样的功能在App.vue页面中 要实现 调用 另一个页(ExtensionMonitor.vue)中的函数 并将参数 传过去下面将实现的步骤写下来,供大家参考1.......
  • matlab solve函数解方程 带参数
    以Gaussianp.d.f.求方差的一元一次方程为例,已知均值(MU)/样本点(x,y),求方差(sigma2)。实参赋值MU=4.5e-8;%均值x_thres=5.1e-4;%找一个好的门限->对于solve(s......
  • C语言自创函数
    为什么要采用自创函数?在设计较复杂的程序时,一般采用自顶向下的方法,将问题划分为几个部分,各个部分再进行细化,直到分解为较好解决问题为止。模块化程序设计是指在进行程序......
  • 初识函数
    //非函数方式//#include<stdio.h>//intmain()//{// inta=0;// intb=0;// scanf_s("%d%d",&a,&b);// intc=a+b;//// printf("%d\n",c);// return......
  • 积性函数(积性函数概念、欧拉筛求积性函数、莫比乌斯反演)学习笔记
    1、积性函数2、欧拉筛求积性函数3、莫比乌斯反演4、狄拉克雷卷积......
  • 函数
    基本概念函数的定义函数可以没有参数以及返回值func函数名称([参数类型1],[参数类型2])[返回值]{ 函数体 return返回内容}funcadd(aint,bint)int{ f......
  • 追寻抽象函数(三)
    2019人教版必修一第161页12题对于函数\(f(x)=a-\frac{2}{2^x+1}\;\;(a\in\textbf{R})\)(1)探究函数\(f(x)\)d的单调性;(2)是否存在实数\(a\)使函数\(f(x)\)为奇函数?问......
  • React组件设计模式-纯组件,函数组件,高阶组件
    一、组件(1)函数组件如果你想写的组件只包含一个render方法,并且不包含state,那么使用函数组件就会更简单。我们不需要定义一个继承于React.Component的类,我们可以定......
  • openGauss 条件表达式函数介绍
    条件表达式函数:coalesce(expr1,expr2,…,exprn)描述:返回参数列表中第一个非NULL的参数值。COALESCE(expr1,expr2)等价于CASEWHENexpr1ISNOTNULLTHENexpr1ELSE......