分享

机器学习 损失函数

 univasity 2023-11-02 发布于法国

损失函数

  • what is 损失函数
  • 均方误差
  • 交叉熵误差
  • 计算mini-batch学习的损失函数
  • why 损失函数

 

what is 损失函数

神经网络学习目标是找到各层合适的权重参数w和偏置b,使得最终的输出结果能够与实际结果更加接近。那神经网络的这些权重参数是如何得到的:靠损失函数这个指标来进行一步步训练优化得到。

通过使损失函数最小,来寻找最优权重参数。学习的目的就是以该损失函数为基准,找出能使它的值达到最小的权重参数。

均方误差

在这里插入图片描述

yk是神经网络的输出, tk是监督数据, k是数据的维数。

用python实现均方误差函数:

def mean_squared_error(y, t):
    return 0.5 * np.sum((y-t)**2)

下面是调用这个函数的例子:

以手写数字识别为例,数组下标对应的是0-9的数字,y1和y2是神经网络经过softmax函数的输出,y1、y2的元素值是该网络经过判断这张图片,得到的0-9数字的概率。t是监督数据,t[2]=1,表明这张图片是2 。看到均方误差输出结果,可以发现,y1的损失函数比y2小,这是因为y1[2]=0.6,而y2[2]=0.1,也就是说y1估计出来的更接近真实的判断。

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
from common.functions import mean_squared_error


if __name__ == '__main__':
    y1 = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
    t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
    y2 = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
    r1 = mean_squared_error(np.array(y1), np.array(t))
    print(r1)
    r2 = mean_squared_error(np.array(y2), np.array(t))
    print(r2)

输出:

0.09750000000000003
0.5975

交叉熵误差

在这里插入图片描述

yk是神经网络的输出, tk是正确解标签, k表示数据的维数。

如果标签为one-hot表示,即tk中只有正确解标签索引为1,其他均为0 。

那么式子只计算对应正确解标签的输出的自然对数。

如上面的例子,t[2]=1,正确解标签索引为2,对应的神经网络输出为y1[2]=0.6,则交叉熵误差为-log0.6。

在这里插入图片描述

由上图y=logx曲线可看出,对于对数函数y=logx,x=1时,y=0;

交叉熵误差是一个-log函数,也就意味着,交叉熵误差值越小,神经网络在对应正确解标签的输出越接近1,即神经网络的判断和正确解标签越接近。

用python实现交叉熵误差函数:

函数里面的参数y、t是Numpy数组,函数计算log时,加上了一个微小值,这是防止出现np.log(0)导致后续计算无法进行。

def cross_entropy_error(y, t):
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

调用这个函数的例子:和均方误差调用的例子类似。

import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
from common.functions import cross_entropy_error


if __name__ == '__main__':
    y1 = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
    t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
    y2 = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
    r1 = cross_entropy_error(np.array(y1), np.array(t))
    print(r1)
    r2 = cross_entropy_error(np.array(y2), np.array(t))
    print(r2)

输出:

0.510825457099338
2.302584092994546

计算mini-batch学习的损失函数

上述仅对单个数据进行了损失函数的计算,实际工程中,要把所有训练数据的损失函数的总和作为学习的指标。以交叉熵误差为例:

在这里插入图片描述

数据有N个, tnk表示第n个数据的第k个元素的值( ynk是神经网络的输出, tnk是监督数据)。

这个式子,也就是把所有数据的损失函数值加起来再除以总的数据个数。通过除以N可以求单个数据的平均损失函数,与训练数据的数量无关。

由于数据集的数据量可能会很大,求全部数据的损失函数的和,将花费很长时间。可以从全部数据中抽出一小部分数据,作为全部数据的近似,称为mini-batch(小批量),然后对每个mini-batch学习。

下面介绍一下如何使用python进行mini-batch的损失函数计算。

首先,从训练数据中随机抽取数据得到mini-batch:
调用(x_train, t_train), (x_test, t_test) = load_mnist(one_hot_label=True, normalize=True)函数,读取出MINIST数据,输出x_train.shape、t_train.shape可以看到,训练数据有60000个。使用np.random.choice(train_size, batch_size)可以从0到train_size-1之间随机选择batch_size个数字。输出batch_mask可以得到一个索引数组。把索引对应的数据存到小批量数据集里,抽出来的数据就有了。也就是说在60000个数据里面随机选了十个数据,存到了x_batch、t_batch里面。

import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
from dataset.mnist import load_mnist

(x_train, t_train), (x_test, t_test) = load_mnist(one_hot_label=True, normalize=True)

if __name__ == '__main__':
    print(x_train.shape)
    print(t_train.shape)
    train_size = x_train.shape[0]
    batch_size = 10
    batch_mask = np.random.choice(train_size, batch_size)
    print(batch_mask)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    

输出:

(60000, 784)
(60000, 10)
[44839  5657 46048 51825 44057 50445  1374 19821 38720 14117]
(10, 784)
(10, 10)

之后,编写mini-batch版本的交叉熵误差函数:

函数参数y是神经网络输出,它是个二维的,第一维是该数据在mini-batch数据集里面的索引,第二维是数据,t是监督数据。y[np.arange(batch_size), t] 能抽出各个数据正确解标签对应的神经网络的输出。

重点的是,只用求神经网络在正确解标签处的输出。举个例子y[0,2],这就取出来了mini-batch里面第一个数据在2处的输出。

def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    # 监督数据是one-hot-vector的情况下,转换为正确解标签的索引
    if t.size == y.size:
        t = t.argmax(axis=1)
             
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

why 损失函数

寻找最优权重和偏置时,要使损失函数尽可能小。

为什么不能用识别精度来作为指标,使让精度尽可能高,来寻找最优参数?

我的理解是,精度是除法做出来的,对网络的权重和偏置调整后,可能除法的结果没什么变化,也有可能出现突然的变化。这样的话无法进行调优,因为结果是不连续的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多