机器学习中的损失函数(均方误差,交叉熵误差)及其python实现

本文深入探讨了神经网络中两种常见的损失函数——均方误差和交叉熵误差,详细解释了它们的计算方式及在mini-batch学习中的应用,旨在帮助读者理解如何通过这些指标评估模型性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

神经网络NN以某个指标为线索寻找最优参数,NN的学习中用的指标被称为损失函数,它是表示NN性能的指标,即NN对训练数据在多大程度上不拟合,不一致。
很多函数都可以作为损失函数loss function,但常用的是均方误差和交叉熵误差等。

一、均方误差Mean Squared Error

E=12∑k(yk−tk)2E=\frac12\sum_{k}(y_k-t_k)^2E=21k(yktk)2
yky_kyk是NN的输出
tkt_ktk是one-hot标签,只有正确解的标签为1,其他均为0.
kkk是数据维数
所以,均方误差计算NN的输出和正确标签数据的各个元素的差值的平方,再求总和。

例如下图的python程序,识别0-9的数字,假设2是正确解,则t=[0,0,1,0,0,0,0,0,0,0]是one-hot标签,y是NN输出,则第一个y(2的概率最高,0.7)的均方误差更小:
在这里插入图片描述

二、交叉熵误差Cross Entropy Error

(1)单个训练数据的交叉熵误差

只计算正确解标签的输出的自然对数。
E=−∑ktklog⁡eykE=-\sum_{k}t_k\log_e y_kE=ktklogeyk

yky_kyk是NN的输出
tkt_ktk是one-hot标签,只有正确解的标签为1,其他均为0.
kkk是数据维数

单个训练数据的交叉熵误差只计算正确解标签的输出的自然对数。

