机器学习中的损失函数

前言

机器学习中,一般将数据分为训练数据测试数据两部分来进行学习和
实验等。首先,使用训练数据进行学习,寻找最优的参数;然后,使用测试
数据评价训练得到的模型的实际能力。为什么需要将数据分为训练数据和测
试数据呢?因为我们追求的是模型的泛化能力。为了正确评价模型的泛化能
力,就必须划分训练数据和测试数据。另外,训练数据也可以称为监督数据。
泛化能力是指处理未被观察过的数据(不包含在训练数据中的数据)的
能力。获得泛化能力是机器学习的最终目标。比如,在识别手写数字的问题
中,泛化能力可能会被用在自动读取明信片的邮政编码的系统上。此时,手
写数字识别就必须具备较高的识别“某个人”写的字的能力。注意这里不是“特
定的某个人写的特定的文字”,而是“任意一个人写的任意文字”。如果系统
只能正确识别已有的训练数据,那有可能是只学习到了训练数据中的个人的
习惯写法。
因此,仅仅用一个数据集去学习和评价参数,是无法进行正确评价的。
这样会导致可以顺利地处理某个数据集,但无法处理其他数据集的情况。顺
便说一下,只对某个数据集过度拟合的状态称为过拟合(over fitting)。避免
过拟合也是机器学习的一个重要课题。
泛化能力:以识别字体来举例,就是我不能只能识别出你写的文字,却识别不出别人写的字迹

损失函数

损失函数是表示神经网络性能的“恶劣程度”的指标,即当前的
神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。
以“性能的恶劣程度”为指标可能会使人感到不太自然,但是如
果给损失函数乘上一个负值,就可以解释为“在多大程度上不坏”,
即“性能有多好”。并且,“使性能的恶劣程度达到最小”和“使性
能的优良程度达到最大”是等价的,不管是用“恶劣程度”还是“优
良程度”,做的事情本质上都是一样的。
损失函数有很多种,但是用的比较多的两种分别是“均方误差”和“交叉熵误差”

均方误差

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

比如, yk、 tk是由如下10个元素构成的数据。
>>> y = [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]
数组元素的索引从第一个开始依次对应数字“0”“1”“2”…… 这里,神
经网络的输出y是softmax函数的输出。由于softmax函数的输出可以理解为
概率,因此上例表示“0”的概率是0.1,“1”的概率是0.05,“2”的概率是0.6
等。 t是监督数据,将正确解标签设为1,其他均设为0。这里,标签“2”为1,
表示正确解是“2”。将正确解标签表示为1,其他标签表示为0的表示方法称
为one-hot表示

代码演示:

import numpy as np

y = [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]

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

result = mean_squared_error(np.array(y),np.array(t))
print(result)

输出结果:0.09750000000000003

import numpy as np

y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

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

result = mean_squared_error(np.array(y),np.array(t))
print(result)

输出结果:0.5975

这里举了代码的例子。第一个例子中,正确解是“2”,神经网络的输出的最大
值是“2”;第二个例子中,正确解是“2”,神经网络的输出的最大值是“7”。如
实验结果所示,我们发现第一个例子的损失函数的值更小,和监督数据之间的
误差较小。也就是说,均方误差显示第一个例子的输出结果与监督数据更加吻合。

交叉熵误差

除了均方误差之外, 交叉熵误差(cross entropy error)也经常被用作损
失函数。交叉熵误差如下式所示。


这里, log表示以e为底数的自然对数(log e)。 yk是神经网络的输出, tk是
正确解标签。并且, tk中只有正确解标签的索引为1,其他均为0(one-hot表示)。
因此,公式实际上只计算对应正确解标签的输出的自然对数。比如,假设
正确解标签的索引是“2”,与之对应的神经网络的输出是0.6,则交叉熵误差
是-log 0.6 = 0.51;若“2”对应的输出是0.1,则交叉熵误差为-log 0.1 = 2.30。
也就是说,交叉熵误差的值是由正确解标签所对应的输出结果决定的。

在numpy中log的默认底数为e

如图4-3所示, x等于1时, y为0;随着x向0靠近, y逐渐变小。因此,
正确解标签对应的输出越大,公式的值越接近0;当输出为1时,交叉熵
误差为0。此外,如果正确解标签对应的输出较小,则公式的值较大。

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

这里,参数y和t是NumPy数组。函数内部在计算np.log时,加上了一
个微小值delta。这是因为,当出现np.log(0)时, np.log(0)会变为负无限大
的-inf,这样一来就会导致后续计算无法进行。作为保护性对策,添加一个
微小值可以防止负无限大的发生。
 

代码演示:

import numpy as np

t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]

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

result = cross_entropy_error(np.array(y),np.array(t))
print(result)

运行结果:0.51082545709933802

import numpy as np

t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]

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

result = cross_entropy_error(np.array(y),np.array(t))
print(result)

运行结果:2.3025840929945458

第一个例子中,正确解标签对应的输出为0.6,此时的交叉熵误差大约
为0.51。第二个例子中,正确解标签对应的输出为0.1的低值,此时的交叉
熵误差大约为2.3。由此可以看出,这些结果与我们前面讨论的内容是一致的





 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值