[Deep learning]——损失函数(loss function)

一、训练数据和测试数据

机器学习中,一般将数据分为训练数据和测试数据来进行学习和实验等。首先使用训练数据进行学习,寻找最优的参数;然后使用测试数据评价训练得到的模型的实际能力。 

1、为什么需要将数据分为训练数据和测试数据呢?

因为我们追求的是模型的泛化能力,为了正确评价模型的泛化能力,就必须划分训练数据和测试数据。

  • 注:训练数据也可以称为监督数据

泛化能力是指处理未被观察过的数据(不包含在训练数据中的数据)的能力。获得泛化能力是机器学习的最终目标。

2、验证数据

神经网络中除了权重和偏置等参数,超参数也经常出现。这里所说的超参数是指:比如各层的神经元数量、batch大小、参数更新时的学习率或者权值衰减等。

注意:不能使用测试数据去评估超参数的性能,因为如果使用测试数据调整超参数,超参数的值会对测试数据发生过拟合。因此调整超参数必须使用超参数专用的确认数据,用来调整超参数的数据一般称为验证数据。

  • 训练数据用于参数(权重和偏置)的学习
  • 验证数据用于超参数的性能评估
  • 测试数据用于验证模型的泛化能力

二、损失函数

损失函数(loss function)是用来估量模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。 

1、均方误差

可以作为损失函数的有很多,其中最有名的当属 均方误差(mean squared error:MSE

函数实现

import numpy as np

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

#函数测试
def function_test():
    #设置本案例的正解是2
    t = [0,0,1,0,0,0,0,0,0,0]

    #测试1:假设预测为2的概率最大
    y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
    print(mean_squared_error(np.array(y), np.array(t)))

    # 测试2:假设预测为7的概率最大
    y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
    print(mean_squared_error(np.array(y), np.array(t)))

if __name__ == '__main__':
    function_test()

实验结果所示:我们发现第一个例子的损失函数的值更小,和监督数据之间的误差较小。也就是说:均方误差显示第一个例子的输出结果与监督数据更加吻合。 

 2、交叉熵误差

除了均方误差之外,交叉熵误差(cross entropy error)也经常经用作损失函数

函数实现

import numpy as np

#cross entropy error
#y是神经网络输出、t是监督数据
def cross_entropy_error(y, t):
    # log函数在x向0靠近时会变成负无穷大,这样会导致无法计算
    # 作为保护性措施,添加一个微小值可以防止负无穷大的发生
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

#函数测试
def function_test():
    #设置本案例的正解是2
    t = [0,0,1,0,0,0,0,0,0,0]

    #测试1:假设预测为2的概率最大
    y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
    print(cross_entropy_error(np.array(y), np.array(t)))

    # 测试2:假设预测为7的概率最大
    y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
    print(cross_entropy_error(np.array(y), np.array(t)))

if __name__ == '__main__':
    function_test()

 三、mini-batch学习

机器学习使用训练数据进行学习。使用训练数据进行学习,严格来说,就是针对训练数据计算损失函数的值,找出使得该值尽可能小的参数,因此计算损失函数时,必须将所有的训练数据作为对象。

如果以全部数据为对象求损失函数的和,则计算过程会花费较长的时间。再者遇到大数据量时(几百万、几千万之多),这种情况下以全部数据为对象计算损失函数是不现实的。因此,我们从全部的数据中选出一部分,作为全部数据的“近似”,这种选出一小批数据的做法就是mini-batch学习(小批量学习) 

 1、MNIST数据集的mini-batch化

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

def get_data():
    #开启正规化和 one-hot编码表示
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
    return x_train, t_train

#mini-batch学习
#batch_size:每批数据的量
def mini_batch(x_train, t_train, batch_size):
    train_size = x_train.shape[0] #多少训练数据
    #np.random.choice(total, size):每次从0~total中随机取出batch_size个数据的索引
    batch_mask = np.random.choice(train_size, batch_size)
    #截取出数据
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    return x_batch, t_batch

if __name__ == '__main__':
    x_train, t_train = get_data()
    print(mini_batch(x_train, t_train, 10))

2、mini-batch版交叉熵误差的实现

这里我们需要对单个数据的交叉熵误差做一下改良,实现一个可以同时处理单个数据和批量数据(数据作为batch集中输入)两种情况的函数。

(1)使用one-hot编码的情况

#ont-hot编码方式的
def cross_entropy_error(y, t):
    #如果是一个数据时
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
    #取出数据的第一维度,也就是批次中数据的个数
    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size

(2)监督数据是标签形式的(非one-hot编码方式)

#监督数据是标签形式的
def cross_entropy_error_label(y, t):
    #如果是一个数据时
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
    #取出数据的第一维度,也就是批次中数据的个数
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Star星屹程序设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值