如,若正确解是2,而NN输出中2的概率是0.6,则交叉熵误差是−1∗ln0.6=−0.51-1*ln0.6=-0.511ln0.6=0.51
在这里插入图片描述
所以,当NN输出的正确解的概率y为1时,交叉熵损失为0;随着正确解的概率y向0减小,交叉熵损失减小(向负值减小,实际上损失值是在增大)

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0,1,0.01)
delta = 1e-5
y = -np.log(x + delta) # 保护性对策,加个微小值,防止出现log(0)=-inf
plt.plot(x,y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('cross entropy error')
plt.show()

在这里插入图片描述

(2)mini-batch学习,多个数据的交叉熵误差

实际的机器学习任务中,一般不会一次计算一个训练数据的输出的损失函数,因为这样很慢,如果数据集大,比如有100000个训练数据,则每计算一个输入数据的损失函数后更新参数的学习过程十分耗时。所以我们计算损失函数需要针对所有训练数据,即把由所有训练数据计算出的损失函数的总和作为学习指标。 但这样做仍然存在问题,因为这样做对于大数据集,计算过程也需要花很长的时间,对于有几百万,几千万数据量的数据集,求其损失函数总和去更新参数几乎是不现实的。所以我们采用mini-batch。

mini-batch学习:
从全部数据中选出一部分,作为全部数据的“近似”。这种小批量数据叫做mini-batch,比如,从100000个训练数据中随机选择一批,如100个,用这100个训练数据的损失函数的总和作为学习指标,不断随机选择mini-batch,重复学习过程以更新参数实现参数寻优。

抽取mini-batch以近似总体所有训练数据的行为,类似于抽样,比如调查电视收视率,男性平均身高,女性平均身高,不会调查所有电视机和所有人,只以被抽取的个体为处理对象。
但是要知道,这种多次随机抽取mini-batch不保证所有训练数据都被抽取到,毕竟是随机抽取嘛,很好理解。所以随机抽取的实现,在实际任务中经常是先把所有训练数据随机打乱,乱序后,从数据的开头到结尾依次按序取一个mini-batch,这样不仅保证了一个batch的随机性,还保证所有训练数据被用到学习任务中去。

交叉熵误差改为一个小批量数据的损失函数的总和,再平均:

E=−1N∑n∑ktnklog⁡ynkE=-\frac1N\sum_{n}\sum_{k}t_{nk}\log y_{nk}E=N1nktnklogynk

  • N是mini-batch的size,即有多少个数据,如上例的100,除以N是为了正规化求出单个数据的“平均损失函数”,以获得和训练数据数量无关的统一指标
  • tnkt_{nk}tnk是第n个数据的第k维的标签,0或1
  • ynky_{nk}ynk是第n个数据第k维的NN的输出

可以看出,mini-batch学习中的交叉熵损失函数,是mini-batch中所有N个训练数据的正确标签对应输出的自然对数之和的负数。

从训练数据中随机抽取一个mini-batch的python实现:

如MNIST手写数据集,有60000张28×2828\times2828×28的训练图片,把图像拉长为一维数组(flatten函数),即NN的输入X_train是一个60000×78460000\times78460000×784的矩阵(python中是numpy数组),假设mini-batch的size是50,则

import numpy as np

# x_train, t_train分别是训练数据集和训练标签集
train_size = x_train.shape[0] # 取X_train的行数,60000
batch_size = 50
batch_mask = np.random.choice(train_size, batch_size) # 随机选择50个索引值
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

mini-bacth版交叉熵误差

# mini-bacth版交叉熵误差,可同时处理单个数据和批量数据(mini-bacth),针对one-hot标签
def cross_entropy_error(y, t):
    # 如果输入数据是一维的,即单个数据,则需要确保把y,t变为行向量而非列向量
    # 确保后面计算batch_size为1
    if y.ndim == 1:
        t = t.reshape(1, t.size) # t是one-hot标签
        y = y.reshape(1, y.size)

    batch_size = y.shape[0] # y的行数
    return -np.sum(t * np.log(y + 1e-7)) / batch_size

# mini-bacth版交叉熵误差,可同时处理单个数据和批量数据(mini-bacth),针对非one-hot标签
def cross_entropy_error(y, t):
    # 如果输入数据是一维的,即单个数据,则需要确保把y,t变为行向量而非列向量
    # 确保后面计算batch_size为1
    if y.ndim == 1:
        t = t.reshape(1, t.size) # t是非one-hot标签,如手写数字识别中的0-9
        y = y.reshape(1, y.size)

    batch_size = y.shape[0] # y的行数
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size
### 实现均方误差损失函数机器学习中,均方误差(Mean Squared Error, MSE)是一种常见的用于回归任务的损失函数。该函数通过计算预测值与真实值之间的平方差并取平均值得到最终的损失值。 对于给定的真实值 \( y \) 和预测值 \( \hat{y} \),MSE 的数学表达式如下: \[ \text{MSE}(y,\hat{y})=\frac{1}{n}\sum_{i=1}^{n}(y_i-\hat{y}_i)^2 \] 其中 \( n \) 表示样本数量[^1]。 下面是使用 Python 编程语言实现均方误差损失函数的方法之一: ```python import numpy as np def mean_squared_error(y_true, y_pred): """ 计算均方误差. 参数: y_true (numpy.ndarray): 真实标签数组. y_pred (numpy.ndarray): 预测标签数组. 返回: float: 均方误差值. """ return np.mean((y_true - y_pred)**2) ``` 此代码片段定义了一个名为 `mean_squared_error` 的函数,它接收两个参数:一个是实际的目标变量值列表或向量;另一个是由模型产生的对应于这些输入的数据点的预测输出。这两个参数都应该是相同长度的一维 NumPy 数组。接着利用广播机制和矢量化操作快速高效地完成了整个批量数据上的均方误差计算工作[^2]。 为了验证上述实现的有效性和准确性,可以通过构建一些简单的测试案例来进行检验。例如: ```python if __name__ == "__main__": # 测试用例 true_values = np.array([3., -0.5, 2., 7.]) predicted_values = np.array([2.5, 0., 2., 8.]) mse_loss = mean_squared_error(true_values, predicted_values) print(f"The Mean Squared Error is {mse_loss}") ``` 这段程序会打印出所计算得到的具体数值,从而帮助确认自定义均方误差函数是否按预期运行[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值